编写testbench的主要目的是为了对使用的硬件描述语言设计的电路进行仿真验证。本系列的博客都是基于vivado 2017.4 Xilinx验证平台。采用的开发板为ZYNQ-7000系列的器件。
一、Testbench 的一般结构
一般编写的测试文件包含一下内容:
module Test_bench(); //通常无输入出 通常无输入出
信号或变量声明定义
逻辑设计中输入对应 reg型
逻辑设计中输出对应 wire 型
使用 initial 或 always语句产生激励 语句产生激励
例化待测试模块
监控和比较输出响应
endmodule
二、时钟激励编写
1. 时钟激励产生方法一:50%占空比
parameter ClockPerilod=10
initial
begin
clk_i=0;
forever
#(ClockPerilod/2) clk_i = ~clk_i; //最常用的产生方式
end
2. 时钟激励产生方法二:50%占空比
parameter ClockPerilod=10
initial
begin
clk_i=0;
#(ClockPerilod/2) clk_i = ~clk_i;
end
3. 时钟激励产生方法三:固定数量的时钟脉冲
parameter ClockPerilod=10
initial
begin
clk_i=0;
repeat (6)
#(ClockPerilod/2) clk_i = ~clk_i;
end
3. 时钟激励产生方法四:产生非占空比为50%的时钟脉冲
parameter ClockPerilod=10
initial
begin
clk_i=0;
forever
begin
#(ClockPerilod/2) clk_i = 0;
#((ClockPerilod/2)+2) clk_i = 1;
end
end
三、复位信号的编写
1. 复位信号产生方法一:异步复位
initial
begin
rst_n_i = 1;
#100
rst_n_i = 0;
#100
rst_n_i = 0;
end
2. 复位信号产生方法二:同步复位
initial
begin
rst_n_i = 1;
@(negedge clk_i)
rst_n_i = 0;
#100 //固定时间复位
repeat(10) @(negedge clk_i); //固定周期数复位
@(negedge clk_i)
rst_n_i = 1;
end
3. 复位信号产生方法三:复位任务封装
将复位信号设计成可封装的模块。
task reset; //关键词加task名字
input [31:0] reset_time; //复位时间可调,输入复位时间
RST_ING = 0; //复位方式可调,低电平或高电平
begin
rst_n = RST_ING; //复位中
#reset_time; //复位时间
rst_n_i = ~RST_ING; //撤销复位,复位结束
end
endtask
四、双向信号的设计
1. 双向信号描述一:
// 为双向端口设置中间变量 inout_reg作为 inout的输出寄存,其中 的输出寄存,其中 inout变量定义为 wirewire 型,使用输出能控制传方向型
//inout bir_port;
wire bir_port;
reg bir_port_reg;
reg bi_port_oe;
assign bi_port = bi_port_oe ? bir_port_reg : 1'bz;
2. 双向信号描述二:强制force
// 当双向端口作为输出时,不需要对其进行初始化而只开通三态门
// 当双向端口作为输入时,只需要对其初始化并关闭三态门赋值// 使用 wirewire 型数据,通过 force命令来对双向端口进行输入赋值
//assign dinout = (!en) din : 16'hz;完成双向赋值
initial
begin
force dinout = 20;
#200
force dinout = dinout - 1;
end
五、特殊信号的设计
1. 特殊激励信号描述一:输入信号任务封装
task i_data;
input [7:0] dut_data;
begin
@(posedge data_en); send_data=0;
@(posedge data_en); send_data=dut_data[0];
@(posedge data_en); send_data=dut_data[1];
@(posedge data_en); send_data=dut_data[2];
@(posedge data_en); send_data=dut_data[3];
@(posedge data_en); send_data=dut_data[4];
@(posedge data_en); send_data=dut_data[5];
@(posedge data_en); send_data=dut_data[6];
@(posedge data_en); send_data=dut_data[7];
#100
end
endtask
// 调用方法: i_data(8'hXX);
2. 特殊激励信号描述二:多输入信号任务封装
task more_data;
input [7:0] a;
input [7:0] b;
input [31:0] times;
output [8:0] c;
begin
repeat (times) //等待times个时钟上升沿
@(posedge clk_i)
c=a+b; // 时钟上升沿a,b相加
end
endtask
//调用方法: more_input(x,y,z); //按照声明顺序
3. 特殊激励信号描述三:输入信号产生,一次SRAM写信号产生
initial
begin
cs_n = 1; //片选无效
wr_n = 1; //写使能无效
rd_n = 1; //读使能无效
addr = 8'hxx; //地址无效
data = 8'hzz; //数据无效
#100
cs_n = 0; //片选有效
wr_n = 0; //写使能有效
addr = 8'hF1; //写入地址
data = 8'h2C; //写入数据
#100
cs_n = 1;
wr_n = 1;
#10
addr = 8'hxx;
data = 8'hzz;
4. testbench中@与wait
//@使用沿触发
//wait语句都是使用电平触发
initial
begin
start = 1'b1;
wait(en = 1'b1);
#10
start = 1'b0;
end