Functional Verification: What is a SystemVerilog Virtual Interface?
When I learned the SystemVerilog verification features, one concept had me baffled – virtual interfaces. What are these and why are they needed?
What is an interface?
Start with an interface. Quick summary: Back in Verilog days, a module had ports, which were individual signals. To connect two modules, each with 9 ports, you had to list all 9 signals. This is very error prone.
When you connect your TV to a DVD player, do you connect individual wires? No, you plug an HDMI cable, click, and are done. You don’t even have to know how many wires are in an HDMI cable (It is 20!). In SystemVerilog, a bundle of wires is called an interface.
An interface contains wires and synthesizable methods to perform operations such as sending and receiving transactions. An interface is RTL, just like your design. Here is an interface with 7 signals and a task to receive a transaction.
task receive(output logic [31:0] data);
Real hardware is static. If your chip is fabricated with 3M gates, it can’t suddenly have 4M gates just because you need a little boost. In simulation, the RTL design is static. It is described at compile time and can’t grow or shrink. Likewise, your simulation has a fixed number of interfaces, specified at compile time, and can’t change at run time.
SystemVerilog classes and objects are dynamic. If you need to send 1000 transactions, construct 1000 objects. Need 2000? Just construct more. If your UVM testbench decides it needs 2 drivers instead of the default of 1, it just creates another driver (or agent) at runtime.
Since objects are dynamic, they can’t contain interfaces. Otherwise, when you construct that second driver at runtime, it would create a second interface, which is not allowed.
But an object can contain pointers. For example, an agent has a pointer (handle / class variable) to the objects for the driver, monitor, etc. How can you make a pointer to the RTL interface?
In SystemVerilog, the keyword “virtual” usually means pointer. A virtual interface is a just pointer to an interface.
Here is the test module with a colors interface and a driver. When it constructs the driver, it passes a pointer to the (physical) interface.
module test(colors_ifc c_ifc);
d = new(c_ifc); // Pass interface
The driver class saves the pointer in a virtual interface, so it can use it later to drive signals.
virtual colors_ifc v_ifc; // Pointer to RTL instance
function new(input virtual colors_ifc c_ifc);
v_ifc = c_ifc;
task send(input logic [31:0] data);
v_ifc.r = data;
The Driver class is reusable as it can point to any color_ifc. If your testbench need to connect to two interfaces, it just constructs two Driver objects, passing in each interface instance.
Want to learn more about SystemVerilog and UVM? Visit Siemens EDA training for a list of courses or explore our many learning paths with the OneGlance Map. We offer courses taught by live instructors and On Demand Training for self-paced learning.
Blog Author: Chris Spear, Principal Customer Training Engineer, Siemens EDA Learning Services. Author of the book SystemVerilog for Verification