( ESNUG 351 Item 7 ) ---------------------------------------------- [5/4/00]
Subject: ( ESNUG 347 #1 ) Reactions To Cliff's Nonblocking Verilog Paper
> 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 flip-flop coding style with nonblocking
> assignments
From: "Alex Kumets"
John,
Cliff's Example 14 will work better if we use nonblocking during reset:
module dffx (q, d, clk, rst);
output q;
input d, clk, rst;
reg q;
always @(posedge clk)
// if (rst) q = 1'b0;
if (rst) q <= 1'b0;
else q <= d;
endmodule
Also, we may use blocking-only assignments in our design ( making much more
'always' ) but nonblocking assignments make source code much better to read
and maintain
- Alex Kumets
Wave Systems
---- ---- ---- ---- ---- ---- ----
From: Andrew Roy
John,
I think that there is a problem with Example 14 in Cliff's paper e-mailed
in ESNUG 347. The (synchronous) reset is done with a blocking assignment,
and the "clock edge" assignment is done with a nonblocking assignment.
This violates Cliff's Guideline #1 and Guideline #5, and is probably not
synthesizable with Synopsys tools.
Was this intentional, or a typo/file translation error? If it was
intentional, why is a synchronous reset handled differently than the
asynchronous reset of Cliff's Example 17 (and some other examples)?
- Andy Roy
Adaptec
---- ---- ---- ---- ---- ---- ----
From: Neil Crook
Hi John,
In Example 14 of Cliff's paper, Cliff mixes blocking and nonblocking
assignments within an always block (in violation of his Guideline #5).
I believe the = should be an <=. If so, it would avoid confusion to
fix this up...
In his Example 17, surely the whole point is that the temporary
variable n1 can be deleted, so that the second assignment to q2
becomes: q2 <= q1 ^ q3;
- Neal Crook
Micron
---- ---- ---- ---- ---- ---- ----
From: Oren Rubinstein
Hi, John,
I didn't see Cliff's presentation at SNUG (I was in a different session),
but this is indeed a very thorough analysis of the different cases. All of
Cliff's guidelines have been standard practice for us, for a long time.
I'd add one guideline of my own - add a #1 in the nonblocking assignments
to sequential elements:
a <= #1 b;
instead of
a <= b;
There are two reasons for this:
1. It allows mixed RTL and gate-level simulations to run correctly,
by providing 1ns of hold time to the gate-level flip-flops.
2. It's so much easier to understand what you see on the waves display
when you're trying to debug something, because signals change 1 ns
after the clock edge.
Good paper, Cliff.
- Oren Rubinstein
GigaPixel Corp. Santa Clara, CA
---- ---- ---- ---- ---- ---- ----
From: Alain Raynaud
John,
I can't help it, I have to add my 2 cents to Cliff Cummings otherwise
excellent paper on nonblocking Verilog assignments. And believe me, I'm
not trying to start a language war either...
We, European designers, never cease to wonder why our American friends
have such a hard time dealing with a relatively simple issue (Cliff's
paper lists a total of 8 rules), when it all fits in one golden rule:
"Verilog blocking vs. nonblocking is the same as VHDL variable vs. signal".
For those of you who are not familiar with VHDL, let me restate the VHDL
variable rule with a Verilog spin: "blocking assignments should be used
for intermediate computations inside an always block, whereas
nonblocking assignments should be used to export outputs of an always
block to other blocks or ports".
If you look carefully, this one rule is exactly the equivalent, but more
powerful, of guidelines #1, #3 and #4. It also shows that guideline #5
and #6 are actually overkill.
Of course, I am aware that the VHDL variable semantics has one major
restriction: you cannot do a nonblocking assignment to the same signal
in different always blocks. But I believe it's a small price to pay for
peace of mind...
- Alain "where is VHDL when you need it?" Raynaud
Tensilica, Inc. Santa Clara, CA
---- ---- ---- ---- ---- ---- ----
From: "Steve Glaser"
John,
While it's not synthesizeable, another common misuse of blocking vs.
nonblocking is in tunable external delay elements. These are pretty handy
in testbench code. However, using it correctly violates Cliff's
Guideline #3.
Guideline #3: When modeling combinational logic with an "always"
block, use blocking assignments.
We commonly use something like the following...
function real n2r;
input delay;
reg [31:0] delay;
n2r = delay * 0.01;
endfunction
...
reg [31:0] sci_dly; // written by Vera
initial begin
sci_dly = 32'd0;
out = 1'b0;
end
always @(in)
out <= #(n2r(sci_dly)) in; // don't use blocking assignment here
The n2r function scales and converts an integer to a real. It helps since
Vera doesn't do floats as nicely. It's not critical to the issue (except
some Verilogs won't let you use a non-integer as a delay, even if it was
a constant).
If this code used blocking assignment, and input edges happen faster than
the delay value, then input edges will get lost and not show (delayed) up
on the output.
- Steve Glaser
Avici Systems North Billerica, MA
P.S. I assume Cliff meant nonblocking on both assignments in his Example 14.
Otherwise this would violate his Guideline #5.
---- ---- ---- ---- ---- ---- ----
From: "Vigyan Singhal"
John,
I have a comment/question on Cliff's following myth:
> 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 on 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: "The last nonblocking assignment wins!"
The Verilog LRM appears to be inconsistent on this issue. I picked up the
following from section 9.2 on "Procedural assignments":
"When multiple non-blocking assignments are scheduled to occur in
the same register in a particular time slot, the order in which the
assignments are evaluated is not guaranteed -- the final value of
the register is indeterminate. As shown below, the value of register
a is not known until the end of time step 4.
module multiple2 (out);
output out
reg a;
initial a = 1;
// The register's assigned value is indeterminate
initial begin
a <= #4 0; // schedules a = 0 at time 4
a <= #4 1; // schedules a = 1 at time 4
end // At time 4, a = ??
endmodule
This seems to contradict Cliff's earlier quote from Section 5.4.1... Which
is correct, and why does the LRM seem to be inconsistent? In fact, I have
seen an example (more complicated than this one) where DC picked the first
assignment, but we thought it wasn't DC's fault since the RTL was not
deterministic. Perhaps we should have treated it as a synthesis bug.
- Vigyan Singhal
---- ---- ---- ---- ---- ---- ----
From: Bob Emberley
Hi John,
I found Cliff's paper, "Coding Styles That Kill!" very informative. Several
of the pitfalls that Cliff described can be categorized as "read-write" or
"write-write" race conditions. Surelint is able to detect and warn the user
about these types of problems. Here is a summary of the SureLint results
using Cliff's examples:
Example 1: two read-write races are reported.
Example 2: no race is reported, as expected.
Example 7: two read-write races are reported.
Example 8: two read-write races are reported.
Example 11: no race is reported, as expected.
Example 15: no race is reported, as expected.
Example 26: two write-write races are reported.
Without going into too much of an advertisement, SureLint is able to detect
5 different types of races:
read-write
write-write
trigger propagation
combinational loop
UDP races (conflicts in UDP table)
The read-write and write-write are the most common and dangerous.
- Bob Emberley, FAE
Verisity Design Campbell, CA
|
|