Skip to content

GLS · Chapter 2 · Netlists & Standard-Cell Libraries

Sequential Cell Models: Notifiers & Timing Checks

A sequential cell's model does more than capture data on a clock edge; it also watches its own timing, and that mechanism explains a whole class of gate-level unknown X. Inside a flip-flop's model live timing checks for setup, hold, recovery, removal, and pulse width, plus a small notifier register. When a check fires, because the stimulus changed a data input inside the setup or hold window, it toggles the notifier, and because the notifier feeds the cell's primitive, that toggle drives the flop output to X. So a timing violation has a visible, dynamic effect. The crucial scope point is that this is dynamic and stimulus-limited, firing only when the applied stimulus happens to violate a window, whereas static timing analysis is exhaustive. This lesson dissects a representative model and clarifies that these checks do not replace STA.

Foundation13 min readGLSTiming ChecksNotifierSetup/HoldSequential Cells

Chapter 2 · Section 2.5 · Netlists & Standard-Cell Libraries

Project thread — every flop in the counter (2.6) carries these $setup/$hold checks and a notifier. A check firing on the counter's data path is one way its output can go X — distinct from the reset-gap X of 2.6; knowing the difference is the debugging skill.

1. Why Should I Learn This?

A flip-flop output going X mid-simulation, after reset, with data flowing — is one of the more alarming gate-level sights, and the notifier/timing-check mechanism explains it exactly. A $setup or $hold check fired (the stimulus changed data inside the window), toggled the notifier, and the notifier — a UDP input — drove the output to X. Recognising notifier-X as a dynamic timing-check firing (not a random glitch) is what turns a scary X into a specific, diagnosable event.

This lesson completes the cell model — function (2.3), timing arcs (2.4), and now timing checks — and it directly precedes 2.6, where the counter's flops carry these very checks. It also stakes out an accuracy boundary: gate-level timing checks are dynamic and stimulus-limited, not a substitute for STA (0.3).

2. Real Silicon Story — the flop X that was a timing check, mistaken for STA coverage

A gate-level run, SDF-annotated (Chapter 4), shows a flop output snapping to X deep into the test. The engineer, seeing timing-driven X, concludes that GLS is now covering timing and treats the run as a timing signoff — reasoning 'if there were a setup/hold problem, GLS would show it, and here it's showing one, so GLS is checking timing thoroughly.'

Two things are conflated. First, the X itself: it came from a timing check — a $setup or $hold inside the flop's specify block fired because the stimulus changed the data input inside the timing window, which toggled the flop's notifier, and because the notifier is an input to the cell's UDP, the toggle drove the output to X. That part is correct and useful — a dynamic signal that this edge saw a timing violation. But the inference is wrong: this mechanism is stimulus-limited. A timing check fires only if the applied stimulus happens to violate it on that edge; paths the stimulus never exercises, or violations the stimulus never triggers, produce no notifier-X at all. STA, by contrast, checks every path's setup/hold statically and exhaustively. So a notifier-X proves a violation occurred under this stimulus — it does not prove the absence of violations elsewhere, and GLS timing checks are not a timing signoff. The post-mortem lesson: a sequential cell's specify block carries timing checks ($setup/$hold/...) and a notifier; a firing check toggles the notifier, which — being a UDP input — drives the flop output to X, giving a timing violation a dynamic effect in GLS; but this is stimulus-limited, so notifier-X confirms a violation under this stimulus and does not replace STA's static, exhaustive timing check.

3. Concept — timing checks, the notifier, and the X they produce

A sequential cell's model (2.3) adds timing self-monitoring to its specify block:

  • Timing checks (system tasks in specify):
    • $setup (D, posedge CK, limit, notifier) — data D must be stable limit before the clock edge.
    • $hold (posedge CK, D, limit, notifier) — data stable limit after the edge.
    • $recovery / $removal — asynchronous set/reset must be released a safe distance from the clock edge.
    • $width / $period — minimum pulse width / clock period.
  • The notifier — a reg passed as the last argument to each check and wired as an input to the cell's UDP (2.3).
  • A firing check toggles the notifier. When the stimulus violates a check's window, the check toggles the notifier reg.
  • The notifier toggle drives the output to X. Because the notifier is a UDP input, its toggle makes the state table emit X — so a timing violation produces a dynamic X on the flop output.
  • Dynamic + stimulus-limited. A check fires only if the applied stimulus violates it on that edge — GLS does not explore timing exhaustively. STA is static + exhaustive. GLS timing checks complement, do not replace, STA (0.3).
  • ASIC context: the check limits come from the .lib/SDF for the signoff corner (2.2/2.4).

