Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • RTL Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
    • STA Foundations
    • Setup, Hold and Slack
      • Core Equations and Slack
      • Interpretation Shortcut
      • Worked Numeric Examples
      • Example 1: Setup Failure
      • Example 2: Hold Failure
      • Fix Strategy: Setup vs Hold
    • Skew and Variation
    • Timing Exceptions
    • Clock Gating
    • RTL for Timing
    • Clock Architecture
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

‹Setup, Hold and Slack
  1. Topics
  2. RTL Design
  3. Timing & Clocking
  4. Setup, Hold and Slack
  5. Worked Numeric Examples

Part 5 · Timing & Clocking · Intermediate

Worked Numeric Examples

Six paths with varied logic delay and skew checked against the slack equations.

On this page

    Why this matters

    Zero-delay RTL simulation cannot show a timing violation. A small model with fixed delays, six paths and known slack shows how the equations turn into setup and hold failures at the capture edge.

    After this lesson you can: compute setup and hold slack for six paths from logic delay and skew, and trace one launch to its capture edge.

    Timing model

    Zero-delay functional RTL simulation cannot establish physical timing. This teaching model adds fixed clock-to-Q, logic and capture-clock delays and checks transitions around capture edges. It has no library characterization, uncertainty, variation or analog metastability model.

    Clock-to-Q is fixed at 0.35 ns for both min and max, with 0.12 ns setup and 0.06 ns hold. Real STA uses distinct early/late values. A violated window drives the modeled output to X as a diagnostic, not a prediction of silicon behavior. Monitoring starts at 5 ns after startup settles.

    Six paths

    Path

    Logic (ns)

    Skew (ns)

    Setup slack

    Hold slack

    Expected after warmup (not newly simulated)

    0

    1.45

    0.00

    +0.08

    +1.74

    clean

    1

    1.64

    0.00

    −0.11

    +1.93

    28 setup violations

    2

    1.65

    +0.30

    +0.18

    +1.64

    clean: slightly longer logic, helped by useful skew

    3

    0.05

    0.00

    +1.48

    +0.34

    clean: short path, no skew

    4

    0.05

    +0.38

    +1.86

    −0.04

    28 hold violations

    5

    0.25

    +0.38

    +1.66

    +0.16

    clean: 0.2 ns of added delay fixes hold

    Setup slack (dark bars) and hold slack (light bars) of the six paths. Path 1 fails setup by 0.11 ns and path 4 fails hold by 0.04 ns; the failing bars point left of zero.

    Read each pair of bars as one path: the upper bar is setup slack, the lower bar is hold slack, and anything left of the zero line fails.

    • Paths 0 to 2 have long logic, so setup is small and hold is large. Path 1 is the only setup failure (-0.11 ns).

    • Paths 3 to 5 have short logic, so the picture flips: setup is large and hold is small. Path 4 is the only hold failure (-0.04 ns).

    • Skew moves both bars at once: path 2's +0.30 ns skew lifts setup to +0.18 ns and lowers hold to +1.64 ns; path 4's +0.38 ns skew is what pushes hold below zero.

    • Path 5 is path 4 with 0.20 ns more logic: hold rises by 0.20 to +0.16 ns and setup falls by 0.20 to +1.66 ns.

    Check the arithmetic

    Diagram
    Path 1 setup:  T + skew - tsu - tcq - logic = 2.00 + 0.00 - 0.12 - 0.35 - 1.64 = -0.11
    Path 2 setup:  2.00 + 0.30 - 0.12 - 0.35 - 1.65 = +0.18
    Path 4 hold:   tcq + logic - skew - thold = 0.35 + 0.05 - 0.38 - 0.06 = -0.04
    Path 5 hold:   0.35 + 0.25 - 0.38 - 0.06 = +0.16

    The checker below compares arithmetic against independent expected slack constants, verifies violation signs in both directions, and checks exact counts across 28 monitored captures (5 through 59 ns, plus each path's skew). It finds 28 setup violations on path 1 and 28 hold violations on path 4. Per-event and per-path failures print timestamps, measured margins and expected counts, then exit with a fatal verdict.

    Trace one launch at 5 ns

    Path

    Data transition

    Relevant capture / deadline

    Expected observation

    1

    5 + 0.35 + 1.64 = 6.99 ns

    Next capture 7.00; setup deadline 6.88 ns

    At 7.00, data age 0.01 < 0.12 ns: setup fails by 0.11 ns

    2

    5 + 0.35 + 1.65 = 7.00 ns

    Next capture 7.30; setup deadline 7.18 ns

    Data age 0.30 ns: setup passes; no coincident capture

    4

    5 + 0.35 + 0.05 = 5.40 ns

    Same capture 5.38; hold deadline 5.44 ns

    At 5.40, data age from clock 0.02 < 0.06 ns: hold fails by 0.04 ns

    Common mistakes

    Common pitfall

    The local transition-window checker is bounded to nonnegative skew, logic delay shorter than one period, and data arrival strictly between the same and next capture edges. Parameter guards reject cycle-early or cycle-late arrival; timestamp guards reject coincident D/capture events. A zero-time settle step makes same-timestamp detection independent of active-event ordering for these active-region drivers; it is simulator scheduling, not physical delay. Path 1 deliberately uses 1.64 rather than 1.65 ns to avoid data arriving exactly on its next capture edge. Large-skew early capture needs edge-tagged checking or STA, not relabeling a local setup event as a hold proof.

    Tip

    As a checker mutation, set path 1 LOGIC to 1.50 without updating expected values: the missing setup events and changed slack must cause FAIL. Setting path 4 SKEW to 0.48 must trigger the unsupported early-arrival guard. Setting path 1 LOGIC to 1.65 must trigger the coincident-event guard.

    Check yourself Path 2 is slightly longer than path 1 but passes. What changed, and what is the cost?

    Capture arrives 0.30 ns later. Without skew, path 2 would have -0.12 ns setup slack; with skew it has +0.18 ns. Its hold slack drops from +1.94 to +1.64 ns, and outgoing full-cycle setup paths lose 0.30 ns with fixed other terms.

    Testbench

    The delay-annotated model and the six-path testbench that checks violations against slack.

    dff_chk.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    `timescale 1ns/1ps
    
    // Teaching-only local windows. #0 settles active events without advancing time.
    module dff_chk #(parameter real TCQ = 0.35, TSU = 0.12, THD = 0.06) (
      input  logic clk, d,
      output logic q,
      output int   setup_viol, hold_viol
    );
      realtime t_clk = -100.0, t_d = -100.0;
      localparam real ARM_TIME = 5.0;
      initial begin setup_viol = 0; hold_viol = 0; q = 1'b0; end
    
      always @(d) begin
        t_d = $realtime;
        #0;
        if ($realtime >= ARM_TIME) begin
          if ($isunknown(d)) $fatal(1, "%m unknown D at %0.3f ns", $realtime);
          if (t_clk == t_d) $fatal(1, "%m unsupported coincident D/clock at %0.3f ns", t_d);
          if ($realtime - t_clk < THD && t_clk >= ARM_TIME) begin
            hold_viol++;  q <= #TCQ 1'bx;
            $display("%m HOLD at %0.3f ns: D=%b clock=%0.3f age=%0.3f required=%0.3f", $realtime, d, t_clk, $realtime-t_clk, THD);
          end
        end
      end
    
      always @(posedge clk) begin
        t_clk = $realtime;
        #0;
        if ($realtime >= ARM_TIME && $isunknown(d))
          $fatal(1, "%m unknown D at capture %0.3f ns", $realtime);
        if ($realtime >= ARM_TIME && t_clk == t_d)
          $fatal(1, "%m unsupported coincident D/clock at %0.3f ns", t_clk);
        if ($realtime >= ARM_TIME && $realtime - t_d < TSU) begin
          setup_viol++;  q <= #TCQ 1'bx;
          $display("%m SETUP at %0.3f ns: D=%b last_D=%0.3f age=%0.3f required=%0.3f", $realtime, d, t_d, $realtime-t_d, TSU);
        end else
          q <= #TCQ d;
      end
    endmodule
    
    // launch flop -> combinational delay -> capture flop whose clock arrives SKEW later
    module timing_path #(parameter real T = 2.0, LOGIC = 1.45, SKEW = 0.0) (
      input logic clk,
      output int setup_viol, hold_viol,
      output real slack_setup, slack_hold
    );
      localparam real TCQ = 0.35, TSU = 0.12, THD = 0.06;
      initial begin
        if (T != 2.0 || LOGIC < 0.0 || LOGIC >= T || SKEW < 0.0 ||
            SKEW >= TCQ + LOGIC || TCQ + LOGIC > T + SKEW)
          $fatal(1, "%m unsupported timing model: T=%0.3f LOGIC=%0.3f SKEW=%0.3f", T, LOGIC, SKEW);
      end
      logic q1, d1, d2, q2, clk2;
      int sv1, hv1, sv2, hv2;
    
      assign d1   = ~q1;                     // launch a new value every cycle
      dff_chk #(TCQ, TSU, THD) ff1 (.clk(clk), .d(d1), .q(q1), .setup_viol(sv1), .hold_viol(hv1));
      assign #(LOGIC) d2 = q1;               // combinational path delay
      assign #(SKEW)  clk2 = clk;            // only nonnegative skew is supported
      dff_chk #(TCQ, TSU, THD) ff2 (.clk(clk2), .d(d2), .q(q2), .setup_viol(sv2), .hold_viol(hv2));
    
      assign setup_viol = sv2;
      assign hold_viol  = hv2;
      assign slack_setup = T + SKEW - TSU - TCQ - LOGIC;     // data must arrive before the next capture edge minus setup
      assign slack_hold  = TCQ + LOGIC - SKEW - THD;         // data must not arrive before the previous edge + hold
    endmodule
    

    Remember

    • The model uses 0.35 ns clock-to-Q, 0.12 ns setup and 0.06 ns hold.

    • Path 1 (1.64 ns of logic) fails setup, path 4 fails hold, and skew moves the slack of both checks in opposite directions.

    • A violated window drives the modelled output to X as a diagnostic. It does not predict silicon.

    Rule of thumb: compute the slack by hand, then see whether the model agrees.

    How this was checked

    The checker compares arithmetic against independent expected slack constants, verifies violation signs in both directions, and counts 28 monitored captures (5 to 59 ns, plus each path's skew). Run with Icarus Verilog 13.0 (2026-10-16): prints PASS, with 28 setup violations on path 1 and 28 hold violations on path 4.

    The three mutations suggested in the lesson (path 1 logic 1.50, path 4 skew 0.48, path 1 logic 1.65) are proposed checks and were not run.

    The model has no library characterisation, uncertainty, variation or analogue metastability model. Real STA uses distinct early and late values.

    Keep going

    • Interview: run a mock interview on this topic

    Related topics

    • Example 1: setup failure

    Previous

    123 / 350

    Next: Example 1: Setup Failure

    Up next

    Up nextExample 1: Setup Failure

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Core Equations and Slack
    • Example 2: Hold Failure
    • Fix Strategy: Setup vs Hold