# Which of the following PRBS generator algorithms is favored practice and why?

I am currently learning Verilog and trying to make a PRBS generator in Verilog. While doing that, I have tried different combinations as shown in the code and pictures below. Later on, I have to put it on an Artix A7 FPGA. I'll add a clock frequency divider circuit later on for the PRBS to show on a speed perceivable to human eye.

Which one is better for real life implementation? I am sure that due to reasons like space, time, energy or some other reason, one will be preferable over other.

Configurations are like

1. Output is register and has non-blocking assignment to it
module prbs_gen(clk, prbs);
input clk;
output reg prbs;
reg[31:0] temp = 32'b11010101110101011101010111010101;
reg x;

always @(posedge clk)
begin
prbs <= temp[0];
x = temp[1]^temp[0];
temp = temp >> 1;
temp[31] = x;
end
endmodule

1. Output is reg but has blocking assignment to it, inside always block
module prbs_gen(clk, prbs);
input clk;
output reg prbs;
reg[31:0] temp = 32'b11010101110101011101010111010101;
reg x;

always @(posedge clk)
begin
prbs = temp[0];
x = temp[1]^temp[0];
temp = temp >> 1;
temp[31] = x;
end
endmodule

1. Output is reg and blocking assignment with "assign" keyword inside "always" block
module prbs_gen(clk, prbs);
input clk;
output reg prbs;
reg[31:0] temp = 32'b11010101110101011101010111010101;
reg x;

always @(posedge clk)
begin
assign prbs = temp[0];
x = temp[1]^temp[0];
temp = temp >> 1;
temp[31] = x;
end
endmodule

1. Output type isn't specified, but the blocking assignment is out of the "always" block
module prbs_gen(clk, prbs);
input clk;
output prbs;
reg[31:0] temp = 32'b11010101110101011101010111010101;
reg x;

assign prbs = temp[0];
always @(posedge clk)
begin
x = temp[1]^temp[0];
temp = temp >> 1;
temp[31] = x;
end
endmodule

1. Output is reg and non-blocking assignment to it in "always" block
module prbs_gen(clk, prbs);
input clk;
output reg prbs;
reg[31:0] temp = 32'b11010101110101011101010111010101;
reg x;

always @(posedge clk)
begin
prbs <= temp[0];
x = temp[1]^temp[0];
temp = temp >> 1;
temp[31] = x;
end
endmodule


Common testbench code

module tb();
reg clk;
wire prbs;

prbs_gen uut(clk, prbs);
initial clk = 0;
always #5 clk = ~clk;
endmodule


Codes with waveforms below.

• much better to put the code text into a code block (select and ctrl-k) than post pictures of it, then you get a scrollable copy/pastable window in your question that's much easier for potential answerers to handle, it's also text searchable so your question can be found by future users of search engines. Jun 11 at 14:04
• You might want to contrast the 'hardware' approach that takes an XOR of the all sequence defining bits, then shifts the result into the end of a shift register, with the 'software' approach that XORs each sequence defining bit in the shift register with the bit being shifted out. Subject to some straightforward symmetries, they produce the same sequence. Jun 11 at 17:57
• @Neil_UK okay I'll put the code as well. But I don't have the pictures now so I have to keep them as it is. Jun 11 at 22:45
• Don't mix blocking and non-blocking assignment, and don't mix blocking assignment and sequential element description, if you want to manage maintainable code/project. Jun 12 at 2:35
• And didn't your tool complain about that assign in always? Jun 12 at 2:39

Your 5 code examples do not adhere to good Verilog coding practices. For example, the 1st example uses both blocking and nonblocking assignments inside the same always block. Generally, it is better to use nonblocking assignments to infer sequential logic. The paper Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kill! offers detailed guidelines and explanations. In a nutshell:

In general, the answer is simulation related. Ignoring the above guidelines can still infer the correct synthesized logic, but the pre-synthesis simulation might not match the behavior of the synthesized circuit.