Here is the setup/hold window a check guards:

Setup and hold window around a clock edge; data changing inside the window fires a timing check that toggles the notifier and drives the flop output to XSetup/hold window — a violation fires the check, toggles the notifier, drives Q to XSetup/hold window — a violation fires the check, toggles the notifier, drives Q to Xclkdsetupsetupholdholdclock edgeclock edge⚠ setup time violation⚠ setup time violation
Figure 1 — a flip-flop's setup/hold window and the timing check that guards it (representative). Data D must be stable for the SETUP time BEFORE the clock edge and the HOLD time AFTER it. If the stimulus changes D INSIDE this window, the cell's $setup or $hold check FIRES, toggling the flop's NOTIFIER reg; because the notifier is an input to the cell's UDP (2.3), the toggle drives the flop output Q to X. This is a DYNAMIC effect — it happens only on the specific edge the stimulus violates. STA, by contrast, checks this window on EVERY path statically and exhaustively; GLS timing checks are stimulus-limited and do not replace STA.

4. Mental Model — the notifier is the flop's own alarm; pulling it forces X

5. Working Example — a representative sequential cell with checks and a notifier

Here is a representative rising-edge DFF model tying together the UDP (2.3), the arc (2.4), and the timing checks + notifier of this lesson.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Rising-edge DFF cell model with timing checks + notifier — REPRESENTATIVE (shape only)
module DFFRX1 (Q, D, CK, RN);
  output Q; input D, CK, RN;
  reg notify;                                  // the NOTIFIER reg
  // function: UDP takes the notifier as an input (a toggle -> Q goes X)
  DFF_udp_n u0 (Q, D, CK, RN, notify);         // sequential UDP (2.3), notifier wired in
  specify
    (CK => Q) = 0;                             // clk-to-Q ARC (placeholder -> SDF, 2.4)
    // TIMING CHECKS — last arg is the notifier; a violation toggles it -> Q goes X
    $setup (D, posedge CK, 0, notify);         // D stable BEFORE CK
    $hold  (posedge CK, D, 0, notify);         // D stable AFTER CK
    $recovery (posedge RN, posedge CK, 0, notify);  // async reset release vs CK
    $width (posedge CK, 0, 0, notify);         // min pulse width
  endspecify
endmodule

The notify reg is both the last argument of every check and an input to the UDP. So when a check fires:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# NOTIFIER MECHANISM (representative):
stimulus changes D inside CK's setup window
   -> $setup check FIRES
   -> toggles 'notify'
   -> 'notify' is a UDP input, so the toggle makes the state table emit X
   -> Q goes X on THIS edge  (dynamic effect of the timing violation)
# Fires ONLY if the stimulus violates the window on this edge. STA checks EVERY path, always.

And a representative simulator log of a firing check:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# Simulator log — REPRESENTATIVE (format varies by tool)
"$setup violation on DFFRX1 u_cnt.q_reg[2]: D changed 0.03ns before posedge CK"
#   -> notifier toggled -> u_cnt.q_reg[2].Q = X   (this edge only)
# Absence of such a message != timing proven. That is STA's job (static, exhaustive).

Same flop the counter (2.6) uses — a check firing there is one way the counter's output goes X.

6. Debugging Session — a flop X from a firing timing check (real violation or artifact?)

1

A flip-flop output goes X mid-simulation from a firing $setup/$hold check toggling the notifier — recognise it as a dynamic timing-check firing (notifier-X), then triage whether it is a real setup/hold violation or an artifact such as checks active during reset

NOTIFIER-X = A TIMING CHECK FIRED (DYNAMIC, STIMULUS-LIMITED)
Symptom

