Skip to content

Verilog · Chapter 18 · Timing Checks

Timing Checks in Verilog — Chapter 18 Overview

Delay modelling made a simulation behave in time, so signals now arrive late. This chapter adds the other half of timing-aware simulation, the instruments that judge whether late is too late. A real flip-flop needs its data stable for a window around the clock edge, a setup time before it and a hold time after it, and if data changes inside that window the flop can go metastable. Plain RTL simulation has no delays, so it cannot even represent that window and is blind to the violation. Timing checks are the simulator instruments that live inside a specify block and detect when a signal arrives outside its required window, reporting the problem and usually forcing the affected value to an unknown so you can see it. This overview explains why they exist, surveys the family, previews what a violation does, and maps out the deeper lessons ahead.

Intermediate14 min readVerilogTiming ChecksSetupHoldGate-Level

Chapter 18 · Timing Checks (Overview)

1. The Engineering Problem

A flip-flop does not capture data the instant the clock ticks. It needs its data input to be stable for a window around the clock edge — for a setup time before the edge and a hold time after it. If the data changes inside that window, the flop may go metastable and capture an unpredictable value. This is a hard physical fact about every register in every chip.

the-window-rtl-cannot-see.v
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   // A real flop's requirement:
   //   data must be STABLE from (clk_edge - setup) to (clk_edge + hold)
   //
   //   data:  ____×____|‾‾‾‾‾‾|____    (× = a change too close to the edge)
   //   clk :  __________|‾‾‾‾‾‾‾‾‾‾    (rising edge here)
   //                    ↑ if data changed inside the window → VIOLATION
   //
   // In RTL simulation (zero-delay) the window has ZERO width — there is
   // nothing to violate. The flop always captures cleanly. The bug is not
   // fixed; it is INVISIBLE.

RTL simulation is timing-blind (Chapter 17 overview), so it cannot represent the window, let alone catch a change inside it. The question this chapter answers:

How does a simulation detect that a signal arrived too late or too early — that data changed inside a flop's setup/hold window, or that a pulse was too narrow? The answer is timing checks: simulator instruments that watch the windows real hardware requires and flag a violation when one is broken.

2. What Is a Timing Check?

A timing check is a built-in, $-prefixed simulator instrument that monitors the time between two events and reports a violation if that time is outside an allowed limit. It does not compute logic and it does not delay signals — it watches and judges.

a-timing-check-in-context.v
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   module dff (output reg q, input d, clk);
       // ... functional + path-delay model ...
       specify
           // PATH DELAY (Chapter 17.4) — how long clk→q takes:
           (posedge clk => (q +: d)) = 2;
 
           // TIMING CHECK (this chapter) — data must be stable 1 ns BEFORE
           // the clock edge, or it is a setup violation:
           $setup(d, posedge clk, 1);
       endspecify
   endmodule

A timing check has three essential parts: the signal being judged (d), the reference event it is judged against (posedge clk), and the limit (the setup time, 1). When the gap between the data change and the clock edge falls short of the limit, the check fires — it prints a violation message and (through a mechanism covered in 18.5) typically forces the captured value to X.

3. Mental Model — Delays Make Signals Late; Checks Judge Whether Late Is Too Late

4. The Family of Timing Checks

The checks fall into three groups by engineering purpose. This overview names them; the sub-pages drill each.

GroupChecksWhat they guard
Synchronous data vs clock$setup, $hold, $setupholddata stable in the window around a clock edge
Asynchronous control vs clock$recovery, $removal, $recremreset/set released far enough from a clock edge
Waveform integrity$width, $period, $nochange, $skewminimum pulse width, clock period, no-change windows, signal skew

The two big ideas: the first two groups are window checks — they judge the gap between a signal and a reference edge (data-to-clock, or control-to-clock). The third group judges a signal's own waveform — is the pulse wide enough, is the clock period long enough. Every check answers the same kind of question — did this event happen within the allowed time? — for a different pair of events.

5. Visual Explanation

Three figures frame the chapter.

5.1 Visual A — the capture window (setup and hold)

The setup/hold window — the keepout zone around a clock edge

data flow
The setup/hold window — the keepout zone around a clock edgesetup windowdata stable BEFORE theedgeclock edgecapture happens herehold windowdata stable AFTER theedge
A flip-flop requires its data to be stable across a window: the setup time before the clock edge and the hold time after it. A data change inside this keepout zone is a timing violation — and the flop may capture an unpredictable value. Timing checks watch this window.

5.2 Visual B — where timing checks live (the specify block)

The specify block — path delays and timing checks together

data flow
The specify block — path delays and timing checks togetherspecify ...endspecifythe cell's timingregionmodule pathdelayshow long signals take(Ch 17.4)timing checkswhen signals mustarrive (this chapter)
A complete cell model holds two things in its specify block: the module path delays that time the cell (Chapter 17.4) and the timing checks that verify its inputs arrive within their required windows (this chapter). Chapter 17 built the first half; Chapter 18 builds the second.

5.3 Visual C — what a violation does

