Verilog Synthesis, Coding Styles That Kill
Verilog Synthesis, Coding Styles That Kill
Clifford E. Cummings
ABSTRACT One of the most misunderstood constructs in the Verilog language is the nonblocking assignment. Even very experienced Verilog designers do not fully understand how nonblocking assignments are scheduled in an IEEE compliant Verilog simulator and do not understand when and why nonblocking assignments should be used. This paper details how Verilog blocking and nonblocking assignments are scheduled, gives important coding guidelines to infer correct synthesizable logic and details coding styles to avoid Verilog simulation race conditions.
1.0 Introduction
Two well known Verilog coding guidelines for modeling logic are: Guideline: Use blocking assignments in always blocks that are written to generate combinational logic [1]. Guideline: Use nonblocking assignments in always blocks that are written to generate sequential logic [1].
But why? 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. To understand the reasons behind the above guidelines, one needs to have a full understanding of the functionality and scheduling of Verilog blocking and nonblocking assignments. This paper will detail the functionality and scheduling of blocking and nonblocking assignments. Throughout this paper, the following abbreviations will be used: RHS - the expression or variable on the right-hand-side of an equation will be abbreviated as RHS equation, RHS expression or RHS variable. LHS - the expression or variable on the left-hand-side of an equation will be abbreviated as LHS equation, LHS expression or LHS variable.
According to the IEEE Verilog Standard, the two always blocks can be scheduled in any order. If the first always block executes first after a reset, both y1 and y2 will take on the value of 1. If the second always block executes first after a reset, both y1 and y2 will take on the value 0. This clearly represents a Verilog race condition.
Again, according to the IEEE Verilog Standard, the two always blocks can be scheduled in any order. No matter which always block starts first after a reset, both nonblocking RHS expressions will be evaluated at the beginning of the time step and then both nonblocking LHS variables will be updated at the end of the same time step. From a users perspective, the execution of these two nonblocking statements happen in parallel.
Blocking assignments Evaluate RHS of nonblocking assignments Active Events Continuous assignments $display command execution Evaluate inputs and change outputs of primitives Inactive Events
#0 blocking assignments Update LHS of nonblocking assignments $monitor command execution $strobe command execution Other specific PLI commands
Nonblocking Events
Monitor Events
The active events queue is where most Verilog events are scheduled, including blocking assignments, continuous assignments, $display commands, evaluation of instance and primitive inputs followed by updates of primitive and instance outputs, and the evaluation of nonblocking RHS expressions. The LHS of nonblocking assignments are not updated in the active events queue. Events are added to any of the event queues (within restrictions imposed by the IEEE Standard) but are only removed from the active events queue. Events that are scheduled on the other event queues will eventually become "activated," or promoted into the active events queue. Section 5.4 of the IEEE 1364-1995 Verilog Standard lists an algorithm that describes when the other event queues are "activated." Two other commonly used event queues in the current simulation time are the nonblocking assign updates event queue and the monitor events queue, which are described below. The nonblocking assign updates event queue is where updates to the LHS expression of nonblocking assignments are scheduled. The RHS expression is evaluated in random order at the beginning of a simulation time step along with the other active events described above. The monitor events queue is where $strobe and $monitor display command values are scheduled. $strobe and $monitor show the updated values of all requested variables at the end of a simulation time step, after all other assignments for that simulation time step are complete.
A fourth event queue described in section 5.3 of the Verilog Standard is the inactive events queue, where #0-delayed assignments are scheduled. The practice of making #0-delay assignments is generally a flawed practice employed by designers who try to make assignments to the same variable from two separate procedural blocks, attempting to beat Verilog race conditions by scheduling one of the assignments to take place slightly later in the same simulation time step. Adding #0-delay assignments to Verilog models needlessly complicates the analysis of scheduled events. The author knows of no condition that requires making #0-delay assignments that could not be easily replaced with a different and more efficient coding style and hence discourages the practice. Guideline #8: Do not make assignments using #0 delays. The "stratified event queue" of Figure 1 will be frequently referenced to explain the behavior of Verilog code examples shown later in this paper. The event queues will also be referenced to justify the eight coding guidelines given in section 5.0.
In contrast, the oscillator in Example 4 uses nonblocking assignments. After the first @(clk) trigger, the RHS expression of the nonblocking assignment is evaluated and the LHS value scheduled into the nonblocking assign updates event queue. Before the nonblocking assign updates event queue is "activated," the @(clk) trigger statement is encountered and the always block again becomes sensitive to changes on the clk signal. When the nonblocking LHS value is updated later in the same time step, the @(clk) is again triggered. The osc2 example is selftriggering (which is not necessarily a recommended coding style).
module osc2 (clk); output clk; reg clk; initial #10 clk = 0; always @(clk) #10 clk <= ~clk; endmodule Example 4 - Self-triggering oscillator using nonblocking assignments
clk
In the pipeb1, Example 5 code, the sequentially ordered blocking assignments will cause the input value, d, to be placed on the output of every register on the next posedge clk. On every clock edge, the input value is transferred directly to the q3-output without delay. This clearly does not model a pipeline register and will actually synthesize to a single register! (See Figure 3).
module pipeb1 (q3, d, clk); output [7:0] q3; input [7:0] d; input clk; reg [7:0] q3, q2, q1; always @(posedge clk) begin q1 = d; q2 = q1; q3 = q2; end endmodule Example 5 - Bad blocking-assignment sequential coding style #1
q3
clk
In the pipeb2 example, the blocking assignments have been carefully ordered to cause the simulation to correctly behave like a pipeline register. This model also synthesizes to the pipeline register shown in Figure 2.
module pipeb2 (q3, d, clk); output [7:0] q3; input [7:0] d; input clk; reg [7:0] q3, q2, q1; always @(posedge clk) begin q3 = q2; q2 = q1; q1 = d; end endmodule Example 6 - Bad blocking-assignment sequential coding style #2 - but it works!
In the pipeb3 example, the blocking assignments have been split into separate always blocks. Verilog is permitted to simulate the always blocks in any order, which might cause this pipeline simulation to be wrong. This is a Verilog race condition! Executing the always blocks in a different order yields a different result. However, this Verilog code will synthesize to the correct pipeline register. This means that there might be a mismatch between the pre-synthesis and postsynthesis simulations. The pipeb4 example, or any other ordering of the same always block statements will also synthesize to the correct pipeline logic, but might not simulate correctly.
module pipeb3 (q3, d, clk); output [7:0] q3; input [7:0] d; input clk; reg [7:0] q3, q2, q1; always @(posedge clk) q1=d; always @(posedge clk) q2=q1; always @(posedge clk) q3=q2; endmodule Example 7 - Bad blocking-assignment sequential coding style #3 module pipeb4 (q3, d, clk); output [7:0] q3; input [7:0] d; input clk; reg [7:0] q3, q2, q1; always @(posedge clk) q2=q1; always @(posedge clk) q3=q2; always @(posedge clk) q1=d; endmodule Example 8 - Bad blocking-assignment sequential coding style #4
If each of the four blocking-assignment examples is rewritten with nonblocking assignments, each will simulate correctly and synthesize the desired pipeline logic.
module pipen1 (q3, d, clk); output [7:0] q3; input [7:0] d; input clk; reg [7:0] q3, q2, q1; always @(posedge clk) begin q1 <= d; q2 <= q1; q3 <= q2; end endmodule Example 9 - Good nonblocking-assignment sequential coding style #1 module pipen2 (q3, d, clk); output [7:0] q3; input [7:0] d; input clk; reg [7:0] q3, q2, q1; always @(posedge clk) begin q3 <= q2; q2 <= q1; q1 <= d; end endmodule Example 10 - Good nonblocking-assignment sequential coding style #2 module pipen3 (q3, d, clk); output [7:0] q3; input [7:0] d; input clk; reg [7:0] q3, q2, q1; always @(posedge clk) q1<=d; always @(posedge clk) q2<=q1; always @(posedge clk) q3<=q2; endmodule Example 11 - Good nonblocking-assignment sequential coding style #3
10
module pipen4 (q3, d, clk); output [7:0] q3; input [7:0] d; input clk; reg [7:0] q3, q2, q1; always @(posedge clk) q2<=q1; always @(posedge clk) q3<=q2; always @(posedge clk) q1<=d; endmodule Example 12 - Good nonblocking-assignment sequential coding style #4
Upon examination of the pipeline coding styles shown in this section: 1 out of 4 blocking assignment coding styles was guaranteed to simulate correctly 3 out of 4 blocking assignment coding styles were guaranteed to synthesize correctly 4 out of 4 nonblocking assignment coding styles were guaranteed to simulate correctly 4 out of 4 blocking assignment coding styles were guaranteed to synthesize correctly. Although, if confined to one always block with carefully sequenced assignments, it was possible to code the pipeline logic using blocking assignments. On the other hand, it was easy to code the same pipeline logic using nonblocking assignments; indeed, the nonblocking assignment coding styles all would work for both synthesis and simulation.
If an engineer is willing to limit all modules to a single always block, blocking assignments can be used to correctly model, simulate and synthesize the desired logic. Unfortunately this reasoning leads to the habit of placing blocking assignments in other, more complex sequential always blocks that will exhibit the race conditions already detailed in this paper.
11
module dffx (q, d, clk, rst); output q; input d, clk, rst; reg q; always @(posedge clk) if (rst) q <= 1'b0; else q <= d; endmodule Example 14 - Preferred D-flipflop coding style with nonblocking assignments
It is better to develop the habit of coding all sequential always blocks, even simple single-block modules, using nonblocking assignments as shown in Example 14. Now consider a more complex piece of sequential logic, a Linear Feedback Shift-Register or LFSR.
There is no way to order the assignments in Example 15 to model the feedback loop unless a temporary variable is used.
12
One could group all of the assignments into one-line equations to avoid using a temporary variable, as shown in Example 16, but the code is now more cryptic. For larger examples, oneline equations might become very difficult to code and debug. One-line equation coding styles are not necessarily encouraged.
module lfsrb2 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; always @(posedge clk or negedge pre_n) if (!pre_n) {q3,q2,q1} = 3'b111; else {q3,q2,q1} = {q2,(q1^q3),q3}; endmodule Example 16 - Functional but cryptic LFSR with blocking assignments
If the blocking assignments in Example 15 and Example 16 are replaced with nonblocking assignments as shown in Example 17 and Example 18, all simulations function as would be expected from an LFSR.
module lfsrn1 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; wire n1; assign n1 = q1 ^ q3; always @(posedge clk or negedge pre_n) if (!pre_n) begin q3 <= 1'b1; q2 <= 1'b1; q1 <= 1'b1; end else begin q3 <= q2; q2 <= n1; q1 <= q3; end endmodule Example 17 - Functional LFSR with nonblocking assignments
13
module lfsrn2 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; always @(posedge clk or negedge pre_n) if (!pre_n) {q3,q2,q1} <= 3'b111; else {q3,q2,q1} <= {q2,(q1^q3),q3}; endmodule Example 18 - Functional but cryptic LFSR with nonblocking assignments
Based on the pipeline examples of section 8.0 and the LFSR examples of section 10.0, it is recommended to model all sequential logic using nonblocking assignments. A similar analysis would show that it is also safest to use nonblocking assignments to model latches Guideline #1: When modeling sequential logic, use nonblocking assignments. Guideline #2: When modeling latches, use nonblocking assignments.
14
module ao4 (y, a, b, c, d); output y; input a, b, c, d; reg y, tmp1, tmp2; always @(a or b or c or d) begin tmp1 <= a & b; tmp2 <= c & d; y <= tmp1 | tmp2; end endmodule Example 19 - Bad combinational logic coding style using nonblocking assignments
The code shown in Example 20 is identical to the code shown in Example 19, except that tmp1 and tmp2 have been added to the sensitivity list. As describe in section 7.0, when the nonblocking assignments update the LHS variables in the nonblocking assign update events queue, the always block will self-trigger and update the y-outputs with the newly calculated tmp1 and tmp2 values. The y-output value will now be correct after taking two passes through the always block. Multiple passes through an always block equates to degraded simulation performance and should be avoided if a reasonable alternative exists.
module ao5 (y, a, b, c, d); output y; input a, b, c, d; reg y, tmp1, tmp2; always @(a or b or c or d or tmp1 or tmp2) begin tmp1 <= a & b; tmp2 <= c & d; y <= tmp1 | tmp2; end endmodule Example 20 - Inefficient multi-pass combinational logic coding style with nonblocking assignments
15
A better habit to develop, one that does not require multiple passes through an always block, is to only use blocking assignments in always blocks that are written to model combinational logic.
module ao2 (y, a, b, c, d); output y; input a, b, c, d; reg y, tmp1, tmp2; always @(a or b or c or d) begin tmp1 = a & b; tmp2 = c & d; y = tmp1 | tmp2; end endmodule Example 21 - Efficient combinational logic coding style using blocking assignments
The code in Example 21 is identical to the code in Example 19, except that the nonblocking assignments have been replaced with blocking assignments, which will guarantee that the youtput assumes the correct value after only one pass through the always block; hence the following guideline: Guideline #3: When modeling combinational logic with an always block, use blocking assignments.
The same logic that is implemented in Example 22 could also be implemented as two separate always blocks, one with purely combinational logic coded with blocking assignments and one with purely sequential logic coded with nonblocking assignments as shown in Example 23.
16
module nbex1 (q, a, b, clk, rst_n); output q; input clk, rst_n; input a, b; reg q, y; always @(a or b) y = a ^ b; always @(posedge clk or negedge rst_n) if (!rst_n) q <= 1'b0; else q <= y; endmodule Example 23 - Combinational and sequential logic separated into two always blocks
Guideline #4: When modeling both sequential and combinational logic within the same always block, use nonblocking assignments.
The code in Example 25 will most likely simulate correctly most of the time, but Synopsys tools will report a syntax error because the blocking assignment is assigned to the same variable as one of the nonblocking assignments. This code must be modified to be synthesizable.
17
module ba_nba6 (q, a, b, clk, rst_n); output q; input a, b, rst_n; input clk; reg q, tmp; always @(posedge clk or negedge rst_n) if (!rst_n) q = 1'b0; // blocking assignment to "q" else begin tmp = a & b; q <= tmp; // nonblocking assignment to "q" end endmodule Example 25 - Synthesis syntax error - blocking and nonblocking assignment to the same variable
As a matter of forming good coding habits, the author encourages adherence to the following: Guideline #5: Do not mix blocking and nonblocking assignments in the same always block.
When Synopsys tools read this type of coding example, the following warning message is issued:
Warning: In design 'badcode1', there is 1 multiple-driver net with unknown wired-logic type.
18
When the warning is ignored and the code from Example 26 is compiled, two flipflops with outputs feeding a 2-input and gate are inferred. The pre-synthesis simulation does not even closely match the post-synthesis simulation in this example. Guideline #6: Do not make assignments to the same variable from more than one always block.
The below output from the above simulation shows that the $display command was executed in the active events queue, before the nonblocking assign update events were executed.
$display: a = 0 $monitor: a = 1 $strobe : a = 1
19
15.2 #0-delay assignments Myth: #0 forces an assignment to the end of a time step Truth: #0 forces an assignment to the "inactive events queue"
module nb_schedule1; reg a, b; initial begin a = 0; b = 1; a <= b; b <= a; $monitor $display $strobe #0 $display #1 $monitor $display $strobe $display #1 $finish; end endmodule ("%0dns: ("%0dns: ("%0dns: ("%0dns: ("%0dns: ("%0dns: ("%0dns: ("%0dns: \$monitor: a=%b b=%b", $stime, a, b); \$display: a=%b b=%b", $stime, a, b); \$strobe : a=%b b=%b\n", $stime, a, b); #0 : a=%b b=%b", $stime, a, b); \$monitor: a=%b b=%b", $stime, a, b); \$display: a=%b b=%b", $stime, a, b); \$strobe : a=%b b=%b\n", $stime, a, b); #0 : a=%b b=%b", $stime, a, b);
The below output from the simulation on the previous page shows that the #0-delay command was executed in the inactive events queue, before the nonblocking assign update events were executed.
0ns: 0ns: 0ns: 0ns: 1ns: 1ns: 1ns: 1ns: $display: #0 : $monitor: $strobe : $display: #0 : $monitor: $strobe : a=0 a=0 a=1 a=1 a=1 a=1 a=1 a=1 b=1 b=1 b=0 b=0 b=0 b=0 b=0 b=0
Guideline #7: Use $strobe to display values that have been assigned using nonblocking assignments.
20
15.3 Multiple nonblocking assignments to the same variable Myth: Making multiple nonblocking assignments to the same variable in the same always block is undefined Truth: Making multiple nonblocking assignments to the same variable in the same always block is defined by the Verilog Standard. The last nonblocking assignment to the same variable wins! Quoting from the IEEE 1364-1995 Verilog Standard [2], pg. 47, section 5.4.1 - Determinism "Nonblocking assignments shall be performed in the order the statements were executed. Consider the following example:
initial begin a <= 0; a <= 1; end
When this block is executed, there will be two events added to the nonblocking assign update queue. The previous rule requires that they be entered on the queue in source order; this rule requires that they be taken from the queue and performed in source order as well. Hence, at the end of time-step 1, the variable a will be assigned 0 and then 1." Translation: Last nonblocking assignment wins!
21
References
[1] [2] IEEE P1364.1 Draft Standard For Verilog Register Transfer Level Synthesis IEEE Standard Hardware Description Language Based on the Verilog Hardware Description Language, IEEE Computer Society, IEEE Std 1364-1995 Clifford Cummings, "Correct Methods For Adding Delays To Verilog Behavioral Models," International HDL Conference 1999 Proceedings, pp. 23-29, April 1999.
[3]
22
23