Blocking vs Non-Blocking

Operators = vs <=, scheduling semantics.

Mohith N
Updated: 19 March 2026
7 min read

The distinction between blocking and non-blocking assignments is one of the most important and frequently misunderstood concepts in Verilog. Getting this wrong leads to simulation results that do not match synthesized hardware behavior, which is a critical failure in digital design. This topic appears consistently in GATE examinations and university assessments.

Blocking vs Non-Blocking Assignment SchedulingBlocking ( = )Statement 1: a = b;waits, then proceedsStatement 2: c = a;c gets NEW value of aExecutes like softwareUsed for combinational logicOrder of statements mattersRHS evaluated, LHS updated immediatelyNon-Blocking ( <= )Statement 1: a <= b;Statement 2: c <= a;c gets OLD value of aRHS of all evaluated firstLHS of all updated togetherUsed for sequential logicOrder of statements does not matter
Figure 1: Scheduling semantics of blocking and non-blocking assignments in Verilog always blocks

Core Concept: The Two Assignment Operators

Inside a Verilog procedural block, two assignment operators exist. The blocking assignment uses the = operator. The non-blocking assignment uses the <= operator. Although both operators appear inside always blocks and both assign values to reg variables, their execution semantics are fundamentally different and model entirely different types of hardware.

A blocking assignment executes immediately. When the simulator encounters a = b, it evaluates b right now, assigns it to a right now, and only then moves to the next statement. The next statement sees the updated value of a. This behavior is sequential and software-like, which makes it appropriate for modeling combinational logic where signal values must be propagated through a chain of computations in the correct order.

A non-blocking assignment uses a two-phase mechanism. When the simulator encounters a <= b, it evaluates the right-hand side immediately and stores the result in a temporary holding area, but it does not update a yet. It moves on to the next statement without waiting. Only after all non-blocking assignments in the current time step have been evaluated does the simulator update all left-hand side variables simultaneously. This models the behavior of flip-flops sampling their inputs on a clock edge: all inputs are captured at the same moment, and all outputs update together.

Mathematical and Scheduling Model

Verilog simulation operates on a stratified event queue. Within a single simulation time step, events are processed in defined regions: the Active region, the NBA (Non-Blocking Assignment update) region, and others. Blocking assignments execute and update in the Active region. Non-blocking assignments evaluate their RHS in the Active region but schedule the LHS update in the NBA region, which occurs after all active events are processed.

This scheduling model ensures that when multiple flip-flops are clocked simultaneously, each flip-flop captures the value its input had before the clock edge, not the value another flip-flop may have just written. This is exactly the correct behavior for a synchronous digital circuit. If blocking assignments were used for flip-flops, the order of the always blocks in the file would affect the simulation result, causing nondeterminism.

Practical Understanding: Which to Use Where

The golden rule followed universally in professional RTL design is: use blocking assignments (=) inside always @(*) blocks for combinational logic, and use non-blocking assignments (<=) inside always @(posedge clk) blocks for sequential logic. Mixing the two inside the same always block is legal but strongly discouraged because it produces confusing and often incorrect behavior.

A concrete illustration: if you have two flip-flops A and B connected in series, where B should capture the old value of A on each clock edge, and you write A = D; B = A; using blocking assignments in the same always block, then B gets the new value of A (just written in the same step), not the old value. The circuit behaves like only one flip-flop exists. With non-blocking assignments A <= D; B <= A;, both right-hand sides are evaluated before any left-hand side is updated, so B correctly captures the previous value of A.

Example
Given:
Two flip-flops in series: Q1 captures D on posedge clk, Q2 captures Q1 on posedge clk.
Initial state: Q1=0, Q2=0, D=1

Why this formula applies:
Sequential pipeline: each FF captures old value. Non-blocking required.

Formula:
  always @(posedge clk) begin
    Q1 <= D;    // captures D before update
    Q2 <= Q1;   // captures OLD Q1 before update
  end

Substitution:
At posedge clk with D=1, Q1=0, Q2=0:
  RHS evaluated: Q1_new = D = 1, Q2_new = Q1 = 0 (old value)
  LHS updated:   Q1 = 1, Q2 = 0

Calculation:
Next posedge clk: D=1, Q1=1, Q2=0
  RHS: Q1_new=1, Q2_new=Q1=1
  After update: Q1=1, Q2=1
  Correct 2-cycle pipeline delay.

Final Answer with units:
After 2 clock edges, Q2 follows D with a 2-cycle delay. This is correct behavior.
Exam Tip: GATE frequently shows a code snippet with blocking assignments in a clocked always block and asks what Q1 and Q2 will be. Remember: = in sequential logic causes the second FF to see the updated value, effectively collapsing the pipeline. <= preserves the old values. Identify the operator first, then trace the waveform.

Mechanism: Two-Phase Non-Blocking Execution

Non-Blocking Assignment: Two-Phase Execution at posedge clkPhase 1: Active RegionEvaluate all RHS valuesRHS of Q1 <= D => temp1=DRHS of Q2 <= Q1 => temp2=Q1Q1 and Q2 NOT yet changedOld values preservedNo race conditionPhase 2: NBA RegionUpdate all LHS valuesQ1 = temp1 (new D value)Q2 = temp2 (old Q1 value)Both updated simultaneouslyCorrect FF pipeline behaviorResultQ2 = old Q12-stage pipeline preserved
Figure 2: Two-phase execution model of non-blocking assignments ensuring correct sequential logic behavior
  • Blocking (=): RHS evaluated, LHS updated immediately. Next statement sees new value. Used in combinational always blocks.
  • Non-blocking (<=): RHS evaluated immediately, LHS updated in NBA region after all active events. All updates happen simultaneously.
  • Non-blocking preserves old values across all FFs in the same clock edge, preventing false data propagation.
  • Mixing = and <= in the same sequential always block is a common source of subtle simulation bugs.
  • The order of non-blocking statements within a block does not affect the final result; order of blocking statements does.

Quick Revision

  • = (blocking): immediate update, software-like, use in always @(*) for combinational logic.
  • <= (non-blocking): deferred update, hardware-like, use in always @(posedge clk) for sequential logic.
  • Non-blocking evaluates RHS in Active region, updates LHS in NBA region.
  • Series pipeline FFs must use <= to avoid one FF seeing another's updated output in the same clock cycle.
  • Order matters for =, does not matter for <=.
  • Exam trap: blocking assignment in clocked block collapses multi-stage pipelines into one stage.
  • Do not mix = and <= in the same always block. Use consistently per block type.

Procedural Assignment Semantics

Test your knowledge on this topic.

Question 1 of 3

Q1.Which assignment operator must be used to model sequential logic flip-flops?