Why `$monitor` output assignment result before time step?

2026-04-30

Stack Overflow: View Question

Tags: verilog, system-verilog

Score: 1 | Views: 83

The asker has a short Verilog snippet that mixes blocking and non-blocking assignments to the same variable, then uses $monitor to observe the result. They expect the non-blocking assignment (a<=a+1) to take effect at time 1, so they anticipate the monitor printing at time 1. Instead, the monitor fires at time 0 with the final value of 2. The question is: why?

This is a deceptively deep question because the answer requires understanding three distinct aspects of the Verilog scheduling semantics simultaneously:

The asker's mental model likely assumes that a<=a+1 defers its update until the #1 delay. That is not how non-blocking assignments work. An NBA without an explicit intra-assignment delay (a <= #1 a+1) schedules into the NBA region of the current time step. The #1 on the next line is a separate statement that simply suspends the initial block; it has no effect on the already-scheduled NBA.

To get the expected behavior, the asker would need to write a <= #1 a+1;, which explicitly delays the NBA update by one time unit. Alternatively, placing the NBA in a separate always block triggered at a later time would also defer it.

A useful diagnostic technique here is to replace $monitor with $strobe (which also prints in the Postponed region) or to add $display calls at strategic points in the Active region to see intermediate values. This makes the scheduling order visible.

The challenge: Understanding the interplay between blocking assignments, non-blocking assignment scheduling regions, and $monitor's Postponed-region semantics within a single Verilog time step.

All newsletters