interface 和 module是同樣的, 都是靜態的變量, 也就是在程序開始時, 內存中就有了其實例.
interface Rx_if (input logic clk);
logic [7:0] data;
logic soc, en, clav, rclk;
clocking cb @(posedge clk);
output data, soc, clav;
input en;
endclocking : cb
modport DUT (output en, rclk,
input data, soc, clav);
modport TB (clocking cb);
endinterface : Rx_if
...
...
program automatic test(
Rx_if.TB Rx[4],
Tx_if.TB Tx[4],
output logic rst);
........
Driver drv[4];
//實例化了4個 Driver 對象,每一個 Driver對象帶有1個實例化的虛接口
.........
initial begin
virtual Rx_if.TB vRx_t=Rx;
//建立一組虛接口,因爲這裏定義了virtual,因此實例化的時候能夠有Rx[].
for (int i=0; i<4; i++) begin
drv[i] = new(...., vRx[i]);
end
rst <= 1;
repeat (10) @Rx[0].cb;
rst <= 0;
for (int i=0; i<4; i++) begin
drv[i].run(5, driver_done); //發送
.......
end
..........
endprogram : test
最後在頂層:
module top;
logic clk, rst;
Rx_if Rx[4] (clk);
,,,,
atm_router a1 (Rx[0], Rx[1], Rx[2], Rx[3], Tx[0], Tx[1], Tx[2], Tx[3], clk, rst);
test t1 (Rx, Tx, rst);
initial begin
clk = 0;
forever #20 clk = !clk;
end
endmodule : top
定義一個interface,且實例化多個後,若是沒有定義virtual,則在任何一個實例中修改了某個信號值,在其餘實例中都會受到影響。若是定義了virtual,則每一個實例獨立。若是該interface只有一個實例,可用可不用virtual,有多個實例,須要virtual。
再舉個例子:8位計數器
`timescale 1ns/1ns
interface X_if (input logic clk);
logic [7:0] din, dout;
logic reset_l, load;
clocking cb @(posedge clk);
output din, load;
input dout;
endclocking
always @cb
//接口裏面也能夠帶子程序,斷言,initial,always塊等代碼。
$strobe("@ : %m: dout= , din= , load= , reset= ",
$time, dout, din, load, reset_l);
modport DUT (input clk, din, reset_l, load,
output dout);
modport TB (clocking cb, output reset_l);
endinterface
// Simple 8-bit counter with load and active-low reset
`timescale 1ns/1ns
module DUT(X_if.DUT xi);
logic [7:0] count;
assign xi.dout = count; //們想要輸出的結果就是計數器
always @(posedge xi.clk or negedge xi.reset_l)
begin
if (!xi.reset_l) count = 0;
else if (xi.load) count = xi.din;
else count++;
end
endmodule
////////////////////////////////
`timescale 1ns/1ns
program automatic test();
parameter NUM_XI = 2; // Number of interface instances
typedef virtual X_if.TB vXi_t;
vXi_t vxi[NUM_XI];
//虛接口數組
class Driver;
//在測試程序中定義類
vXi_t xi;
int id;
function new(vXi_t xi, int id);
this.xi = xi;
this.id = id;
endfunction
task reset;
fork
begin
$display("@ : %m: Start reset [ ]", $time, id);
// Reset the device
xi.reset_l <= 1;
xi.cb.load <= 0;
xi.cb.din <= 0;
@(xi.cb)
xi.reset_l <= 0;
@(xi.cb)
xi.reset_l <= 1;
$display("@ : %m: End reset [ ]", $time, id);
end
join_none
endtask
task load;
fork
begin
$display("@ : %m: Start load [ ]", $time, id);
xi.cb.load <= 1;
xi.cb.din <= id + 10;
xi.cb.load <= 0;
repeat (5) @(xi.cb);
$display("@ : %m: End load [ ]", $time, id);
end
join_none
endtask
endclass
Driver driver[];
initial begin
// Connect the local virtual interfaces to the top
$display("Test.v: There are NUM_XI = interfaces", NUM_XI);
if (NUM_XI <= 0) $finish;
driver = new[NUM_XI];
//建立driver, 每一個DUT 要對應一個driver
vxi = top.xi;
//XMR跨模塊鏈接。這種是推薦作法,就不用帶參數了program automatic test(X_if xi[NUM_XI]); 了。
//注意這裏實際上是把top模塊中生成的xi[]數組的句柄傳過來的
for (int i=0; i《NUM_XI; i++)
begin
driver[i] = new(vxi[i], i);
driver[i].reset;
end
foreach (driver[i])
driver[i].load;
repeat (10) @(vxi[0].cb);
$display("@ : Test completed", $time);
$finish;
end
endprogram
////////////////////////////////////////////////////////
`timescale 1ns/1ns
parameter NUM_XI = 2; // Number of interface instances
module top;
// Clock generator
bit clk;
initial forever #20 clk = !clk;
X_if xi [NUM_XI] (clk); // Instantiate N Xi interfaces
// Generate N DUT instances
generate
for (genvar i=0; i《NUM_XI; i++)
begin : dut
DUT d (xi[i]);
end
endgenerate
// Instantiate the testbench, overriding the parameter with number of instances
test tb();
endmodule : top