怎么写testbench( 二 )


出错级别为note,在模拟器的输出窗口将会显示:图2再看一个例子:assert (s_cyi((DWIDTH-1)/4) = '0')and (s_ovi = '0')and (s_qutnt = conv_std_logic_vector(v_quot,DWIDTH))and (s_rmndr = conv_std_logic_vector(v_remd,DWIDTH))report "ERROR in division!"severity failure;断言的条件有4 个并且是与的关系,只要其中一个条件不成立则整个表达式为假,断言成立 。如果断言成立将输出“ERROR in division!“这个消息 。
并且通知模拟器出错级别为failure,这一般会停止模拟 。这个断言实际是在对结果进行验证 。
二、实际testbench分析下面将详细分析一个实际的testbench,它是用来测试8051 的ALU单元的除法功能的 。8 位的除法器,被除数和除数的组合共有256*256=65536 种 。
我们采用的方法是穷举所有的输入组合,这样的代码覆盖率可以达到100% 。它的验证必须通过程序自动完成,否则通过人工方法工作量太大 。
把要测试的程序当作一个元件,例如想象成一个74 系列数字电路 。Testbench 的作用是在被测试电路的输入端加上激励,然后比较被测试电路的输出和计算出来的期望值是否一致 。
对我们这个例子来说,在要仿真的ALU 输入端产生65536 种输入组合,然后将ALU产生的对应输出值和testbench 算出的期望值相比较,如果有错误产生则停止模拟并输出信息 。ALU 的除法单元的输入有4 个,分别是被除数、除 。
2. 怎样写testbench 如何编写testbench的总结? 1.激励的设置 相应于被测试模块的输入激励设置为reg型,输出相应设置为wire类型,双向端口inout在测试中需要进行处理 。
方法1:为双向端口设置中间变量inout_reg作为该inout的输出寄存,inout口在testbench中要定义为wire型变量,然后用输出使能控制传输方向 。eg: inout [0:0] bi_dir_port; wire [0:0] bi_dir_port; reg [0:0] bi_dir_port_reg; reg bi_dir_port_oe; assign bi_dir_port=bi_dir_port_oe?bi_dir_port_reg:1'bz; 用bi_dir_port_oe控制端口数据方向,并利用中间变量寄存器改变其值 。
等于两个模块之间用inout双向口互连 。往端口写(就是往模块里面输入) 方法2:使用force和release语句,这种方法不能准确反映双向端口的信号变化,但这种方法可以反映块内信号的变化 。
具体如示: module test(); wire data_inout; reg data_reg; reg link; #xx; //延时 force data_inout=1'bx; //强制作为输入端口。
#xx; release data_inout; //释放输入端口 endmodule 从文本文件中读取和写入向量 1)读取文本文件:用 $readmemb系统任务从文本文件中读取二进制向量(可以包含输入激励和输出期望值) 。
$readmemh 用于读取十六进制文件 。例如: reg [7:0] mem[1:256] // a 8-bit, 256-word 定义存储器mem initial $readmemh ( "mem.data", mem ) // 将.dat文件读入寄存器mem中 initial $readmemh ( "mem.data", mem, 128, 1 ) // 参数为寄存器加载数据的地址始终 2)输出文本文件:打开输出文件用?$fopen 例如: integer out_file; // out_file 是一个文件描述,需要定义为 integer类型 out_file = $fopen ( " cpu.data " ); // cpu.data 是需要打开的文件,也就是最终的输出文本 设计中的信号值可以通过$fmonitor, $fdisplay, 2. Verilog和Ncverilog命令使用库文件或库目录 ex). ncverilog -f run.f -v lib/lib.v -y lib2 +libext+.v //一般编译文件在run.f中,库文件在lib.v中,lib2目录中的.v文件系统自动搜索 使用库文件或库目录,只编译需要的模块而不必全部编译 3.Verilog Testbench信号记录的系统任务: 1). SHM数据库可以记录在设计仿真过程中信号的变化. 它只在probes有效的时间内记录你set probe on的信号的变化. ex). $shm_open("waves.shm"); //打开波形数据库 $shm_probe(top, "AS"); // set probe on "top",第二个参数: A -- signals of the specific scrope S -- Ports of the specified scope and below, excluding library cells C -- Ports of the specified scope and below, including library cells AS -- Signals of the specified scope and below, excluding library cells AC -- Signals of the specified scope and below, including library cells 还有一个 M,表示当前scope的memories,可以跟上面的结合使用,"AM" "AMS" "AMC" 什么都不加表示当前scope的ports; $shm_close //关闭数据库 2). VCD数据库也可以记录在设计仿真过程中信号的变化. 它只记录你选择的信号的变化. ex). $dumpfile("filename"); //打开数据库 $dumpvars(1, top.u1); //scope = top.u1, depth = 1 第一个参数表示深度,为0时记录所有深度; 第二个参数表示scope,省略时表当前的scope. $dumpvars; //depth = all scope = all $dumpvars(0); //depth = all scope = current $dumpvars(1, top.u1); //depth = 1 scope = top.u1 $dumpoff //暂停记录数据改变,信号变化不写入库文件中 $dumpon //重新恢复记录 3). Debussy fsdb数据库也可以记录信号的变化,它的优势是可以跟debussy结合,方便调试. 如果要在ncverilog仿真时,记录信号,首先要设置debussy: a. setenv LD_LIBRARY_PATH :$LD_LIBRARY_PATH (path for debpli.so file (/share/PLI/nc_xl//nc_loadpli1)) b. while invoking ncverilog use the +ncloadpli1 option. ncverilog -f run.f +debug +ncloadpli1=debpli:deb_PLIPtr fsdb数据库文件的记录方法,是使用$fsdbDumpfile和$fsdbDumpvars系统函数,使用方法参见VCD 注意: 在用ncverilog的时候,为了正确地记录波形,要使用参数: "+access+rw",否则没有读写权限 在记录信号或者波形时需要指出被记录信号的路径,如:tb.module.u1.clk. ……………………………………………………………………………………………………… 关于信号记录的系统任务的说明: 在testbench中使用信号记录的系统任务,就可以将自己需要的部分的结果以及波形文件记录下来(可采用sigalscan工具查看),适用于对较大的系统进行仿真,速度快,优于全局仿真 。