Verilog Blocking vs Non-Blocking Assignments
Blocking (=) and non-blocking (<=) assignments are the concept that separates engineers who understand Verilog from those who merely write it. Choosing wrong does not usually produce a syntax error — it produces a design that simulates one way and synthesises another.
Blocking =: evaluate and update immediately
A blocking assignment completes before the next statement runs, exactly like a software assignment. Inside a clocked block this creates an unintended chain — the updated value is used by the very next line in the same tick.
Non-blocking <=: sample now, update at tick end
All non-blocking right-hand sides are evaluated first, using the old values; the left-hand sides are updated together at the end of the time step. That is precisely how a bank of real flip-flops behaves on a clock edge. The shift register below makes the difference visible:
module shift_compare;
reg clk;
reg a, b, c; // non-blocking chain (correct shift register)
reg x, y, z; // blocking chain (collapses!)
reg din;
always @(posedge clk) begin
// non-blocking: b gets OLD a, c gets OLD b -> proper 3-stage shift
a <= din; b <= a; c <= b;
// blocking: x=din, then y=x(=din), then z=y(=din) -> all equal din
x = din; y = x; z = y;
end
always #5 clk = ~clk;
initial begin
clk = 0; din = 0; a=0;b=0;c=0;x=0;y=0;z=0;
#7 din = 1; // one pulse into both chains
#10 din = 0;
#40 $finish;
end
always @(posedge clk)
$display("t=%0t | NB a,b,c=%b%b%b | B x,y,z=%b%b%b", $time, a,b,c, x,y,z);
endmodulet=5 | NB a,b,c=000 | B x,y,z=000 t=15 | NB a,b,c=000 | B x,y,z=111 t=25 | NB a,b,c=100 | B x,y,z=111 t=35 | NB a,b,c=010 | B x,y,z=000 t=45 | NB a,b,c=001 | B x,y,z=000 t=55 | NB a,b,c=000 | B x,y,z=000
Read the log: the non-blocking chain a,b,c moves the pulse one stage per clock, a true shift register. The blocking chain x,y,z collapses — all three take din on the same edge, inferring a single flip-flop instead of three.
The rules that keep you safe
| Block | Use | Why |
|---|---|---|
always @(posedge clk) | <= non-blocking | models parallel flip-flop update |
always @(*) combinational | = blocking | matches evaluate-then-use semantics |
| Never | mix = and <= for the same reg | race / sim-synth mismatch |
▶ Try it in the ChipXpert Lab
Run the comparison above in the lab, then change the blocking chain to non-blocking and re-simulate — watch x,y,z turn into a proper shift register.
Check yourself
Why does the blocking chain <code>x=din; y=x; z=y;</code> not shift?
Because each blocking assignment finishes before the next runs. On one edge x becomes din, then y reads the new x, then z reads the new y — so all three equal din after a single edge.
What actually gets synthesised from the blocking chain?
A single flip-flop feeding x, with y and z as aliases of it — not three registers. The simulation and the gate-level netlist can therefore disagree, which is why the rule is: clocked logic always uses non-blocking.
Share your question in comments or talk to our mentor team for batch guidance.
Learn Verilog with mentors, labs and placement support
This free series is maintained by the ChipXpert training team in Hyderabad & Bengaluru. Go deeper with instructor-led courses on real EDA tools.
Explore VLSI Courses