What Is the Difference Between Blocking and Nonblocking Assignments in Verilog?

A blocking assignment (=) updates its variable immediately, so the next statement in the same block already sees the new value. A nonblocking assignment (<=) only schedules the update: every right-hand side in that time step is read first, and all the left-hand sides change together at the end of the step. That is exactly how flip-flops on one clock edge behave, so the rule most teams follow is: nonblocking in clocked blocks, blocking in combinational blocks.

What you'll learn

  • What the simulator does with = and <= in the same time step
  • Why a shift register written with = collapses into a single flip-flop, shown in simulation
  • How two clocked blocks with = can race, and why <= cannot
  • The two coding rules that avoid both problems, and the lint warning that catches them

Conventions and assumptions

Verilog-2001 syntax, which is also valid SystemVerilog. Every example below was simulated in Icarus Verilog 12 and linted with Verilator 5.036 with all warnings on. The language rules come from IEEE 1800-2023, which absorbed the Verilog standard (IEEE 1364) in 2009.

What does the simulator do with each one?

The standard splits each simulation time step into regions. Blocking assignments execute in the active region, in statement order, like assignments in C. A nonblocking assignment also evaluates its right-hand side in the active region, but the update goes into the NBA (nonblocking assignment) region, which runs only after every active process at that time has finished. So on a clock edge, every always @(posedge clk) block reads the old values of all the registers, and only then do the registers change. That is the same thing real flip-flops do: they all sample their D inputs at the edge, then their Q outputs change.

Worked example: a three-stage shift register

Here is a shift register written the usual way, with nonblocking assignments. Each register takes the value its neighbor had before the edge.

Nonblocking: three flip-flops in a chain
always @(posedge clk) begin
  q1 <= d;
  q2 <= q1;
  q3 <= q2;
end

Now the same block with blocking assignments. q1 takes d, then q2 reads the q1 that was just written (which is already d), then q3 reads that q2. All three end up equal to d on the same edge.

Blocking: the chain collapses
always @(posedge clk) begin
  q1 = d;
  q2 = q1;   // reads the q1 just written
  q3 = q2;   // reads the q2 just written
end

What the simulation shows

Both versions start at 0, d is 1 before the first edge and 0 after it. Icarus Verilog prints:

After edgeNonblocking q1 q2 q3Blocking q1 q2 q3
11 0 01 1 1
20 1 00 0 0
30 0 10 0 0

The nonblocking version moves the 1 down the chain one stage per clock, as a shift register should. The blocking version copies d into all three registers at once: in simulation it is one flip-flop with three outputs, and a synthesis tool will build it that way too, so you lose two pipeline stages without any error. Verilator flags the blocking version with three BLKSEQ warnings (blocking assignment in sequential logic); the nonblocking version is clean.

Why can two always blocks race?

When two blocks are triggered by the same edge, the standard does not say which runs first. With blocking assignments the order matters:

A race with =, and the fix with <=
// Two always blocks, blocking: a race
always @(posedge clk) a = b;
always @(posedge clk) b = a;

// The same with nonblocking: a clean swap
always @(posedge clk) c <= d;
always @(posedge clk) d <= c;

Starting from a = 0 and b = 1, one edge should swap them. In Icarus Verilog the blocking pair gave a = 0 and b = 0: the b = a block ran first and overwrote b before a read it. Another simulator, or the same one after an unrelated edit, may run them the other way round and give 1 and 1. The nonblocking pair gave c = 1 and d = 0 every time, because both right-hand sides are read before either variable changes. A race like this can pass every test in one simulator and fail in another, or disagree with the synthesized hardware.

So when is = the right choice?

  • In combinational blocks, always @(*) or always_comb: blocking makes each line see the one above it, like a chain of gates, and avoids the simulation mismatches that <= can cause there.
  • For temporary variables inside a clocked block that are computed and used in the same block, as long as nothing outside the block reads them.
  • In testbench code that drives stimulus between clock edges.

The two rules

  • Use <= for anything assigned in a clocked (posedge or negedge) block.
  • Use = in combinational blocks, and never mix = and <= on the same variable.

Common mistakes

  • Writing a pipeline or shift register with = and wondering why the latency is shorter than expected.
  • Assigning the same register from two different always blocks: even with <= the result depends on which runs last, and synthesis will reject it.
  • Using <= in a combinational block, so a later line reads a stale value and the block needs extra passes to settle in simulation.
  • Adding #1 delays to work around a race instead of fixing the assignment type.

Check your understanding

  • Q1. In the blocking shift register, what single change to the statement order would make it behave like a real shift register? Answer: write it backwards, q3 = q2; q2 = q1; q1 = d. It works, but it breaks the moment someone reorders the lines, so use <= instead.
  • Q2. A clocked block computes sum = a + b; then out <= sum; with sum used nowhere else. Is the = a problem? Answer: no. sum is a temporary inside one block; out is the register.
  • Q3. Why does Verilator warn about = in the clocked block but not about = in an always @(*) block? Answer: in combinational logic the in-order update is the intended behavior.

Related

Sources

Last verified

Simulated in Icarus Verilog 12 and linted with Verilator 5.036 on 14 November 2026; the simulation output in the table is copied from that run. Scheduling regions and assignment rules checked against IEEE 1800-2023.

Keep going