Testbench基本入门

1 编写testbench目的


        编写testbench的主要目的是为了对使用硬件描述语言(HDL)设计的电路进行仿真验证,测试设计电路的功能、部分性能是否与预期的目标相符。


编写testbench进行测试的过程如下:


1)  产生模拟激励(波形);


2)  将产生的激励加入到被测试模块并观察其输出响应;


3)  将输出响应与期望进行比较,从而判断设计的正确性。


2 基本的testbench结构


module test_bench;


// 通常testbench没有输入与输出端口


信号或变量定义声明


使用initial或always语句来产生激励波形


例化设计模块


监控和比较输出响应


endmodule


        简单的testbench的结构通常需要建立一个顶层文件,顶层文件没有输入和输出端口。在顶层文件里,把被测模块和激励产生模块实例化进来,并且把被测模块的端口与激励模块的端口进行对应连接,使得激励可以输入到被测模块。端口连接的方式有名称和位置关联两种方式,我们常常使用“名称关联”方式。


3 产生激励的一些描写方式


3.1 产生时钟的几种方式


1)使用initial方式产生占空比50﹪的时钟


initial


begin


       CLK = 0;


       #delay;


       forever


              #(period/2) CLK = ~CLK;


end


注意一定要给时钟赋初始值,因为信号的缺省值为z,如果不赋初值,则反相后还是z,时钟就一直处于高阻z状态。


产生的时钟信号如下图所示:


c0dde695-5450-4041-ab44-03469fe810c9.jpg


2)使用always方式


initial


       CLK = 0;


always


       #(period/2) CLK = ~CLK;


3)使用repeat产生确定数目的时钟脉冲


initial


begin


       CLK = 0;


       repeat(6)


              #(period/2) CLK = ~CLK;


end


该例使用repeat产生3个时钟脉冲,产生的波形如下:


4ca4658b-1ab3-47a0-816a-338241d331be.jpg


4)产生占空比非50﹪的时钟


initial


       CLK = 0;


always


begin


       #3 CLK = ~CLK;


       #2 CLK = ~CLK;


end


6ba51d6b-304e-4be5-b70e-1ec4abd977c5.jpg


3.2 产生复位信号的几种形式


1)异步复位


initial


begin


       Rst = 1;


       #100;


       Rst = 0;


       #500;


       Rst = 1;


end


0ee5a93a-49ab-4daf-ba14-11c62ba2199b.jpg


2)同步复位1


initial


begin


       Rst = 1;


       @(negedge CLK);  // 等待时钟下降沿


       Rst = 0;


       #30;


       @(negedge CLK);  // 等待时钟下降沿


       Rst = 1;


end


4f117d94-d280-4a76-aa1e-2f916c04d317.jpg


2)同步复位2


initial


begin


       Rst = 1;


       @(negedge CLK);  // 等待时钟下降沿


       repeat (3) @(negedge CLK);   // 经过3个时钟下降沿


       Rst = 1;


end


48ddf415-e60e-4567-bdda-b62d7ad57745.jpg


4 testbench实例


4.1 2-4解码器实例


module dec2x4(A, B, Enable, Z);


input A, B, Enable;


output[3:0] Z;


reg [3:0] Z_o;


assign Z = Z_o;


always@(A or B or Enable)


begin


       if(Enable == 1'b0)


              Z_o = 4'b1111;


       else


              case({A, B})


                     2'b00: Z_o = 4'b1110;


                     2'b01: Z_o = 4'b1101;


                     2'b10: Z_o = 4'b1011;


                     2'b11: Z_o = 4'b0111;


                     default: Z_o = 4'b1111;


              endcase


end


endmodule


测试模块:


`timescale 1ns/100ps


 


module testbench;


       reg a, b, en;


       wire [3:0] z;


//例化被测试模块


dec2x4 DUT(.A(a),.B(b),.Enable(en),.Z(z));


//产生输入激励


initial


begin


       en = 0;


       a = 0;


       b = 0;


       #10 en = 1;


       #10 b = 1;


       #10 a = 1;


       #10 b = 0;


       #10 a = 0;


       #10 $stop;


end


//显示输出结果


always@(en or a or b or z)


begin


       $display("At time %t, input is %b%b%b, output is %b", $time, a, b, en, z);


end


endmodule


下面是测试模块执行时产生的输出和功能仿真波形:


130c149d-d27c-42e3-b1aa-be41cb8ff86b.jpg


84a2d624-08f2-49c5-a4d4-432117a34081.jpg


4.2 时序检测器


        下面是一个时序检测器的验证实例。被测模型用于检测数据线上连续三个1的序列。在时钟的每个上升沿检查数据。


module Count3_1s(Data, Clock, Detect3_1s);


       input Data, Clock;


       output Detect3_1s;


       integer Count;


       reg Detect3_1s;


initial


begin


       Count = 0;


       Detect3_1s = 0;


end


always@(posedge Clock)


begin


       if(Data == 1)


              Count = Count + 1;


       else


              Count = 0;


       if(Count>=3)


              Detect3_1s = 1;


       else


              Detect3_1s = 0;


end


endmodule


测试模块:


`timescale 1ns/100ps


module testbench;


       reg Data, Clock;


       wire Detect;


       integer Out_file;


// 待测试模块的应用实例


Count3_1s      DUT(Data,Clock,Detect);  // 位置关联方式


initial


begin


       Clock = 0;


       forever


       #5 Clock = ~Clock;


end


initial


begin


       Data = 0;


       #5 Data = 1;


       #40 Data = 0;


       #10 Data = 1;


       #40 Data = 0;


       #20 $stop;  // 仿真结束


end


// 创建一个记录文件:


initial


       Out_file = $fopen("results.txt");


// 在文件中保存监控信息


always@(posedge Clock)


begin


       if(Detect == 1'b1)


              $fwrite(Out_file,"At time %t, Detect out is 1\n", $time);


end


endmodule

猜你喜欢

转载自blog.csdn.net/Autumn_He/article/details/79931287
今日推荐