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/caseon anX-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
Xpropagation, modeled correctly at the individual-gate level, can spreadXthrough 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 asXvalues 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.