Your examples give you the simulation results you were expecting. It will be interesting to see what results you get on your FPGA. Since your code is short (only 4 lines in the always block), you may get the FPGA results you expect. But, with larger designs, it will become more important to stick to these guiddelines.

blocking assignment with "assign" keyword inside "always" block

This is known as a procedural continuous assignment, and it is not a common coding style. You can read more about it in the IEEE Std 1800-2017, section 10.6 Procedural continuous assignments. You should avoid this. In fact, this syntax is scheduled for deprecation.

Here are some minor tips which would make your code easier to understand and maintain.

You can use underscore separators for the 32-bit constant you use to initialize temp. It is common to separate groups of 4 bits:

reg[31:0] temp = 32'b1101_0101_1101_0101_1101_0101_1101_0101;


It is even easier to understand using hexadecimal notation:

reg [31:0] temp = 32'hd5d5_d5d5;


It is confusing to name a signal x since "x" is also used to represent the Verilog "unknown" value.

Simplify the module port declaration by using ANSI-style ports:

module prbs_gen (
input clk,
output reg prbs
);


I think this code is equivalent to yours while adhering to the guidelines:

module prbs_gen (
input clk,
output reg prbs
);
reg [31:0] temp = 32'hd5d5_d5d5;

always @(posedge clk) begin
prbs <= temp[0];
temp <= {(temp[1]^temp[0]), temp[31:1]};
end
endmodule

• thanks for telling the good practices. Jun 13 at 4:51
• in the code you have posted, correct me if I'm wrong. At first clock edge temp[0] is stored somewhere, {(temp[1]^temp[0]), temp[31:1]} is stored after the clock pulse values are assigned to prbs and temp. I actually don't know the way/order statements are executed in Verilog ( like blocking is instant assignment, non-blocking is after the block is (and other always blocks if any) is executed, what is computed earlier initial block or always etc.). If I could know that, coding will get easier with lesser lines. Jun 13 at 5:02
• @ItachiUchiha: The paper has a good description of some of the aspects of nonblocking assignment behavior. There are many more resources available on the topic as well. Jun 15 at 10:26

Verilog is a hardware description language. Since you are just beginning to learn Verilog coding, I highly recommend drawing a circuit diagram of the hardware first before writing out Verilog code. Here is the circuit diagram that I came up with.

Neatly divide your Verilog code into combinational logic and sequential logic. Prefer assign statements for simple combinational logic. Use always blocks with non-blocking statements for sequential logic. Keep your always block simple. Of course these are dealt with in detail in the paper toolic shared in the other answer.

module prbs_gen(
input clk,
output reg prbs);

reg [31:0] temp = 32'b1101_0101_1101_0101_1101_0101_1101_0101;
wire temp_xor;

// Combinational logic
assign prbs = temp[0];
assign temp_xor = temp[0] ^ temp[1];

// Sequential logic (Shift register)
always @ (posedge clk)
begin
temp[0] <= temp[1];
temp[1] <= temp[2];
temp[2] <= temp[3];
.
.
.
temp[30] <= temp[31];
temp[31] <= temp_xor;
end

endmodule



The above code is a direct translation of the circuit diagram I drew and a verbose code. Of course we could make the always block concise by using the following statements

   always @ (posedge clk)
temp <= {temp_xor, temp[31:1]};


OR maybe even this would work and synthesize

   always @ (posedge clk)
temp <= temp >> 1;


Even though the last piece of code would work, I would not recommend it, especially for a beginner, because it's very hard to connect the above piece of code with the circuit diagram.

Lastly, regarding the question on space, time, energy for the different codes. Although your codes are different, you are just describing the same piece of hardware in different ways. So most likely all of your codes could have the same area, and power. Taking less time or space or power depends on how you construct your hardware circuit diagram and not by the coding style. Verilog supports different coding styles to describe the same hardware.