How to interpret blocking vs non blocking assignme

2019-01-02 21:11发布

问题:

I am a little confused about how blocking and non blocking assignments are interpreted when it comes to drawing a hardware diagram. Do we have to infer that a non blocking assignment gives us a register? Then according to this statement c <= a+b , c would be a register right, but not a and b?

module add (input logic clock,  
output logic[7:0] f);   

logic[7:0] a, b, c;  

always_ff @(posedge clock)  
begin   
  a = b + c;   
  b = c + a;   
  c <= a + b;  
end   

assign f = c;  

endmodule

回答1:

It's definitely a bit tricky to get your head around the differences between blocking and nonblocking assignments initially. But no fear - there's a handy rule of thumb:

If you want to infer combo logic with an always block, use blocking assignments (=). If you want sequential logic, use a clocked always block with nonblocking assignments (<=). And try not to mix the two.

Your code above is probably not the best example. Without knowing what adder/flipflop structure you were trying to build, there's the danger of having combo feedback paths (which are bad). And since you've no input buses, you're essentially trying to construct a, b & c out of thin air!

But to answer your question, any variable assigned to within a clocked always block will infer a flipflop, unless its assigned using the blocking operator (=) and used as a kind of a local variable.

module add
  (
   input clock,
   input [7:0] in1,
   input [7:0] in2,
   output logic [7:0] f1, f2, f3, f4, f5
   );   


   // f1 will be a flipflop
   always_ff @(posedge clock) begin
      f1 = in1 + in2;
   end


   // f2 will be a flipflop
   always_ff @(posedge clock) begin
      f2 <= in1 + in2;
   end


   // f3 will be a flipflop
   // c1 will be a flipflop
   logic [7:0] c1;
   always_ff @(posedge clock) begin
      c1 <= in1 + in2;
      f3 <= c1 + in1;
   end


   // f4 will be a flipflop
   // c2 is used only within the always block and so is treated
   // as a tmp variable and won't be inferred as a flipflop
   logic [7:0] c2;
   always_ff @(posedge clock) begin
      c2 = in1 + in2;
      f4 = c2 + in1;
   end


   // c3 will be a flipflop, as it's used outside the always block
   logic [7:0] c3;
   always_ff @(posedge clock) begin
      c3 = in1 + in2;
   end

   assign f5 = c3 + in1;

endmodule

A big reason for following the rule of thumb and not mixing blocking and nonblocking assignments within an always block, is that mixing your assignments can cause serious simulation mismatches between RTL sims and gate-sims/real hardware operation. The verilog simulator treats = and <= quite differently. Blocking assignments mean 'assign the value to the variable right away this instant'. Nonblocking assignments mean 'figure out what to assign to this variable, and store it away to assign at some future time'. A good paper to read to understand this better is: Also see: http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf



回答2:

The conventional Verilog wisdom has it all wrong. There is no problem with using blocking assignments for a local variable. However, you should never use blocking assignments for synchronous communication, as this is nondeterministic.

A non-blocking assignment within a clocked always block will always infer a flip-flop, as dictated by the semantics.

Whether a blocking assignment within a clocked always block infers a flip-flop or not depends entirely on how it is used. If it is possible that the variable is read before being assigned, a flip-flop will be inferred. Otherwise, this is like a temporary variable and it will result in some combinatorial logic.



回答3:

Just want to add to Jan Decaluwe's answer. It seems that there is very little code in the wild that actually actually uses what Jan Decaluwe's describes, even though it is absolutely right. Mixing blocking and non-blocking statements is now a taboo, thanks to Mr.Cummings.

The trouble is, most places avoid using blocking statements for local variables and there is very little code in the immediate search space of Google that looks gives an example of how it is done. The only place where I have found the coding style as mentioned by Jan is the winning code in this article. And this, I came across accidentally



回答4:

I had a hard time over this too.

But firstly, you should understand that non-blocking or blocking is actually nothing to do with whether a latch/ff would be created!

For their difference you could understand it simply(at beginning) by this point: i. If use blocking, sentences after it could not be executed until block sentence LHS assigned value, since what changed to LHS of it could be updated and used if the variable is used. However, for non-blocking, it don't block following sentence like parallel with following sentence(actually RHS calculation should be done first, but it doesn't matter, ignore it when you confuse). The LHS don't change/updated for this time's execution (updated next time when always block trigged again). And following sentence use the old value, as it updated at the end of execution cycle.

a = 0; b= 0;
a = 1;
b = a;
--> output a = 1, b = 1;
a = 0; b= 0;
a <= 1;
b = a;
--> output a = 1, b = 0;

One key point is to find whether in you code (always block) there is any case variable not assigned value but could happen. If you don't pass value to it and that case occurs, then latch/ff is created to keep the value.

For example,

always @(*) begin
    if(in) out = 1;
    else out = 0;
end
--> this end without latch/ff
always @(*) begin
    if(in) out = 1;
end
--> this end with one latch/ff to keep value when in = 0, as it might happen and you didn't assign value to out as in=1 do. 

Following could also create latch/ff:

always @(*) begin
    if(in) a = 1;
    else b = 1;
end

--> latch/ffs created for in=1, b no assignment, in=0 a no assignment.

In addition, when you sense posedge of clk always @(posedge clk), it is bound to end with latch/ff. Because, for clk, there must exist negative edge, and you don't do anything, latch/ffs are created to keep all the old value!



回答5:

please you can always interpret the verilog in digital domain just you have to understand what will happen if the same code you wrote will be converted in gate level , i personally dont go by the rule that to use non blocking in seq or use blocking in combinational , this will limit your thinking . stick to the digital side of the code only here is what will happen if your code is converted to gate level just see you want this only

  1. first the full adder wiil be made -- inputs a and b
    1. output will go to flip flop creating output a having sync with clk
    2. now since the assignment is blocking so the new a will be then applied to next full added having this new a and c as input , output of it will go to dffcsync to clk creating new b
    3. now since b = c + a; is there which is blocking statment so b is updated to this new b
    4. now its c<=a+b now what happens is a full adder is created having a and b as input which goes to dff sync to clk , now is there would be other condition like again say a=c;
    5. then a dff will be created having the old c not the new one just created by the non blocking statement and the output of this dff sync to clk goes to a and a gets updated

thanks regards Rahul jain



回答6:

I can answer your question, but I think one paper would be best for this so I recommend you to read out this paper of Clifford Cummings. It will clear all your doubts and in addition to it will strengthen your understanding of verilog.

http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf



标签: