SystemVerilog Scheduling Semantics

How the simulator orders events. Understanding these regions is crucial to avoiding race conditions and ensuring deterministic simulation.

The Stratified Event Queue

SystemVerilog divides a single time slot into multiple "regions" to order execution.

Region What happens here?
1. Preponed Sampling values for assertions (SVA). Values here are "stable".
2. Active Blocking assignments (=), continuous assignments (assign), primitive evaluations.
3. Inactive #0 delays. (Try to avoid using these).
4. NBA Non-Blocking Assignments (<=) updates happen here.
5. Observed Evaluation of Assertions properties.
6. Reactive Execution of Testbench programs, Checker code.
7. Postponed $monitor, $strobe. Read-only region at end of time slot.

Deep Dive: The #0 Delay Trap

You might see code like #0 b = a;. This is not a "zero time" delay in the physical sense, but a Delta Cycle delay.

Why is #0 Dangerous?

Using #0 explicitly moves an event from the Active region to the Inactive region. While this can fix some race conditions by forcing an ordering, it is a "band-aid" solution that makes code fragile. If someone else adds another #0 later, the race condition returns.

Event Ordering Example

initial begin
    a = 0;
    #0 a = 1; // Moves to Inactive region
    $display("First: %0d", a); // Executes in Active region (prints 0)
end
initial begin
    #0 $display("Second: %0d", a); // Executes in Inactive region (prints 1)
end
                            

Active vs NBA (Race Condition Prevention)

The separation of Active (Evaluation) and NBA (Update) regions prevents race conditions in sequential logic.

// BAD: Potential Race
always @(posedge clk) a = b;
always @(posedge clk) b = a; 
// Result depends on which 'always' block runs first in Active region.
// GOOD: Deterministic
always @(posedge clk) a <= b;
always @(posedge clk) b <= a;
// Both 'b' and 'a' vary based on OLD values captured in Active region.
// Updates happen later in NBA region.

Interview Check

Q: What is the difference between $display, $strobe, and $monitor?
$display executes immediately in the Active region (can show old or transient values).
$strobe executes in the Postponed region (shows final stable values of the time slot).
$monitor runs in Postponed region whenever its arguments change.