什么是接口?
接口是一种将信号封装到块中的方法。 所有相关信号都组合在一起以形成一个接口块,以便可以将同一接口重新用于其他项目。 而且,与DUT和其他验证组件的连接也变得更加容易。
例
APB总线协议信号被放到给定的接口中。 请注意,信号在interface和endinterface内声明。
interface apb_if (input pclk);//接口端口
logic [31:0] paddr;
logic [31:0] pwdata;
logic [31:0] prdata;
logic penable;
logic pwrite;
logic psel;
endinterface
为什么信号要声明为logic?
logic是一种新的数据类型,它使您可以通过assign语句并在过程块中驱动此类信号。 请记住,在verilog中,您只能在程序块中驱动reg,而在assign语句中仅驱动连接。 但这仅仅是一个原因。
连接到DUT的信号应支持4种状态,以便可以捕获X / Z值。 如果这些信号类型为bit,则X / Z将会显示为0,并且您可能会错过DUT具有X / Z值的情况。
如何定义端口方向?
接口信号可以在各种验证组件以及DUT中使用,因此modport用于定义信号方向。 可以将不同的modport定义传递给不同的组件,这使我们可以为每个组件定义不同的输入输出方向。
// Filename : myBus.sv
interface myBus (input clk);
logic [7:0] data;
logic enable;
// 从TestBench的角度来看,'data' 是输入, 'write' 是输出
modport TB (input data, output enable);
//从DUT的角度来看, 'data'是输出, 'enable' 是输入;
modport DUT (output data, input enable);
endinterface
如何将接口与DUT连接?
应该在实例化DUT的顶部测试平台模块中创建一个接口对象,并将其传递给DUT。必须确保将正确的Modport分配给DUT。
// Filename : dut.sv
module dut (myBus.DUT busIf);//将接口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;
// 创建时钟
always #10 clk = ~clk;
// 创建一个接口对象
myBus busIf (clk);
// 实例化DUT;通过busIf的modport DUT
dut dut0 (busIf.DUT);
//Testbench代码:让我们摆动启用
initial begin
enable <= 0;
#10 enable <= 1;
#40 enable <= 0;
#20 enable <= 1;
end
endmodule
有什么优势?
接口可以包含任务,函数,参数,变量,功能覆盖范围和断言。 这使我们能够通过此块中的界面监视和记录交易。 由于该信息被封装在接口中,因此无论连接到端口多少,都可以更轻松地连接到设计。
//端口
dut dut0 (.data (data),
.enable (enable),
// all other signals
);
//带有接口-可以进行更高级别的抽象
dut dut0 (busIf.DUT);
如何参数化接口?
对模块的处理方式相同。
interface myBus #(parameter D_WIDTH=31) (input clk);
logic [D_WIDTH-1:0] data;
logic enable;
endinterface
什么是时钟块?
时钟模块内部指定的信号将相对于该时钟进行采样/驱动。 接口中可能有多个时钟块。 请注意,这是与测试台相关的信号。 您想控制TB何时驱动和采样来自DUT的信号。 解决部分竞争条件,但不能完全解决。 您还可以参数化偏斜值。
interface my_int (input bit clk);
// 接口代码的其余部分
clocking cb_clk @(posedge clk);//定义时钟块
default input #3ns output #2ns;
input enable;
output data;
endclocking
endinterface
在上面的示例中,我们指定了默认情况下,应在clk构成之前3ns采样输入,在clk构成之后2ns驱动输出。
如何使用时钟块?
//调用时钟模块
@ busIf.cb_clk;
//使用时钟块信号
busIf.cb_clk.enable = 1;
在赋值1之前没必要等待时钟上升沿,这样,可以确保在下一个posek clk之后2ns驱动使能。
参考文献:
【1】http://chipverify.com/systemverilog/systemverilog-interface