Skip to content

GLS · Chapter 7 · Reset & Initialization Debug

Working Example: Debugging a Stuck Reset

This capstone debugs a stuck reset on the counter using the whole chapter as a differential diagnosis. A counter that never counts can be stuck for several reasons: reset held asserted so the counter freezes at zero, reset never reaching some flops so those bits stay unknown, reset released too near a clock edge and injecting unknowns at deassertion, or a sync-versus-async style or polarity mismatch. The lesson walks that diagnosis, ruling causes in and out from the waveform, and learns to tell frozen-at-zero apart from stuck-at-unknown, since they point to different root causes. It lands on the primary cause, a reset held asserted by a polarity or logic error, and fixes it at the source. It ties together reset behaviour, uninitialised flops, release timing, and sequencing to close the reset chapter.

Foundation13 min readGLSResetCounterDebuggingWorked Example

Chapter 7 · Section 7.5 · Reset & Initialization Debug

Project thread — the counter closes the reset chapter as it opened Chapters 2–4. A clean reset here is the foundation the mini-SoC's multi-domain reset (7.4) builds on. Chapter 8 takes timing violations (recovery/removal, setup/hold) as its whole subject.

1. Why Should I Learn This?

"The counter won't count" has several reset causes — and the differential diagnosis is the chapter as a procedure.

  • You rule causes in and out from the waveform (held / gap / recovery / style).
  • You practise distinguishing frozen-at-0 from stuck-at-X — different root causes.
  • You end with a source fix, having proven the cause, not guessed.

It integrates 7.1–7.4 on the counter and closes the reset chapter.

2. Real Silicon Story — the counter that never left zero

A counter in bring-up never countedcount sat at 0000 forever. The first guess was "the counter logic is broken."

The counter was fine. Reset was held asserted: a polarity error in the reset logic kept rst_n = 0 (asserted) permanently, so every clock edge re-cleared the flops to 0 — a frozen counter, not a broken one. Fixing the polarity so reset released after power-up let the counter count immediately.

Lesson: a counter frozen at 0 (not X) usually means reset is stuck asserted — the logic works, but reset never lets go. Distinguish frozen-at-0 (held reset) from stuck-at-X (coverage/recovery) — they have different causes.

3. Concept — the differential diagnosis

A counter that won't count has distinguishable reset causes. Read the symptom first:

  • Frozen at 0000 (defined, all zeros) → reset held asserted (A): polarity/logic keeps rst_n = 0; every edge re-clears (7.1). The counter works; reset never releases.
  • Stuck at xxxx (or some bits X) → reset not reaching those flops:
    • Coverage gap (B): reset net never wired to a subtree (7.4/2.6) — X from t=0, never clears.
    • Recovery-window release (C): X appears at deassertion, with a $recovery/$removal message (7.3).
  • Clears late / wrongstyle/polarity mismatch (D): sync reset expected immediate, or reversed polarity (7.1).

The diagnostic tells:

  • Value0000 (held reset) vs xxxx (gap/recovery).
  • Timing — from t=0 (gap) vs at deassertion (recovery) vs never releases (held).
  • Log$recovery/$removal message points to release timing (C).

This example's primary cause: (A) reset held asserted — counter frozen at 0000 by a polarity/logic error.

Scope: GLS surfaces the stuck reset; the fix is at the source (reset logic). GLS stays dynamic — STA signs off reset timing (0.3).

Stuck-reset differential diagnosis: frozen at 0 is held reset; xxxx from t=0 is coverage gap; X at deassertion is recovery; late/wrong is style/polarityvalue: 0 vs Xtiming + logA. Frozen at 0000reset HELD asserted(polarity/logic) → 7.1[primary]B. xxxx from t=0coverage GAP — reset neverreaches flops → 7.4/2.6C. X at deassertionrecovery-window release (+$recovery msg) → 7.3D. Clears late/wrongsync/async style orpolarity mismatch → 7.112
Figure 1 — differential diagnosis of a stuck reset on the counter (representative). Read the symptom: FROZEN at 0000 -> reset HELD asserted (polarity/logic keeps rst_n=0; every edge re-clears) [primary here]. STUCK at xxxx from t=0 -> coverage GAP (reset never reaches those flops, 7.4/2.6). X at DEASSERTION + recovery message -> recovery-window release (7.3). Clears late/wrong -> sync/async style or polarity mismatch (7.1). Value + timing + log distinguish them; fix at the source.

4. Mental Model — read the symptom before reaching for a fix

