SystemVerilog Scheduling Semantics noted that the Active-Inactive-NBA cluster can loop if a new event lands back in Active. This article makes that concrete — what that looping actually looks like when it settles normally, and what happens on the rare occasion it doesn't.

12 min read | Intermediate Level

What You'll Learn

  • What a delta cycle is, and why multi-level combinational logic needs more than one to fully settle
  • Why none of this delta-cycle activity advances simulation time
  • What happens when a combinational loop has no way to reach a stable state
  • How to recognize the classic mistake that causes a simulation to hang at time 0

What Is a Delta Cycle?

A delta cycle is one pass through the Active-Inactive-NBA region cluster that doesn't advance simulation time. If evaluating one event causes a signal to change, and that change causes another piece of logic sensitive to it to become active, that second piece of logic gets its own delta cycle — still at the exact same time value, just one step later in an internal sequence the simulator tracks but $time never reflects.

Delta cycles loop through the Active, Inactive and NBA regions before time advances

Multi-Level Combinational Logic Needs Multiple Delta Cycles

Here, a single signal change ripples through three levels of combinational logic:


module tb;
  reg a;
  wire b, c, d;

  assign b = a;
  assign c = b;
  assign d = c;

  initial begin
    a = 0;
    #10 a = 1;
    #1 $display ("[%0t] a=%b b=%b c=%b d=%b", $time, a, b, c, d);
  end
endmodule

When a changes to 1 at 10ns, that change triggers assign b = a, which triggers assign c = b, which triggers assign d = c — each one its own delta cycle, cascading through all three levels of logic. All of this happens at the exact same time value, 10ns; none of it advances $time even slightly. By the time the $display runs, one full time unit later at 11ns, every level has long since settled: a=1 b=1 c=1 d=1.

Quick Check

Q: Does adding a fourth level of combinational logic (assign e = d;) require simulation time to advance any further for everything to settle?

Show Answer

No. It requires one additional delta cycle — the fourth level's own propagation — but all of that still happens at the same time value as the original change. Delta cycles scale with how many levels of logic a change has to ripple through, not with simulation time.

When the Loop Never Stops: A Combinational Feedback Loop

Delta cycles settle when each new one leads to a stable state. But a purely combinational loop with an odd number of inversions and no clocked element to break the cycle never reaches one:


module tb;
  reg a;

  always @ (a)
    a = ~a;

  initial begin
    a = 0;
    #10 $display ("[%0t] a=%b", $time, a);
  end
endmodule

a starts at 0. That very assignment triggers the always @(a) block, since a just changed — it inverts a to 1. That change triggers the same block again — a flips back to 0. And again, and again, forever — each flip is its own delta cycle, and each one immediately triggers another, with no way to ever stabilize. Simulation time never reaches 10ns, because it never advances past the original 0ns at all. Depending on the simulator, this either hangs indefinitely with no error, or terminates with an explicit "too many iterations without advancing time" message once an internal safety limit is hit.

Quick Check

Q: Would replacing always @(a) a = ~a; with always @(posedge clk) a <= ~a; (toggling on a clock edge instead) cause the same hang?

Show Answer

No. That's an ordinary, correctly-behaving toggle flip-flop — it only changes on a clock edge, which requires simulation time to actually advance between toggles. The hang specifically comes from a change triggering itself again with no time delay anywhere in the loop, which a clocked element inherently prevents.

Where Does This Matter in Practice?

A simulation stuck at time 0 with no progress, or an explicit iteration-limit error, is one of the most common early debugging experiences in RTL design — and it's very often exactly this: an accidental combinational feedback path, sometimes through several levels of gates or a mux whose output unintentionally loops back into its own input. Recognizing "time isn't advancing at all" as the specific symptom, rather than assuming the simulator itself is broken, is the fastest way to know what to actually look for.

Common Beginner Mistakes

Mistake #1: Assuming delta cycles cost simulation time

Delta cycles never advance $time, no matter how many of them occur. Why? A long chain of combinational logic can take many delta cycles to fully settle, but as far as anything checking $time is concerned, all of that happens instantaneously, at a single time value.

Mistake #2: Assuming a stuck simulation is a tool problem

A simulation that never progresses past time 0 is far more often caused by an accidental combinational loop in the code than by an actual simulator bug. Why? As this article's second example shows, this is a direct, well-understood consequence of how delta cycles work — not a mysterious failure.

Mistake #3: Creating an odd number of inversions in a feedback loop

Any purely combinational loop with an odd number of inversions and no clocked element to break the cycle can never reach a stable state. Why? Each pass around the loop flips the value again, generating an endless sequence of delta cycles — this is exactly why real sequential logic always includes a clocked (registered) element somewhere in any feedback path.

Mistake #4: Confusing a delta-cycle hang with a slow simulation

These look similar from the outside (nothing seems to be happening) but are fundamentally different. Why? A slow simulation is still advancing $time, just gradually; a delta-cycle hang means $time is completely frozen — checking whether time is moving at all is the fastest way to tell the two apart.

Practice Exercise

Challenge: Predict a 3-Inverter Ring

Given three continuous assignments forming a ring — assign a = ~c; assign b = ~a; assign c = ~b; — would this settle to a stable state, or hang? Compare your answer to what a 2-inverter ring (assign a = ~b; assign b = ~a;) would do.

Hint

Count the total number of inversions encountered going all the way around each loop back to the starting signal — and check whether that count is odd or even.

Solution

The 3-inverter ring hangs. Going around the loop passes through 3 inversions — an odd number — so no stable fixed point exists; each full pass around the loop flips the starting value again, generating endless delta cycles, just like the single self-inverting signal in this article's main example.

The 2-inverter ring settles. It has 2 inversions — an even number — so a stable fixed point exists (in fact, two of them: a=0,b=1 or a=1,b=0). Once reached, nothing further changes, and no more delta cycles are triggered. The general rule: an odd number of inversions around a pure combinational loop never stabilizes; an even number does.

Summary

In this tutorial, you learned:

  • A delta cycle is one pass through Active-Inactive-NBA that doesn't advance simulation time
  • Multi-level combinational logic settles through as many delta cycles as it has levels, all at the same time value
  • A purely combinational loop with an odd number of inversions and no clocked element never reaches a stable state, generating endless delta cycles instead
  • A simulation stuck at time 0 with no progress is a strong, specific signal to look for an accidental combinational feedback path
  • The key way to tell a delta-cycle hang apart from a merely slow simulation is whether $time is advancing at all
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5