DUT这边的Interface定义:
interface aa_bb_if();
logic a2b_rsp_vld ;
logic [ 1:0] a2b_rsp_ts ;
modport a2b(
output a2b_rsp_vld ,
output a2b_rsp_ts
);
modport b2a(
input a2b_rsp_vld ,
input a2b_rsp_ts
);
endinterface
验证环境这边对应的Interface定义:
interface dv_aa2bb_interface (input bit clk, input bit rst_n);
parameter setup_time = 0.01;//ns
parameter hold_time = 0.01;//ns
logic [ 0:0] aa_bb_rsp_vld;
logic [ 1:0] aa_bb_rsp_ts; //
clocking driver_cb @(posedge clk);
default input #setup_time output #hold_time;
output aa_bb_rsp_vld;
output aa_bb_rsp_ts;
endclocking: driver_cb
clocking monitor_cb @(posedge clk);
default input #setup_time output #hold_time;
input aa_bb_rsp_vld;
input aa_bb_rsp_ts;
endclocking: monitor_cb
modport drv_cb(clocking driver_cb);
modport mon_cb(clocking monitor_cb);
`ifdef ASSERT_ON
//----------------add your assertion of interface here -----------------//
// property err_valid;
// @(posedge clk) $rose(err) |=> $fell(valid);
// endproperty
// assert_err_valid: assert property(err_valid);
`endif
endinterface: dv_aa2bb_interface
top_tb层的例化连接:
module top_tb();
//......
aa_bb_if aa2bb_if ;
XX_DUT U_DUT(
.clk (clk),
.u_aa_bb_if (aa2bb_if )
);
`include "top_if.sv"
endmodule
top_if的连接:
dv_aa2bb_interface u_dv_aa_bb_interface[1] (.clk(`TOP_TB.clk),.rst_n(`TOP_TB.rst_n));
//这里还有一个关键步骤:interface的句柄赋值给 virtual interface并set给对应组件;
virtual dv_aa2bb_interface vir_dv_aa_bb_interface[1];
vir_dv_aa_bb_interface = u_dv_aa_bb_interface;
foreach(vir_dv_aa_bb_interface[i])begin
uvm_config_db #(virtual dv_aa2bb_interface )::set(null, $sformatf("uvm_test_top.env.m_aa_bb_agent[%0d]*",i), "bus",vir_dv_aa_bb_interface[i]);
end
//assign:右边是驱动源
assign `TOP_TB.aa2bb_if.a2b_rsp_vld = u_dv_aa_bb_interface[0].aa_bb_rsp_vld ;
assign `TOP_TB.aa2bb_if.a2b_rsp_ts = u_dv_aa_bb_interface[0].aa_bb_rsp_ts ;
还有一种场景是环境代码都是直接放到pakage里面:
1)interface定义同上;
2)interface文件在filelist中,要放到声明interface文件的前面编译;
3)top层:
4)refm层:
一般做到interface的东西:
- 接口覆盖率;
- 断言检查vld有效时,data不是X/Z态;复位无效时,没有vld有效报文输出;
一些问题记录:
记录:如果interface里面的信号声明用了logic,可能会被定义成变量类型,而不是wire类型,在顶层assign连接时会有报错。不能驱动一个variable。
Input port cannot be driven - #4 by stas2005 - SystemVerilog - Verification Academy
我向 Synopsys 提交了一个案例,这是我得到的答复。希望可能对其他人有所帮助。
从下面的(LRM,语言参考手册)可以看出,对声明为输入端口的变量进行赋值是不允许的。
23.3.3.2 变量的端口连接规则
如果端口声明使用变量数据类型(variable data type),则其方向控制实例化时的连接方式,规则如下:
— 输入端口可以连接到兼容数据类型的任意表达式。当变量连接到输入端口声明时,隐含持续赋值(continuous assignment)。对声明为输入端口的变量进行赋值是非法的。如果未连接,该端口应具有对应数据类型的默认初始值。当在
addr
的端口声明中使用logic
时,addr
变为变量(非线网类型)。当省略logic
时,addr
变为线网类型,此时直接对其赋值是合法的。你可以通过两个实验验证:省略
logic
时,addr
变为wire
(线网)类型。module A ( input [31:0] addr ///<— 省略logic //input logic [31:0] addr ); wire [31:0] addr; ///<---- 无错误!合法 logic [31:0] addr; ///<— 错误!非法 wire [31:0] addr_local; assign addr_local = addr; endmodule