Skip to content

GLS · Chapter 6 · X-Propagation

Why RTL Hides Bugs the Netlist Exposes

One of the strongest reasons gate-level simulation exists is that RTL can hide bugs the netlist reveals. RTL is X-optimistic: a behavioral if or case handed an unknown select quietly picks a branch and produces a definite value, masking an uninitialized control. The synthesized netlist has no such behavior, so its mux propagates the unknown and exposes the same signal. The key fact underneath is that synthesis does not preserve X semantics. The gate-level netlist is logically equivalent for defined inputs, but it behaves differently on unknowns, so a bug that is invisible in RTL simulation can appear in GLS. This is not a synthesis defect; it is why GLS is a distinct, valuable check. This lesson shows the mechanism with a simple mux in three languages.

Foundation12 min readGLSX-OptimismRTLSynthesisUninitialized

Chapter 6 · Section 6.4 · X-Propagation

Project thread — the FSM's power-up X (5.5) is exactly this: RTL's behavioural reset/optimism can hide an uninitialized state the netlist exposes. 6.6 root-causes it end to end.

1. Why Should I Learn This?

"It passes RTL simulation" is not the same as "it's correct" — and this lesson explains the gap.

  • RTL optimism resolves unknowns to a branch, hiding uninitialized control.
  • The netlist propagates X, exposing the same bug.
  • Synthesis doesn't preserve X semantics — so GLS is a distinct check, not a redundant one.

This is the why behind gate-level X debugging and the FSM X of 6.6.

2. Real Silicon Story — the "verified" block that came up wrong in silicon

A control block passed extensive RTL simulation — no X, all tests green. In silicon it occasionally powered up in the wrong mode.

The mode select was driven by a register that lacked a proper reset. In RTL, the mode case was X-optimistic: with the select X, it fell through to a default branch and produced a definite, plausible mode — so RTL never showed a problem. The netlist mux propagated X, and a gate-level run would have flagged it — but GLS had been skipped as "redundant with RTL." Silicon, of course, powered up at some real value — sometimes the wrong mode.

Lesson: RTL optimism can make an uninitialized-control bug invisible. GLS (which propagates X) is the check that catches it — it is not redundant with RTL.

3. Concept — how RTL hides, how the netlist exposes

RTL is X-optimistic (hides):

  • if (sel) a; else b; with sel = X → takes elsedefinite b. The unknown is gone.
  • case (sel) … default: … endcase with sel = X → often the defaultdefinite. Unknown hidden.
  • Behavioural initial values / resets that model state the gates don't have.

The netlist exposes:

  • Synthesis maps the conditional to a mux, which propagates X on an unknown select (differing data, 6.3).
  • Gate flops power up X (no initial, 2.6) — no behavioural init to hide it.
  • The X surfaces at outputs, flagging the uninitialized source.

The key fact (accuracy):

  • Synthesis does not preserve X semantics. It preserves logic for defined inputs; behaviour on unknowns legitimately differs between RTL and gates.
  • So an RTL "pass" on unknowns is not authoritative — GLS is the distinct check.
  • Neither is silicon truth (6.2) — but the gate X flags a real uninitialized source RTL hid.
Uninitialized select: RTL if/case picks a branch and hides it (RTL passes); netlist mux propagates X and exposes it (GLS catches)RTLsimGLSUninitializedselect (X)RTL if/case → picksa branchDefinite value →BUG HIDDEN (RTLpasses)Netlist mux →propagates XX at output →BUG EXPOSED (GLScatches)
Figure 1 — why RTL hides what the netlist exposes (representative). Given an uninitialized select (X): the RTL behavioural if/case is X-OPTIMISTIC -> it picks a branch/default and outputs a DEFINITE value, HIDING the bad select (RTL passes). Synthesis maps the same conditional to a MUX, which propagates X on an unknown select -> the netlist EXPOSES the bug in GLS. Synthesis does NOT preserve X semantics, so a bug invisible in RTL appears in GLS -- which is exactly why GLS is a distinct check.

4. Mental Model — RTL rounds off uncertainty; the netlist keeps it

RTL behavioural code rounds off uncertainty to a clean answer; the netlist keeps the uncertainty as X.

  • Ask RTL "which branch if the select is unknown?" and it picks one — a confident (possibly wrong) answer.
  • Ask the netlist mux the same and it says "unknown" (X) — honest, if noisier.
  • Silicon picks a real branch — but not guaranteed to be RTL's guess.

