Skip to content

SystemVerilog · Module 15

Input & Output Skews

SystemVerilog clocking block skews — the granular timing margins around each clock edge. Input skew controls exactly when the testbench samples DUT outputs; output skew controls when the testbench drives DUT inputs. #1step, #N, #0, and #-N — what each resolves to, when each is right, and the protocol-specific choices for APB / AXI / SPI / DDR.

Module 15 · Page 15.3

Skews are the timing margins built into a clocking block. The input skew controls exactly when the testbench samples a DUT output relative to the clock edge. The output skew controls when the testbench drives a DUT input — giving the DUT guaranteed setup time before its next sampling edge. Choosing the right skews eliminates every timing-related false failure in a synchronous testbench: TB reads pre-edge stale values, DUT reads mid-flight stimulus, cross-protocol setup-time violations. This page walks the four skew forms (#1step, #N, #0, #-N), the per-signal override mechanism, and the protocol-specific defaults that production VIPs use for APB, AXI, SPI, and DDR.

1. Engineering Problem — Why Skews Exist

In real silicon, every flip-flop has two timing requirements specified in its datasheet:

  • Setup time — the signal must be stable for at least T_setup nanoseconds before the clock edge.
  • Hold time — the signal must remain stable for at least T_hold nanoseconds after the clock edge.

A testbench that drives a signal at exactly the clock edge gives the DUT zero setup time. Real silicon would fail this — STA would flag a setup violation; a fabricated chip would produce metastable outputs. Simulation may or may not catch the problem depending on which Active-region operation the scheduler evaluates first — the canonical TB-DUT race covered in program-block.

Clocking-block skews are the simulation equivalent of these silicon timing margins:

  • The output skew says "drive the new value N time units after the clock edge" — giving the DUT a full clock period (minus N) of setup time before its next sampling edge.
  • The input skew says "sample the DUT output M time units before the clock edge" — capturing a stable post-NBA-settled value, not a mid-evaluation Active-region snapshot.

Together, the two skews shape every TB↔DUT signal exchange into the natural setup-before-edge, sample-before-edge pattern of real synchronous interfaces. Choosing the wrong skew (#0 for inputs, #0 for outputs, a skew larger than the clock period) reintroduces the very race the clocking block was meant to eliminate.

2. Mental Model — Skew = Margin From the Edge

The picture every engineer carries:

A skew is a labelled offset from the active clock edge. Positive skew (#N, N > 0) means after the edge. Negative skew (#-N) means before the edge. #0 means at the edge. The special form #1step means one simulator time step before the edge — guaranteed to fall in the Postponed region of the previous time step, after every NBA has committed and before any current-edge Active activity starts. The four forms cover every realistic timing relationship between the testbench and the DUT.

Three invariants this picture preserves:

  • #1step is the only choice that is structurally race-free for inputs. The other forms can race with DUT-side evaluations in the same Active region; #1step cannot — it samples before any current-edge activity begins.
  • Output skew gives the DUT setup time. The DUT's next sampling edge is one full clock period after the current edge. If the TB drives at #N after the current edge, the DUT has period − N time units of setup before its next sample. Standard #1 gives period − 1 — adequate for any synchronous DUT.
  • Skew magnitude must be less than the clock period. Skew #15 on a 10 ns clock samples or drives in the next cycle — reading the wrong value or driving past a cycle boundary. The simulator typically accepts the declaration but produces semantic chaos.

3. Visual Explanation — Three Input Skews Compared

The waveform below puts the three most common input skew values side-by-side on the same DUT output transition. #1step reads the previous cycle's settled value (the safe default). #0 reads at the edge — in the Active region where the DUT's NBA may not have committed yet. #2 reads after the DUT's propagation delay has settled.

Figure — three input skews on the same DUT output transition

12 cycles
Figure — three input skews on the same DUT output transitioninput #1step: safe pre-edge sampleinput #1step: safe pre…input #0: RACE — Active regioninput #0: RACE — Activ…input #2: post-propagation sampleinput #2: post-propaga…clkDUT outputoldoldoldoldnewnewnewnewnewnewnewnewinput #1stepSNAP=oldSNAP=oldSNAP=oldSNAP=oldSNAP=oldSNAP=oldSNAP=oldSNAP=oldSNAP=oldinput #0SNAP=?SNAP=?SNAP=?SNAP=?SNAP=?SNAP=?SNAP=?SNAP=?input #2SNAP=newSNAP=newSNAP=newSNAP=newSNAP=newSNAP=newt0t1t2t3t4t5t6t7t8t9t10t11
At cycle 4, the DUT output transitions from old to new. input #1step (default) samples in the Postponed region of cycle 3 — reads the stable old value, guaranteed pre-edge. input #0 samples at exactly cycle 4 — in the Active region where NBA may not have committed yet (race). input #2 samples 2 cycles after the edge — DUT output has fully propagated, reads the new value. The three sampling points capture three different values, all from the same DUT output trace.

The teaching: same DUT signal, same clock edge — three different captured values depending on the skew. Choosing the wrong skew means the testbench's notion of what the DUT said at the edge silently disagrees with reality.

4. Syntax & Semantics — #1step, #N, #0, #-N

4.1 Input skew — declaration forms

SystemVerilog — input skew declarations and what each form means
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
clocking cb @(posedge clk);
    default input #1step;      // all inputs use #1step unless overridden
 
    input sig_a;               // uses default: #1step (safe pre-edge)
    input #2   sig_b;          // per-signal: 2 time units AFTER edge
    input #-1  sig_c;          // per-signal: 1 time unit BEFORE edge
    input #0   sig_d;          // per-signal: AT the edge (use with care)
endclocking

4.2 Output skew — declaration forms

SystemVerilog — output skew declarations and what each form means
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
clocking cb @(posedge clk);
    default output #1;         // all outputs driven 1 time unit AFTER edge
 
    output sig_a;              // uses default: #1
    output #3   sig_b;         // per-signal: driven 3 time units AFTER edge
    output #0   sig_c;         // driven AT the edge (Active region — risky)
    output #-2  sig_d;         // driven 2 time units BEFORE the edge — pre-edge setup
endclocking

4.3 Combined defaults — the canonical declaration

SystemVerilog — the canonical clocking block with both default skews
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
clocking cb @(posedge pclk);
    default input  #1step      // sample just before posedge — race-free
            output #1;         // drive 1 time unit after posedge — gives DUT (period − 1) setup
 
    input  pready, pslverr, prdata;   // DUT outputs the TB samples
    output psel, penable, pwrite, paddr, pwdata;  // DUT inputs the TB drives
endclocking

#1step for inputs, #1 for outputs — the recommended default for any synchronous interface. Per-signal overrides only when a specific signal genuinely needs different timing (DUT outputs with known propagation delay, fast paths needing maximum setup).

4.4 The four skew forms in one reference table

Skew valueWhen event occursUse for inputUse for output
#1stepPostponed region of the time step just before the clock edgeDefault — safest input sampling, race-freeNot applicable for outputs
#0Exactly at the clock edge (Active region)Combinational DUT outputs valid at the edgeImmediate drive — avoids skew but may race
#N (N > 0)N time units after the clock edgeDUT outputs with known propagation delay NStandard — gives DUT (period − N) setup
#-N (N > 0)N time units before the clock edgeSample the previous cycle's stable valueDrive N units before edge — maximum DUT setup

Hard constraint: the skew magnitude must be less than the clock period. A #15 skew on a 10 ns clock crosses into the previous or next cycle, producing semantically incorrect sampling/driving. Most simulators accept the declaration but the behaviour is undefined — and is a frequent source of regression noise.

5. Simulation View — What Each Skew Resolves To

The simulator divides time into discrete time steps. Within each step there are ordered scheduling regions: Preponed → Active → Inactive → NBA → Observed → Reactive → Postponed. Skews map onto specific positions in this region sequence:

  • #1step schedules the sample in the Postponed region of the time step before the clock edge. At this point, every non-blocking assignment from the previous edge has committed; no current-edge Active or NBA activity has started. The most stable, deterministic, race-free sampling point available.
  • #0 schedules the event in the Active region of the current time step — the same region the DUT's <= schedules its NBA updates to commit. Whether the TB sees the pre-NBA value or the post-NBA value depends on simulator evaluation order. Race.
  • #N (positive) schedules the event N time units in absolute time after the clock edge. For an input, this means sampling after the DUT's combinational propagation has settled (use for DUT outputs with known delay). For an output, this means driving with period − N of setup before the DUT's next sampling edge.
  • #-N (negative) schedules the event N time units in absolute time before the clock edge. For an input, this samples in the previous cycle's stable window (capture a value that was already settled). For an output, this drives the signal before the upcoming edge — giving the DUT maximum setup time, useful when the protocol requires stable inputs well before the edge.

Why #1step beats #0: at #0, the simulator hasn't finished evaluating the Active region. The DUT's q <= d assignment may still be in the NBA queue, not committed to q yet. #1step is guaranteed to fall after every previous-cycle NBA commit and before any current-cycle Active activity. There is no simulator implementation where #1step races and #0 doesn't; in many it's the reverse.

6. Waveform — Both Skews Working Together in One Cycle

In a complete read-modify-write cycle, both skews are active simultaneously. The TB reads a DUT output via input skew, then drives a response via output skew — within the same clock cycle, both operations race-free.

Figure — both skews active in one cycle: read at #1step (before edge), drive at #1 (after edge)

12 cycles
Figure — both skews active in one cycle: read at #1step (before edge), drive at #1 (after edge)input #1step: TB samples DUT output (=a) pre-edgeinput #1step: TB sampl…output #1: TB drives new value (=y) after edgeoutput #1: TB drives n…DUT next edge: sees TB drive with full setupDUT next edge: sees TB…clkDUT outputTB drivesXXXXTB readsREAD=aREAD=aREAD=aREAD=aREAD=aREAD=aREAD=aREAD=aREAD=aTB writesWRITE=yWRITE=yWRITE=yWRITE=yWRITE=yWRITE=yWRITE=yWRITE=yt0t1t2t3t4t5t6t7t8t9t10t11
At cycle 4 (posedge clk): TB reads the DUT output via input #1step (sampled in cycle 3's Postponed — reads the stable previous-cycle value). At cycle 4 + 1 time unit: TB drives the new output via output #1 (DUT will see the new value with full setup time before cycle 6's edge). The read happens BEFORE the edge; the drive happens AFTER. They never overlap; neither races with DUT-side evaluations.

The asymmetry is the entire teaching: inputs look backward (read settled values from the previous cycle's stable window), outputs look forward (drive values that the DUT will sample at its next edge). The clocking block encodes both disciplines in one declaration.

7. Synthesis — Not Applicable

Clocking block skews are a procedural simulation construct. They have no hardware footprint and no place in synthesisable RTL — synthesis tools reject the clocking keyword entirely. This section is intentionally omitted; the topic does not warrant it.

The corresponding hardware-side discipline is the STA-verified setup/hold margin on each signal at each flop. The skew declarations are the verification-side counterpart: they model what the hardware naturally has via timing-arc analysis, ensuring the testbench gives the DUT the same temporal isolation that real silicon does.

8. Verification View — Protocol-Specific Skew Choices

Different protocols have different timing requirements. The clocking block's skew defaults are the right answer for the standard synchronous case; per-signal overrides handle the protocol-specific exceptions. The most common production patterns:

8.1 APB (AMBA Peripheral Bus) — defaults are correct

SystemVerilog — APB clocking block with default skews
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// 10 ns clock period. Signals registered on posedge.
// Standard synchronous interface — defaults work cleanly.
clocking apb_cb @(posedge pclk);
    default input  #1step
            output #1;                      // 9 ns DUT setup — adequate
    input  pready, pslverr, prdata;
    output psel, penable, pwrite, paddr, pwdata;
endclocking

APB is the simplest case: one clock, all signals registered, no fast combinational paths. #1step input + #1 output is correct out of the box.

8.2 AXI4 — per-signal override for the read-data path

SystemVerilog — AXI4 clocking block with per-signal skew on rdata
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// 5 ns clock period. DUT logic has propagation delays on some paths.
// Sample rdata 2 ns after edge — captures the post-propagation value.
clocking axi_cb @(posedge aclk);
    default input  #1step
            output #1;
    input  awready, wready, bvalid, bresp;
    input  #2 rdata;                        // rdata path: 2 ns DUT propagation
    output awvalid, awaddr, wvalid, wdata, wlast, bready;
    output #0 arvalid;                       // read address: drive immediately
endclocking

Two per-signal overrides: input #2 rdata (sample after the DUT's combinational propagation has settled), output #0 arvalid (drive immediately at the edge to maximise setup time for the slave's read-address sampling). Every other signal uses the defaults.

8.3 SPI — opposite edges for drive vs sample

SystemVerilog — SPI clocking blocks: negedge driver, posedge monitor
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
interface spi_if (input sclk);
    logic mosi, miso, cs_n;
 
    // Master drives MOSI on negedge so the slave's posedge sample is stable
    clocking master_cb @(negedge sclk);
        default input #1step output #1;
        output mosi;                        // driven after negedge
        input  miso;                        // sampled just before negedge
    endclocking
 
    // Monitor captures what the slave sees — on posedge
    clocking monitor_cb @(posedge sclk);
        default input #1step;
        input mosi, miso;                   // capture both lines at the slave's sample point
    endclocking
endinterface

SPI Mode 0: master shifts data out on negedge sclk; slave samples on posedge sclk. Two clocking blocks — one per edge — each with its own skew discipline. The interface bundles the signals; the clocking blocks bundle the per-edge timing contracts.

8.4 Fast designs — tight setup-time budget

SystemVerilog — fast clock with tight setup budget
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// 4 ns clock period. DUT needs 1 ns setup minimum.
// TB must drive no later than 3 ns after posedge.
clocking fast_cb @(posedge clk);            // 4 ns period
    default input  #1step
            output #1;                      // 3 ns DUT setup — within spec
endclocking
// If you used output #2: only 2 ns DUT setup — marginal
// If you used output #3: only 1 ns DUT setup — at the limit; STA would flag this

For fast clocks, the skew choice directly bounds the verification's representation of DUT setup time. A protocol that specs T_setup ≥ 1 ns on a 4 ns clock leaves the TB room to use output #3, but any reasonable VIP picks #1 to stay well clear of the boundary.

8.5 Per-signal overrides in mixed-timing interfaces

SystemVerilog — mixed combinational and registered paths in one interface
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
interface mixed_if (input clk);
    logic reg_out;       // registered DUT output
    logic comb_out;      // combinational DUT output — valid at the edge
    logic slow_out;      // slow DUT path — settles 3 ns after edge
    logic fast_in;       // input the DUT needs early — drive before edge
 
    clocking cb @(posedge clk);
        default input #1step output #1;
 
        input          reg_out;             // default: #1step (registered path)
        input  #0      comb_out;            // combinational: stable at edge
        input  #3      slow_out;            // slow path: wait 3 ns for propagation
        output #-3     fast_in;             // drive 3 ns BEFORE edge for max setup
    endclocking
endinterface

The pattern: declare the safe defaults at the top, override per-signal only when a specific path genuinely needs different timing. Each override is a documented timing-relationship statement; defaults are the contract for the rest of the interface.

9. Industry Usage — Where Skew Choices Land in Real Verification

  • Every shipping APB / AHB / AXI / DDR VIP ships with a clocking block per channel using #1step input + #1 output as defaults. Per-signal overrides appear on signals with known propagation delays (memory-read paths, ECC-decode paths). The defaults are the industry standard; anything else is documented protocol-specific deviation.
  • SPI / I²C / UART VIPs use multiple clocking blocks per interface — one per active edge (e.g., negedge for the master driver, posedge for the slave sampler). The skew per clocking block is #1step/#1 — the multi-clocking-block construct is what handles the multi-edge timing, not exotic skew values.
  • DDR controllers use clocking blocks anchored to both the rising and falling edges (DDR2/3/4 are dual-edge). Each clocking block has its own skew; the verification environment treats the two edges as independent timing domains.
  • High-speed serial interfaces (PCIe Gen3+, USB SuperSpeed, Ethernet 10G) that approach the simulator's time-resolution limits use #1step exclusively for inputs and #1 for outputs — even small positive skews can exceed the per-cycle budget at multi-gigahertz rates.
  • CDC verification environments use one clocking block per domain (per /learnings/systemverilog/clocking-blocks-deep-dive §8.4). Each domain's skews are independent; the destination domain's input skew is the sampling reference for the two-flop synchroniser.
  • Sign-off CDC formal flows (JasperGold CDC, Conformal LP) consume the clocking-block skew declarations as the verification's timing reference. Skews that exceed the clock period or use non-standard values are flagged as setup/hold-relationship violations.
  • Vendor lint rules (Spyglass, Synopsys VC SpyGlass CDC, Cadence Conformal CDC) check that every clocking block has explicit default skews declared. Implicit defaults (the LRM-permitted "if no default is given, signals are sampled at #0") are flagged as a discipline violation.

10. Design Review Notes — What a Senior Will Flag

Pattern in the diffWhat review will say
clocking cb @(posedge clk); input data; endclocking (no default skew declaration)"Implicit skew defaults to #0 per LRM — racy. Always declare default input #1step output #1; explicitly. Every shop's lint rule flags missing defaults."
input #0 q; on a registered DUT output"Samples at the edge in Active region — NBA may not have committed yet. Use #1step for registered outputs; #0 is only valid for combinational outputs valid at the edge."
input #15 data; on a 10 ns clock"Skew magnitude (15) exceeds clock period (10) — samples into the next cycle, reading the wrong value. Skew must be less than period."
output #0 req; on a synchronous interface"Drives at the edge in Active region — races with DUT-side evaluations. Use #1 for period − 1 setup; use #-N if the protocol genuinely needs pre-edge driving."
Per-signal skews on every signal with no default declaration"Declare the default once at the top; per-signal overrides only when truly needed. Each per-signal skew is one more thing for the next engineer to verify."
Async signals (resets, interrupts) listed in the clocking block with a skew"Async signals belong outside the clocking block. Attaching a clock skew to an asynchronous signal models a timing relationship that doesn't exist in hardware."
input #-5 prev_data; on a 10 ns clock with no comment"Negative skew reads from the previous cycle's stable window — uncommon enough to need a comment explaining why. Most readers will assume it's a bug."
Two clocking blocks in the same interface with different skews for the same signal"Two clocking blocks for the same signal is fine (master vs slave perspective), but different skews on the same signal across clocking blocks is suspicious — they should agree on when the signal is sampled / driven. Verify the protocol requires the difference; if not, harmonise."
default output #-1; (negative default for outputs)"Drives before the edge by default — non-standard. Most readers expect output #N (positive) for the standard post-edge drive. Negative as default is a discipline outlier; should be output #1 with per-signal #-N overrides only where needed."
Skew with no time unit on a multi-time-precision design"#2 is ambiguous if the surrounding scope has multiple timeunit/timeprecision declarations. Use explicit units (#2ns, #100ps) when the time-precision scope is non-trivial."

The single highest-value rule: default input #1step output #1; is the canonical declaration. Any deviation should be documented inline with a one-line comment explaining the timing reason. The defaults are the contract; per-signal overrides are the documented exceptions.

11. Debugging Guide — Real Failures, Real Fixes

1

TB sees pre-NBA q value despite using a clocking block

INPUT-#0-RACE
Buggy Code
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
clocking cb @(posedge clk);
    default input #0;                       // BUG: samples at edge
    input q;
endclocking
 
// TB reads bus.cb.q at the posedge → in Active region
// → may capture pre-NBA value depending on simulator evaluation order
Symptom
Same TB-DUT race the clocking block was supposed to eliminate. Test passes on VCS, fails on Questa. q is registered in the DUT via q <= d; and the TB reads q immediately after the edge but sees the pre-edge value about 30 % of the time. Looks like a DUT bug; isn't.
Root Cause
input #0 samples in the Active region — the same region where the DUT's q <= d schedules its NBA update. Whether the NBA commits before or after the TB's read depends on simulator evaluation order. This is exactly the Active-region race the clocking block was meant to fix.
Fix
Change to default input #1step;. #1step samples in the Postponed region of the previous time step — guaranteed before any current-edge Active or NBA activity. The race is structurally eliminated. Reserve input #0 for combinational DUT outputs that are valid at the edge (rare and always commented).
2

DUT samples wrong stimulus value mid-cycle

OUTPUT-#0-DRIVE-RACE
Buggy Code
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
clocking cb @(posedge clk);
    default output #0;                      // BUG: drives at edge
    output psel, paddr;
endclocking
 
bus.cb.psel  <= 1;
bus.cb.paddr <= 32'h1000;
// DUT may sample psel=0 (old) or psel=1 (new) at this same edge
Symptom
Randomly the DUT processes a half-applied transaction — psel=1 but paddr is still the previous value. Same TB code, same DUT, simulator-dependent reproducibility. Coverage shows transactions completing at unexpected addresses.
Root Cause
output #0 schedules the drive at the same time as the clock edge. The DUT samples its inputs at that same edge. Race: did the DUT sample paddr before or after the TB drove it? Simulator-dependent.
Fix
Use the standard default output #1;. The DUT sees the new values one time unit after the edge — with period − 1 of setup time before its next sampling edge. Race eliminated. output #0 is only appropriate for combinational signals that have no setup-time requirement, which is rare.
3

TB reads next-cycle data instead of current-cycle data

POSITIVE-INPUT-SKEW-TOO-LARGE
Buggy Code
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// 10 ns clock period
clocking cb @(posedge clk);
    default input #1step;
    input #15 data;                         // BUG: 15 > period (10)
endclocking
Symptom
Every captured data value lags one cycle behind what the DUT produced. The TB log shows transactions completing at the wrong timing relationships; assertions fire unexpected data sequence. Looks like a DUT pipeline bug.
Root Cause
Input skew (15 ns) exceeds the clock period (10 ns). The sample point lands in the next cycle, capturing the value the DUT produced at the next edge — not the current one. Some simulators warn; others accept silently.
Fix
Skew magnitude must be strictly less than the clock period. For a 10 ns clock, the practical input-skew range is #1step to #9 (post-edge sampling) or #-9 to #-1 (pre-edge sampling from the previous cycle). If the DUT's propagation is slower than the clock period, the design is broken at the timing level — not solvable in the clocking block.
4

TB drives the wrong direction; bus contention on every cycle

WRONG-DIRECTION
Buggy Code
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
clocking cb @(posedge clk);
    default input #1step output #1;
    output ack;                             // BUG: ack is driven by the DUT
    output ready;                           // BUG: ready is driven by the DUT
endclocking
Symptom
Simulator warnings: "multiple drivers on ack". Waveform shows ack and ready as X across every cycle. Test fails to complete a single transaction. Looks like a DUT-output bug; it's actually a TB-direction bug.
Root Cause
The clocking block direction is from the testbench's perspective: output means "TB drives this signal." ack and ready are driven by the DUT — they should be input (TB reads what the DUT produces). The TB now tries to drive signals the DUT is also driving — multi-driver conflict shows as X.
Fix
Change to input ack; and input ready;. The clocking block direction is opposite to the DUT's port direction: a signal declared output in the DUT's port list is input in the testbench's clocking block. Always ask "does the TB read this (input) or drive this (output)?"
5

`input #1step` reads stale value; engineer expected post-edge value

SKEW-DIRECTION-MISUNDERSTOOD
Buggy Code
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
clocking cb @(posedge clk);
    default input #1step;
    input data_out;
endclocking
 
// At posedge N:
@(bus.cb);
x = bus.cb.data_out;
// Engineer expected x = value computed by DUT AT posedge N
// Actually got x = value computed by DUT AT posedge N-1 (one cycle stale)
Symptom
Test compares x against the expected DUT output for cycle N and consistently fails. The DUT computed the right value; the TB just captured it one cycle late. Looks like a DUT-functional bug; it's a TB-sampling-time misunderstanding.
Root Cause
input #1step samples before the current edge — capturing the value set up during cycle N−1. If the engineer wanted the value the DUT computed at edge N (after its NBA commits), they need a positive input skew that lets the DUT's propagation settle: e.g., input #2 if the DUT takes 2 ns to propagate.
Fix
Choose the input skew that matches which cycle's value the testbench needs. For "the value the DUT had at the end of the previous cycle (pre-edge)": #1step. For "the value the DUT computed at this edge (post-NBA-commit)": input #N where N exceeds the DUT's propagation delay. Most testbenches actually want #1step — the value the DUT held going into the edge — which matches how SVA and coverage also sample.

12. Interview Insights — What Interviewers Actually Probe

Default input skew: #1step — samples one simulation time step before the clock edge, in the Postponed region of the previous time step. At that point, all NBA assignments from the previous edge have committed; no current-edge Active or NBA activity has started. Reading there is guaranteed race-free against any current-edge DUT evaluation.

Default output skew: #1 — drives the signal one time unit after the clock edge. The DUT sees the new value with (period − 1) setup time before its next sampling edge — for a 10 ns clock, 9 ns of setup, plenty for any synchronous DUT. #0 would drive at the edge and race; negative skews are only needed for protocols requiring stable pre-edge stimulus.

13. Exercises

1. Design — skew choices for a DDR controller (Foundation)
Write a clocking block for a DDR2 controller interface where data is sampled on both posedge and negedge of dqs_clk. Use two clocking blocks (one per edge). Pick appropriate default input and default output skews for each. Explain why DDR specifically needs dual-edge clocking blocks.

2. Debug — the silent skew race (Intermediate)
A teammate's APB testbench uses clocking cb @(posedge pclk); default input #0; ... endclocking. The test passes on VCS, fails on Questa with assertion pready_check firing inconsistently. Identify the bug, predict the race mechanism in scheduler terms, and write the one-line fix.

3. Code review — the cross-period skew (Intermediate)
A teammate submits clocking cb @(posedge clk); where clk has a 10 ns period and the block declares input #12 slow_data;. Identify the bug, predict the symptom (what value will the TB capture and why), and write the fix considering the design's true timing requirements.

4. Trade-off — output #1 vs output #-1 (Advanced)
A junior teammate proposes a coding rule: "always use output #-1 instead of output #1 — drive before the edge to give the DUT maximum setup time." Argue the case against the blanket rule. Consider what assumptions break (the prior cycle's stable window), what protocols this would violate (anything that doesn't have stable inputs the cycle before the edge), and when negative output skew is actually the right choice.

14. Summary

Skews are the per-signal timing margins in a clocking block. Input skew controls when the TB samples DUT outputs (#1step for safe pre-edge sampling, #N for post-propagation sampling, #-N for previous-cycle stable-window sampling). Output skew controls when the TB drives DUT inputs (#1 standard post-edge drive, #0 immediate drive — risky, #-N for protocols needing pre-edge stimulus).

Defaults to memorise. default input #1step output #1; is the canonical declaration for any synchronous interface. #1step is the only structurally race-free input skew. Skew magnitude must be less than the clock period. Direction in a clocking block is from the testbench's perspective — opposite the DUT's port direction. Per-signal overrides only where the timing genuinely differs from the default.

Next up: 15.4 — Program Block Limitations & Best Practices — the constraints, restrictions, the modern module + clocking block alternative, and why UVM moved past program blocks entirely. Closes Module 15 with the operational discipline the deep-dive lessons established the theoretical foundation for.