Skip to content

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 X backward 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 X appears 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 unresetreal 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 an X operand yields X, 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 X and 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 X clears at reset; the FSM starts in IDLE and advances legally.

Scope: the X here is real (uninitialized state) — fixed by reset, not waived; GLS stays dynamic (STA signs off, 0.3).

FSM X trace: reset gap causes uninitialized state X, which flows through output logic to busy/done; fix is a proper resetpower-up Xpropagatesclears XReset gapstate flop's reset neverconnected (2.6)state = Xuninitialized (6.1); real,not pessimism (6.2)busy/done = Xstate X flows via outputlogic (6.3)RTL hid itbehavioural reset/optimism(6.4)xprop catches earlyforce state X in RTL (6.5)Fix: proper resetreset every state flop → Xclears12
Figure 1 — root-causing the FSM X (representative). The X traces backward: busy/done = X (6.3, comparison with an X state) <- state = X (uninitialized) <- a state flop whose RESET was never connected (reset gap, 2.6). Real, not pessimism (6.2). RTL hid it via behavioural reset/optimism (6.4); xprop would catch it in RTL (6.5). Fix at the SOURCE: connect/assert reset to every state flop -> X clears, FSM starts in IDLE.

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/done are Xwho fed them? The state (X).
  • State is Xwhy? 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):

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

The root cause and the source fix:

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

Practical context (representative, tool-neutral):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# 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 cycles
Before the fix, state and busy/done are X even after reset; after connecting reset to every state flop, state resets to IDLE and outputs are cleanresetresetafter fix: X clears; before: still Xafter fix: X clears; b…clkrst_nbusy (before fix)XXXXXXXXXbusy (after fix)XXdone (after fix)XXt0t1t2t3t4t5t6t7t8
Representative. BEFORE: a state flop's reset is unconnected, so state[1] stays X even after rst_n — busy/done are X and the FSM never advances. AFTER: reset connected to every state flop, so state resets to IDLE at reset release, then steps legally (RUN→busy, DONE→done). The X was real uninitialized state, fixed at the source (reset).

6. Debugging Session — the full FSM X root-cause

1

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

The FSM's busy/done outputs are X and stay X even after reset is applied — the FSM never enters a legal state.

Root Cause

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

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 (RUNbusy, DONEdone). 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 X as 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 X backward 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 X at reset and the FSM runs legally.

Senior Engineer Thinking

  • Beginner: "busy/done are X — let me force them to 0 in the testbench."
  • Senior: "That's a symptom. busy/done are X because state is X because 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 X backward: busy/donestate → the unreset flop.
  • Applied the five lenses (source, real?, flow, why-hidden, shift-left).
  • Confirmed the X is 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

  1. Run the FSM netlist with one state flop's reset disconnectedbusy/done are X and stay X after reset.
  2. Observe: trace backward — the X is on state[1], driven by a DFFX1 with no RN.
  3. Change: swap it for a DFFRX1 with RN=rst_n (reset on every state bit).
  4. Expect: the X clears at reset; the FSM steps IDLE→RUN→DONE. Then enable xprop in the RTL run and confirm the state X would 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 X back — outputs come from state, which is X because 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 Xbusy/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. The X was 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 up X (2.6) and never clears.
  • Apply the five lenses: source (uninitialized state, 6.1), real not pessimism (6.2), flow (state Xbusy/done via output logic, 6.3), why RTL hid it (behavioural reset/optimism, 6.4), shift-left (xprop, 6.5).
  • Trace the X backwardbusy/donestate → the unreset flop — to reach the root cause.
  • Fix at the source: a proper reset on every state flop, asserted long enough — the X clears and the FSM starts in IDLE and advances legally.
  • The X was 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 backward busy/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) → X clears, FSM starts in IDLE. Real bug GLS caught that RTL hid. Chapter 6 complete; next: Chapter 7 — reset & initialization debug.