Back to Interview Prep

SystemVerilog Interview Questions - Part 3: Interfaces & Assertions

May 20, 2026 HDL2Chips Team SystemVerilog

This part covers SystemVerilog interfaces, clocking blocks, assertions, and UVM testbench concepts. These topics are frequently asked in verification engineer interviews at companies like Synopsys, Cadence, and Qualcomm.

Q21 What is a SystemVerilog interface and how does it differ from a module?

An interface encapsulates communication signals and protocols into a single reusable construct. Unlike a module, an interface does not describe behavior or hardware logic — it only bundles signals and can include tasks, functions, and modports. Interfaces simplify design changes by grouping related signals and enable protocol reuse across multiple testbench components. They can be instantiated like modules but are intended for connection and transaction-level modeling.

Q22 What is a modport in a SystemVerilog interface?

A modport (module port) defines the direction of signals within an interface from the perspective of a particular module or component. For example, a bus interface can have a master modport that declares certain signals as outputs for the master and inputs for the slave, and a slave modport with the opposite directions:

interface axi_if;
  logic [31:0] addr, wdata;
  logic       valid, ready;
  modport master (output addr, valid, input ready, wdata);
  modport slave  (input addr, valid, output ready, wdata);
endinterface

Modports enforce correct signal direction at compile time and make interfaces self-documenting.

Q23 Explain clocking blocks in SystemVerilog. Why are they used?

A clocking block specifies the synchronization of signals relative to a clock edge. It defines input sampling and output drive timing, helping avoid race conditions between the testbench and the DUT:

clocking cb @(posedge clk);
  input  #1step data;
  output #1     addr;
endclocking

Key benefits: (1) Inputs are sampled just before the clock edge (#1step), (2) Outputs are driven after the clock edge, (3) Clocking blocks centralize timing for all interface signals, (4) They enable cycle-accurate synchronization in verification environments.

Q24 What is the difference between immediate and concurrent assertions?

Immediate assertions (assert(expr)) are procedural checks that execute at a specific simulation time. They are non-temporal and evaluate immediately. Concurrent assertions (assert property (@(posedge clk) expr)) are temporal and checked continuously over time using sequences and properties. Concurrent assertions use a clock expression and can span multiple clock cycles. Immediate assertions are placed inside always_comb or initial blocks, while concurrent assertions are placed outside procedural code or within checker constructs.

Q25 Explain $rose, $fell, and $past system functions with an example.

These are built-in SystemVerilog assertion functions for edge detection and history:

  • $rose(signal) — returns true if signal changed to 1 from 0 in the current cycle
  • $fell(signal) — returns true if signal changed to 0 from 1
  • $past(signal, n) — returns the value of signal n clock cycles ago
property req_ack;
  @(posedge clk) $rose(req) |=> ##[1:5] ack;
endproperty

property stable_check;
  @(posedge clk) $fell(busy) |=> ($past(data) == data);
endproperty

The first property asserts that after a rising edge of req, ack must be high within 1 to 5 cycles. The second checks that data stays stable after busy falls.

Q26 What is a mailbox in SystemVerilog? How is it different from a queue?

A mailbox is a built-in thread-safe communication mechanism used to exchange messages between processes. It behaves as a FIFO with blocking or non-blocking put/get operations. Mailboxes are ideal for testbench components running in parallel (e.g., generator driving a driver):

mailbox #(transaction) mbx = new();
mbx.put(tr);    // blocking send
mbx.get(tr);    // blocking receive
mbx.try_put(tr); // non-blocking
mbx.try_get(tr); // non-blocking

A queue is a primitive array type and is not thread-safe. Queue operations require explicit synchronization. Mailboxes handle synchronization internally, making them safer for multi-process environments.

Q27 What is a semaphore? Give a typical verification use case.

A semaphore is a synchronization object that controls access to a shared resource. It maintains a key count — a process must get a key before accessing the resource and must put it back when done. A common use case is managing access to a shared bus in a multi-master testbench:

semaphore bus_sem = new(1); // only one key
bus_sem.get();     // acquire bus
// drive transactions on shared bus
bus_sem.put();     // release bus

Without semaphores, multiple drivers could corrupt each other's bus transactions.

Q28 What is a virtual interface and why is it needed in UVM?

A virtual interface is a reference (pointer) to an actual physical interface. It is needed in UVM because UVM components (classes) cannot directly instantiate hardware interfaces — they exist as static design elements. A virtual interface provides a handle that UVM components can use to drive and sample DUT signals:

class driver extends uvm_driver #(transaction);
  virtual axi_if vif;
  function void connect_phase(uvm_phase phase);
    vif = top_module.axi_if_inst; // connect in test layer
  endfunction
endclass

Without virtual interfaces, testbench components would have no way to interact with the RTL signals.

Q29 Compare uvm_component and uvm_object. When would you use each?

uvm_component inherits from uvm_object but has a hierarchical name, a parent, and a well-defined simulation phase execution (build, connect, run, etc.). Components are permanent and exist throughout the simulation. uvm_object is the base class for transient data items like transactions, sequences, and config objects. Objects are created and destroyed dynamically and do not participate in the UVM phase scheme. Use a component when you need a persistent testbench block (driver, monitor, scoreboard) and an object for data that flows between components.

Q30 List the major UVM phases and their execution order.

The UVM phases execute in this order:

  1. build_phase — Construct components and configure the environment
  2. connect_phase — Connect TLM ports and virtual interfaces
  3. end_of_elaboration_phase — Display topology and finalize configuration
  4. start_of_simulation_phase — Print banners and set initial states
  5. run_phase (main) — Execute actual testbench activity (task, consumes time)
  6. extract_phase — Collect results from monitors/scoreboards
  7. check_phase — Check for errors and protocol violations
  8. report_phase — Print test summary and pass/fail status
  9. final_phase — Last cleanup operations

All phases except run_phase are function-based (zero time). The run_phase is a task that consumes simulation time.

Master these SystemVerilog concepts and practice building UVM testbenches. Good luck!