Skip to content

GLS · Chapter 8 · Timing-Violation Debug

Timing Checks, Notifiers & X-Injection

This lesson connects timing violations to unknown-propagation through the notifier mechanism. A cell's specify block holds timing checks for setup, hold, recovery, removal, and width, each with a notifier register that also feeds the cell's primitive. When a check fires, it toggles the notifier, and the primitive drives the cell output to an unknown. That injected unknown then propagates through downstream logic like any other, so a single timing violation can become a wide propagation problem, sometimes flooding the design from one small violation. This lesson traces the path from check to notifier to unknown to propagation, and shows how to manage the flood without masking real violations by disabling checks wholesale. Static timing analysis remains the arbiter of real timing throughout.

Foundation12 min readGLSNotifierX-InjectionTiming ChecksX-Propagation

Chapter 8 · Section 8.5 · Timing-Violation Debug

Project thread — a $setup/$hold firing on a counter/FSM flop injects X that flows to outputs (as in 6.6). This lesson is the bridge between a timing violation and the X-propagation it causes; 8.6 sees it on a clock-gated block.

1. Why Should I Learn This?

A timing violation rarely stays put — via the notifier it becomes an X that spreads.

  • Check → notifier → UDP → X is the injection path (2.5).
  • The injected X propagates (Chapter 6) — one violation can flood downstream.
  • Managing the flood without disabling real checks is the skill (8.4).

This unifies timing-violation debug (Ch8) with X-propagation (Ch6).

2. Real Silicon Story — one violation, a screen full of X

A single $hold violation on one flop produced a screen full of X downstream — dozens of signals unknown. The team assumed dozens of bugs.

There was one bug. The hold violation injected X on that flop (notifier), and the X propagated through the downstream logic (Chapter 6) — fanning out to everything the flop fed. Fixing the single hold race (add delay, 8.3) cleared the entire flood.

Lesson: a timing violation becomes an X-propagation problem — one injected X can flood the design. Trace the flood back to the single injecting violation; don't count the symptoms as separate bugs.

3. Concept — X-injection and its propagation

The injection path (recap 2.5):

  • A cell's specify block has timing checks ($setup/$hold/$recovery/$removal/$width), each with a notifier reg.
  • On a violation, the check firestoggles the notifier.
  • The notifier is a UDP input, so the toggle drives the cell output to XX-injection.

The propagation (Chapter 6):

  • The injected X flows downstream by the X-flow rules (6.3): muxes propagate on unknown selects, flops capture X, controlling values absorb it.
  • One injected X can fan out widely — a flood from a single violation.

