Zero-delay simulation runs a gate-level netlist with every gate and wire delay set to zero, so it checks that the synthesised logic does the right thing without checking when it does it. Use it early, after synthesis and before SDF-annotated timing simulation, to catch functional problems in the netlist quickly: wrong connectivity, reset and initialisation issues, X-propagation, and scan or test-mode behaviour. It cannot find setup or hold violations, glitches caused by real delays, or metastability, so it is a first step, not a sign-off.
Key takeaways
- Zero-delay gate-level simulation (GLS) verifies basic function and liveness of the synthesised design, ignoring gate and wire delays.
- It runs much faster than SDF timing simulation and needs no delay files.
- Equivalence between RTL and netlist is best proven with formal equivalence checking (LEC); zero-delay GLS complements it.
- Zero delay is not glitch free: events in the same time step are ordered by delta cycles, which can create zero-width pulses and race conditions.
- Timing correctness comes from static timing analysis (STA) and, where needed, SDF-annotated timing simulation.
What zero-delay simulation is
Zero-delay simulation is a technique widely used in digital design verification, especially for gate-level netlist simulation. Its goal is to verify the basic functionality and liveness of the synthesised design without considering the timing delays of the gates and wires.
In practice the simulator is told to ignore the delays in the cell library models (the specify blocks and gate delays), and timing checks such as $setup and $hold are switched off. Simulators provide command-line options for this, for example delay-mode options such as +delay_mode_zero and options that disable timing checks such as +notimingcheck. Exact option names differ between simulators, so check your tool's documentation.
Why and when to use it
Zero-delay simulation is a fast and efficient way to verify the basic functionality of the synthesised design, but it cannot guarantee timing correctness or reliability. It should be used as a preliminary step before more accurate and comprehensive timing simulation. It is useful for several reasons:
- Speed. It runs much faster than timing simulation, which requires SDF (Standard Delay Format) files to annotate the delays of each element in the netlist. This saves simulation time and resources, especially for large and complex designs, and it can start as soon as a netlist exists, before place and route.
- Checking the netlist against the RTL. It helps confirm that the netlist behaves like the RTL (Register Transfer Level) code that was synthesised. The rigorous way to prove logical equivalence is formal equivalence checking with tools such as Cadence Conformal LEC or Synopsys Formality, which do not need simulation. Running the same testbench on both the netlist and the RTL and comparing outputs is a useful extra check that also exercises the testbench, reset sequence and real stimulus. Together they help detect synthesis errors, wrong constraints or mismatches that could cause functional bugs.
- Special blocks and modes. It can be used to check behaviour that RTL simulation or formal checks may not fully cover: asynchronous reset and power-up sequences, X-propagation from uninitialised flops, scan chains and test modes inserted during synthesis, and the hookup of blocks such as PLLs, transceivers and memories. These blocks often have different simulation models or black boxes in RTL, zero-delay and timing simulation, and they can affect the rest of the design differently in each.
What it cannot catch
Zero-delay simulation is not sufficient to ensure the correctness and robustness of the design. It cannot capture the effects of real timing delays, such as setup and hold violations, glitches, metastability and so on, which may cause functional failures or data corruption. It should therefore be complemented by timing simulation, which verifies the design under realistic timing conditions and constraints. Timing simulation can also validate the results of static timing analysis (STA), which checks whether the design meets its timing requirements without simulating it.
| Method | Delays | Finds | Misses |
|---|---|---|---|
| RTL simulation | None (behavioural) | Functional bugs in the design intent | Synthesis issues, inserted logic (scan, clock gating) |
| Formal equivalence (LEC) | Not applicable | Any logical difference between RTL and netlist | Reset sequencing, testbench-level behaviour, timing |
| Zero-delay GLS | Zero | Netlist function, reset, X issues, test modes | Setup, hold and real glitches |
| Unit-delay GLS | One unit per gate or flop | As zero-delay, with fewer races | Real timing |
| SDF timing GLS | Back-annotated | Timing behaviour of key paths, async interfaces, timing-check violations | Paths and corners the tests do not exercise |
| STA | Calculated from libraries and parasitics | Setup and hold on every constrained path | Functional bugs, wrong or missing constraints |
Zero delay is not the same as glitch free
A common belief is that zero-delay simulation cannot show glitches. It can. Within one simulation time step, the simulator processes events in a series of delta cycles. If a signal fans out through an inverter on one branch and not the other, the two branches can update in different delta cycles, and a gate fed by both can produce a pulse of zero width. If that pulse drives a clock pin or an asynchronous reset, it can toggle a flop that would not toggle in silicon, or the other way round.
The example below is a gate-level 2:1 multiplexer with a classic static-1 hazard. With a = b = 1, the output y should stay at 1 whatever s does.
// Gate-level 2:1 mux with a static-1 hazard.
// Build with -DGATE_DELAY=0 (zero delay) or -DGATE_DELAY=1 (unit delay).
`ifndef GATE_DELAY
`define GATE_DELAY 0
`endif
`timescale 1ns/1ns
module mux2_gates (input a, input b, input s, output y);
wire s_n, t0, t1;
not #(`GATE_DELAY) u_inv (s_n, s);
and #(`GATE_DELAY) u_a0 (t0, a, s);
and #(`GATE_DELAY) u_a1 (t1, b, s_n);
or #(`GATE_DELAY) u_or (y, t0, t1);
endmodule
module tb;
reg a = 1'b1, b = 1'b1, s = 1'b1;
wire y;
integer falls = 0;
mux2_gates dut (.a(a), .b(b), .s(s), .y(y));
always @(negedge y) if ($time > 0) begin
falls = falls + 1;
$display(" y fell at %0t ns", $time);
end
always @(posedge y) if ($time > 0) $display(" y rose at %0t ns", $time);
initial begin
#10 s = 1'b0; // a = b = 1, so y should stay 1
#10 s = 1'b1;
#10;
$display("GATE_DELAY=%0d y=%b falling edges on y=%0d", `GATE_DELAY, y, falls);
$finish;
end
endmodule
Results with Icarus Verilog:
$ iverilog -DGATE_DELAY=0 -o z.vvp mux_hazard.v && vvp z.vvp
y fell at 10 ns
y rose at 10 ns
GATE_DELAY=0 y=1 falling edges on y=1
$ iverilog -DGATE_DELAY=1 -o u.vvp mux_hazard.v && vvp u.vvp
y rose at 2 ns
y fell at 12 ns
y rose at 13 ns
GATE_DELAY=1 y=1 falling edges on y=1
In zero delay, y falls and rises again at 10 ns: a zero-width pulse created by delta-cycle ordering when s goes from 1 to 0. With a 1 ns delay per gate, the same hazard appears as a 1 ns glitch from 12 to 13 ns (the rise at 2 ns is just y leaving its initial X state). Whether a given simulator shows the zero-width pulse depends on its event ordering, which is exactly why zero-delay results on clock and reset paths must be treated with care.
Common problems in zero-delay GLS
- Clock-to-data races. In the netlist the clock passes through buffers, clock gates and muxes. With zero delay, data launched by one flop can reach the next flop in the same time step as its clock edge, so the capture flop may see new data instead of old data. Common fixes are a small unit delay on flop outputs (many library models allow this with a define), or a unit-delay mode for the whole netlist.
- X-pessimism and X-optimism. Gate-level models propagate X differently from RTL, so uninitialised flops without reset can flood the design with X values. Reset or initialise state deliberately rather than forcing values.
- Testbench probes. Hierarchical paths and signal names change during synthesis, so testbench probes written for RTL may need updating.
- Memories and hard macros. Their behavioural models may need a zero-delay or no-timing option of their own.
How interviewers probe this topic
- "Why run gate-level simulation if we have STA and LEC?" Expect answers on reset and initialisation, X-propagation, test modes, and catching constraint or netlist issues that the other methods assume away.
- "What is the difference between zero-delay and unit-delay simulation?" Unit delay adds a small fixed delay per element, which removes most clock-to-data races without needing an SDF file.
- "Can zero-delay simulation show a glitch?" Yes, as zero-width pulses from delta-cycle ordering, as in the example above.
- "What does SDF timing simulation add?" Real delays from the layout, timing checks in the cell models, and the behaviour of asynchronous interfaces and multi-cycle paths under those delays.
FAQ
Is zero-delay simulation the same as RTL simulation?
No. Both ignore real delays, but zero-delay simulation runs the synthesised netlist with library cell models, including any logic added during synthesis such as scan and clock gating.
Do I still need timing simulation if STA is clean?
Many teams run a limited set of SDF timing simulations on key modes, such as reset, power-up, asynchronous interfaces and test, to confirm the constraints are complete and correct. STA remains the primary timing sign-off.
When should zero-delay GLS start?
As soon as there is a stable synthesised netlist, usually with a small set of smoke tests, then a larger regression as the netlist matures.

Your comments will be moderated before it appears here.