A violation, from detection to consequence

data flow
A violation, from detection to consequencedata changes inthe windowthe violating eventtiming checkfiresviolation reportednotifier togglesthe model's hook(18.5)output forced toXthe metastable valuemade visible
When a signal lands inside a forbidden window, the timing check fires: it prints a violation message and, through a notifier register, the cell model typically forces the captured value to X. The X then propagates — turning an invisible metastable event into a visible, traceable one. Chapter 18.5 drills this mechanism.

6. Where Timing Checks Live, and Where Their Limits Come From

  • They live in the specify block — the construct introduced in 17.4 for path delays. The same block that says how long clk→q takes also says how long before the edge data must be stable. One region, two roles.
  • They run in gate-level simulation. Timing checks are meaningful only when timing exists — i.e., on a delay-annotated netlist. In zero-delay RTL they have nothing to check.
  • Their limits come from the cell library, via SDF. Just as SDF back-annotates path delays (17.4), it back-annotates the setup/hold/recovery values. The specify block declares which checks exist; SDF supplies the numbers for the real silicon.

So a timing check is not something you typically hand-write into your RTL — it is part of the cell model, exercised when you run gate-level simulation with real timing. What every engineer must understand is what the check means and what its firing tells you.

7. What a Violation Does — A Preview

When a timing check fires, two things happen (drilled in 18.5):

  1. A violation message is printed — naming the check, the signals, the times, and the shortfall. This is the diagnostic record.
  2. The affected value is usually forced to X — through an optional notifier register the check toggles, which the cell model uses to drive the output unknown. This models the real consequence: a setup/hold violation can leave a flop metastable, and X is how simulation represents "unpredictable."

The X then propagates downstream, which is both the point and the pitfall — it makes the violation visible, but a single early violation can spread X across a netlist (the "X-pessimism" problem, also 18.5). Turning an invisible timing failure into a visible X is exactly what timing checks are for.

8. Chapter 18 Roadmap

Five sub-pages, concept-first, then mechanism.

  • 18.1 Setup & Hold Fundamentals — the universal concept: the capture window, why a violation causes metastability, the relationship to clock period and skew. The page every engineer needs, independent of the Verilog tasks.
  • 18.2 $setup, $hold & $setuphold — the synchronous data-vs-clock checks: how they are written, the reference edge, and the combined $setuphold.
  • 18.3 $recovery, $removal & $recrem — the asynchronous control checks: why an async reset released too close to a clock edge is its own hazard, and the reset-comes-out-in-X scenario.
  • 18.4 $width, $period, $nochange & $skew — the waveform-integrity checks: minimum pulse width, clock period, no-change windows, and signal skew.
  • 18.5 Violation Behaviour — Notifiers & X-Propagation — what a fired check actually does: the notifier register, X-propagation, X-pessimism, and how to debug a netlist-wide X flood back to one early violation.

Read in order, you go from what setup and hold are to how Verilog checks them to what happens when one fails and how to debug it.

9. Industry Perspective

In a real flow, timing is signed off two ways that complement each other:

  • Static timing analysis (STA) is the primary sign-off: it checks every path against the clock without simulating vectors, exhaustively, across corners. It is how a chip's timing is actually guaranteed.
  • Gate-level simulation with timing checks is the dynamic cross-check: it runs your actual test vectors on the delay-annotated netlist and fires timing checks on the paths those vectors exercise. It catches things STA can mishandle — X-propagation behaviour, reset-release sequencing, and the dynamic interaction of real stimulus with real delays.

The two are partners: STA proves all paths meet timing in the abstract; GLS proves the design behaves correctly under real stimulus with real timing, and timing checks are what make a GLS run report a timing problem instead of silently producing wrong data. Understanding timing checks is therefore essential to reading and debugging any gate-level simulation.

10. Common Misconceptions

"RTL simulation catches setup/hold violations." False. RTL is zero-delay — the setup/hold window has zero width, so there is nothing to violate. Timing checks only do their job on a delay-annotated netlist in gate-level simulation.

"A timing check fixes a timing problem." False. A timing check detects and reports; it never repairs. Meeting timing is the job of the design (faster logic, pipelining, a longer clock period) and is proven by STA. The check is the alarm, not the fix.

"Timing checks are part of the synthesized hardware." False. Like all of the specify block, timing checks are simulation-only. Synthesis ignores them. They model and verify behaviour; they are not built.

"Every timing-check violation is a real bug." Not necessarily. A violation flags that a signal arrived outside a window on the exercised path — which may be a real bug, or may be a false/unexercised path, or a missing constraint. A violation is a signal to investigate, interpreted alongside STA, not an automatic verdict.

11. DebugLab

The violation RTL never reported

