Day 57: Blocking vs non-blocking assignments — the rule that prevents most bugs
The rule that prevents most bugs
Two assignment operators, two behaviors. Blocking (=) executes immediately and in order, like software. Non-blocking (<=) samples all right-hand sides first, then updates all left-hand sides together at the end of the time step — modeling how real flip-flops all capture their inputs on the same edge (exactly the 'sample-then-commit' you built into your Stage-0 simulator).
// SEQUENTIAL logic -> use non-blocking (<=)
always @(posedge clk) begin
q1 <= d; // a shift register works because all sample old values
q2 <= q1; // q2 gets the OLD q1, not the new one
end
// COMBINATIONAL logic -> use blocking (=)
always @(*) begin
sum = a + b; // ordered, immediate
out = sum + c; // sees the just-computed sum
end
// MIXING them in one block, or using = for sequential, causes
// simulation/synthesis mismatches and races. Don't.Why the shift register only works with NBA
With non-blocking, q2 <= q1 captures the *old* q1, so data advances exactly one stage per clock — a correct shift register. With blocking, q2 = q1 would see q1's *new* value and the whole chain collapses. This is the software echo of the hold-time issue from Stage 0, Day 31 — same bug, same fix.
Cliff Cummings' famous paper distills it to rules you should be able to recite: use `<=` for sequential (clocked) logic, `=` for combinational, and never mix them in one block. Follow that and simulation matches synthesis; break it and you get races that pass in one and fail in the other — the worst kind of bug.
Key terms
- Blocking assignment (=)
- Executes immediately and in order within the block; use for combinational logic.
- Non-blocking assignment (<=)
- Samples all RHS, then updates all LHS together at time-step end; use for sequential logic.
- Race condition
- Order-dependent behavior that can differ between simulation and synthesis.
- Cummings rules
- The canonical guidance: NBA for clocked logic, blocking for combinational, never mixed.
Before moving on, you should be able to
You are coding a clocked shift register. Which assignment operator do you use, and why?