GLS · Chapter 6 · X-Propagation
Where X Comes From at the Gate Level
X is the currency of gate-level debugging, and the first skill is knowing where it originates. X is the simulator's value for unknown, and at the gate level it has several distinct sources. It comes from uninitialized state that never saw reset, from timing-check violations that toggle a notifier, from multiple drivers fighting on a net or an undriven tri-state, from explicit unknowns in cell models, and from unknown inputs propagating inward. The gate level surfaces the X that RTL's initialization and optimism often hide. This lesson catalogs those sources, shows several of them in a waveform, and frames X as a modelling value the simulator uses for uncertainty rather than a literal silicon voltage. Knowing the source is the first step toward tracing an X back to its root cause.
Foundation12 min readGLSX-PropagationUnknownResetContention
Chapter 6 · Section 6.1 · X-Propagation
Project thread — the FSM's power-up X from 5.5 is source (1): uninitialized state. This chapter builds the X-debugging skill; 6.6 root-causes that exact FSM X.
1. Why Should I Learn This?
Every gate-level X debug begins with one question: where did this X come from? Guessing wastes hours; knowing the source list makes it a lookup.
- Five recurring sources cover almost every gate-level
X. - The source determines the fix (reset vs stimulus vs drive-conflict vs model).
Xis a modelling value — so anXis a flag to investigate, not proof of broken silicon.
This opens the chapter (6.2 pessimism/optimism, 6.3 flow, 6.4 why RTL hides it, 6.5 control, 6.6 the FSM).
2. Real Silicon Story — three Xs, three different causes
A gate-level run showed X on three different nets. The team assumed one root cause and chased it as a single bug.
They were three separate sources: one net was an uninitialized flop (no reset, 2.6); another was a notifier X from a $hold violation (timing-check, 3.2); the third was bus contention where two drivers briefly fought. One "fix" could never address all three — each needed its own (reset, stimulus timing, drive enable).
Lesson: gate-level X is not one phenomenon. Identify which source each X has before fixing — the source dictates the remedy.
3. Concept — the five sources of gate-level X
- (1) Uninitialized state. Flops power up
X(noinitial); only reset clears them (2.6). The classic power-upX. - (2) Timing-check violations.
$setup/$hold/… fires → notifier toggles → flop outputX(2.5/3.2). Appears during the run, near an edge. - (3) Multi-driver contention / floating nets. Two active drivers on a net →
X; an undriven tri-state →Z, treated asXby many downstream gates. - (4) Explicit unknowns in cell models. UDP rows emit
Xfor ambiguous inputs (2.3); synthesized don't-cares. - (5) Unknown inputs propagating in.
Xon a primary input, unconnected pin, or unmodelled block flows through the logic.
Framing:
Xis a modelling value for unknown, not a silicon voltage — real HW resolves to a level;Xsays simulation doesn't know which.- The gate level surfaces
Xthat RTL init/optimism hides (6.4). - An
Xis a flag to investigate — could be a real bug (uninitialized state) or pessimism (2.3/6.2).
4. Mental Model — X is "I don't know", and it has an origin
Read X literally as the simulator saying "I don't know this value" — and every "I don't know" has a reason.
- Never had a value → uninitialized (reset it).
- Corrupted at capture → timing-check violation (fix stimulus/timing).
- Two answers at once → contention (fix the drive/enable).
- The model itself says unknown → UDP
Xrow (pessimism? 6.2). - Told an unknown → unknown input flowed in (trace upstream).
Debugging X is asking why the simulator doesn't know — and the five sources are the menu of reasons.
5. Working Example — several X sources in one run
Representative snippets showing distinct sources:
// (1) uninitialized: flop with no reset -> Q powers up X until (if ever) loaded
DFFX1 u_q (.D(d), .CK(clk), .Q(q)); // no RN -> q = X at power-up (2.6)
// (3) contention: two drivers on one net -> X
assign bus = en_a ? a : 1'bz;
assign bus = en_b ? b : 1'bz; // if en_a & en_b both 1 and a!=b -> bus = X
// (5) unknown input: an unconnected input pin floats -> X propagates
AND2X1 u_g (.A(sig), .B(/*unconnected*/), .Y(y)); // B = X -> y may be XPractical context (representative, tool-neutral):
# Map an X to its source (tool-neutral):
# X present from time 0, cleared by reset .......... (1) uninitialized state
# X appears near a clock edge + $setup/$hold msg ... (2) timing-check violation
# X on a shared net + contention/multi-driver warn . (3) contention / floating (Z->X)
# X from a cell with ambiguous inputs (UDP) ........ (4) model unknown (pessimism? 6.2)
# X traced back to an input/unconnected pin ........ (5) unknown input propagatingThree X sources in one waveform:
Three X sources: uninitialized (from t=0), timing-check (near an edge), contention (drivers fight)
8 cycles6. Debugging Session — one waveform, three X sources
Three nets show X and are chased as one bug, but they have three different sources — an uninitialized flop, a timing-check violation, and bus contention — each requiring its own fix; identifying the source per X is the first debugging step
IDENTIFY THE SOURCE BEFORE FIXINGA gate-level run shows X on three nets. The team assumes one root cause and applies a single fix that clears only one.
Three distinct sources. Net A is X from t=0 and clears on reset → uninitialized state (source 1, no/late reset, 2.6). Net B goes X near a clock edge, with a $hold message → timing-check violation (source 2, notifier X, 3.2). Net C goes X when two drivers conflict, with a contention warning → multi-driver contention (source 3). Because the sources differ, no single fix addresses all three. The waveform timing (from t=0 vs near-edge vs on-conflict) and the log messages distinguish them — guessing a common cause is the mistake.
Diagnose per X by source: (1) apply/repair reset for the uninitialized flop; (2) fix stimulus timing (drive clear of the window, 5.3) or investigate a real path for the timing-check X; (3) fix the drive/enable logic for the contention. Use the simulation log (violation/contention messages) plus the waveform timing of each X to identify its source first. The lesson: gate-level X has five recurring sources — uninitialized state, timing-check violations, contention/floating, model unknowns, and unknown inputs — and the source, read from the waveform timing and the log, determines the fix; never assume one cause. (X is a modelling value — a flag to investigate, possibly pessimism, 6.2 — not automatic proof of broken silicon; and GLS stays dynamic, STA signs off, 0.3.)
7. Common Mistakes
- Assuming all
Xs share one cause. Five distinct sources; identify each. - Ignoring the log. Violation/contention messages often name the source.
- Treating every
Xas a real bug. Could be pessimism (2.3/6.2) — investigate. - Forgetting
Z→X. A floating tri-state reads asXdownstream. - Reading
Xas a silicon voltage. It's a modelling value for unknown.
8. Industry Best Practices
- Classify each
Xby source (uninit / timing / contention / model / input) before fixing. - Read the simulation log alongside the waveform.
- Use
Xtiming (from t=0 vs near-edge vs on-conflict) as a source clue. - Treat
Xas a flag to investigate — real bug vs pessimism (6.2). - Keep GLS/STA distinct —
Xdebugging is dynamic; STA signs off timing.
Senior Engineer Thinking
- Beginner: "There's
Xeverywhere — the netlist is broken." - Senior: "Each
Xhas a source. From t=0 → uninitialized. Near an edge with a$holdmessage → timing check. On a shared net → contention. Let me classify each, then fix by source."
The senior treats each X as a sourced event and reads waveform timing + log to classify it.
Silicon Impact
Getting the source right is what makes X debugging efficient and correct. Misclassify, and you apply the wrong fix — resetting a flop that was actually a contention issue, or waiving a real uninitialized-state X as "pessimism" and letting a power-up bug reach silicon (the reset-gap escape, 2.6/0.3). Because gate-level X surfaces problems RTL hides (6.4), the source you identify often maps to a real design fix (reset, drive enable) or a real timing issue (STA). Efficient source classification turns a scary wall of X into a prioritized bug list.
Engineering Checklist
- Classified each
Xby source (uninit / timing / contention / model / input). - Read the simulation log for violation/contention messages.
- Used each
X's timing (t=0 vs near-edge vs on-conflict) as a clue. - Judged real bug vs pessimism (6.2) per
X. - Applied the source-appropriate fix (reset / stimulus / drive / model).
Try Yourself
- Build a small netlist with an unreset flop, a contended bus, and an unconnected input — run it.
- Observe: three
Xs with different timing (from t=0, on-conflict, propagated). - Change: fix each by its source — add reset, resolve the drive conflict, connect the input.
- Expect: each
Xclears only when its own source is addressed — proving one fix per source.
Any free Verilog simulator shows X, Z, contention warnings, and unconnected-port notes. No paid tool required.
Interview Perspective
- Weak: "
Xmeans the netlist is wrong." - Good: "
Xcomes from uninitialized flops, timing-check violations, contention, model unknowns, or unknown inputs." - Senior: "
Xis the simulator's 'unknown', and it has five recurring sources. I classify each by its waveform timing and the log — power-up (uninit), near-edge ($hold), on-conflict (contention) — then fix by source. And I treatXas a flag to investigate: real bug or pessimism, not a silicon voltage."
9. Interview / Review Questions
10. Key Takeaways
- Gate-level
Xhas five recurring sources: uninitialized state (power-upX, 2.6), timing-check violations (notifierX, 2.5/3.2), multi-driver contention / floating (Z→X), explicit model unknowns (UDPXrows, 2.3), and unknown inputs propagating in. - The source determines the fix — reset, stimulus timing, drive/enable, or model — so classify each
Xbefore fixing. - Use each
X's waveform timing (from t=0 / near-edge / on-conflict) and the simulation log to identify its source. Xis a modelling value for unknown, not a silicon voltage — a flag to investigate (real bug vs pessimism, 6.2), and the gate level surfacesXthat RTL hides (6.4).Xdebugging is dynamic — STA still signs off timing (0.3). Next: 6.2 — X-pessimism vs X-optimism.
Quick Revision
Five sources of gate-level
X: uninitialized state (power-up, 2.6), timing-check violation (notifier, 3.2), contention/floating (Z→X), model unknowns (UDP, 2.3), unknown inputs. Source (from waveform timing + log) determines the fix — classify before fixing.X= "unknown" (modelling value), a flag to investigate (real bug vs pessimism, 6.2), surfaced by the gate level. Next: 6.2 — pessimism vs optimism.