A stuck reset is a diagnosis, and the symptom narrows the cause before you touch anything.

  • All zeros, forever → the doctor sees a patient held down (reset asserted) — free them (release reset).
  • Unknown (X), from the start → a limb never got the signal (coverage gap) — connect it.
  • X right at wake-up → woken too abruptly (recovery violation) — wake gently (synchronize).
  • Wakes on the wrong cue → wrong alarm type/polarity (style mismatch) — fix the alarm.

Same complaint ("won't count"), four diagnoses — read value, timing, and log first.

5. Working Example — the stuck-reset trace and fix

The counter with reset held asserted (the primary cause):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Counter reset logic — REPRESENTATIVE. BUG: polarity error holds reset asserted.
// rst_n is active-low; but the reset source drives it the wrong way:
assign rst_n = ~por_done;    // BUG: por_done=1 (done) -> rst_n=0 (ASSERTED) forever -> frozen at 0
// The counter flops re-clear every edge:
DFFRX1 u_q0 (.D(n0), .CK(clk), .RN(rst_n), .Q(count[0]));   // RN=0 always -> count stays 0000

The source fix (correct polarity so reset releases):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// FIX — correct polarity: release reset once power-on reset completes
assign rst_n = por_done;     // por_done=1 -> rst_n=1 (RELEASED) -> counter counts

The other causes, distinguished (representative):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# Same symptom "counter won't count", four causes (tool-neutral):
#   count = 0000 forever ............ (A) reset HELD asserted (polarity/logic) [THIS case]
#   count = xxxx from t=0 ........... (B) coverage GAP — reset net not reaching flops (7.4/2.6)
#   count = xxxx at reset RELEASE ... (C) recovery-window release + $recovery msg (7.3)
#   count clears late / on wrong cue  (D) sync/async style or polarity mismatch (7.1)

Practical context (representative, tool-neutral):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# Stuck-reset diagnosis flow (tool-neutral):
#   1) read count VALUE: 0000 (held reset) vs xxxx (gap/recovery)
#   2) read TIMING: from t=0 (gap) / at deassertion (recovery) / never releases (held)
#   3) read LOG: $recovery/$removal -> release timing (7.3)
#   4) fix at SOURCE: reset polarity/logic (A), reset routing (B), synchronizer (C), style (D)

The counter stuck at 0, then fixed, as a real waveform:

Stuck reset: counter frozen at 0000 (reset held asserted) → fixed (reset releases, counter counts)

9 cycles
Before the fix rst_n stays 0 and count stays 0000; after the fix rst_n releases and the counter countsbefore: rst_n stuck 0 → frozenbefore: rst_n stuck 0 …after: releases → countsafter: releases → coun…clkrst_n (before: held)count (before)000000000rst_n (after: releases)count (after)000123456t0t1t2t3t4t5t6t7t8
Representative. BEFORE: a polarity error holds rst_n = 0 (asserted), so count is frozen at 0000 — the counter works but reset never releases. AFTER: correct polarity releases rst_n after power-up, and count advances 0,1,2,3. The symptom value (0000, not xxxx) pointed straight to a held reset, not a coverage gap or recovery violation.

6. Debugging Session — the counter that won't count

1

A counter never counts and the logic is suspected, but a differential diagnosis on value (0000 vs xxxx), timing, and log shows reset is held asserted by a polarity error — the counter works; reset never releases — fixed at the source

FROZEN AT 0 = HELD RESET; xxxx = GAP/RECOVERY
Symptom

The counter never countscount sits at 0000. The counter logic is suspected.

Root Cause

Reset held asserted, diagnosed by the symptom value and timing. The counter is frozen at 0000 — a defined value, not xxxx — which rules out a coverage gap (B, would be X from t=0) and a recovery-window release (C, would be X at deassertion with a $recovery message). Frozen at zero means the flops are being re-cleared every edge: reset is stuck asserted. Tracing the reset logic finds a polarity error — the reset source drives rst_n = 0 (asserted) permanently — so RN = 0 on every counter flop holds count at 0. The counter logic is correct; reset simply never releases. This is cause (A), distinguished from the others precisely because the value is 0000, not xxxx.

Fix

Fix the reset source so reset releases after power-up (correct the polarity/logic so rst_n goes to 1 once reset should deassert). Re-run: count advances 0,1,2,3,…. Had the symptom been xxxx instead, the diagnosis would branch: from t=0coverage gap (route reset to the missing flops, 7.4/2.6); at deassertion + $recoveryrecovery-window release (add a reset synchronizer, 7.3); late/wrong cuesync/async style or polarity (7.1). The lesson: debug a stuck reset as a differential diagnosis — read value (0000 = held reset vs xxxx = gap/recovery), timing, and log to distinguish held-assertion, coverage gap, recovery-window release, and style/polarity — then fix at the source. (GLS surfaced the stuck reset; it stays dynamic — STA signs off reset timing, 0.3.)