Managing X-injection (without masking real violations):

  • Trace the flood to its source — the single injecting violation (don't count symptoms).
  • Fix the injecting violation (real → design, 8.2/8.3; artifact → run, 8.4) — clears the whole flood.
  • Selective control exists (per-instance notifier/check control, +notimingchecks) but is a blunt tool: disabling checks hides real violations (8.4). Use it narrowly and justified, never wholesale.

Framing (accuracy):

  • The notifier X is a modelling flag (Chapter 6) — investigate the source.
  • STA is the arbiter of real timing; managing X-injection changes simulation noise, not the underlying timing (2.5/0.3).
Timing check fires, toggles notifier, UDP injects X, which propagates downstream flooding the designspreadsback-traceTiming check fires$setup/$hold violation(2.5)Notifier togglesreg is a UDP inputX injected on outputUDP drives cell output X(X-injection)X propagates (Ch6)muxes/flops/non-controlling→ floodTrace flood → sourceone injecting violation,not many bugsFix the injectingviolationreal → design / artifact →run (8.2-8.4)12
Figure 1 — X-injection and propagation (representative). A timing check ($setup/$hold/...) fires on a violation and TOGGLES the notifier reg; because the notifier is a UDP input, the cell output is driven to X (X-INJECTION, 2.5). That injected X then PROPAGATES downstream by the X-flow rules (Ch6) -- through muxes, flops, and non-controlling gates -- so one violation can flood the design. Manage by tracing the flood to the single injecting violation and fixing IT (real -> design, artifact -> run); disabling checks wholesale would hide real violations (8.4).

4. Mental Model — one leak floods the whole floor

A timing violation is a single pipe leak (the injected X); propagation is the water spreading across the floor.

  • One leak (notifier X) can soak an entire room (downstream fan-out) — it looks like many problems.
  • You don't mop every puddle as a separate issue — you find the one leak and fix it (the injecting violation).
  • Turning off the water main (disabling all checks) stops the flood and hides the next real leak (8.4) — too blunt.

Trace the water back to the one leak, fix that, and the floor dries.

5. Working Example — one violation, a propagating flood

The injection and its spread (representative):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// X-injection at the source flop — REPRESENTATIVE (2.5)
$hold (posedge CK, D, 0, notify);     // hold violation -> notifier toggles -> q = X (injected)
// q feeds a fan-out cone:
assign a = q & sel;                   // controlling? if sel=0, X absorbed; if sel=1, X propagates (6.3)
assign b = q ^ c;                     // XOR: no controlling value -> X propagates (6.3)
assign out = {a, b, ...};             // one q=X floods multiple outputs
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# The flood, traced back (tool-neutral):
#   symptom: out[7:0] mostly X  (looks like many bugs)
#   trace back via X-flow (6.3): out <- a,b <- q  (single X source)
#   root: ONE $hold violation injecting X on q
#   fix:  fix that hold race (8.3) -> whole flood clears  (do NOT disable checks wholesale, 8.4)

Practical context (representative, tool-neutral):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# Manage X-injection (tool-neutral):
#   1) a flood of X? trace back via X-flow (6.3) to the ONE injecting violation
#   2) classify it (8.4): real (design fix, 8.2/8.3) or artifact (run fix)
#   3) fix the SOURCE -> the whole flood clears
#   4) selective check/notifier control is a BLUNT tool -- narrow + justified only; never wholesale
#   5) STA remains the arbiter of real timing (0.3)

One injected X flooding downstream, as a real waveform:

One hold violation injects X on a flop; the X propagates and floods downstream outputs

8 cycles
A hold violation drives a flop to X, and that X propagates to multiple downstream signalsone X on q → floods a, bone X on q → floods a,…CKq (X injected)XXXXa = q & selXXXXb = q ^ cXXXXt0t1t2t3t4t5t6t7
Representative. A $hold violation injects X on q (notifier). q feeds a and b, which feed out — so one injected X floods multiple downstream signals (they all go X where q propagates). It looks like many bugs but is ONE: fixing the single hold race on q clears the whole flood. Disabling checks would hide it (8.4).

6. Debugging Session — a screenful of X from one violation

1

A single timing violation injects X that propagates and floods dozens of downstream signals, looking like many bugs; tracing the flood back through the X-flow rules reaches the one injecting violation, and fixing it clears the whole flood without disabling checks

ONE INJECTED X FLOODS DOWNSTREAM — TRACE TO THE SOURCE
Symptom

One timing check fires, and dozens of downstream signals go X. It looks like many separate failures.

Root Cause

One X-injection, propagated. The timing violation fired a check, which toggled the notifier, which drove the cell output to X (2.5) — X-injection. That single X then propagated through the downstream fan-out by the X-flow rules (6.3): non-controlling gates (XOR) and unknown-select muxes pass it, flops capture it — so one injected X floods everything the flop feeds. The dozens of Xs are symptoms of a single violation, not dozens of bugs. Counting them separately (or, worse, disabling checks to silence them, 8.4) misreads a propagation flood as many faults.

Fix

Trace the flood back through the X-flow (6.3) to the single injecting violation, then classify and fix that source (8.4): if real (long path / hold race / skew), fix the design (8.2/8.3); if artifact (edge-aligned stimulus, reset-active check, wrong corner), fix the run. Fixing the one source clears the whole flood. Only if the modelling X-pessimism is genuinely excessive should you use narrow, justified check/notifier control — never disable checks wholesale (it hides real violations, 8.4). The lesson: a timing violation injects X via the notifier, and that X propagates like any unknown (Chapter 6) — so one violation can flood the design; trace the flood back to the single injecting violation and fix it, rather than counting symptoms or disabling checks. (The notifier X is a modelling flag; STA is the arbiter of real timing, 2.5/0.3.)

7. Common Mistakes

  • Counting propagated Xs as separate bugs. One injection can flood many signals.
  • Disabling checks to silence the flood. Hides the real injecting violation (8.4).
  • Not tracing the X back through the X-flow rules (6.3) to the source.
  • Fixing symptoms downstream instead of the injecting violation.
  • Forgetting the X is a modelling flag. Investigate the source (Chapter 6).

8. Industry Best Practices

  • Trace an X flood back to the single injecting violation (6.3).
  • Fix the source (real → design, artifact → run, 8.2–8.4) — the flood clears.
  • Use check/notifier control narrowly and justified — never wholesale (8.4).
  • Treat the notifier X as a flag — investigate, don't waive or mask.
  • Keep STA as the arbiter of real timing.

Senior Engineer Thinking

  • Beginner: "Dozens of Xs — dozens of timing bugs."
  • Senior: "Or one violation injecting X that propagated. Let me trace the flood back through the X-flow to the source flop — fixing that one violation should clear all of it. I won't disable checks."

The senior reads an X flood as one injected X propagating and fixes the source.

Silicon Impact

Understanding X-injection prevents two failures. First, misattribution: a screenful of X from one violation looks like a catastrophe, and teams may over-react (or, worse, disable checks to quiet it, 8.4 — masking the real source that then ships, 0.3). Second, inefficiency: chasing dozens of propagated symptoms instead of the one source wastes days. Recognising that a timing violation becomes an X-propagation problem — trace the flood back to the single injecting violation, fix it — turns an overwhelming X flood into a single, targeted fix. And keeping checks on (managing injection narrowly, deferring to STA) ensures the next real violation still fires. This is the bridge that makes Ch6 and Ch8 one skill.

Engineering Checklist

  • Traced the X flood back to the single injecting violation (6.3).
  • Classified the source (real vs artifact, 8.4).
  • Fixed the source (design or run) — confirmed the flood cleared.
  • Used check/notifier control narrowly (never wholesale).
  • Kept the notifier X as a flag; deferred real-timing signoff to STA.

Try Yourself

  1. Create a $hold violation that injects X on a flop feeding a fan-out cone (an XOR and an unknown-select mux).
  2. Observe: the single X floods multiple downstream signals (X-injection + propagation, 6.3).
  3. Change: fix the one hold race (add delay, 8.3).
  4. Expect: the entire flood clears from one fix — proving it was one injected X, not many bugs. Confirm you never had to disable a check.

Any free Verilog simulator with SDF timing checks reproduces X-injection and its propagation. No paid tool required.

Interview Perspective

  • Weak: "A timing violation just prints a message."
  • Good: "A timing check fires, toggles the notifier, and injects X on the output, which then propagates downstream."
  • Senior: "A timing violation becomes an X-propagation problem: the notifier injects X, and it floods the fan-out by the X-flow rules. So a screenful of X is often one violation — I trace it back to the single injecting source and fix that (real → design, artifact → run), never disabling checks wholesale (which would mask real ones). The X is a flag; STA is the arbiter."

9. Interview / Review Questions

10. Key Takeaways

  • A timing check that fires toggles a notifier, and because the notifier is a UDP input, the cell output is driven to XX-injection (2.5).
  • The injected X then propagates downstream by the X-flow rules (Chapter 6) — so one timing violation can flood the design with X.
  • A screenful of X is often one injecting violation, not many bugs — trace the flood back through the X-flow (6.3) to the single source.
  • Fix the source (real → design, 8.2/8.3; artifact → run, 8.4) and the whole flood clears; use check/notifier control narrowlynever disable checks wholesale (masks real violations, 8.4).
  • The notifier X is a modelling flag (Chapter 6); STA is the arbiter of real timing (2.5/0.3). Next: 8.6 — a clock-gated block violation.

Quick Revision

Timing violation → X-propagation: check fires → notifier toggles → UDP injects X (X-injection, 2.5) → X propagates (Ch6 rules). One violation can flood the design — a screenful of X is often ONE source. Trace the flood back (6.3) to the single injecting violation; fix IT (real → design, artifact → run, 8.4). Manage injection narrowly — never disable checks wholesale (masks real ones). STA is the arbiter. Next: 8.6 — a clock-gated block violation.