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)— dataDmust be stablelimitbefore the clock edge.$hold (posedge CK, D, limit, notifier)— data stablelimitafter 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
regpassed 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 emitX— so a timing violation produces a dynamicXon 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:
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.
// 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
endmoduleThe notify reg is both the last argument of every check and an input to the UDP. So when a check fires:
# 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:
# 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?)
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)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.'
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.
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-
Xas a random glitch. A$setup/$holdmessage means a timing check fired and toggled the notifier → a specific, diagnosable event. - Reading notifier-
Xas '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-
Xmeans 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-
Xas a firing timing check. The$setup/$holdmessage 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-
Xis 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
Xmid-sim — must be a random glitch, or GLS is proving my timing." - Senior: "That
Xwith a$setupmessage 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
Xas a notifier-X(firing timing check) via its$setup/$holdmessage. - Triaged real violation vs artifact (reset-active checks, async crossing, wrong-corner limits — deep methods Ch8).
- Kept scope honest: notifier-
Xis 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
- Instantiate the representative
DFFRX1model above and clock it normally —QfollowsDcleanly (no check fires). - Observe: now drive
Dto change just before aposedge CK(inside the setup window); the$setupcheck fires, togglesnotify, andQgoesXon that edge. - Change: move the
Dtransition well clear of the clock edge and re-run. - Expect: no violation, no notifier-
X—Qis 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/$holdcheck fires on a violation and toggles the flop's notifier, which drives the output toX." - 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-Xconfirms 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
specifyblock carries timing checks —$setup,$hold,$recovery,$removal,$width— plus a notifierregthat 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-
Xis 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/$holdmessage), 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/$widthlive inspecify; each takes a notifierregthat is also a UDP input. A firing check toggles the notifier → flop output goesX(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.