虚接口
接口定义了验证平台与被测设计进行通信的信号,虚接口和对应的通用方法可以将验证平台与设计分隔开:
定义接口类型:interface variable_if; ... endinterface
例化实体接口:variable_if variable_if()
例化虚接口:virtual variable_if variable_vf;
接口类型的定义是一个过程块
虚接口通常是类的一个成员,该成员通过构造函数参数初始化或者过程初始化。
可以将虚接口看作对应接口类型的一个句柄
一般来说:实接口的例化在验证顶层模块中,虚接口的例化在各个类中,或类中的构造函数里,做绑定时一般在顶层模块中,将实接口传递给dut模块和其他虚接口。
端口模式
端口模式的定义在接口类型定义中定义,端口模式用于指定接口中的信号方向,使用关键字modport定义端口模式:
interface variable_if ;
wire a,b,c,d;
modport master(input a,b,output c,d); //主端口模式,端口名master
modport slave(output a,b,intput c,d); //从端口模式,端口名slave
endinterface
①端口模式引用在模块声明中
module a (variable_if.master i);... endmodule
module b (variable_if.slave i);... endmodule
模块a的端口列表采用variable_if类型的主端口模式;模块b的端口列表采用variable_if类型的从端口模式
以上是在模块声明时指定了端口模式,在接下来的顶层连接中,可以不指定端口模式,直接引用实现连接。
module top;
variable_if p(); //顶层模块例化实接口p()
a u1(.i(p)); //将实接口绑定到模块端口列表中,模块a的例化u1可以自动查找端口模式
b u2(.i(p)); //将实接口绑定到模块端口列表中,模块b的例化u2可以自动查找端口模式
endmodule
②端口模式用作顶层例化连接
在模块声明中,不指定端口模式:
module a (variable_if i);... endmodule
module b (variable_if i);... endmodule
在顶层连接中指定端口模式:
module top;
variable_if p(); //顶层模块例化实接口p()
a u1(.i(p.master)); //引用实接口的模块端口master绑定到模块端口列表
b u2(.i(p.slave)); //引用实接口的模块端口master绑定到模块端口列表
endmodule
③模块定义和例化连接时都采用端口模式
注意采用相同的端口名字(master/slave)
时钟控制块
端口模式可以指定接口中信号的方向,而时钟控制块用于指定信号所遵循的时钟信号。
①时钟控制模块的定义
该模块在接口定义中定义,定义时钟控制模块使用clocking关键字,是一个过程块:
clocking ck @(clock_event);...endclocking
声明了一个名为ck的时钟控制块,块内信号以时钟事件进行时钟控制。
②时钟偏差
在时钟事件发生时,输入信号需要被采样,输出信号需要被驱动,双向信号即被驱动又被采样。
时钟偏差是指信号偏离时钟事件多少个时间单位被采样或被驱动。
输入偏差默认为负值,也就是在时钟事件之前的某个时间被采样;输出偏差默认为正,也就是在时钟事件之后的某个时间被驱动。
通过使用defualt来指定整个时钟控制块的时钟偏差,
default input #10ns output #2ns;
该语句定义了时钟控制模块所有默认信号相对于时钟事件有10ns的输入偏差和2ns的输出偏差。
③块内信号
时钟控制模块内的信号不仅指明了方向,还指明了时序,在某一个时钟事件下同步动作,块内不同信号可以定义不同的偏差。
clocking ck1 @(posedge clock);
default input #10ns output #2ns;
input data,ready,enable=top.mem1.enable;//默认上升沿采样的输入信号,可以层次化引用
output negedge ack;//下降沿驱动的输出信号
input #1 step addr;//上升沿采样的输入信号,输入偏差为1 step
endclocking
除非另有说明,一般默认输入偏差为1step,输出偏差为0
1step是一个特殊的时间单位,其值由精度来决定
④接口定义中的时钟控制模块
1、时钟控制块在接口中定义好之后,一般被引用到端口模式中用于创建同步端口。
interface A_Bus (intput bit clk);
wire req,gnt;
wire [7:0] addr,data;
clocking sb @(posdege clk);
input gnt;
output req,addr; 时钟控制块,定义时钟事件、块内信号
inout data; 、输入输出偏差未给定,为缺省值。
endclocking
modport stb(clocking sb); //采用时钟控制块的端口模式,为同步端口
modport tb (input gnt,output req,addr,inout data); //异步端口
endinterface
2、我们在模块声明中定义两个器件:这两个器件的端口列表都是名为b,接口类型为A_Bus,端口模式为stb
module dev1(A_Bus.stb b);...endmodule
module dev2(A_Bus.tb b);...endmodule
3、在顶层模块中需要使用接口例化完成连接:
module top;
bit clk;
A_Bus b1(clk); //例化两个实接口b1、b2
A_Bus b2(clk);
dev1 d1 (b1); //dev1模块在声明时引用了带时钟控制的端口模式,因此
dev2 d2 (b2); 此处传入的接口b1为同步接口。同理dev2模块在声明
Endmodule 时引用的普通端口模式,因此,此处传入的接口b2为异步
接口