3.5.4HDL & Digital Design Flow

Blocking vs non-blocking assignments

1,850 words8 min readdifficulty · medium3 backlinks

WHY does this distinction even exist?

WHAT each does (the scheduling rule):

Blocking = Non-blocking <=
Evaluation of RHS immediately sampled at start of time step
Update of LHS immediately, before next stmt deferred to end of time step
Later statements see the new value? Yes No (they see the old value)
Models combinational logic / sequential software-like steps edge-triggered flip-flops

HOW the scheduler actually runs it (first principles)

Verilog simulation at each time step has regions. Simplified:

  1. Active region — evaluate & apply blocking assignments; evaluate the RHS of non-blocking assignments and stash the result.
  2. NBA (non-blocking) regionapply all the stashed non-blocking updates.

Figure — Blocking vs non-blocking assignments

Worked Example 1 — Swap two registers (the classic)

always @(posedge clk) begin
    a <= b;
    b <= a;
end

What happens? At the edge, RHS sampled first: a's new value = old b, b's new value = old a. Then both update. Result: values swap. ✔

Why this step? Because <= uses old a in line 2, not the value line 1 just assigned.

Now with blocking:

always @(posedge clk) begin
    a = b;   // a becomes old b
    b = a;   // a is ALREADY b, so b = b  -> NO swap!
end

Why this step? = applies line 1 immediately, so line 2 sees the new a. Both end up equal to old b. This synthesizes a single flop plus a wire — not a swap.


Worked Example 2 — Pipeline / shift register

Goal: q1 -> q2 -> q3 shift each clock.

always @(posedge clk) begin
    q3 <= q2;
    q2 <= q1;
    q1 <= d;
end

Why this works regardless of order? All RHS (q2, q1, d) are sampled from pre-edge values, then applied. So q3 gets old q2, etc. — a true 3-stage shift register. Reordering the three lines gives the same hardware.

With blocking = (wrong for this):

q1 = d; q2 = q1; q3 = q2;   // q3 = q2 = q1 = d ALL in one clock -> collapses!

Why this fails? Immediate updates ripple d all the way to q3 in a single cycle → you built one flip-flop, not three.


Worked Example 3 — Combinational logic (blocking is correct)

always @(*) begin
    tmp = a & b;    // intermediate
    y   = tmp | c;  // uses just-computed tmp
end

Why blocking here? This is a data-flow: tmp must be ready before y uses it, exactly like ripple through gates. Using <= would make y use the old tmp, producing wrong/latched behaviour in simulation.


The Golden Rules (80/20 — memorize these)


Common Mistakes (Steel-manned)


Recall Feynman: explain to a 12-year-old

Imagine a class doing a partner-swap dance. Blocking = the teacher tells kid A "go stand where B is," and A instantly moves; then tells B "go where A is" — but A already moved, so B copies A's new spot. They both end up in the same place — no swap! Non-blocking = the teacher takes a photo first, then says "everyone, move to where your partner was in the photo." Now they truly swap, because everyone looked at the old picture. Clocked chips work like the photo version: at each tick, all flip-flops look at the "before" picture and then jump together.


Active Recall

What does the = (blocking) operator do inside an always block?
Evaluates RHS and updates LHS immediately, before the next statement runs (ordered, software-like).
What does <= (non-blocking) do?
Samples all RHS values at the start of the time step, then updates all LHS together at the end — later statements still see old values.
Which assignment type for clocked/sequential logic?
Non-blocking <=.
Which assignment type for combinational logic (always @(*))?
Blocking =.
Why does a<=b; b<=a; swap correctly?
Both RHS use pre-edge (old) values, then both update simultaneously, so a↔b exchange.
Why does blocking a=b; b=a; fail to swap?
a is updated immediately, so line 2 uses the new a; both become old b.
Does the order of non-blocking statements affect the result?
No — all RHS are sampled before any LHS update, so order is irrelevant.
What hardware bug comes from using = in a shift register?
The data ripples through all stages in one clock, collapsing many flip-flops into one.
Golden rule linking clock and operator (mnemonic)?
"Clock? Non-blocK" — posedge blocks use <=.
Why can mixing = and <= for one variable cause problems?
It creates ordering/race ambiguity and simulation–synthesis mismatch.

Connections

Concept Map

uses

uses

RHS applied immediately

sample RHS then defer

synthesizes to

synthesizes to

modeled by

Active region

NBA region

reproduces

enables

breaks

Verilog always block

Blocking assignment =

Non-blocking assignment <=

Later stmts see new value

Later stmts see old value

Combinational logic chain

Parallel flip-flops

Scheduler regions

Sample and stash RHS

Apply all LHS together

Correct register swap

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Dekho, Verilog ke always block ke andar do tarah ke assignment hote hain. Blocking (=) normal software line jaisa chalta hai — ek statement pehle poora hota hai, uska result turant update ho jaata hai, tabhi agli line chalti hai. Non-blocking (<=) thoda alag hai: pehle saari RHS (right hand side) values ko ek saath "photo" ki tarah sample kar leta hai (edge se pehle wali values), phir end me sabhi LHS ko ek saath update karta hai. Isliye baad wali line ko purani value hi dikhti hai.

Yeh chhota sa difference hardware me bada farak laata hai. Jab tum clocked logic likhte ho (always @(posedge clk)), tumhe flip-flops chahiye jo edge par ek saath, purani values lekar update hote hain — iske liye <= use karo. Classic example: a<=b; b<=a; sahi se swap karta hai, kyunki dono old values use karte hain. Agar = lagao (a=b; b=a;) to swap fail — dono b ban jaate hain, kyunki line 1 turant apply ho gaya.

Ulta, combinational logic (always @(*)) me tumhe data flow chahiye — pehle tmp banao, phir tmp use karke y. Yahan = sahi hai, kyunki turant update chahiye. Yaad rakhne ka trick: "Clock? Non-blocK" — clock wala block me <=, aur combo (combinational) me =.

Sabse important rule: kabhi ek hi variable ke liye = aur <= mix mat karo, aur ek variable ko do alag always blocks se assign mat karo — warna race condition aur simulation vs synthesis mismatch ho jaayega. Bas yeh 80/20 rules pakad lo, exam aur real chip design dono me kaam aayenge.

Go deeper — visual, from zero

Test yourself — HDL & Digital Design Flow

Connections