How to interpret blocking vs non blocking assignments in Verilog?

system-verilog, verilog

Solution

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

Problem

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 ```

Original source