Blocking vs Non-Blocking Assignemts 
Author Message
 Blocking vs Non-Blocking Assignemts

Quote:

> See page 161 of Thomas & Moorby.

My 2nd edition T&M makes no mention whatever of non-blocking assignment,
presumably there's a newer edition now?  I never used any version of
Verilog that didn't have <= , but presumably it was a late addition to
the language - can some historian clarify?

Quote:
> I have had to deal with a lot of code written by engineers who didn't
> clearly understand the difference and it is always a real pain to
> straighten out.

yes, I'm with you on that one.

My $0.02:

In clocked always blocks, use <= to assign to anything that you hope
will synthesise to a real flipflop.  This has the extremely happy
side-effect that the assignment doesn't take effect until _all_ the
calculations in the always block have been performed.  So you can go on
using a reg in expressions, even after it has been assigned-to in the
code, and you will get the pre-clock contents of the register.  This
is usually what you want.  Mark Hess's suggestion about adding a
parameterised delay to the non-blocking assignment is a good one:
it can make the flipflop's behaviour much more obvious in simulation.

For anything else (i.e. anything that you intend will synthesise to
combinatorial logic) use blocking assignment, and shed {*filter*} and tears
in your efforts to avoid unexpected latches.

This strategy is just one aspect of something all HDL codists should be
trying to do all the time:  make sure that your synthesisable code is
written in such a way that its behaviour in simulation exactly
corresponds
with what you expect the real hardware to do.

Hope this helps a bit.

Jonathan Bromley
--



Sat, 17 Mar 2001 03:00:00 GMT  
 Blocking vs Non-Blocking Assignemts
...

Quote:
>combinatorial logic) use blocking assignment, and shed {*filter*} and tears
>in your efforts to avoid unexpected latches.

>This strategy is just one aspect of something all HDL codists should be
>trying to do all the time:  make sure that your synthesisable code is
>written in such a way that its behaviour in simulation exactly
>corresponds
>with what you expect the real hardware to do.

Verilint from interHDL detects constructs that make the simulation
incompatible with the synthesized code, and in particular the misuse
of blocking/nonblocking assignments. For more info contact

Eli

--
Eli Sternheim
interHDL, Inc.
4984 El Camino Real, Suite 210
Los Altos, CA. 94022-1433
phone: 650-428-4200
fax:   650-428-4201



Sat, 17 Mar 2001 03:00:00 GMT  
 Blocking vs Non-Blocking Assignemts
Another caveat with use of Non Blocking Assigns (NBAs) from simulation
point of view is that their mutual order in the same time slot is not
supposed to be guaranteed by simulators.

For example (from IEEE LRM),

initial
begin
  a <= #4 0;
  a <= #4 1;
end

In the above code, coming from VHDL world, you will assume that the
final value of a after 4 time units will be 1 since this is a sequential
block, but IEEE Verilog standard says that in Verilog, one cannot
guarantee what the final value will be, it can either 0 or 1.

Which means that different simulators *can* potentially end up with
different values of a. This provides some leeway to simulators to do
some optimizations (like ignore or efficiently re-order multiple
assignments), but at the cost of determinism.

-Ashutosh



Sat, 17 Mar 2001 03:00:00 GMT  
 Blocking vs Non-Blocking Assignemts
Tommy,

this dosn't do what your diagram suggests it should. Your logic
does this...
              _   _   _   _   _
 clock      _| |_| |_| |_| |_| |
                     :   :
              ___ ___ ___ ___ ___
 count      -|n-2|n-1| n |n+1|n+2
              --- --- --- --- ---
                     :   :
              ___________________
 reference  _|         n
              -------------------
                     :   :
                      ___
 match      _________|   |_______

...which is what I expect you intended :-)

All the same it's a neat example, but I reckon it's often simpler (and
therefore quicker and less error prone) to stick to a simple convention
which yields "scabby" code (IYHO) then to analyze each and every situation
to see if it is safe and/or appropriate to do things differently.

R

Quote:

> Here's an example of where blocking assigns in a sequential block may be more
> appropriate than non blocking assigns.

> Suppose I have an up counter which is being compared against a value held in a
> register.  I want a match flag to assert when the counter reaches the reference
> value. Specifically, I want the flag to assert on the same clock edge which
> increments the counter to the reference value.  AND, I want my match
> output to be registered.  That is, I want match to be the q of a
> flip-flop, with no logic between that q and the module port.  So, I want:

>              _   _   _   _   _
> clock      _| |_| |_| |_| |_| |
>                     :
>              ___ ___ ___ ___ ___
> count      -|n-2|n-1| n |n+1|n+2
>              --- --- --- --- ---
>                     :
>              ___________________
> reference  _|         n
>              -------------------
>                     :
>                      ___________
> match      _________|

> Now, with non blocking assigns I can't do:

>         //========================================

>           begin
>             count[7:0] <= count[7:0] + 7'b1;
>             if(count[7:0] == reference[7:0])
>               match <= 1'b1;
>             else
>               match <= 1'b0;
>           end
>         //========================================

> because the if() will only go true on the clock edge AFTER
> the one which makes count equal the reference.

> Of course I could do (DONT TRY THIS AT HOME):

>         //========================================

>           begin
>             count[7:0] <= count[7:0] + 7'b1;
>             if(count[7:0] == (reference[7:0] - 7'b1))
>               match <= 1'b1;
>             else
>               match <= 1'b0;
>           end
>         //========================================

> But then I'd infer an 8-bit subtractor and get fired (or at least
> flamed something rotten...)

> So what about:

>         //========================================

>           count <= count+1

>         assign match = (count[7:0] == reference[7:0]) ? 1:0;
>         //========================================

> But then match isn't registered.  I've got a comparator in between
> the flop output and the port.  Hello timing budgets in synthesis.

> Or - still getting into contortions because of insisting on
> non-blocking assigns - I could try:

>         //========================================
>         assign next_count[7:0] = count[7:0] + 7'b1;


>           count[7:0] <= next_count[7:0];


>           if(next_count[7:0] == reference[7:0])
>               match <= 1'b1;
>             else
>               match <= 1'b0;
>         //========================================

> That does the job, but it's just plain scabby.

> Given all those shennanigans, why not just
> use blocking assigns:

>         //========================================

>           begin
>             count[7:0] = count[7:0] + 7'b1;
>             if (count[7:0] == reference[7:0])
>               match = 1'b1;
>             else
>               match = 1'b0;
>           end
>         //========================================

> Nice'n'concise and a clear description of WHAT I
> want to do, rather than HOW I want it done.

> t

--
=====================================================================
Robert R Fairlie - IC Design, Motorola, Scotland
Tel.  - +44 1355 566039
======================================================================


Sat, 17 Mar 2001 03:00:00 GMT  
 Blocking vs Non-Blocking Assignemts
Here's an example of where blocking assigns in a sequential block may be more
appropriate than non blocking assigns.

Suppose I have an up counter which is being compared against a value held in a
register.  I want a match flag to assert when the counter reaches the reference
value. Specifically, I want the flag to assert on the same clock edge which
increments the counter to the reference value.  AND, I want my match
output to be registered.  That is, I want match to be the q of a
flip-flop, with no logic between that q and the module port.  So, I want:

             _   _   _   _   _  
clock      _| |_| |_| |_| |_| |
                    :
             ___ ___ ___ ___ ___
count      -|n-2|n-1| n |n+1|n+2
             --- --- --- --- ---
                    :
             ___________________
reference  _|         n
             -------------------
                    :
                     ___________
match      _________|

Now, with non blocking assigns I can't do:

        //========================================

          begin
            count[7:0] <= count[7:0] + 7'b1;
            if(count[7:0] == reference[7:0])
              match <= 1'b1;
            else
              match <= 1'b0;
          end
        //========================================

because the if() will only go true on the clock edge AFTER
the one which makes count equal the reference.

Of course I could do (DONT TRY THIS AT HOME):

        //========================================

          begin
            count[7:0] <= count[7:0] + 7'b1;
            if(count[7:0] == (reference[7:0] - 7'b1))
              match <= 1'b1;
            else
              match <= 1'b0;
          end
        //========================================

But then I'd infer an 8-bit subtractor and get fired (or at least
flamed something rotten...)

So what about:

        //========================================

          count <= count+1    

        assign match = (count[7:0] == reference[7:0]) ? 1:0;
        //========================================

But then match isn't registered.  I've got a comparator in between
the flop output and the port.  Hello timing budgets in synthesis.

Or - still getting into contortions because of insisting on
non-blocking assigns - I could try:

        //========================================
        assign next_count[7:0] = count[7:0] + 7'b1;


          count[7:0] <= next_count[7:0];


          if(next_count[7:0] == reference[7:0])
              match <= 1'b1;
            else
              match <= 1'b0;
        //========================================

That does the job, but it's just plain scabby.

Given all those shennanigans, why not just
use blocking assigns:

        //========================================

          begin
            count[7:0] = count[7:0] + 7'b1;
            if (count[7:0] == reference[7:0])
              match = 1'b1;
            else
              match = 1'b0;
          end
        //========================================

Nice'n'concise and a clear description of WHAT I
want to do, rather than HOW I want it done.

t



Sat, 17 Mar 2001 03:00:00 GMT  
 Blocking vs Non-Blocking Assignemts

Quote:

> I was wondering what long time Verilog coders use when coding synthesizable
> code, blocking (=) or non blocking (<=)?

In general:

        sequential blocks use non-blocking <=
        combinational blocks use blocking   =

The reason is code clarity, although I think this is a bit tenuous and reflects
the relatively "low-level" of verilog.

If a designer is used to thinking in terms of real flip-flops then a sequential
block in which all assignments are non-blocking may be a clearer
representation.  He knows that every "x <= y" happens independently of the
others and so the question "which *particular* value of y?" is never raised.
The particular value of y is the one it contained AT POSEDGE of CLOCK.

Blocking assignments complicate this because the value of the right hand side
of each assignment may depend on preceding assignments.

For example, in:


     begin
        q1 <= d;
        q2 <= q1;
     end

a posedge of clock makes q2 get the value of q1 as it was at that same posedge
of clock.  RHS values are - as the block's name suggests - ALWAYS AT POSEDGE OF
CLOCK.  So you get two flops in sequence:

                             __________________ q1
                 _______    |    _______
        d ------|       |---.---|       |------ q2
                |       |       |       |
    clock ---.--|>   |   .---|>   |
             |   -------    |    -------
             `--------------'

But in the blocking case:


     begin
        q1 = d;
        q2 = q1;
     end

a posedge of clock makes q2 get the value of q1 as it will be at *NEXT* posedge
of clock.  In other words, a posedge of clock makes q2 get the value of d at
that same posedge of clock.  In other other words, q2 gets whatever q1 gets.
So you get two flops in parallel:

                 _______    
        d ------|       |--- q1
                |       |      
    clock ------|>   |
                 -------

                 _______    
        d ------|       |--- q2
                |       |      
    clock ------|>   |
                 -------

Now, it can be argued that this "code-clarity" based argument for non-blocking
assignments is valid only because designers are still thinking in terms of
flip-flops.  That is, they are still thinking (by choice or necessity) in terms
of implementation details.  IMO, that is not a good thing.  It would be better
if our HDL was powerful enough to free us from such worries.  After all, my
earlier comment:

        "Blocking assignments complicate this because the value of the right
         hand side of each assignment may depend on preceding assignments."

would make most programmers (functional programmers excepted?) say "so what!?".
And I tend to share that sentiment.

t



Sat, 17 Mar 2001 03:00:00 GMT  
 Blocking vs Non-Blocking Assignemts

Quote:

>But in the blocking case:


>     begin
>    q1 = d;
>    q2 = q1;
>     end

>a posedge of clock makes q2 get the value of q1 as it will be at *NEXT* posedge
>of clock.  In other words, a posedge of clock makes q2 get the value of d at
>that same posedge of clock.  In other other words, q2 gets whatever q1 gets.
>So you get two flops in parallel:

do you think this is how this block synthesizes ? I think synopsys DC creates the
same logic for both your examples consistent with your first description.

muzo




Sat, 17 Mar 2001 03:00:00 GMT  
 Blocking vs Non-Blocking Assignemts

Quote:

> This strategy is just one aspect of something all HDL codists should be
> trying to do all the time:  make sure that your synthesisable code is
> written in such a way that its behaviour in simulation exactly
> corresponds
> with what you expect the real hardware to do.

You don't mean that we should actually *learn* the language, do you?

--
===================================================================
Jan Decaluwe              ===              Easics               ===
Design Manager            ===  VHDL-based ASIC design services  ===
Tel: +32-16-395 600          ===================================
Fax: +32-16-395 619      Interleuvenlaan 86, B-3001 Leuven, BELGIUM



Sat, 17 Mar 2001 03:00:00 GMT  
 Blocking vs Non-Blocking Assignemts

Quote:

> In summary then, one should use non-blocking assignments to synchronous
> signals and blocking assignments in combinational constructs. Don't mix
> them together.

> I hope this has been helpful.

Not really. I fail to see what would be wrong with: (elaborating on our
examples)


   begin
     d = a & b;
     z = c | d;
   end

or


   begin
     d  = a & b;
     z <= c | d;
   end

if that's the behaviour you need.

--
===================================================================
Jan Decaluwe              ===              Easics               ===
Design Manager            ===  VHDL-based ASIC design services  ===
Tel: +32-16-395 600          ===================================
Fax: +32-16-395 619      Interleuvenlaan 86, B-3001 Leuven, BELGIUM



Sat, 17 Mar 2001 03:00:00 GMT  
 Blocking vs Non-Blocking Assignemts

Quote:

> Here's an example of where blocking assigns in a sequential block may be more
> appropriate than non blocking assigns.

I disagree - see below...

Quote:

> < deleted requirements, basically a counter with a match flag >

> Now, with non blocking assigns I can't do:

>         //========================================

>           begin
>             count[7:0] <= count[7:0] + 7'b1;
>             if(count[7:0] == reference[7:0])
>               match <= 1'b1;
>             else
>               match <= 1'b0;
>           end
>         //========================================

Numerous possibilities:
 1. replace 'if(count[7:0] == reference[7:0])' with
    'if(count[7:0] + 7'b1 == reference[7:0])'

in synthesis it will optimise out to 1 incrementer (unless
timing becomes critical - in which case it has the option
of duplicating logic and/or re-pipelining to gain speed).

 2. (my preferred) Take the match definition outside & make
    it an assign.
    assign match = (count[7:0] == reference[7:0]);

 3. (very explicit - if you don't trust synthesizers)

    assign next_count = count[7:0] + 7'b1;


      begin
        count <= #`FFDELAY next_count;
        match <= #`FFDELAY (next_count == reference);
      end

    // this style can be irritating to read but synthesizes
    // quickly and without surprises

- Show quoted text -

Quote:
> Given all those shennanigans, why not just
> use blocking assigns:

>         //========================================

>           begin
>             count[7:0] = count[7:0] + 7'b1;
>             if (count[7:0] == reference[7:0])
>               match = 1'b1;
>             else
>               match = 1'b0;
>           end
>         //========================================

> Nice'n'concise and a clear description of WHAT I
> want to do, rather than HOW I want it done.

So, how does it map to h/w? In Synopsys it would (IIRC)
generate incorrect logic. I hope your gate level verification
strategy is up to scratch (I do almost no gate level
sims & I haven't had a Synopsys induced bug in more than
20 designs).

A very clever behavioural synthesizer will map it to the
same as the 'always + assign' example (which you dismissed
as bad for timing - can you say, "late design phase
surprises?").

Hugh.



Sun, 18 Mar 2001 03:00:00 GMT  
 Blocking vs Non-Blocking Assignemts

Quote:
> I was wondering what long time Verilog coders use when coding
> synthesizable code, blocking (=) or non blocking (<=)? Is there
> something I am missing on this topic. Most examples I see use
> blocking (=) and yet my code does not simulate properly unless
> non blocking assignments (<=) are used.

One approach the uses only non-blocking assignments, which both
synthesizes correctly and simulates correctly, and which I have
used for large amounts of production code is the following:

// D flip-flop

reg qreg;
wire d,q, clk;

assign #1 q = qreg;

// D flip-flop configured to toggle

reg qreg;
wire d,q,clk,load;

   if (load) qreg = d;
   else qreg = ~q;         // note -- RHS uses "q", not "qreg"
   end
assign #1 q = qreg;

I, personally, find this easier than approaches using " <= "
since everything within an always clause executes in sequence;
and the synthesis reflects this sequentially-expressed logic,
even if one assigns multiply to the register bits.  For example,
the following also works, and there is no exact parallel using
concurrent assignments:

// D flip-flop configured to toggle -- second version

reg qreg;
wire d,q,clk,load;

   qreg = ~q;
   if (load) qreg = d;
   end
assign #1 q = qreg;

The disadvantage, of course, is having to declare two variables
(i.e. "q" and "qreg") for each inferred flip-flop.  Also,
using an explicit delay to synchronize things might conflict
with timing results if one is careless.

Steve



Sun, 18 Mar 2001 03:00:00 GMT  
 
 [ 27 post ]  Go to page: [1] [2]

 Relevant Pages 

1. blocking vs non blocking

2. blocking vs non-blocking

3. blocking vs non blocking

4. std blocks vs blocks+cache ( was: block behavior)

5. blocking and non-blocking assignment

6. Strange behaviour with blocking and non-blocking assignment

7. blocking/non-blocking

8. Blocking and Non-blocking assignment ?

9. Blocking/Non-Blocking

10. block and non-block?

11. Blocking and non-blocking sockets

12. blocking/non-blocking

 

 
Powered by phpBB® Forum Software