Skip to content

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).
  • X is a modelling value — so an X is 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 (no initial); only reset clears them (2.6). The classic power-up X.
  • (2) Timing-check violations. $setup/$hold/… fires → notifier toggles → flop output X (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-stateZ, treated as X by many downstream gates.
  • (4) Explicit unknowns in cell models. UDP rows emit X for ambiguous inputs (2.3); synthesized don't-cares.
  • (5) Unknown inputs propagating in. X on a primary input, unconnected pin, or unmodelled block flows through the logic.

Framing:

  • X is a modelling value for unknown, not a silicon voltage — real HW resolves to a level; X says simulation doesn't know which.
  • The gate level surfaces X that RTL init/optimism hides (6.4).
  • An X is a flag to investigate — could be a real bug (uninitialized state) or pessimism (2.3/6.2).
Five sources of gate-level X converging: uninitialized state, timing-check violations, contention, explicit model unknowns, unknown inputs1. Uninitializedstateflops power up X → resetclears (2.6)2. Timing-checkviolationnotifier X near an edge(2.5/3.2)3. Contention /floatingtwo drivers → X; tri-stateZ → X4. Model unknownsUDP X rows / don't-cares(2.3)5. Unknown inputsX in from pins/inputspropagatesX on a netsource determines the fix —investigate12
Figure 1 — the five sources of gate-level X (representative). Uninitialized state (flops power up X, cleared only by reset), timing-check violations (notifier X near an edge), multi-driver contention / floating tri-state (Z treated as X), explicit unknowns in cell models (UDP X rows), and unknown inputs propagating in — all converge as X on nets. The source determines the fix. X is a modelling value for 'unknown', not a silicon voltage; the gate level surfaces X that RTL often hides.

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 X row (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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// (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 X

Practical context (representative, tool-neutral):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# 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 propagating

Three X sources in one waveform:

Three X sources: uninitialized (from t=0), timing-check (near an edge), contention (drivers fight)

8 cycles
One signal is X from power-up until reset, another goes X near a clock edge, a third goes X when two drivers conflictuninit Xuninit…timing-check X / contention Xtiming-check X / conte…clkrst_nq_initXXq_tcXbusXt0t1t2t3t4t5t6t7
Representative. q_init is X from power-up until reset clears it (source 1). q_tc goes X for one edge when a $hold check fires (source 2). bus goes X while two drivers briefly conflict (source 3). Same value X, three different origins — each needs a different fix.

6. Debugging Session — one waveform, three X sources

1

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 FIXING
Symptom

A gate-level run shows X on three nets. The team assumes one root cause and applies a single fix that clears only one.

Root Cause

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.

Fix

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 X as a real bug. Could be pessimism (2.3/6.2) — investigate.
  • Forgetting ZX. A floating tri-state reads as X downstream.
  • Reading X as a silicon voltage. It's a modelling value for unknown.

8. Industry Best Practices

  • Classify each X by source (uninit / timing / contention / model / input) before fixing.
  • Read the simulation log alongside the waveform.
  • Use X timing (from t=0 vs near-edge vs on-conflict) as a source clue.
  • Treat X as a flag to investigate — real bug vs pessimism (6.2).
  • Keep GLS/STA distinctX debugging is dynamic; STA signs off timing.

Senior Engineer Thinking

  • Beginner: "There's X everywhere — the netlist is broken."
  • Senior: "Each X has a source. From t=0 → uninitialized. Near an edge with a $hold message → 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 X by 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

  1. Build a small netlist with an unreset flop, a contended bus, and an unconnected input — run it.
  2. Observe: three Xs with different timing (from t=0, on-conflict, propagated).
  3. Change: fix each by its source — add reset, resolve the drive conflict, connect the input.
  4. Expect: each X clears 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: "X means the netlist is wrong."
  • Good: "X comes from uninitialized flops, timing-check violations, contention, model unknowns, or unknown inputs."
  • Senior: "X is 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 treat X as a flag to investigate: real bug or pessimism, not a silicon voltage."

9. Interview / Review Questions

10. Key Takeaways

  • Gate-level X has five recurring sources: uninitialized state (power-up X, 2.6), timing-check violations (notifier X, 2.5/3.2), multi-driver contention / floating (ZX), explicit model unknowns (UDP X rows, 2.3), and unknown inputs propagating in.
  • The source determines the fix — reset, stimulus timing, drive/enable, or model — so classify each X before fixing.
  • Use each X's waveform timing (from t=0 / near-edge / on-conflict) and the simulation log to identify its source.
  • X is a modelling value for unknown, not a silicon voltage — a flag to investigate (real bug vs pessimism, 6.2), and the gate level surfaces X that RTL hides (6.4).
  • X debugging 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 (ZX), 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.