Sequential RTL
Blocking vs Non-Blocking Assignments in Verilog
Learn when to use = and <= in Verilog, how event scheduling changes simultaneous register updates, and how to verify the difference with a runnable example.
3 min read · Updated
Use non-blocking assignment (<=) for state-holding variables updated by an edge-triggered process, and blocking assignment (=) for calculations in combinational procedural logic. The distinction is about simulation scheduling: = updates immediately within the current process, while <= evaluates its right-hand side now and schedules its left-hand-side update for the non-blocking-assignment region.
That is a strong RTL rule, not a claim that one character alone determines hardware. Event controls, assignment coverage, data flow, resets, and synthesis all matter.
Quick comparison
| Question | Blocking = |
Non-blocking <= |
|---|---|---|
| When does the left side change in simulation? | Immediately before the next statement in that process | Later in the current simulation time slot |
| What does a later statement in the same process see? | The newly written value | The pre-update value until scheduled updates occur |
| Normal RTL use | always @(*) combinational calculations |
Edge-triggered register/state updates |
| Common failure | Procedural ordering changes a clocked result | Using it in combinational logic can obscure intended calculation order |
Why simultaneous register updates expose the difference
On an active clock edge, real flip-flops sample their inputs together. Non-blocking assignments model that “evaluate together, update together” behavior.
Consider two one-bit registers that should exchange values on every rising edge:
always @(posedge clk) begin
left <= right;
right <= left;
endBoth right-hand sides use pre-edge values, so 01 becomes 10.
With blocking assignments:
always @(posedge clk) begin
left = right;
right = left;
endThe first statement changes left immediately. The second statement then reads that new left, so starting from 01 produces 11, not a swap.
Do not reduce this to “blocking always synthesizes fewer registers.” Tools infer and optimize from the complete design. The reliable conclusion is that the blocking process does not simulate the intended simultaneous sampling, and a synthesis tool may not diagnose that intent mismatch.
Predict before running
Both modules below use an active-high synchronous reset: rst is sampled only on posedge clk because it is not in the event control. Reset loads left=0 and right=1; the next two rising edges attempt the exchange.
Before running it, predict both pairs after each edge.
Expected output:
EDGE 1 nonblocking=10 blocking=11
EDGE 2 nonblocking=01 blocking=11
PASSThe non-blocking pair swaps on each edge because both expressions read the pre-edge values. The blocking pair becomes 11 on the first exchange and stays there. The #1 after each rising edge is a testbench observation delay: capture happens on the edge; the later print avoids racing the scheduled non-blocking updates.
Practical rules
- Use non-blocking assignments for state-holding variables in an edge-triggered RTL process, including reset assignments to those variables.
- In an intended combinational process, assign defaults and calculate with blocking assignments.
- Never mix blocking and non-blocking assignments on the same state-holding variable or drive it from multiple processes.
- Treat lint warnings about blocking assignments in sequential RTL as design-review prompts.
Advanced code sometimes uses a local temporary with blocking assignment inside a sequential process, but that requires deliberate data-flow reasoning. It does not change the rule for the state-holding outputs.
Sources and verification
- AMD Vivado Synthesis: Blocking and Non-Blocking Assignments
- Verilator warnings reference: BLKSEQ and BLKANDNBLK
Example provenance: SkillLift Labs authored this exchange example as a parallel demonstration, not as a course build answer. tests/scripts/tutorial-verified-examples.test.ts compiles it in Verilog-2005 mode, reproduces the published output, and independently checks the reset and both edge results. The same test exercises the article-to-runner source split. Automation verifies those stated properties; human technical review for indexing remains a separate gate.