Skip to main content

Gate-Level Simulation & X-Propagation

Every simulation in Testbench and UVM ran against RTL — behavioral, unsynthesized, no real gate delays. Gate-level simulation (GLS) runs the same testbench against the actual post-synthesis netlist, with real cell delays back-annotated from an SDF (Standard Delay Format) file — and it routinely exposes a class of bug RTL simulation structurally cannot, centered on how each kind of simulation handles an unknown value.

GLS isn't one mode — zero-delay, unit-delay, and timing-annotated all answer different questions​

Running the netlist doesn't automatically mean timing is being checked. GLS is actually run in one of a few distinct modes: zero-delay (the netlist runs with no timing data at all — every gate switches instantly, purely a functional check that the synthesized structure still computes the right thing); unit-delay (every gate gets a uniform, nominal delay — enough to shake out gross ordering/race issues without needing real characterized timing yet); and SDF-annotated (the mode described below, with the netlist's actual per-cell delays back-annotated from the SDF file). Teams commonly run zero-delay or unit-delay GLS first, as a cheaper functional-only pass, before committing to the more expensive timing-annotated run — the same "cheap check first" logic RTL linting uses, just one stage later in the flow.

Why GLS exists at all, given RTL simulation already ran clean​

RTL simulation models intent — an always_ff block behaves like an idealized flip-flop with zero delay outside of what the RTL author wrote. Synthesis turns that same behavior into real gates with real propagation delays, real reset/scan insertion, real clock-gating cells — none of which existed as distinct entities in the RTL at all. A bug in exactly how those real structures interact — a race between a gated clock and its enable, a reset sequencing issue only visible with real cell delays — can pass RTL simulation with 100% functional coverage and still be a real, silicon-relevant bug GLS is specifically positioned to catch.

The X-optimism / X-pessimism problem​

Simulators use X to represent a genuinely unknown value — uninitialized memory, a signal legitimately unresolvable at that point in simulation. RTL and gate-level simulation propagate X through logic differently, and both directions of that difference are real problems, not just simulator quirks:

Example: a 2-to-1 mux with an unknown select line

sel : X
a : 0
b : 1
y : ?
  • X-optimism — RTL simulation's higher-level operators (if/case on an X-valued condition, for instance) can resolve to a specific, concrete branch rather than propagating the uncertainty — silently hiding a real ambiguity that gate-level logic (built from actual gates with no such shortcut) would correctly show as unresolved. A bug masked this way in RTL simulation can then appear, seemingly out of nowhere, only once GLS runs against the real gates — because RTL simulation was never actually exercising the uncertain case at all, just quietly picking an answer.
  • X-pessimism — the opposite failure: gate-level X propagation, modeled correctly at the individual-gate level, can spread X through convergent logic (a mux where both inputs are equal, XORed paths that should cancel) far more aggressively than real silicon ever would, producing false alarms and unnecessary debugging on a "bug" that would never actually occur on the real chip. Left unmanaged, X-pessimism can also cause an entire simulation to lock up as X values keep propagating and re-propagating with no logic ever resolving to a concrete value.

Neither direction is the "safe" one to ignore — X-optimism hides real bugs until GLS or silicon; X-pessimism wastes real debug time chasing bugs that were never there. Both are why GLS, run with X-propagation specifically in mind rather than assumed away, remains a distinct, necessary step even after thorough RTL-level verification.

What's next​

CDC, RDC, linting, and now GLS/X-propagation all concern functional and structural correctness. The next two pages turn to two more specialized dimensions a real front-end flow has to verify: power intent and timing.