In short: A clocking block is a SystemVerilog construct that groups signals under a single clock and applies explicit input/output skews, so a testbench samples and drives DUT signals synchronously relative to a clock edge instead of chasing zero-time races. It is the backbone of race-free, reusable stimulus in interface-driven verification environments like UVM.
A clocking block is a named region, declared inside a module, interface, or program, that bundles a set of signals together with a clocking event (typically a clock edge) and a set of timing skews that govern exactly when those signals are sampled and when they are driven. Introduced in the IEEE 1800 SystemVerilog standard, it exists primarily to solve a verification problem: the testbench and the design under test (DUT) both live in the same simulation timeline, and without a disciplined timing contract, the testbench can easily read a signal before or after the DUT has updated it, producing non-deterministic results.
The construct is deceptively small. You name it, you give it a clocking event such as @(posedge clk), and then you list the signals you care about, each tagged as an input (sampled by the testbench) or output (driven by the testbench). Once declared, every reference to a clocked signal through that block is automatically synchronized to the clock edge, and the skews decide whether sampling happens just before the edge and driving just after it.
In event-driven simulation, signals updated at the same simulation time can be evaluated in an order the language does not fully pin down between the design and the testbench domains. If a testbench reads a DUT output at the exact instant the clock rises, it may observe either the old value or the newly computed one. This is the classic zero-time race condition, and it makes a passing test one day fail the next after an unrelated change, or behave differently across simulators.
SystemVerilog's scheduler divides each time step into ordered regions. Design logic driven by nonblocking assignments settles in the NBA region, while clocking-block sampling is defined to occur in the Observed region and clocking-block outputs are applied in the Re-NBA region. Because a clocking block sampling event is specified to read values as they existed at the Postponed/steady state just before the active edge, the testbench always sees stable, settled data rather than mid-flight transitions.
#1step, meaning inputs are sampled in the Preponed region at the value they held in the final moment of the previous time step — guaranteeing the testbench never catches a signal mid-transition on the active edge.Skew is the heart of the mechanism. Each clocking block can specify a default skew, and individual signals can override it. Two directions matter:
#1step samples the value from the end of the previous time step, which is the safest choice and the default. A skew of #2ns would sample 2 ns before the edge.output #1 or a small nonzero delay so stimulus changes land cleanly after the edge, well clear of the DUT's own setup window.A representative declaration reads:
clocking cb @(posedge clk); default input #1step output #1; input data_out, valid; output data_in, enable;endclockingNow writing cb.data_in <= 8'hAA; schedules the drive one time unit after the next rising edge, and reading cb.data_out returns the value sampled a step before that edge. The timing contract is explicit, documented, and identical across every simulator that conforms to the standard.
The construct becomes most powerful when placed inside a SystemVerilog interface. An interface bundles the physical wires of a protocol; adding a clocking block gives it a synchronous view that a testbench can connect to through a modport. This separates the pin-level connectivity from the timing discipline, so the same interface can expose one clocking block for the driver and another for the monitor, each with skews appropriate to its role.
Using wait(cb.valid); or @(cb); lets sequential testbench code advance in step with the clock. In UVM environments, drivers and monitors reach into a virtual interface's clocking block for every pin wiggle, which is precisely why reusable verification IP behaves deterministically regardless of the integration timescale.
Real projects and industry tool flows, with certification.
Explore CourseTron Courses →All three major simulators — Synopsys VCS, Cadence Xcelium, and Siemens Questa — implement the IEEE 1800 scheduling regions that make clocking blocks deterministic, which is the whole point of codifying the behavior in the standard. In practice, engineers lean on a few tool-aware habits:
force/assignment on an interface signal with clocking-block drives on the same signal reintroduces races the block was meant to remove.<=) assignment to clocking-block outputs so drives schedule in the correct region.#1 output skew means one time unit of the block's own timescale, so a mismatched `timescale can silently change when stimulus lands.#1step while the driver applies output skew, avoiding the two stepping on each other.When a waveform shows stimulus changing exactly on the edge rather than a hair after it, that is usually the first clue a clocking block was bypassed somewhere in the environment.
It eliminates zero-time race conditions between the testbench and the DUT by defining exactly when signals are sampled (before the edge) and driven (after the edge), so results are deterministic and portable across simulators.
It means the signal is sampled in the Preponed region at the value it held at the very end of the previous time step. This guarantees the testbench reads a settled value and never catches a signal in transition on the active edge; it is also the default input skew.
A modport declares signal directions and access for a particular connection to an interface, while a clocking block adds synchronous timing — a clock event plus skews. They are complementary: a modport can reference a clocking block to give a testbench role a race-free, direction-correct view of the bus.
Clocking-block output drives are scheduled into the Re-NBA region after the clock edge. Using <= ensures the drive is queued correctly for that region with the specified output skew, keeping stimulus clear of the DUT's setup window and avoiding glitches on the edge.
Related: functional coverage in SystemVerilog · the VLSI Glossary · all courses.