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
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
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.
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
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!
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
- first the full adder wiil be made -- inputs a and b
- output will go to flip flop creating output a having sync with clk
- 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
- now since b = c + a; is there which is blocking statment so b is updated to this new b
- 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;
- 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
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