An SDF-annotated (Chapter 4) gate-level run shows a flip-flop output going X mid-simulation — after reset, with data flowing — accompanied by a $setup or $hold violation message in the log. The engineer is unsure whether this is a real timing bug or a simulation artifact, and whether the run now 'covers timing.'

Root Cause

The X is a notifier-X: a timing check fired. Inside the flop's specify block, a $setup/$hold check watched the data pin against the clock edge; the stimulus changed the data input inside the timing window, so the check fired and toggled the flop's notifier reg. Because the notifier is an input to the cell's UDP (2.3), toggling it made the state table emit X — the flop output went unknown on that edge. This is the dynamic effect of a timing violation in GLS, and it is correct behaviour of the model. Whether the underlying violation is real or an artifact is the triage question: it may be a genuine setup/hold problem (a real path too slow/fast under this stimulus), or an artifact — e.g. timing checks active during reset (before the design is in a defined state), around an asynchronous domain crossing (where the check is not physically meaningful), or from mis-scaled check limits / wrong-corner SDF. Deep triage of these belongs to Chapter 8; the foundational recognition here is: an X appearing on a flop with a $setup/$hold message is a timing-check firing driving a notifier-X — a dynamic, stimulus-specific event — not a random glitch. And critically, neither interpretation makes the run a timing signoff: the check fired because this stimulus violated it on this edge; it says nothing about paths or edges the stimulus did not exercise.

Fix

First, identify the X as a notifier-X from a firing timing check (the accompanying $setup/$hold message is the tell). Then triage: if it is a real violation, it is a timing bug to fix at the source (path timing, or the stimulus/constraint); if it is an artifact (checks active during reset, async crossing, wrong-corner limits), address the check condition — deep methods in Chapter 8. Throughout, keep the scope honest: timing checks + notifiers make a violation visible dynamically, but they are stimulus-limited — a check fires only if the applied stimulus violates it on that edge, so notifier-X confirms a violation under this stimulus and its absence proves nothing. Timing signoff — every path, statically, exhaustively — is STA, not GLS (0.3). So use notifier-X as a dynamic flag that complements STA: GLS confirms the design functions under real stimulus and surfaces violations your test happens to exercise; STA proves the timing across all paths. (And ensure the check limits/SDF are the right corner, 2.2/2.4 — an ASIC-signoff consistency point.)

7. Common Mistakes

  • Treating notifier-X as a random glitch. A $setup/$hold message means a timing check fired and toggled the notifier → a specific, diagnosable event.
  • Reading notifier-X as 'GLS is doing timing signoff.' It is stimulus-limited — it confirms a violation under this stimulus, not the absence of others (0.3).
  • Assuming no notifier-X means timing is proven. Absence proves nothing — STA (static, exhaustive) proves timing.
  • Leaving timing checks active during reset / across async crossings. Common artifact sources of notifier-X (deep triage, Chapter 8).
  • Using wrong-corner check limits / SDF. Match the corner STA signed off (ASIC context, 2.2/2.4).

8. Industry Best Practices

  • Recognise notifier-X as a firing timing check. The $setup/$hold message identifies it — a dynamic, stimulus-specific event, not noise.
  • Triage real violation vs artifact. Real path problem to fix at source, or artifact (reset-active checks, async crossing, wrong corner) — deep methods in Chapter 8.
  • Keep the scope honest. Notifier-X is dynamic + stimulus-limited; it confirms a violation under this stimulus and does not replace STA's static, exhaustive check (0.3).
  • Match check limits and SDF to the signoff corner. ASIC-consistent timing (2.2/2.4).
  • Use GLS and STA as complements. STA proves timing across all paths; GLS timing checks confirm the design functions under real stimulus and flag exercised violations.

Senior Engineer Thinking

  • Beginner: "A flop went X mid-sim — must be a random glitch, or GLS is proving my timing."
  • Senior: "That X with a $setup message is a notifier-X — a timing check fired on this edge under this stimulus. Is it a real violation or an artifact (reset-active check? async crossing? wrong corner)? Either way, it's not timing signoff — that's STA."

The senior reads notifier-X as a dynamic timing-check firing, triages real-vs-artifact, and never mistakes it for STA's exhaustive proof.

Silicon Impact

