Verilog · Chapter 18.4 · Timing Checks
$width, $period, $nochange & $skew in Verilog — Waveform-Integrity Checks
Some timing checks judge a signal against its own shape instead of comparing data to a clock. The width check confirms a pulse is wide enough, so a runt clock or reset pulse is caught. The period check confirms a clock is not running faster than its cells allow. The nochange check confirms a signal stays stable across a window, which latches and gated paths require. The skew check confirms two related signals arrive close enough together. Three of these fire when something is too small, while skew is the odd one out and fires when a separation is too large. This page groups all four and explains what each one guards, the glitch-rejection threshold, and the comparison direction that trips people up.
Intermediate13 min readVerilogTiming Checks$width$period$skew
Chapter 18 · Section 18.4 · Timing Checks
1. The Engineering Problem
A gated clock develops a sliver of a pulse — a few hundred picoseconds wide — and a downstream flop behaves erratically. There is no data setup or hold violation; the data is fine. The problem is the clock's own shape: the pulse is too narrow for the flop to act on reliably.
// Some timing requirements are about a SIGNAL'S OWN WAVEFORM:
// - is the clock's high phase wide enough? → $width
// - is the clock period long enough? → $period
// - did a control stay stable across a gate window? → $nochange
// - did two related clocks arrive close enough? → $skew
//
// None of these compares data to a clock. They judge a signal's shape,
// or the separation between two signals.Setup/hold (18.1–18.2) and recovery/removal (18.3) all measure one signal against the clock. But a real cell also requires its clock to have a minimum high time, a minimum period, and sometimes that a control input not change during a sensitive window. These are waveform-integrity checks.
$width,$period,$nochange, and$skewjudge a signal's own waveform — or the separation between two signals — rather than data against a clock. Three of them fire when something is too small;$skewfires when a separation is too large.
2. Mental Model — Judge the Shape, Not the Data-to-Clock Gap
3. $width — Minimum Pulse Width
$width checks that a pulse — from one edge to the next opposite edge of the same signal — is at least limit wide.
// $width(reference_event, limit, [threshold], [notifier]);
$width(posedge clk, 2.0, 0.1, notifier);
// ^edge ^min ^glitch-reject ^notifier- Measures from the reference edge (
posedge clk) to the next opposite edge (the followingnegedge) — i.e., the high pulse width. Anegedgereference would check the low pulse. - Fires when that pulse is narrower than
limit— a runt pulse the cell cannot act on reliably. - The
thresholdargument is glitch rejection: pulses narrower thanthresholdare treated as glitches and not reported as width violations (they are assumed filtered, not real edges). So with2.0, 0.1, a pulse between 0.1 and 2.0 is a violation; below 0.1 it is ignored as a glitch. This separates "a real but too-narrow pulse" from "noise." - Typical use: minimum clock high/low time, minimum asynchronous reset pulse width.
4. $period — Minimum Clock Period
$period checks that the time from one edge to the next same-direction edge is at least limit.
// $period(reference_event, limit, [notifier]);
$period(posedge clk, 5.0, notifier);
// ^edge ^min period ^notifier- Measures from the reference edge to the next edge of the same direction (
posedgetoposedge) — one full cycle. - Fires when the period is shorter than
limit— the clock is running faster than the cell's characterized maximum frequency. - Where
$widthguards the pulse,$periodguards the cycle. A clock can have a legal high time and still violate the period if its low time is too short.
5. $nochange — Stability Across a Window
$nochange checks that a signal does not change during a window defined relative to a reference event.
// $nochange(reference_event, data_event, start_offset, end_offset, [notifier]);
$nochange(posedge clk, d, 0, 0, notifier);
// ^reference ^data ^start ^end ^notifier- The
data_event(d) must remain stable in the window fromreference + start_offsettoreference + end_offset. - Fires when
dchanges inside that window. - Its natural home is level-sensitive logic: a transparent latch requires its data to be stable while the latch is open; a gated path requires its control to hold steady across the gating window.
$nochangeexpresses "this must not move during this interval," which setup/hold (edge-relative) cannot.
6. $skew — Maximum Separation (the Direction Flip)
$skew checks that two related signals arrive within limit of each other — it is a maximum check, the opposite direction from everything else in the chapter.
// $skew(reference_event, data_event, limit, [notifier]);
$skew(posedge clk1, posedge clk2, 0.5, notifier);
// ^reference ^data ^max ^notifier- Fires when the gap between the two events is greater than
limit— the signals drifted too far apart. - Compare the others:
$setup/$hold/$width/$periodfire when an interval is less than a limit (too small);$skewfires when it is more than the limit (too large). This reversal of the comparison is the single most common confusion with$skew. - Typical use: bounding the skew between two clocks (or two related control signals) that downstream logic assumes arrive together. (Variants
$timeskewand$fullskewrefine when the check evaluates and which signal leads; they share$skew's "too far apart" semantics.)
Visual A — what each check guards, and which direction it fires
Four waveform-integrity checks — three minimums and one maximum
data flow7. The "Fires When" Summary
| Check | Measures | Fires when | Direction |
|---|---|---|---|
$width | one edge → next opposite edge (a pulse) | pulse shorter than limit | minimum |
$period | one edge → next same edge (a cycle) | period shorter than limit | minimum |
$nochange | a signal across a reference-relative window | signal changes in the window | stability |
$skew | gap between two signals | gap larger than limit | maximum |
Reading the table: the first three guard against something being too small or unstable; $skew alone guards against something being too spread out. Keep the direction straight and these four are simple.
8. Where They Live, and Where the Limits Come From
Like every timing check, these live in the specify block (17.4), run in gate-level simulation on a delay-annotated netlist, accept a notifier (18.5) that forces affected outputs to X, and get their limits from the cell library via SDF. The specify block declares the check; SDF supplies the minimum width, minimum period, and skew numbers characterized for the real silicon.
9. Common Mistakes
- Treating
$skewlike the others.$skewfires when the gap is too large;$setup/$hold/$width/$periodfire when it is too small. Inverting that misreads every skew result (§6, §7). - Confusing the
$widththreshold with the limit. Thelimitis the minimum legal width; thethresholdis glitch rejection (pulses below it are ignored, not flagged). They are different arguments with different jobs (§3). - Using
$widthwhere$periodis meant (or vice versa).$widthguards a single pulse (edge to opposite edge);$periodguards a full cycle (edge to same edge). A clock can pass one and fail the other (§3, §4). - Reaching for setup/hold to express a stability window. A "must not change during this interval" requirement on level-sensitive logic is
$nochange, not an edge-relative setup/hold (§5). - Expecting them to synthesise. All are simulation-only (Chapter 17 overview).
10. Debugging Lab
The runt clock pulse that $width caught
11. Interview Q&A
12. Exercises
Exercise 1 — Which check?
Choose the check for each: (a) the clock high time must be at least 1.5 ns; (b) the clock must not run faster than 500 MHz; (c) two clocks must arrive within 0.3 ns of each other; (d) a latch's data must not change while it is transparent.
Exercise 2 — Direction of fire
For each, say whether the check fires when the interval is too small or too large: $width, $period, $skew.
Exercise 3 — Limit vs threshold
In $width(posedge clk, 2.0, 0.1, notifier), what happens to a 0.05 ns pulse? A 1.0 ns pulse? A 3.0 ns pulse?
Exercise 4 — Explain the runt pulse
A combinational gated clock gclk = clk & en fires a $width violation. Explain why, and give the design fix.
13. Summary
$width, $period, $nochange, and $skew are the waveform-integrity checks — they judge a signal's own shape, or two signals' separation, not data against a clock:
$width— minimum pulse width (edge to opposite edge); fires when too narrow; takes a glitch-rejection threshold.$period— minimum clock period (edge to same edge); fires when too short.$nochange— stability across a reference-relative window; fires when the signal changes in it (level-sensitive logic).$skew— maximum separation between two signals; fires when the gap is too large — the direction flip versus all the others.- Where — the
specifyblock, in gate-level simulation; limits from SDF; notifier forcesX.
The crux to keep: three of these fire when something is too small or unstable; $skew fires when a separation is too large — same family, opposite comparison.
The final sub-topic of the chapter explains what every fired check actually does: Chapter 18.5 Violation Behaviour — Notifiers & X-Propagation — how a notifier forces an output to X, how that X spreads, and how to debug a netlist-wide X flood back to one early violation.
Related Tutorials
- $recovery, $removal & $recrem — Chapter 18.3; the asynchronous control checks, the rung before these.
- $setup, $hold & $setuphold — Chapter 18.2; the synchronous data-vs-clock checks.
- Timing Checks — Chapter 18 overview; the full check family.
- Violation Behaviour — Notifiers & X-Propagation — Chapter 18.5; what a fired check does, and how to debug it.