Exercises — Blocking vs non-blocking assignments
Two words we will use constantly, both defined on the parent page — repeated here so you never guess:
A reminder of the mental model we lean on the whole page:

The blue camera-flash is non-blocking: photograph everybody's old position first, then everyone jumps at once. The magenta domino is blocking: line 1 moves, then line 2 sees that already-moved value.
Level 1 — Recognition
Exercise 1.1
Which operator (= or <=) belongs in a clocked block, and which in a combinational block? Fill the blanks:
always @(posedge clk)→ use____always @(*)→ use____
Recall Solution 1.1
always @(posedge clk)→<=(non-blocking). Clocked flip-flops all update together on the edge using the pre-edge picture.always @(*)→=(blocking). Combinational logic is a data-flow: each intermediate must be ready before the next line uses it.
Mnemonic from the parent: "Clock? Non-blocK."
Exercise 1.2
In the snippet below, mark each assignment as B (blocking) or N (non-blocking):
x = a;
y <= b;
z <= c;Recall Solution 1.2
x = a;→ By <= b;→ Nz <= c;→ N
The single = is blocking; <= (which looks like a "delay arrow") is non-blocking.
Level 2 — Application (trace the values)
Assume before the clock edge: a = 3, b = 7.
Exercise 2.1
always @(posedge clk) begin
a <= b;
b <= a;
endWhat are a and b after the edge?
Recall Solution 2.1
Non-blocking: sample all RHS first using pre-edge values → RHS of line 1 is old b = 7, RHS of line 2 is old a = 3. Then apply both.
a = 7,b = 3. The values swap. ✔
Exercise 2.2
Same start (a = 3, b = 7), but now blocking:
always @(posedge clk) begin
a = b;
b = a;
endWhat are a and b after the edge?
Recall Solution 2.2
Blocking updates immediately, in order:
- Line 1:
a = b→abecomes7. - Line 2:
b = a→ butais already 7, sob = 7. - Result:
a = 7,b = 7. No swap — both hold oldb. ✘
Exercise 2.3
Start: a = 2, b = 5, c = 0. Trace this single-pass combinational block:
always @(*) begin
c = a + b; // blocking
a = 10; // blocking
endWhat is c right after the block runs once?
Recall Solution 2.3
Blocking, in order:
c = a + b=2 + 5= 7 (uses the currenta = 2).a = 10happens after — it does not retro-changec.- So
c = 7, anda = 10. (In real combinational hardware, changingaafterward re-triggers@(*)and re-runs, but within this single passc = 7.)
Level 3 — Analysis (find the bug)
Exercise 3.1
This is meant to be a 3-stage shift register (d → q1 → q2 → q3), one hop per clock. It doesn't work. What actually gets built, and why?
always @(posedge clk) begin
q1 = d;
q2 = q1;
q3 = q2;
endRecall Solution 3.1
Blocking makes each line apply immediately, so d ripples through all three in one edge:
q1 = dq2 = q1→ now= dq3 = q2→ now= dAfter one clock,q1 = q2 = q3 = d. All three collapse to the same value — the synthesizer builds effectively one flip-flop plus wires, not three stages. See the Pipelining and shift registers note for the intended structure. Fix: use<=, which samples pre-edge values so each stage receives its neighbour's old value.
Exercise 3.2
Combinational block. Why does using <= here break it?
always @(*) begin
tmp <= a & b;
y <= tmp | c;
endRecall Solution 3.2
With <=, tmp is not updated until the end of the pass, so line 2 uses the stale (previous) tmp, not the freshly-computed a & b. The simulator models a wrong/latched value, and it disagrees with the synthesized gate netlist → a classic Synthesis vs Simulation mismatch. The tool may even infer an unintended latch on tmp.
Fix: combinational data-flow needs =, so tmp is ready before y reads it.
Exercise 3.3
Two always blocks both drive q. What is wrong?
always @(posedge clk) q <= d;
always @(posedge clk) q <= e;Recall Solution 3.3
q is assigned from two different clocked blocks. Both fire on the same edge; the two non-blocking updates to the same LHS collide with no defined ordering → a race condition. The final value of q is simulator-dependent, and synthesis will complain about multiple drivers.
Fix (Golden Rule 4): each variable is driven by exactly one always block. Merge the logic (e.g. q <= sel ? e : d;).
Level 4 — Synthesis (write the code)
Exercise 4.1
Write an always block for a 4-stage shift register: input d, stages q1,q2,q3,q4, output is q4. One shift per rising clock edge.
Recall Solution 4.1
Clocked ⇒ non-blocking:
always @(posedge clk) begin
q1 <= d;
q2 <= q1;
q3 <= q2;
q4 <= q3;
endEach stage grabs its neighbour's old value, so data advances exactly one stage per clock. See D Flip-Flops and Registers.
Exercise 4.2
Write a combinational block computing y = (a & b) | c using an intermediate signal p. Which operator, and why?
Recall Solution 4.2
Combinational ⇒ blocking =, and list all inputs (or use @(*)):
always @(*) begin
p = a & b; // ready first
y = p | c; // uses fresh p
end= makes p available immediately for the next line, matching how a signal ripples through gates. Using <= would feed line 2 a stale p.
Exercise 4.3
A register count should increment by 1 every clock, resetting to 0 when rst is high (synchronous reset). Write it.
Recall Solution 4.3
Clocked ⇒ non-blocking; synchronous reset is inside the clocked block:
always @(posedge clk) begin
if (rst)
count <= 0;
else
count <= count + 1;
endcount <= count + 1 samples the old count, adds 1, and defers the update — exactly one increment per edge, no runaway.
Level 5 — Mastery (subtle scheduling)
Exercise 5.1
Before the edge: a = 1. This mixes operators for the same variable in one block. What value does a end up with, and what is the real problem?
always @(posedge clk) begin
a = a + 1; // blocking
a <= a + 2; // non-blocking, same variable
endRecall Solution 5.1
Step through the scheduler:
- Active region:
a = a + 1(blocking) applies immediately →abecomes2. - Then the
<=RHS is sampled using the currenta = 2→ stashed value= 2 + 2 = 4. - NBA region: apply the stash →
a = 4. Finala = 4. But this violates Golden Rule 3 — mixing=and<=for the same variable creates fragile, hard-to-read, tool-dependent behaviour. Never write this in real RTL; the answer is a trap, not a technique.
Exercise 5.2
Two clocked blocks, non-blocking, feeding each other (a proper cross-coupled pair). Before edge: x = 1, y = 0. What are x, y after one edge, and after two edges?
always @(posedge clk) x <= y;
always @(posedge clk) y <= x;Recall Solution 5.2
Both blocks sample RHS from pre-edge values, then update in the NBA region. Different variables ⇒ no illegal double-drive.
- After edge 1: sample old
x = 1,y = 0→ newx = y = 0, newy = x = 1. Sox = 0,y = 1(they swapped). - After edge 2: sample
x = 0,y = 1→x = 1,y = 0(swap back). They ping-pong every clock:(1,0) → (0,1) → (1,0) → …. This is the multi-block version of the swap example, and it works precisely because<=uses the old picture.
Exercise 5.3
Before the edge: sel = 1, a = 4, b = 9, out = 0. Trace this clocked block that mixes a blocking temporary with a non-blocking output (a common legal pattern — the temp is local scratch, not a flip-flop input elsewhere):
always @(posedge clk) begin
tmp = sel ? a : b; // blocking scratch
out <= tmp + 1; // non-blocking flip-flop
endWhat is out after the edge?
Recall Solution 5.3
tmp = sel ? a : bblocking →sel = 1, sotmp = a = 4, applied immediately.out <= tmp + 1: RHS sampled now usingtmp = 4→ stash= 5; applied in NBA region.- Final
out = 5. The blockingtmpis fine here because it is fully computed and consumed within the same pass before the deferred<=samples it.outis still a clean edge-triggered flip-flop.
Recall Ladder
Recall One-line answers to the whole ladder
L1: clock→<=, combinational→=. <= is assignment, not comparison.
L2: <= swap works (old values); = swap fails (both = old b).
L3: blocking shift register collapses to one flop; <= in combinational uses stale intermediates; two blocks on one var = race.
L4: shift register / combinational chain / counter — correct operators as shown.
L5: mixed operators are traceable but forbidden; cross-coupled <= ping-pongs; blocking scratch + <= output is legal.
Order among non-blocking statements is irrelevant?
Which region applies the deferred non-blocking updates?
Why is a=b; b=a; not a swap?
a updates immediately, so line 2 reads the new a; both become old b.Connections
- Parent · Blocking vs Non-blocking
- Always blocks and sensitivity lists
- Combinational vs Sequential logic
- D Flip-Flops and Registers
- Race conditions in RTL simulation
- Synthesis vs Simulation mismatch
- Verilog data types (reg vs wire)
- Pipelining and shift registers