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

  • Start Here6
  • SystemVerilog Language Foundations28
  • Object-Oriented SystemVerilog for Verification30
  • Constraint Randomization — Interview-Critical Deep Dive36
  • SystemVerilog Assertions — Interview-Critical Deep Dive40
  • Functional Coverage in SystemVerilog22
  • Testbench Architecture in SystemVerilog23
  • Advanced Language & Integration25
    • DPI-C: Calling C from SystemVerilog
    • bind: Attaching Verification to RTL
    • Macros, Defines & Compilation
    • Plusargs, Files & Runtime Configuration
    • Simulation Performance & TB Memory
    • RTL/TB Boundaries, Races & Timing
      • Anatomy of a TB/RTL Race
      • Clocking Blocks as the Cure
      • Scheduling Regions: the Full Map
      • Hierarchical References & Force/Release
  • Senior & Interview Preparation21
  • Principal-Level Verification28
Loading lesson

‹RTL/TB Boundaries, Races & Timing
  1. Topics
  2. SystemVerilog
  3. Advanced Language & Integration
  4. RTL/TB Boundaries, Races & Timing
  5. Clocking Blocks as the Cure

Part 7 · Advanced & Integration · Intermediate

Clocking Blocks as the Cure

Input and output skews that move testbench access out of the RTL race window.

On this page

    Sample early, drive late

    A clocking block declares once when the testbench samples and when it drives, relative to its clocking event. The defaults are chosen to dodge the race window on both sides.

    Input skew #1step samples the value held just before the edge, in the Preponed region. Output skew #0 drives in the Re-NBA region of the same step, after the RTL has read its inputs.

    Skew

    Takes effect

    Meaning

    input #1step

    Preponed region

    Samples the stable pre-edge value, the same value the RTL flops capture

    output #0

    Re-NBA region, same time step

    Lands after RTL reads for this edge; the DUT consumes it at the next edge

    output #2ns

    Re-NBA region of the time step 2ns after the clocking event

    Same region, later time slot: the pin changes 2ns after the edge, which reads cleanly on waves

    1step

    One precision unit, not a tunable delay

    Never confuse it with a 1ns delay

    The listing below is an interface with no testbench around it, so it is not run in this course's checks. Icarus 13 has no clocking blocks; Verilator 5.048 compiles them.

    bus_if.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // not-run: interface only, no testbench module; Icarus 13 has no clocking blocks (Verilator 5.048 compiles it)
    interface bus_if (input logic clk);
      logic        valid, ready;
      logic [7:0]  data;
    
      clocking cb @(posedge clk);
        default input #1step output #0;
        input  ready;            // TB samples: value just BEFORE the edge
        output valid, data;      // TB drives: after the edge, in Re-NBA
      endclocking
    
      modport tb (clocking cb);  // TB sees ONLY the skewed view
    endinterface

    The same race, re-walked

    Diagram
    SAME SCENARIO, NOW THROUGH cb - time step at posedge clk
    
      PREPONED
      +------------------------------------------------------+
      | cb inputs sampled = values from BEFORE the edge      |
      | (no process has run yet - ordering is impossible)     |
      +------------------------------------------------------+
                              |
      ACTIVE / NBA            v
      +------------------------------------------------------+
      | RTL always_ff runs: reads din (old value), schedules |
      | dout <= old value in NBA. The TB has touched NOTHING |
      | in this region. No race possible.                    |
      +------------------------------------------------------+
                              |
      RE-NBA (TB drive lands) v
      +------------------------------------------------------+
      | cb drive takes effect HERE - after all RTL reads for |
      | this edge are done. RTL consumes it at the NEXT      |
      | posedge. Deterministic in every simulator.           |
      +------------------------------------------------------+
    
      ORDER A and ORDER B from the race lesson now produce
      IDENTICAL results - ordering no longer matters.

    It moves the TB's sample point and drive point into regions where no RTL process is competing. The block does not pick a friendlier order; it makes every legal order produce the same result.

    The bottom row, dout, still holds the pre-edge value in each slot where din just changed. The drive lands after the edge and the sample keeps the value from before it.

    • Slot 0: din is 12, so dout still holds 00 (the pre-edge value).

    • Slot 1: din is 34, so dout takes 12.

    • Slot 2: din holds 34, so dout takes 34.

    • Slot 3: din is 56, so dout still holds 34.

    • Slot 4: din is 78, so dout takes 56.

    • Slot 5: din holds 78, so dout takes 78.

    Driver and monitor rules

    Every drive goes through the clocking block with a nonblocking assignment, and every sample reads the clocking input. One clock authority per boundary: synchronize with the clocking event, never with a bare edge in some tasks and the block in others.

    • Drive as vif.cb.sig <= val and read as vif.cb.sig. Touching the raw pin reopens the race.

    • ##N needs a default clocking in the enclosing module, interface, program or checker. Class and package code cannot declare one, so it uses repeat (N) @(vif.cb);.

    • ##[1:4] range syntax belongs to assertions and sequences only. Drivers and monitors use plain ##N.

    Common pitfall

    Mixing a clocking drive with a raw assignment to the same pin creates two drivers that fight. Reading the raw signal in a monitor lets the sample race back in through the back door.

    Interview

    Likely question: “What does a clocking block actually do?” Answer with when, not what: Preponed sampling and Re-NBA driving, so ordering stops mattering. For synchronous pin access a module testbench strictly through clocking blocks is already race-free; anything still driven outside the block keeps NBA discipline.

    Check yourself An output skew of #2ns is used instead of #0. Which region does the drive land in?

    Still the Re-NBA region, but of the time step 2ns after the clocking event: same region, later time slot.

    Check yourself A class task uses ##1 with no default clocking in its scope. What happens?

    The delay has no clocking to resolve against, so it is an error. A class cannot declare a clocking block, so write repeat (1) @(vif.cb); instead.

    Testbench

    The runnable equivalent stages the same contract without same-edge gambling. A settled pre-edge drive is captured with one-cycle latency, while a drive landing just after the edge waits for the next one.

    The clocking-block form itself stays in the interface listing above. Same-step drive-and-sample ordering is exactly what this topic refuses to rely on.

    flop8.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    timeunit 1ns; timeprecision 1ps;
    
    module flop8 (
      input logic clk,
      input logic [7:0] d,
      output logic [7:0] q
    );
      always_ff @(posedge clk) q <= d;
    endmodule
    

    Related topics

    • Interfaces

    • Testbench anatomy

    Previous

    208 / 259

    Next: Scheduling Regions: the Full Map

    Up next

    Up nextScheduling Regions: the Full Map

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Hierarchical References & Force/Release
    clkdin12345678dout012345678
    A post-edge drive with a pre-edge sample across six slots