Clocking Blocks & Interfaces Interview

Master SystemVerilog interfaces: clocking blocks, skew, modports, virtual interfaces, and race-free testbench design.

Beginner Level

Fundamentals
What problem does a clocking block solve that a simple @(posedge clk) does not?

Problem with @(posedge clk): Both testbench and DUT execute at the same simulation time, causing race conditions. The order of execution is non-deterministic.

Clocking Block Solution:

  • Input Skew: Samples signals BEFORE the clock edge (sees stable values).
  • Output Skew: Drives signals AFTER the clock edge (DUT sees stable inputs).
clocking cb @(posedge clk);
    default input #1step output #0;
    input  dut_output;  // Sampled before edge
    output dut_input;   // Driven after edge
endclocking

This explicit timing separation eliminates all synchronization races.

What is an interface in SystemVerilog? How does it differ from a struct?

Interface:

  • Encapsulates a bundle of signals.
  • Can contain modports, clocking blocks, tasks, functions.
  • Used for module port connections.
  • Synthesizable (signal bundle) + verification features.

Struct:

  • Groups data into a single compound variable.
  • No procedural code, no modports.
  • Used for data encapsulation, NOT port connections.
interface bus_if(input logic clk);
    logic [31:0] data;
    logic valid, ready;
    modport master(output data, valid, input ready);
    modport slave(input data, valid, output ready);
endinterface
struct packed {
    logic [31:0] data;
    logic valid;
} packet_t;  // Just a data container
What is a modport? Why is it useful to have separate modports for DUT and Testbench?

Modport (Module Port): Defines directional access to interface signals for different users.

interface axi_if;
    logic [31:0] awaddr;
    logic awvalid, awready;
    modport MASTER (output awaddr, awvalid, input awready);
    modport SLAVE  (input awaddr, awvalid, output awready);
endinterface

Benefits:

  • Type Safety: Prevents accidental wrong-direction usage.
  • Clarity: Documents intended signal directions.
  • Tool Checks: Synthesis tools can verify connectivity.

Intermediate Level

Industry Standard
Explain input skew and output skew in a clocking block. If you specify input #2ns and output #1ns, when is each action performed relative to the clock edge?

Input Skew (#2ns): Signal is sampled 2ns BEFORE the clock edge.

Output Skew (#1ns): Signal is driven 1ns AFTER the clock edge.

Timeline:
|----2ns----|------clock edge------|---1ns----|
    ↑                   ↑                ↑
 Sample              Clock            Drive
 Input              Event            Output

Example:

clocking cb @(posedge clk);
    input #2ns  dut_data;   // Read 2ns before posedge
    output #1ns tb_data;    // Write 1ns after posedge
endclocking
What is a virtual interface? Why can't you pass a regular interface handle to a class?

Problem: Interfaces are static (elaborated at compile time). Classes are dynamic (created at runtime). You can't store a static thing in a dynamic object.

Solution: A virtual interface is a handle (like a pointer) that can reference any physical interface instance.

interface bus_if;
    logic [7:0] data;
endinterface
class Driver;
    virtual bus_if vif;  // Virtual interface handle
    function new(virtual bus_if vif);
        this.vif = vif;
    endfunction
    task drive(logic [7:0] d);
        vif.data = d;  // Access interface through handle
    endtask
endclass

Key: The keyword virtual makes it a runtime-resolvable reference.

You have a clocking block inside an interface. In your driver class, you receive a virtual interface handle. Show the syntax to access signal data via the clocking block.
interface axi_if(input logic clk);
    logic [31:0] data;
    logic valid;
    clocking cb @(posedge clk);
        output data, valid;
    endclocking
endinterface
class Driver;
    virtual axi_if vif;
    task send_data(logic [31:0] d);
        // Access via clocking block
        vif.cb.data <= d;
        vif.cb.valid <= 1;
        @(vif.cb);  // Wait for clocking event
        vif.cb.valid <= 0;
    endtask
endclass

Syntax: vif.cb.signal — virtual interface → clocking block → signal.

Advanced Level

Expert
(Timing Analysis) Consider default input #1step output #0;. What does #1step mean? In which simulation region is the input sampled?

#1step: The global time precision (smallest time unit). Effectively means "sample in the Postponed region of the PREVIOUS timestep."

Region: Inputs with #1step skew are sampled in the Postponed region of the prior time step, which is AFTER all design updates have settled.

Why Safest:

  • Postponed is the absolute last region before time advances.
  • All Active, NBA, and Reactive updates are complete.
  • You see the most stable, final value.
clocking cb @(posedge clk);
    default input #1step output #0;  // Industry best practice
    input dut_status;  // Sampled at most stable point
endclocking
Your DUT has a signal dut_ready that goes high 0.5ns AFTER the clock edge (clock-to-output delay). Your clocking block samples it with input #1ns. What value does the TB see?

Timeline:

|----1ns----|--posedge--|--0.5ns--|
    ↑            ↑           ↑
 Sample       Clock     dut_ready
 Point        Edge      changes

Analysis:

  • Input skew of #1ns means sample 1ns BEFORE clock edge.
  • At that point, dut_ready still has its OLD value (from previous cycle).
  • The NEW value (that changes 0.5ns after edge) won't be seen until NEXT cycle's sample.

Answer: TB sees the OLD value. To see the new value in the same cycle, use input #0 or sample later.

Your system has multiple clock domains with separate interfaces and clocking blocks. How do you handle signal crossings in your testbench?

Key Principles:

  1. Separate Interfaces: Each clock domain has its own interface with its own clocking block.
  2. Explicit Synchronization: Use @(domain_a.cb) and @(domain_b.cb) explicitly—never mix.
  3. RTL Synchronizers: Actual CDC (Clock Domain Crossing) must be handled in RTL with proper synchronizers (2FF, handshake, etc.).
interface domain_a_if(input logic clk_a);
    clocking cb @(posedge clk_a); ... endclocking
endinterface
interface domain_b_if(input logic clk_b);
    clocking cb @(posedge clk_b); ... endclocking
endinterface
// In TB: drive on domain A, wait, sample on domain B
@(vif_a.cb);
vif_a.cb.data <= 8'hAB;
repeat(3) @(vif_b.cb);  // Wait for synchronization
assert(vif_b.cb.synced_data == 8'hAB);
Can a clocking block be defined inside a module without using an interface? When would you prefer this?

Answer: Yes! Clocking blocks can be defined directly inside a module or program.

module tb;
    logic clk, data_in, data_out;
    clocking cb @(posedge clk);
        output data_in;
        input  data_out;
    endclocking
    initial begin
        cb.data_in <= 1;
        @(cb);
        if (cb.data_out != expected) $error("Mismatch!");
    end
endmodule

When to Use:

  • Simple, quick testbenches without full VIP infrastructure.
  • Unit tests for small modules where interfaces are overkill.
  • Legacy code migration where adding interfaces is too disruptive.

Prefer Interfaces When: Reusability, complex protocols, or UVM-based VIPs.