system verilog中的interface是为了把测试平台和DUT分割开来而提出来的类型。
interface结构
一个常用的interface主要结构如下:
1 | interface bus(input logic clk); |
可以看出,一个interface一般包括三个部分:
定义信号列表:
列出所有信号及位宽,一般都用logic,不指定方向。
clocking:
指定同步时钟,确定同步信号相当于时钟的时序。
定义信号对于敏感列表的延迟。
规定信号的方向,站在平台的角度看的。input表示需采集端口上的信号,该信号为tb的输入;output表示tb需要驱动该信号,为tb的输出。
modport
对信号进行分组,并指定一组中各信号的方向。
如果不写clocking和modport可不可以?
也可以,但是如果不写,就没有了输入输出信息和延迟时间。输入输出信息在编译的时候可以帮我们检查是否出现错误。延迟信息在仿真网表时非常有用,在仿RTL代码时没有delay,即使是始终上升沿采样对齐也不会有什么问题,但是在网表仿真时,有的地方就会出现采样错误的情况,加上延迟信息可以解决这些问题,更加利于移植与修改。
如果不写clocking的时候,我们在driver和monitor里面需要这么写
1 | @(posedge bus.clk); |
在驱动和采样的时候,这些代码肯定出现不止一次,若需要增加延迟,需要修改多个地方。
而如果加了clocking的时候,代码会变成
1 | @bus.drvm.drvc; |
这样,即使需要修改延迟,只要修改interface里面的就可以了。
因此还是建议加上clocking和modport信息。
interface中的default_skew
default_skew:
input clocking_skew
| output clocking_skew
| input clocking_skew output clocking_skew
输入时滞隐含是负的,它总是指向时钟之前的一个时间,采样时刻提前。
输出时滞隐含是正的,指向时钟之后的一个时间,会晚于时钟沿输出,当前时钟沿不会采集到cb的输出信号变化,避免了时序的竞争。
skew表述:
input #1ps //按ps
input #1 //按默认时序单位
实例
假设有interface代码如下:
1 | interface test_if(input clk); |
而使用代码如下:
1 | test_if ti(clk); |
其中:
- ticbiin和ticbiin_noblock都提前1ns。说明阻塞和非阻塞这里一样。
- ticlkin会和时钟对齐。
- ti.cbo.out会晚1ns输出,这里必须用非阻塞,不然会报错。
- ti.out会和时钟对齐。
- ticboout也会和时钟对齐,即使用的是@ti.cbo。
说明:
- 延时信息,是由ti.cb.xx起作用,而不是@ti.cb起作用。
- 阻塞和非阻塞并没有太大区别,但是建议用非阻塞赋值<=。