Testbench的含义?
testbench是一种验证的手段。首先,任何设计都是会有输入输出的。但是在软环境中没有激励输入,也不会对你设计的输出正确性进行评估。那么此时便有一种,模拟实际环境的输入激励和输出校验的一种“虚拟平台”的产生。在这个平台上你可以对你的设计从软件层面上进行分析和校验,这个就是testbench的含义。
模块实例化
____需要测试的模块(Verilog-module)被称为DUT(Design Under Test),在testbench中需要对一个或者多个DUT进行实例化。
Testbench中的顶层module不需要定义输入和输出。
Testbench中连接到DUT instance的输入的为reg类型、连接到DUT instance的输出的为wire类型。
对于DUT的inout类型变量,在testbench中需要分别使用reg、wire类型的变量进行调用。
_____Testbench.v的创建
_

1
在创建Testbench.v文件时,使用开发平台(ISE、Vivada、Quartus基本相同)创建,可以省去一些简单繁琐的工作(当然也可以自己创建.v文件添加到工程中),如上图所示。
_

2
例如,上图是需要测试的功能模块,我们需要以这个模块为顶层创建它的Testbench.v文件。
_

3
这是通过开发平台创建的Testbench.v文件,内部已经自动将你选择的顶层模块进行例化和变量赋值。(在顶层功能模块有大量的信号需要定义时,用软件生成testbench文件还是比较快捷方便的)
_
Testbench中如何代码编写?
和普通的Verilog功能模块一样,使用assign对wire类型的变量进行赋值。
always和initial是两种对reg变量进行操作的串行控制块,每个initial和always块都会在仿真开始时并行开始运行。
常见的,可以利用它们生成模块所需的时钟和复位信号,如下:
顶层模块
_
testbench模块
_
testbench中变量赋值
_
首行定义了时间单位/时间精度。时间单位为1ns,这样生成的clk_50时钟周期就是20ns、也就是频率为50MHz。
复位信号rst_l在初始为0复位态、在20ns之后为1解除复位。
initial函数:
initial函数模块从仿真0时刻开始执行,而且在整个仿真过程中只执行一次。在一个模块中多个initial函数模块是并行执行的(和always模块一样),且每个块都是各自独立执行的,同一个变量不能在多个initial函数模块中赋值。如果在块内包含了多条行为语句,则需要使用begin和end将他们组合在一个块语句。
仿真中的停止、变量监视和输出
_
有两种仿真控制函数:$finish和$stop。
$stop:用于在仿真时,暂停仿真。运行到$stop的时候,仿真会暂停;此时可以在命令行输入run继续运行仿真。
$finish:仿真停止。运行到$finish的时候,仿真停止退出,此时不可以再继续运行。
但在Modelsim中,$stop任务则是返回到交互模式。如果需要监视仿真中某个变量的变化情况,可以使用$monitor函数,如下图所示:

每当变量列表中的任一变量发生变化,就会产生输出。如果需要在仿真控制台屏幕打印输出,可以使用$display函数,如下图所示:

任务函数Task的用法
_
task模块
_
在testbench中可以将一组重复性的或者相关的命令组合到一起构成一个任务,在tack以及endtack之间定义这个任务。
注意事项:
1、第一行task语句中不能列端口名称,system verilog中可以。
2、输入输出端口数量不受限制,但输出只能为reg。
3、任务中不能出现initial,always。但任务可在initial、always中使用。
task调用
_
在always模块中调用task任务:
1、任务调用语句只能出现在过程块内;
2、任务调用语句和一条普通的行为描述语句的处理方法一致;
3、当被调用输入、输出或双向端口时,任务调用语句必须包含端口名列表,且信号端口顺序和类型必须和任务定义结构中的顺序和类型一致。需要说明的是,任务的输出端口必须和寄存器类型的数据变量对应。