What is an Interface ?
An Interface is a way to encapsulate signals into a block. Normally, you would put all related signals together and create an interface block so that the same code can be re-used for other projects and can be used to connect with the DUT and other verification components.
What does an example look like ?
This is a simple example of how you can put APB signals together and create an interface block. Note that signals are declared within
interface apb_if (input pclk); logic [31:0] paddr; logic [31:0] pwdata; logic [31:0] prdata; logic penable; logic pwrite; logic psel; endinterface
So, why are the signals declared
As you might already know,
logic is a new data type that lets you drive signals of this type via assign statements and in a procedural block. Remember that in verilog, you could drive a
reg only in procedural block and a
wire only in assign statement. But this is only one reason.
Signals connected to the DUT should support 4-states so that X/Z values can be caught. If these signals were
bit then the X/Z would have shown up as 0, and you would have missed that DUT had a X/Z value.
What about port directions ?
Exactly. Since these signals can be used within various verification components as well as the DUT, port directions are specified in
modport block. So, based on what modport is used, the port directions can be changed. Here's an example:
// Filename : myBus.sv interface myBus (input clk); logic [7:0] data; logic enable; // From TestBench perspective, 'data' is input and 'write' is output modport TB (input data, output enable); // From DUT perspective, 'data' is output and 'enable' is input modport DUT (output data, input enable); endinterface
So, how do you connect it with the DUT ?
In the top testbench module, where you instantiate the DUT, create an interface object and pass it to the DUT. Make sure that you pass the correct modport to the DUT.
// Filename : dut.sv module dut (myBus.DUT busIf); always @ (posedge clk) if (busIf.enable) busIf.data <= busIf.data+1; else busIf.data <= 0; endmodule // Filename : tb_top.sv module tb_top; bit clk; bit enable; // Create a clock always #10 clk = ~clk; // Create an interface object myBus busIf (clk); // Instantiate the DUT; pass modport DUT of busIf dut dut0 (busIf.DUT); // Testbench code : let's wiggle enable initial begin enable <= 0; #10 enable <= 1; #40 enable <= 0; #20 enable <= 1; end endmodule
Simple enough. Any other advantages ?
Interfaces can contain tasks, functions, parameters, variables, functional coverage, and assertions. So, you can basically monitor, and record the transactions via the interface within this block. Moreover, when designs contain hundreds of ports, it becomes easier to connect to DUT, because now you don't need to connect each wire of TB with the DUT.
//Before interface dut dut0 (.data (data), .enable (enable), // all other signals ); // With interface - higher level of abstraction possible dut dut0 (busIf.DUT);
How do I parameterize an interface
The same way you would do for a module.
interface myBus #(parameter D_WIDTH=31) (input clk); logic [D_WIDTH-1:0] data; logic enable; endinterface
What are clocking blocks ? I have seen them in interfaces.
Put simply, signals that are specified inside a clocking block will be sampled/driven with respect to that clock. You can have mulitple clocking blocks in an interface. Note that this is for testbench related signals. You want to control when the TB drives and samples signals from DUT. Solves some part of the race condition, but not entirely. You can also parameterize the skew values.
clocking cb_clk @(posedge clk); default input #3ns output #2ns; input enable; output data; endclocking
In the above example, we have specified that by default, input should be sampled 3ns before posedge of clk, and output should be driven 2ns after posedge of clk.
How can I use a clocking block ?
// To wait for posedge of clock @busIf.cb_clk; // To use clocking block signals busIf.cb_clk.enable = 1;
As you can see, you don't have to wait for the posedge of clk, before you assign 1 to enable. This way, you are assured that enable will be driven 2ns after the next posedge clk.