前言
TestBench模块没有输人输出,在TestBench模块内实例化待测设计的顶层模块,并把测试行为的代码封装在内,直接对测试系统提供测试激励。
基本的Textbench结构:
module textbench();
//数据类型声明
//对被测试模块实例化
//产生激励测试
//对输出相应进行收集
endmodule
我们还可以更详细化:
module textbench();
//信号或变量声明定义
//逻辑设计中输入信号在这里对应reg型变量
//逻辑设计中的输出信号在这里对应wire型变量
//例化测试模块
//使用initial或always语句产生激励
//监控和比较输出响应
endmodule
我们给出一个例子:对带复位端的D触发器进行验证的测试模块
`timescale 1ns/1ns
module tb();
reg clock,reset,d; //变量声明
wire q1,q2;
initial clock=0;
always #5 clock=~clock; //生成时钟信号
initial d=1;
begin
reset=1;
#12 reset=0;
#11 reset=1; //仿真信号产生
#17 $stop //仿真控制
end
dff2 dss2(.clock(clock),.reset(reset),.d(d),.q2(q2)); 待测试模块实例化
endmodule
时钟信号
时钟信号是时序电路所必需的信号之一,该信号可以由多种方式产生。
可以使用initial和always结构共同生成时钟信号,被动地检测响应时使用always语句,主动响应时使用initial语句。
它们的区别是:initial语句只执行一次,always语句不断地重复执行
栗子:
reg clock;
initial clock=0;
always #10 clock=~clock;
采用此代码生成的是一个占空比为50%的时钟。
如果只用always语句,可以生成任意占比的时钟,不过在设计的时候一般用不到这一种
栗子:
always 结构占空比为50%的时钟
reg clock;
always begin
#5 clock=0;
#5 clock=1;
end
always 结构任意占空比时钟
reg clock;
always begin
#15 clock=0;
#5 clock=1;
end
还有initial 语句生成时钟,不过我们在此不在涉及这方面的知识.
复位信号
由于时序电路一般会有一个复位端把电路回归到初始状态,所以为了保证时序电路的工作正确,仿真开始时会给电路一个复位信号使其完成初始化。出于电路稳定性和节约功耗两方面考虑,选择高电平作为复位信号
,电路正常工作时只需要维持低电平
即可。
复位信号可分为异步复位信号
和同步复位信号
。
-
同步复位信号是指时钟有效沿到来时对触发器进行复位所产生的信号
-
异步复位信号不依赖于时钟信号,只在系统复位有效时产生复位信号。
举例:
//异步复位信号
reg rst_n;
initial begin
rst_n=1;
#10 rst_n=0;//从10ns开始复位,持续时间为50ns
#50 rst_n=a;
end
//同步复位信号
initial begin
rst_n=1; //将 rst_n初始化为1,在第一个时钟下降沿复位,延时30ns,
@(posedge clock); //在下一个时钟下降沿撤销复位
rst_n=0;
#30 //等待时钟clock下降沿
@(posedge clock);
rst_n=1;
end
编译指令
timescale时间尺度
timescale
命令用来说明跟在该命令后的模块的时间单位和时间精度。使用timescale
命令可以在同一个设计里包含采用了不同时间单位的模块。
例如,一个设计中包含两个模块,其中一个模块的时间延迟单位为纳秒(ns),另一个模块的时间延迟单位为皮秒( ps)。EDA 工具仍然可以对这个设计进行仿真测试。
格式:
`timescale<时间单位>/<时间精度>
在这条命令中,时间单位参量
是用来定义模块中仿真时间和延迟时间的基准单位的
。时间精度参量是用来声明该模块的仿真时间的精确程度的
,该参量被用来对延迟时间值进行取整操作(仿真前),因此该参量又可以被称为取整精度。如果在同一个程序设计里,存在多个timescale
命令,则用最小的时间精度值来决定仿真的时间单位,另外,时间精度值不能大于时间单位值。
用于说明时间单位和时间精度参量值的数字必须是整数
可以为1,10,100
单位只能为:单位为秒(s)、毫秒(ms)、微秒(us)、纳秒(ns)、皮秒(ps)、飞秒(fs)
关于宏定义、条件编译指令、文件包含处理这里不详细阐述
测试相关的系统任务和系统函数
显示任务$display
与 $write
这两个任务能够把指定的信息输出到输出设备中,如仿真器的显示窗口
$display/$write(p1,p2,……,pn) ;
这两个任务的作用基本相同,即将参数p2到 pn按参数pl
给定的格式输出。$display
自动地在输出后进行换行,$write
则不换行。
如果想在一行里输出多个信息,可以使用$write
。
参数pl通常称为“格式控制”,参数p2至 pn通常称为“输出表列”
在$display
和$write
中,其输出格式控制是用双引号括起来的字符串,包含以下两种信息:
格式说明
,由“%”
和格式字符组成。它的作用是将输出的数据转换成指定的格式输出。

特殊字符
,用于格式字符串参数中显示特殊的字符。

如果输出列表中表达式的值包含不确定的值或高阻值,其结果输出遵循以下规则。
在输出格式为十进制的情况下:
如果表达式值的所有位均为不定值,则输出结果为小写的x。
如果表达式值的所有位均为高阻值,则输出结果为小写的z。
如果表达式值的部分位为不定值,则输出结果为大写的X。
如果表达式值的部分位为高阻值,则输出结果为大写的Z。
在输出格式为十六进制和八进制的情况下:
每4位二进制数为一组代表一位十六进制数,每三位二进制数为一组代表一位八进制数。
如果表达式值相对应的某进制数的所有位均为不定值,则该位进制数的输出的结果为小写的X
如果表达式值相对应的某进制数的所有位均为高阻值,则该位进制数的输出结果为小写的z。
如果表达式值相对应的某进制数的部分位为不定值,则该位进制数输出结果为大写的X。
如果表达式值相对应的某进制数的部分位为高阻值,则该位进制数输出结果为大写的Z。
对于二进制输出格式,表达式值的每一位的输出结果为O、l、x 、z
其余的系统常见函数在初始阶段暂时不涉及