Clocking Blocks & Interfaces Interview
Master SystemVerilog interfaces: clocking blocks, skew, modports, virtual interfaces, and race-free testbench design.
Beginner Level
Fundamentals@(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.
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
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 Standardinput #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
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.
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
Expertdefault 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
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
#1nsmeans sample 1ns BEFORE clock edge. - At that point,
dut_readystill 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.
Key Principles:
- Separate Interfaces: Each clock domain has its own interface with its own clocking block.
- Explicit Synchronization: Use
@(domain_a.cb)and@(domain_b.cb)explicitly—never mix. - 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);
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.