首先我们讲下接口(interface)。我们可以把接口看成排插,在dut和tb之间的数据驱动关系都可以使用这个排插来完成。
接口可以将信号和信号的一些使用方法封装到一个盒子里面。这对于设计和验证都便于维护和使用,如果我需要添加新信号,只需要在接口中定义他就行,接口是sv中唯一连通硬件和软件环境的桥梁,接口还可以例化,在顶层例化时,只需要罗列出接口的书数量,不在需要分散的变量作为tb和dut之间的连线。
接下来讲一下竞争的问题,即采样和数据驱动。为了避免出现竞争的问题,我们可以采用非阻塞赋值或者特定的信号延迟来解决。注意:阻塞赋值语句是上面一条语句结束,下面才进行,而非阻塞是说上下两条语句同时执行。阻塞赋值用“=”,非阻塞赋值用‘<=’。
那么该如何避免竞争问题呢?1.在驱动时,添加相应的认为延迟,去模拟真实的延迟行为。
2.可以依靠在采样事件前的某段时刻中进行采样,来模拟建立时间的采样要求,确保采样稳定性。(建立时间:时钟信号有效沿来临之前,信号需要保持稳定的时间。包保持时间:时钟信号有效沿到达之后,输入信号需要保持的稳定时间)。
接下来讲讲接口中的clocking块,我们可以在接口中定义clocking块,他时基于时钟周期对信号进行驱动和采样的方式,可以消除信号竞争的问题。
注意,此图的第二行指出了clocking块中的所有信号在clocking时间的前10ns对其进行输入采样,在事件的后2ns对其进行输出采样。
总而言之,为了避免出现采样竞争的问题,①我们应该在验证环境的驱动环节就添加固定延迟,使得其在仿真波形中更加容易体现出时钟域被驱动信号之间的时序前后关系。
②如果tb采样从dut送出来的数据,在时钟和被驱动信号之间存在delta-cycle的话,应该考虑在时钟采样沿的各部分的更早时间段去模拟建立时间要求采样。
③将clocking块用在interface中,用来声明各个接口域时钟的采样和驱动关系,可以提高数据驱动和采样的准确性。
关于测试的开始和结束,有几点需要注意,首先我们可以通过$finish和$stop退出仿真,finish是退出,stop是在听,我们还有机会继续运行仿真。