4.1接口interface
接口特点:接口在module可以直接声明例化,但在class中只能声明为virtual。正是通过虚接口连接到硬件上,使得“软件”部分可以操作硬件设计;
interface可以在module中声明和实例化,但是module不能存在interface中;
接口内可以定义参数、变量、initial和always块、function、task等;不能定义module
接口内的信号需要DUT连接,因此要用四值逻辑来确保有x和z状态,而非二值逻辑。接口中最好以使用 logic 做为信号的类型。因为logic可以直接赋值,而 wire 必须要被连续赋值语句可来驱动。
reg_intf reg_if(.*); 这句话的意思是,实例化一个名为 reg_if 的接口实例,并将其命名为 reg_intf,并且该实例将包含接口定义中的所有成员信号和/或变量。//只要端口和信号的名字和数组类型相同,就能自动的在当前级别自动连接模块实例的端口到具体信号
接口内的信号必须使用非阻塞赋值驱动(<=)
![]() | ![]() |
Modport:
modport起到的就是整理interface内部的信号的作用,将接口内的信号分组,并定义它们的方向,所以它整理的信号必须要是事先在interface中定义好的信号。
modport中也可以将interface中的方法进行整理,用import将方法引入到modport中,它们对任何使用这个modport的块都是可见的。也就是说在上面的例子中,拿到这个虚接口 vif 的组件可以通过 vif.master.masterRead 的方式,直接调用接口内 masterRead() 任务。
当在时钟块中使用modport的时候,任何同步接口信号都必须加上接口名和时钟块名的前缀
4.2激励时序
clocking时钟块:
时钟块可以保证接口内的信号可以同步地驱动和采样。每一个时钟块都有一个时钟表达式,对应一个时钟域。@(posedge clk)定义了单时钟沿,@(clk)定义了DDR时钟(双沿时钟)还可以通过default指定一个输出和输入信号采样的时钟偏移,可以防止采样时的竞争问题。在RTL仿真时,由于无法确定具体电路的延迟时间,默认情况下时钟驱动电路时会添加一个无限最小的时间(delta cycle)的延迟,这个延迟要比最小时间单位精度还要小(可以理解成远小于1ps)。在一个时间片(time - slot)中可以发生很多的事,例如在仿真时输入run0,即让仿真器运行一个delta-cycle的时间。
由于各种可能性,clk与被采样数据之间如果只存在若干个delta-cycle的延迟,那么采样就会出问题
时钟块的默认时序是在#1step延时之后采样输入信号,在#0延时之后驱动输出信号
program为软件域,不能出现硬件行为相关的过程语句和实例;
program内部定义变量赋值“=”,外部驱动硬件信号”<=”
在program里不允许使用always块,可以使用initial块;
显示:tb中所有program中initial过程快均完成后,仿真才能结束
隐式:在无限循环类program中置入$exit(),可以强制退出该program,系统等待其他program执行完毕后结束
时钟发生器不应该放在程序块里
不要使用功能验证来验证底层时序,时序的检查在STA静态时序分析中完成
4.3断言
assert();判断语句正确测试继续执行,若信号不如何预期,仿真器就会报错
及时断言和并发断言