RTL's rounding is convenient but hides the unknown; the netlist's honesty is why GLS catches the bug. Synthesis changing this behaviour is expected, not a defect.

5. Working Example — the same mux in three languages

The behavioural mux (X-optimistic), in three languages:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// SystemVerilog — behavioural mux: X-OPTIMISTIC on an unknown select
assign y = sel ? a : b;      // sel = X -> resolves to b -> DEFINITE (hides uninitialized sel)
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Verilog — same behaviour (case form also optimistic via default)
always @* case (sel) 1'b1: y = a; default: y = b; endcase   // sel = X -> default -> DEFINITE
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- VHDL — same behaviour
y <= a when sel = '1' else b;   -- sel = 'X'/'U' -> else branch -> DEFINITE (hides it)

After synthesis, this becomes a mux cell whose UDP propagates X on an unknown select (6.3) — so GLS shows X where RTL showed a definite value.

Practical context (representative, tool-neutral):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# Why GLS is NOT redundant with RTL (tool-neutral):
#   synthesis preserves logic for DEFINED inputs; it does NOT preserve X semantics
#   RTL if/case: unknown select -> branch/default -> DEFINITE (hides)
#   netlist mux: unknown select -> X (exposes)
#   => a bug invisible in RTL can appear in GLS. Run GLS; don't assume RTL covers it.
#   (xprop, 6.5, can reproduce some of this in RTL to shift-left.)

RTL hides, netlist exposes — as a real waveform:

Same uninitialized select: RTL outputs a definite value (hidden bug); GLS shows X (exposed bug)

8 cycles
With an unknown select, RTL simulation shows a definite output while gate-level simulation shows XRTL definite (hidden) vs GLS X (exposed)RTL definite (hidden) …clksel (uninit)XXXXXXXXy (RTL sim)y (GLS)XXXXXXXXt0t1t2t3t4t5t6t7
Representative. sel is uninitialized (X). RTL's behavioural mux picks a branch and outputs a definite value every cycle — the bug is HIDDEN and RTL passes. The synthesized netlist mux propagates X — the bug is EXPOSED in GLS. Synthesis didn't preserve X semantics; that difference is exactly why GLS is worth running.

6. Debugging Session — RTL green, GLS shows X

1

A block passes RTL simulation cleanly but GLS shows X on an output, and GLS is doubted as over-pessimistic — but RTL's X-optimism hid an uninitialized control that the netlist mux correctly exposes; synthesis does not preserve X semantics

RTL PASS != CORRECT; GLS IS A DISTINCT CHECK
Symptom

A block is green in RTL simulation but shows X on an output in GLS. The team suspects GLS is being "over-pessimistic" and considers ignoring it.

Root Cause

RTL's X-optimism hid a real bug the netlist exposes. The output depends on a control (a select or mode register) that is genuinely uninitialized (no proper reset, 2.6). In RTL, the behavioural if/case handling that control is X-optimistic — an unknown select resolves to a branch/default, producing a definite value, so RTL never shows a problem. Synthesis maps the conditional to a mux that propagates X on an unknown select (6.3), so GLS exposes the uninitialized control. Crucially, synthesis does not preserve X semantics — the RTL and gate behaviours on unknowns legitimately differ, so the RTL "pass" was not authoritative. The gate X is the honest result, flagging a real uninitialized source.

Fix

Treat the GLS X as a real lead: trace it to its source (6.1) — here an uninitialized control — and fix the source (proper reset/initialization). Do not dismiss it because "RTL passed"; RTL optimism is exactly the mechanism that hides this class of bug. To catch it earlier, enable xprop in RTL (6.5) to reproduce the gate-like X behaviour and shift the find left. The lesson: RTL is X-optimistic and hides uninitialized-control bugs by resolving unknowns to a branch; the netlist propagates X and exposes them — synthesis does not preserve X semantics, so GLS is a distinct check, and a GLS-only X is a real bug to root-cause, not pessimism to ignore. (X is a modelling value; GLS stays dynamic — STA signs off, 0.3.)