7. Common Mistakes

  • Blaming the counter logic for a reset problem.
  • Confusing frozen-at-0 with stuck-at-X. Different causes (held reset vs gap/recovery).
  • Skipping the log. A $recovery/$removal message points to release timing (7.3).
  • Guessing a fix before reading value/timing/log. The symptom narrows the cause.
  • Assuming GLS proves reset timing. It surfaces issues; STA signs off (0.3).

8. Industry Best Practices

  • Read value + timing + log before diagnosing a stuck reset.
  • Distinguish 0000 (held) from xxxx (gap/recovery) — different root causes.
  • Fix at the source (polarity/logic, routing, synchronizer, style).
  • Verify reset release actually happens after power-up.
  • Use GLS to surface, STA to sign off reset timing.

Senior Engineer Thinking

  • Beginner: "The counter won't count — the increment logic must be broken."
  • Senior: "Is it 0000 or xxxx? 0000 means reset is held — the logic's fine, reset never released. Let me check the reset polarity. If it were xxxx, I'd look at coverage or recovery instead."

The senior reads the symptom value first and runs the differential diagnosis before touching the logic.

Silicon Impact

A stuck reset is a bring-up showstopper — a block frozen at 0 or stuck at X simply doesn't function, and in silicon it manifests as a dead or hung block at power-up. The value of the differential diagnosis is speed and accuracy: distinguishing held reset (polarity/logic — a one-line fix) from a coverage gap (routing) from a recovery-window release (synchronizer) from a style mismatch points straight to the right fix, instead of churning on the counter logic. GLS is where these surface cheaply, before tape-out. Mastering the diagnosis — value, timing, log — is what turns "the block is dead" into a targeted, source-level reset fix.

Engineering Checklist

  • Read the symptom value (0000 held vs xxxx gap/recovery).
  • Read the timing (t=0 / deassertion / never releases).
  • Read the log ($recovery/$removal → release timing, 7.3).
  • Fixed at the source (polarity/logic, routing, synchronizer, style).
  • Confirmed reset releases and the counter counts; deferred reset-timing signoff to STA.

Try Yourself

  1. Drive the counter with rst_n held at 0 (polarity error) — count is frozen at 0000.
  2. Observe: the value is 0000 (not xxxx) → reset held, logic fine.
  3. Change: correct the polarity so rst_n releases after power-up.
  4. Expect: the counter counts 0,1,2,3. Then create the other symptoms — disconnect one flop's reset (xxxx from t=0, gap) and release reset near a clock edge (X at deassertion, recovery) — and confirm each diagnosis.

Any free Verilog simulator reproduces all four stuck-reset causes. No paid tool required.

Interview Perspective

  • Weak: "The counter won't count, so I'd debug the increment logic."
  • Good: "I'd check reset first — a counter frozen at 0 is usually reset held asserted."
  • Senior: "I run a differential diagnosis on the symptom: 0000 means reset is held (polarity/logic); xxxx from t=0 means a coverage gap; X at deassertion with a $recovery message means a recovery-window release; a late/wrong clear means a style/polarity mismatch. Value, timing, and log point to the cause, and I fix at the source. GLS surfaces it; STA signs off reset timing."

9. Interview / Review Questions

10. Key Takeaways

  • Debug a stuck reset as a differential diagnosis using the chapter: read the symptom's value, timing, and log to distinguish the cause.
  • Frozen at 0000 (defined) → reset held asserted (polarity/logic keeps rst_n = 0; every edge re-clears) — the counter works, reset never releases (7.1). (This example's cause.)
  • Stuck at xxxx → reset not reaching those flops: coverage gap (X from t=0, 7.4/2.6) or recovery-window release (X at deassertion + $recovery message, 7.3).
  • Clears late/wrongsync/async style or polarity mismatch (7.1).
  • Fix at the source (polarity/logic, routing, synchronizer, style); GLS surfaces the stuck reset and stays dynamic — STA signs off reset timing (0.3). This closes Chapter 7; next, Chapter 8 takes timing-violation debug (recovery/removal, setup/hold).

Quick Revision

Stuck reset = differential diagnosis (value + timing + log). 0000 forever → reset HELD asserted (polarity/logic; counter fine) [this case]. xxxx from t=0 → coverage GAP (7.4/2.6). X at deassertion + $recovery → recovery-window release (synchronizer, 7.3). Late/wrong clear → style/polarity (7.1). Fix at the source. GLS surfaces it; STA signs off reset timing. Chapter 7 complete; next: Chapter 8 — timing-violation debug.