The notifier mechanism is genuinely valuable: it makes a timing violation functionally visible — an X that propagates and can be caught, surfacing timing-dependent functional failures (glitch capture, reset-release races) that pure margin arithmetic might not flag as functional bugs. But mis-scoping it is costly both ways. Treat notifier-X's absence as timing proof, and you skip or under-weight STA — letting a real violation on an unexercised path reach silicon as an intermittent, corner-sensitive failure. Treat every notifier-X as a real bug without triage, and you burn effort on artifacts (reset-active checks, async crossings, wrong-corner limits) that are not real hardware problems. The discipline: use notifier-X as a dynamic complement — it flags violations your stimulus exercises and confirms functional behaviour under real delays — while relying on STA for the exhaustive timing signoff. That division is what keeps timing bugs off the tape-out without chasing ghosts.

Engineering Checklist

  • Identified each mid-sim flop X as a notifier-X (firing timing check) via its $setup/$hold message.
  • Triaged real violation vs artifact (reset-active checks, async crossing, wrong-corner limits — deep methods Ch8).
  • Kept scope honest: notifier-X is dynamic + stimulus-limited, not a timing signoff — that is STA (0.3).
  • Matched timing-check limits / SDF to the signoff corner (ASIC context, 2.2/2.4).
  • Used GLS timing checks and STA as complements, not substitutes.

Try Yourself

  1. Instantiate the representative DFFRX1 model above and clock it normally — Q follows D cleanly (no check fires).
  2. Observe: now drive D to change just before a posedge CK (inside the setup window); the $setup check fires, toggles notify, and Q goes X on that edge.
  3. Change: move the D transition well clear of the clock edge and re-run.
  4. Expect: no violation, no notifier-XQ is clean. Then note: this only tested the edges you drove; STA would check every edge on every path. Prove the scope to yourself.

Any Verilog simulator supports specify timing checks and notifiers; no paid tool is required. Real cell timing-check limits come from the .lib/SDF (vendor/PDK), but the notifier→X mechanism is identical to the representative model.

Interview Perspective

  • Weak: "A setup violation just prints a warning in gate-level sim."
  • Good: "A $setup/$hold check fires on a violation and toggles the flop's notifier, which drives the output to X."
  • Senior: "The notifier is a UDP input, so a firing timing check drives the flop output to X — a dynamic effect. But it's stimulus-limited: the check fires only if my stimulus violates it on that edge. So notifier-X confirms a violation under this stimulus; it doesn't prove timing and doesn't replace STA, which is static and exhaustive. I recognise notifier-X, triage real-vs-artifact, and keep GLS and STA as complements."

9. Interview / Review Questions

10. Key Takeaways

  • A sequential cell's specify block carries timing checks$setup, $hold, $recovery, $removal, $width — plus a notifier reg that is both each check's last argument and an input to the cell's UDP (2.3).
  • A firing check toggles the notifier, and because the notifier is a UDP input, the toggle drives the flop output to X — so a timing violation has a dynamic, visible effect in GLS (notifier-X).
  • Notifier-X is dynamic + stimulus-limited: a check fires only if the applied stimulus violates it on that edge — it confirms a violation under this stimulus and its absence proves nothing.
  • GLS timing checks do not replace STA. STA is static + exhaustive (every path); GLS is dynamic + stimulus-bounded — complementary, not interchangeable (0.3).
  • Recognise notifier-X (via its $setup/$hold message), then triage real violation vs artifact (reset-active checks, async crossing, wrong-corner limits — deep methods in Chapter 8); match check limits/SDF to the signoff corner (2.2/2.4). Next: 2.6 — reading a counter netlist, where these flops carry exactly these checks.

Quick Revision

Sequential cell = function + arcs + timing checks + notifier. $setup/$hold/$recovery/$removal/$width live in specify; each takes a notifier reg that is also a UDP input. A firing check toggles the notifier → flop output goes X (notifier-X) — a dynamic effect. It is stimulus-limited: fires only if the stimulus violates it on that edge; absence proves nothing. STA (static, exhaustive) is timing signoff — GLS checks complement it (0.3). Recognise notifier-X, triage real-vs-artifact (Ch8). Next: 2.6 — reading a counter netlist.