Skip to content

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.

not-every-timing-bug-is-data-vs-clock.v
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   // 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 $skew judge 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; $skew fires 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.v
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   // $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 following negedge) — i.e., the high pulse width. A negedge reference would check the low pulse.
  • Fires when that pulse is narrower than limit — a runt pulse the cell cannot act on reliably.
  • The threshold argument is glitch rejection: pulses narrower than threshold are treated as glitches and not reported as width violations (they are assumed filtered, not real edges). So with 2.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.v
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   // $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 (posedge to posedge) — one full cycle.
  • Fires when the period is shorter than limit — the clock is running faster than the cell's characterized maximum frequency.
  • Where $width guards the pulse, $period guards 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.v
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   // $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 from reference + start_offset to reference + end_offset.
  • Fires when d changes 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. $nochange expresses "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.v
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   // $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/$period fire when an interval is less than a limit (too small); $skew fires 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 $timeskew and $fullskew refine 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 flow
Four waveform-integrity checks — three minimums and one maximum$width — pulsefires if pulse TOO NARROW$period — cyclefires if period TOO SHORT$nochange —stable windowfires if signal CHANGES in window$skew —separationfires if gap TOO LARGE
$width, $period, and $nochange are minimum/stability checks — they fire when a pulse, period, or stable window is too small (or a forbidden change occurs). $skew is the odd one out: a maximum check that fires when two signals are too far apart. Same family, opposite comparison.

7. The "Fires When" Summary

CheckMeasuresFires whenDirection
$widthone edge → next opposite edge (a pulse)pulse shorter than limitminimum
$periodone edge → next same edge (a cycle)period shorter than limitminimum
$nochangea signal across a reference-relative windowsignal changes in the windowstability
$skewgap between two signalsgap larger than limitmaximum

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

  1. Treating $skew like the others. $skew fires when the gap is too large; $setup/$hold/$width/$period fire when it is too small. Inverting that misreads every skew result (§6, §7).
  2. Confusing the $width threshold with the limit. The limit is the minimum legal width; the threshold is glitch rejection (pulses below it are ignored, not flagged). They are different arguments with different jobs (§3).
  3. Using $width where $period is meant (or vice versa). $width guards a single pulse (edge to opposite edge); $period guards a full cycle (edge to same edge). A clock can pass one and fail the other (§3, §4).
  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).
  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.
  • $nochangestability across a reference-relative window; fires when the signal changes in it (level-sensitive logic).
  • $skewmaximum separation between two signals; fires when the gap is too large — the direction flip versus all the others.
  • Where — the specify block, in gate-level simulation; limits from SDF; notifier forces X.

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.