- program和module的区别:program的一个重要作用就是将设计和验证的调度区域以显式的方法来安排。
- 一般设计放在module中,测试采样部分放在program。可以认为program是软件的领地,不应出现always/module/interface,也不应该有其他program的例化。program在驱动内部定义的变量时候应该用阻塞赋值(软件方式),驱动外部模块的硬件信号用非阻塞(硬件方式)。
- program中可以有initial,但是不同于module中的initial,前者在reactive中执行,后者在active。
- SV通过program将DUT和testbench领地做了划分,硬件和软件的执行互补干扰,这是通过不同调度区域的执行顺序来保证的。
- 在执行program之前先执行设计代码的仿真调度,有下列区域
- active(执行设计部分的非阻塞赋值,之后进入NBA)
- inactive(带有#0的进入该区域执行)
- NBA(上述所有赋值生效)
- observe:上述区域全部执行完毕后,设计部分线程执行完毕。后续线程是为验证部分准备的。本区域是为属性断言准备,因为必须等到所有数据被稳定赋值之后才能进行检查。
- reactive:program执行,软件部分对采样值进行计算。若触发内部变量改变则挂起program重新进入active直到整个调度阶段执行完毕再回到reactive。
- task中的阻塞与非阻塞赋值的区别:阻塞赋值用于不受时钟驱动的异步信号,非阻塞赋值用于时钟驱动的信号。
- `include 在test_top中使用,使用相当于把引入的文件一行一行展开。编译的时候要注意避免重复编译。做验证的时候也要把DUT加入进来并首先编译,其次编译program,最后编译top。
编译完毕后在控制台输入下列命令
log -r /* //将顶层涉及到的所有与硬件相关的信号波形全部保存
-
一般来说在testbench里面嵌入一个函数:$ vcdpluson;.可以加入一些选项,如果不带选项,默认把所有的波形文件都记录下来。
【vcdpluson的一些参数选项】
-
interface是program(包括其中的类)和DUT连接的媒介,在interface中声明的信号除了clk之外都没有方向。因此引入了clocking做方向的规定,同时可以模拟硬件的时钟(posedge clock)驱动和采样。
在clocking中可以设置延时,如下图加粗部分,约定在时钟上升沿之前1ns处进行数据采样(input #1ns)这使得数据采样更加稳定,在时钟上升沿1ns之后输出数据(output #1ns)这样观察波形更加容易。
-
modport,连接驱动的DUT。在其参数列表中应该包括刚刚的时钟模块,已经有可能用到的异步信号。program中所有的类,要做驱动都要经过modport。