testbench文件构架
0赞DUT(design under test)
激励信号--输入->待测模块--输出—>波形数据输出->波形的验证->验证结果
预期输出时序波形
2.Testench代码设计风格
a)Testbench文件头编写规范
与VerilogHDL完全一样
b)Module列表编写规范
`timescale 1ns/1ns module Testbench_tb; wire [7:0] led_data; endmodule
Testbench不同于Verilog HDl的地方是没有输入输出类的信号定义,每个激励都是在当前文件中生成的,唯一与外界通信的wire是直连到需要测试的Module上的。而Testbench中的Module信号列表是当前文件需要输出的信号。此处顶层文件定义了led_data为输出信号,便于在modelsim中添加并且观察波形。另外:
(1)Module前必须写时间尺度;
(2)Module后紧跟Testbench需要输出的信号(当模块多时,紧跟当前Module);
(3)相关信号必须写在一起,并注释。
备注:虽然不添加wire信号也无所谓,可以直接在波形中添加待测试Module的信号,但是wire后,设计测试脚本更加清晰。
c)时钟发生器编写规范
//--------------------------- //clock generate module reg clk; reg rst_n; localparam PERIOD=20; //50mhz initial begin clk=0; forever #(PERIOD/2) clk=~clk; end task task_reset; begin rst_n=0; repeat(2) @(negedge clk) rst_n=1; end endtask
理解Testbench可以完全按照c语言的思路,Testbench完全是线程的设计,当然也可以实现always类的并行设计,但是任务的调用必须是线程的。Testbench通过任务的调用来实现激励。规范如下:
(1)该模块放在Testbench的Module之后,必须有且仅有一次定义;
(2)时钟可以通过PERIOD的宏定义修改;
(3)类似时钟的生成可以参考此部分clk设计。
d)模块的例化编写规范
这部分与verilog HDl设计规范完全相同,直接调用需要测试的模块,通过例化完成线路的连接,作为Modelsim分析的目标电路,如:
//------------------------ //the target component instantiation reg spi_cs; reg spi_sck; reg spi_mosi; //-------------------- //SPI data receive from MCU wire rxd_flag; wire [7:0] rxd_data; spi_receiver u_spi_receiver ( //global clock .clk (clk_ref), .rst_n (sys_rst_n), //mcu spi interface .spi_cs (spi_cs), .spi_sck (spi_sck), .spi_mosi (spi_mosi), //.spi_miso (spi_miso), //user interface .rxd_flag (rxd_flag), .rxd_data (rxd_flag) )
e).系统的初始化编写规范
考虑到电路上电都有一个初始化阶段,Testbench为了实现完整的激励,也有必要生成一个系统的初始化模块,该模块如下:
//-------------------------- //system initialiation task task_sysinit; begin spi_cs=1; spi_sck=1; spi_mosi=0; end endtask
该模块简洁明了,唯一的规范便是保证所有输出信号都需要初始化,否则不能正常仿真。
f).生成系统的测试激励
Testbench可以通过设计Task功能来实现任务的模块化编写及调用,而这些部分的目的就是为了在最后生成待测试文件的测试激励,如下:
//------------------------------------ //testbench of the RTL initial begin task_sysinit; task_reset; repeat(5)@(posedge); task_mcu_spi_txd(8'h95); end
在测试激励生成的代码编写规范中,需遵循以下几点:
(1)采用initial设计,生成现成的激励;
(2)必须先进行系统初始化,接着进行复位,然后才能进行其他的激励;
(3)为了代码的可读性及可移植性,激励都通过task去编写及调用,保证代码清晰,便于修改;
(4)同一功能的激励规划在一起,并且需要必要的注释。
//来自FPGA设计技巧与案例开发详解