GLS · Chapter 6 · X-Propagation
Working Example: Root-Causing an X in the FSM
This capstone applies the whole X-propagation toolkit to the exact unknown the adapted FSM testbench surfaced in the previous chapter, root-causing it step by step. The source traces to a state flip-flop that never saw a clean reset, an uninitialized state that powers up unknown. It is a real bug, not simulator pessimism, and the state unknown propagates through the output logic to the busy and done signals. RTL had hidden it because its behavioral reset produced a definite state, masking the missing gate-level reset, and unknown-propagation checking in RTL would have exposed it earlier. The fix is at the source: connect a proper reset to every state flop. A before-and-after waveform shows the unknown clearing once the state is reset, giving a complete, sourced root-cause that hands off to the reset chapter.
Foundation13 min readGLSX-PropagationFSMResetRoot-Cause
Chapter 6 · Section 6.6 · X-Propagation
Project thread — this closes the loop on the FSM X from 5.5: found by an adapted testbench, now root-caused with the chapter's tools. Chapter 7 takes reset (the fix here) as its whole subject; the FSM carries on toward the UART/timer and mini-SoC.
1. Why Should I Learn This?
This is the chapter as a procedure: take an X from symptom to source to fix.
- You apply all five lenses (source, real-vs-pessimism, flow, why-RTL-hid-it, shift-left) on one
X. - You practise tracing an
Xbackward to a real root cause. - You end with a source fix (reset), not a symptom patch.
It closes X-propagation and sets up the reset chapter (Chapter 7).
2. Real Silicon Story — the FSM that hung on power-up
The FSM (from 5.5) occasionally powered up hung — outputs busy/done stuck, never advancing.
The root cause was a state flop whose reset was never connected (a reset-gap, 2.6). It powered up X; the state X propagated to busy/done and the FSM never entered a legal state. RTL had hidden it (behavioural reset made the state definite); a properly adapted GLS run (5.5) surfaced the X, and this root-cause traced it to the unreset flop. A one-line reset fix cleared it.
Lesson: an FSM power-up X is almost always uninitialized state. Trace it to the exact unreset flop and fix the reset — the whole chapter in one bug.
3. Concept — the five-lens root-cause
Applying the chapter to the FSM X:
- (6.1) Source: the
Xappears from t=0 and does not clear on reset → uninitialized state whose reset is missing/incomplete (2.6). - (6.2) Real vs pessimism: the flop is genuinely unreset → real bug (not a UDP
X-pessimism false alarm). - (6.3) Flow: state
X→ output logic (busy = (state==RUN),done = (state==DONE)) →busy/done=X(a comparison with anXoperand yieldsX, 6.3). - (6.4) Why RTL hid it: RTL's behavioural
if (!rst_n) state <= IDLE;plus optimism gave a definite state in RTL — masking the gate-level missing reset. - (6.5) Shift-left: xprop in RTL would have forced the state
Xand caught it earlier.
The fix (source, not symptom):
- Connect/assert a proper reset to every state flop; confirm reset is asserted long enough (2.6).
- The
Xclears at reset; the FSM starts inIDLEand advances legally.
Scope: the X here is real (uninitialized state) — fixed by reset, not waived; GLS stays dynamic (STA signs off, 0.3).
4. Mental Model — follow the X home
Root-causing an X is following it home — backward, net by net, to where it was born.
busy/doneareX→ who fed them? The state (X).- State is
X→ why? It was never reset (uninitialized). - Reset missing → there's home. The reset gap is the root cause.
Then fix home (the reset), not the doorstep (busy/done). The five lenses just make the walk home systematic: source, real?, flow, why-hidden, shift-left.
5. Working Example — the trace, the fix, and the waveform
The output logic that carries the X (from the FSM of 5.5):
// FSM output logic — REPRESENTATIVE. A comparison with an X state yields X (6.3).
assign busy = (state == RUN); // state = X -> (X == RUN) = X -> busy = X
assign done = (state == DONE); // state = X -> done = XThe root cause and the source fix:
// ROOT CAUSE — a state flop whose reset (RN) was never connected -> powers up X
DFFX1 u_state1 (.D(next1), .CK(clk), .Q(state[1])); // no RN! -> X forever
// FIX — use the reset flop and connect reset to EVERY state bit (2.6)
DFFRX1 u_state1 (.D(next1), .CK(clk), .RN(rst_n), .Q(state[1])); // RN=rst_n -> resets to 0Practical context (representative, tool-neutral):
# Root-cause walk (tool-neutral):
# 1) busy/done = X at power-up, NOT cleared by reset -> source is uninitialized state (6.1)
# 2) trace back: busy <- (state==RUN) <- state[1] = X -> which flop drives state[1]?
# 3) inspect that flop: DFFX1 (NO reset pin) -> reset gap (2.6) [real, not pessimism, 6.2]
# 4) fix: DFFRX1 with RN=rst_n on EVERY state bit; assert reset long enough
# 5) shift-left next time: xprop in RTL would have shown state X earlier (6.5)The FSM X, before and after the reset fix, as a real waveform:
FSM X root-cause: state X propagates to busy/done (before) → cleared by a proper reset (after)
9 cycles6. Debugging Session — the full FSM X root-cause
The FSM's busy/done stay X even after reset; tracing the X backward reaches a state flop whose reset was never connected (a reset gap) — a real uninitialized-state bug that RTL hid, fixed by connecting reset to every state flop
TRACE X TO SOURCE; FIX THE RESETThe FSM's busy/done outputs are X and stay X even after reset is applied — the FSM never enters a legal state.
Uninitialized state from a reset gap. Tracing backward (6.3): busy = (state==RUN) and done = (state==DONE) are X because state is X (a comparison with an X operand yields X). state is X because a state flip-flop's reset was never connected — synthesized/instantiated as a DFFX1 with no RN (or a broken reset net), so it powers up X and never clears (2.6). This is real (6.2), not pessimism — a genuinely unreset flop. RTL hid it (6.4): the behavioural if (!rst_n) state <= IDLE; gave a definite state in RTL, masking the missing gate-level reset — which is why it only surfaced in the adapted GLS run (5.5). The five lenses converge on one root cause: a state flop that never saw an asserted reset.
Fix at the source: connect a proper reset to every state flop (use the reset cell DFFRX1 with RN=rst_n), and ensure reset is asserted long enough to force all state (2.6). Re-run: state resets to IDLE, the X clears from busy/done, and the FSM advances legally (RUN→busy, DONE→done). To catch this class earlier next time, enable xprop in RTL (6.5) so the state X appears in RTL regressions. The lesson: root-cause an FSM X by tracing it backward — outputs → state → the unreset flop — using the five lenses (source, real-vs-pessimism, flow, why-RTL-hid-it, shift-left); the fix is at the source (a proper reset to every state flop), not the symptom. (The X was real uninitialized state; GLS stays dynamic — STA signs off timing, 0.3.)
7. Common Mistakes
- Patching the symptom (
busy/done) instead of the source (the reset). - Waiving the
Xas pessimism without tracing it (it's real uninitialized state, 6.2). - Fixing one state bit, not every state flop's reset.
- Assuming RTL's pass meant no bug. RTL hid it (6.4).
- Not adding xprop to catch the class earlier (6.5).
8. Industry Best Practices
- Trace
Xbackward to source (outputs → state → flop) before fixing. - Apply the five lenses systematically (source, real?, flow, why-hidden, shift-left).
- Fix reset at the source — every state flop, asserted long enough.
- Add xprop to RTL regressions to catch the class early (6.5).
- Confirm the fix clears the
Xat reset and the FSM runs legally.
Senior Engineer Thinking
- Beginner: "
busy/doneareX— let me force them to0in the testbench." - Senior: "That's a symptom.
busy/doneareXbecausestateisXbecause a flop's reset is missing. I fix the reset, not the outputs — and add xprop so RTL catches this next time."
The senior traces X to the source and fixes the reset, never the symptom.
Silicon Impact
This capstone is the archetype of a GLS-caught bug: an FSM X from an unreset state flop is a reset-gap that, unfixed, ships an FSM that powers up in an illegal state and hangs intermittently in silicon (0.3) — the exact failure the opening story described, and a classic field-return cause for controllers. The five-lens root-cause turns a scary wall of X into a one-line reset fix at the source, in simulation, before tape-out. And it shows the layered defence: adapt the testbench (Ch5) to surface the X, root-cause with X-propagation (Ch6) to reach the reset gap, xprop (6.5) to catch the class earlier, and Chapter 7 to make reset bullet-proof.
Engineering Checklist
- Traced the
Xbackward:busy/done→state→ the unreset flop. - Applied the five lenses (source, real?, flow, why-hidden, shift-left).
- Confirmed the
Xis real (uninitialized state), not pessimism (6.2). - Fixed at the source: reset on every state flop, asserted long enough (2.6).
- Added xprop to RTL to catch the class earlier (6.5).
Try Yourself
- Run the FSM netlist with one state flop's reset disconnected —
busy/doneareXand stayXafter reset. - Observe: trace backward — the
Xis onstate[1], driven by aDFFX1with noRN. - Change: swap it for a
DFFRX1withRN=rst_n(reset on every state bit). - Expect: the
Xclears at reset; the FSM stepsIDLE→RUN→DONE. Then enable xprop in the RTL run and confirm the stateXwould have appeared there too.
Any free Verilog simulator runs this end-to-end; xprop-style modes are widely available. No paid tool required.
Interview Perspective
- Weak: "The FSM outputs are
X, so I'd force them to a known value in the testbench." - Good: "I'd trace the
Xback — outputs come fromstate, which isXbecause a flop isn't reset — and fix the reset." - Senior: "I root-cause with the five lenses: source (uninitialized state), real not pessimism, flow (state
X→busy/done), why RTL hid it (behavioural reset), and shift-left (xprop). The fix is a proper reset on every state flop — at the source, not the symptom. TheXwas real; GLS caught what RTL hid."
9. Interview / Review Questions
10. Key Takeaways
- The FSM
X(from 5.5) root-causes to uninitialized state: a state flop whose reset was never connected (a reset gap) powers upX(2.6) and never clears. - Apply the five lenses: source (uninitialized state, 6.1), real not pessimism (6.2), flow (state
X→busy/donevia output logic, 6.3), why RTL hid it (behavioural reset/optimism, 6.4), shift-left (xprop, 6.5). - Trace the
Xbackward —busy/done→state→ the unreset flop — to reach the root cause. - Fix at the source: a proper reset on every state flop, asserted long enough — the
Xclears and the FSM starts inIDLEand advances legally. - The
Xwas real (fixed by reset, not waived); GLS caught what RTL hid, and it stays dynamic — STA signs off timing (0.3). This closes Chapter 6; next, Chapter 7 makes reset & initialization bullet-proof.
Quick Revision
Root-cause the FSM
X: trace backwardbusy/done(X) →state(X) → a state flop whose reset was never connected (reset gap, 2.6). Five lenses: source (uninit), real-not-pessimism, flow (6.3), why-RTL-hid-it (6.4), shift-left (xprop, 6.5). Fix the reset on every state flop (source, not symptom) →Xclears, FSM starts inIDLE. Real bug GLS caught that RTL hid. Chapter 6 complete; next: Chapter 7 — reset & initialization debug.