Blocking vs Non-blocking
The single most important rule in Verilog
More beginner designs break from this one topic than any other. The rule is short. Learn it once, apply it always, and you will sidestep bugs that take seniors hours to find.
The two assignments
| Symbol | Name | Picture |
|---|---|---|
| = | Blocking | A to-do list done in order - finish one, then the next |
| <= | Non-blocking | Everyone reads the old values, then all update together |
Why it matters - a tiny shift register
Suppose you want b to take a's value, and c to take b's old value, all on one clock edge - a chain that shifts data along. Watch what each assignment does.
// CORRECT - non-blocking. All read old values, then update.
always @(posedge clk) begin
b <= a;
c <= b; // c gets the OLD b, so data shifts a -> b -> c
end// WRONG for this - blocking. Runs top to bottom in order.
always @(posedge clk) begin
b = a;
c = b; // c gets the NEW b (= a), so b and c both become a
end // the shift is brokenWith non-blocking (<=), the hardware matches your intent: at the clock edge, b grabs a and c grabs the previous b, both at once. With blocking (=) the simulator runs line by line, so c sees the already-updated b. That is not how the flip-flops will behave on the chip, so simulation and silicon disagree.
The rule, in two lines
- Clocked block - always @(posedge clk): use non-blocking <=
- Combinational block - always @(*): use blocking =
Never mix = and <= in the same always block. And never assign the same signal from two different always blocks - the tool will not know which one wins, and you will get x or unpredictable hardware.
If you remember nothing else from this whole path, remember: <= for clocked, = for combinational. Write it on a sticky note. This rule alone separates working RTL from broken RTL.