Ready-to-run snippets

Code Examples

Ready-to-run Verilog, SystemVerilog, and UVM examples. Click any to open it live in the IDE.

← All examples

Quick Refresher: Virtual Interfaces

SystemVerilog Advanced Features

Runnable example from the SystemVerilog Quick Refresher tutorial (Virtual Interfaces)

Open in IDE
design.sv
interface axi_lite_if #(
  parameter int ADDR_W = 32,
  parameter int DATA_W = 32
)(
  input logic clk,
  input logic rst_n
);
  logic [ADDR_W-1:0] awaddr;
  logic              awvalid;
  logic              awready;
  logic [DATA_W-1:0] wdata;
  logic              wvalid;
  logic              wready;
  logic [1:0]        bresp;
  logic              bvalid;
  logic              bready;

  // Modport - defines port directions from each perspective
  modport master (
    input  clk, rst_n,
    output awaddr, awvalid, wdata, wvalid, bready,
    input  awready, wready, bresp, bvalid
  );

  modport slave (
    input  clk, rst_n,
    input  awaddr, awvalid, wdata, wvalid, bready,
    output awready, wready, bresp, bvalid
  );
endinterface

// Module using the interface through a modport
module axi_slave (
  axi_lite_if.slave bus
);
  always_ff @(posedge bus.clk or negedge bus.rst_n) begin
    if (!bus.rst_n) begin
      bus.awready <= 1'b0;
    end else begin
      bus.awready <= bus.awvalid & ~bus.awready;
    end
  end
endmodule
testbench.sv
// Virtual interface - a handle to an interface instance.
// Allows class-based testbenches to drive/sample physical signals.

class axi_txn;
  rand bit [31:0] addr;
endclass

class Driver;
  virtual axi_lite_if vif;     // virtual interface handle

  function new(virtual axi_lite_if vif);
    this.vif = vif;
  endfunction

  task run(axi_txn txn);
    @(posedge vif.clk);
    vif.awaddr  <= txn.addr;
    vif.awvalid <= 1'b1;
    @(posedge vif.clk iff vif.awready);
    vif.awvalid <= 1'b0;
    $display("[%0t] Driver sent address 0x%0h", $time, txn.addr);
  endtask
endclass

// In testbench top
module tb;
  logic clk, rst_n;
  always #5 clk = ~clk;

  axi_lite_if u_if (.clk, .rst_n);
  axi_slave   dut  (.bus(u_if.slave));

  Driver  drv = new(u_if);     // pass interface to class
  axi_txn txn = new();

  initial begin
    clk = 0; rst_n = 0;
    u_if.awvalid = 0;
    #20 rst_n = 1;
    void'(txn.randomize());
    drv.run(txn);
    #20 $finish;
  end
endmodule
Admin mode — edit and delete controls are visible on each row. Use the IDE to add new snippets via File → Save as Snippet.