Why timing checks turn an invisible failure into a visible X
Buggy Code
// A data path feeds a flop. In the real (delay-annotated) netlist, the
// data arrives only 0.3 ns before the clock edge — but the flop's library
// setup requirement is 1.0 ns. That is a setup VIOLATION.
//
// RTL SIMULATION (zero-delay, NO timing checks):
//   - The setup window has zero width. Data and clock are treated as
//     arriving in a clean order. The flop captures a DEFINED value every
//     time. The self-checking test sees consistent data and PASSES.
//   - The violation is not merely unreported — it CANNOT be represented.
//
// GATE-LEVEL SIMULATION WITHOUT the timing check enabled:
//   - Delays exist, so data really does arrive 0.3 ns before the edge.
//   - But with no $setup check, the simulator just captures whatever value
//     is present at the edge — a DEFINED but possibly WRONG value. The run
//     may still look green, while silicon would be metastable. Silent.
//
// GATE-LEVEL SIMULATION WITH the $setup timing check:
//   specify $setup(d, posedge clk, 1.0); endspecify
//   - data changes 0.3 ns before the edge → 0.3 < 1.0 → the check FIRES.
//   - A violation is reported AND the captured value is forced to X.
//   - The X propagates; the test now FAILS visibly at the right place.
Symptom

A design with a genuine setup violation passes RTL simulation and can even pass a naive gate-level run, then fails (or behaves nondeterministically) in silicon. Nothing reports the timing problem. Engineers cannot see WHERE or WHY the design is marginal.

Root Cause

The failure is a setup violation — data arriving inside the flop's required stable window — but NOTHING in the simulation was watching that window:

- RTL is zero-delay, so the window has zero width and the violation literally cannot exist in the model. - A gate-level run with delays but WITHOUT the timing check sees the late data, yet with no $setup instrument it just captures a defined value and moves on — no alarm, no X. The marginality is silent.

A timing check is the missing instrument. $setup(d, posedge clk, 1.0) measures the gap between the data change and the clock edge; when that gap (0.3 ns) is less than the required setup (1.0 ns), the check FIRES — it reports the violation and forces the captured value to X, which then propagates so the failure is visible and traceable.

The lesson: a timing problem you cannot see is not a timing problem you do not have. Timing checks exist to convert an invisible, silent marginality into a loud, located X.

Fix
// The fix is to ENABLE the verification path, not to silence the alarm:
//
//  1. Run gate-level simulation on the DELAY-ANNOTATED netlist (real cell
//     and path delays — Chapter 17), with the cell library's TIMING CHECKS
//     active (they ship in the cells' specify blocks; SDF supplies the
//     setup/hold limits).
//
//  2. When $setup fires, READ the violation: it names the signal, the
//     reference edge, the required time, and the actual gap. That locates
//     the marginal path precisely.
//
//  3. FIX THE PATH, not the check: meet setup at the relevant corner
//     (shorten the path, re-pipeline, or relax the clock) — and confirm
//     with static timing analysis, which checks ALL paths, not just the
//     exercised one.
//
// Never "fix" a violation by deleting the check. The check is the only
// reason you can see the problem at all. (Chapter 18.5 covers what the
// firing does — notifier + X-propagation — in detail.)

12. Interview Q&A

13. Exercises

Conceptual exercises — reason about timing checks; no coding required.

Exercise 1 — Name the window

In your own words, define setup time and hold time, and explain why a data change between them (right at the clock edge) is the most dangerous.

Exercise 2 — Group the checks

Sort these into the three families (synchronous data-vs-clock / asynchronous control-vs-clock / waveform integrity): $hold, $width, $recovery, $setuphold, $period, $removal, $setup.

Exercise 3 — Why X?

Explain why a fired setup check forces the captured value to X rather than to 0 or 1. What real-hardware phenomenon is the X modelling?

Exercise 4 — The silent failure

A design has a real setup violation but passes both RTL simulation and a gate-level run with timing checks disabled. Explain, in two sentences each, why each run failed to report it.

14. Summary

Timing checks are the detection half of timing-aware simulation.

  • The problem — a flop needs data stable in a window (setup before, hold after the clock edge); RTL is zero-delay and cannot represent that window, so it is blind to violations.
  • The instrument — a timing check ($setup, $hold, $recovery, $width, …) watches the time between two events and fires when it is outside the limit, printing a violation and typically forcing the value to X.
  • The families — synchronous data-vs-clock ($setup/$hold/$setuphold), asynchronous control-vs-clock ($recovery/$removal/$recrem), and waveform integrity ($width/$period/$nochange/$skew).
  • Where they live — the specify block (with path delays, 17.4); their limits come from the cell library via SDF; they run in gate-level simulation.
  • What they do, not — they detect, never fix. STA and the design fix timing; the check is the alarm.

The five sub-pages:

  • 18.1 Setup & Hold Fundamentals — the concept.
  • 18.2 $setup, $hold & $setuphold — synchronous data-vs-clock checks.
  • 18.3 $recovery, $removal & $recrem — asynchronous control checks.
  • 18.4 $width, $period, $nochange & $skew — waveform-integrity checks.
  • 18.5 Violation Behaviour — Notifiers & X-Propagation — what a fired check does, and how to debug it.

Chapter 19 Timing Regions then closes the curriculum by explaining the event ordering that decides exactly which values a check observes — the determinism beneath all of it.