7. Common Mistakes

  • Assuming an RTL pass means correct. RTL optimism hides uninitialized-control bugs.
  • Believing synthesis preserves X behaviour. It preserves defined-input logic, not X semantics.
  • Treating GLS as redundant with RTL. It is a distinct check for exactly this class of bug.
  • Dismissing a GLS-only X as pessimism without tracing the source (6.2/6.1).
  • Not shifting left with xprop. RTL xprop (6.5) can catch some of these earlier.

8. Industry Best Practices

  • Run GLS as a distinct check — do not assume RTL covers unknowns.
  • Treat a GLS-only X as a real lead — trace to source (6.1).
  • Enable RTL xprop (6.5) to shift-left the catch.
  • Fix uninitialized sources (reset/init), not the symptom.
  • Educate that synthesis doesn't preserve X semantics — set expectations.

Senior Engineer Thinking

  • Beginner: "It's clean in RTL, so GLS X must be pessimism."
  • Senior: "RTL is optimistic — it resolves unknown selects to a branch and hides them. Synthesis doesn't preserve X semantics, so the gate X is a real finding. Where's the uninitialized source?"

The senior knows RTL optimism hides these bugs and treats a GLS-only X as a real lead to root-cause.

Silicon Impact

This is a first-order reason GLS earns its cost. A class of bugs — uninitialized control, missing reset, unhandled case — is systematically hidden by RTL's X-optimism and systematically exposed by the netlist's X-propagation. Skip GLS (or waive its Xs as pessimism), and these bugs sail through RTL green and surface in silicon as power-up-dependent, mode-wrong, intermittent failures (the reset-gap class, 0.3) — expensive and hard to reproduce. Running GLS and treating its Xs as real leads is precisely how teams catch what RTL cannot. Synthesis not preserving X semantics isn't a flaw to fear — it's the property that makes GLS a distinct, protective check.

Engineering Checklist

  • Ran GLS as a distinct check, not assumed redundant with RTL.
  • Treated each GLS-only X as a real lead → traced to source (6.1).
  • Fixed uninitialized sources (reset/init), not the symptom.
  • Enabled RTL xprop (6.5) to shift-left where possible.
  • Communicated that synthesis doesn't preserve X semantics.

Try Yourself

  1. Simulate the behavioural mux (sel ? a : b) in RTL with sel uninitialized — output is a definite value (RTL passes).
  2. Observe: RTL hides the bad select.
  3. Change: synthesize and run the netlist mux with the same uninitialized sel.
  4. Expect: GLS shows X (bug exposed). Then enable xprop in the RTL run (6.5) and watch the X appear in RTL too — proving the shift-left.

Any free Verilog simulator shows the RTL-vs-GLS divergence; many support an xprop mode. No paid tool required.

Interview Perspective

  • Weak: "If RTL passes, the design is correct."
  • Good: "RTL is X-optimistic — an if/case picks a branch on an unknown select, hiding it; the netlist mux propagates X and exposes it."
  • Senior: "Synthesis preserves defined-input logic but not X semantics, so a bug hidden by RTL optimism appears in GLS — which is why GLS is a distinct check. A GLS-only X is a real lead to root-cause (uninitialized control), and I use RTL xprop to catch it earlier. Neither model is silicon truth, but the gate X flags the real uninitialized source."

9. Interview / Review Questions

10. Key Takeaways

  • RTL is X-optimistic: a behavioural if/case handed an unknown select picks a branch/default and outputs a definite value — hiding an uninitialized control.
  • The synthesized netlist mux propagates X (6.3) and exposes the same uninitialized source in GLS.
  • Synthesis does not preserve X semantics — it preserves defined-input logic; behaviour on unknowns differs — so an RTL pass is not authoritative and GLS is a distinct check.
  • A GLS-only X is a real lead (uninitialized control/reset), not pessimism to dismiss — trace to source (6.1) and fix it; xprop (6.5) can shift the catch left into RTL.
  • Neither model is silicon truth — but the gate X flags a real source; GLS stays dynamic (STA signs off, 0.3). Next: 6.5 — controlling X-propagation (xprop modes).

Quick Revision

RTL X-optimism HIDES uninitialized-control bugs (if/case picks a branch on unknown sel → definite). Netlist mux propagates X → EXPOSES them. Synthesis does NOT preserve X semantics (defined-input logic yes, X no) → a bug invisible in RTL appears in GLS → GLS is a distinct check. A GLS-only X = real lead (trace to source, 6.1), not pessimism. xprop (6.5) shifts the catch left. Next: 6.5 — controlling X-propagation.