( 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


 Sign up for the DeepChip newsletter.
Email
 Read what EDA tool users really think.


Feedback About Wiretaps ESNUGs SIGN UP! Downloads Trip Reports Advertise

"Relax. This is a discussion. Anything said here is just one engineer's opinion. Email in your dissenting letter and it'll be published, too."
This Web Site Is Modified Every 2-3 Days
Copyright 1991-2024 John Cooley.  All Rights Reserved.
| Contact John Cooley | Webmaster | Legal | Feedback Form |

   !!!     "It's not a BUG,
  /o o\  /  it's a FEATURE!"
 (  >  )
  \ - / 
  _] [_     (jcooley 1991)