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状态。


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



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个时钟脉冲,产生的波形如下:



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


initial


       CLK = 0;


always


begin


       #3 CLK = ~CLK;


       #2 CLK = ~CLK;


end



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


1)异步复位


initial


begin


       Rst = 1;


       #100;


       Rst = 0;


       #500;


       Rst = 1;


end



2)同步复位1


initial


begin


       Rst = 1;


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


       Rst = 0;


       #30;


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


       Rst = 1;


end



2)同步复位2


initial


begin


       Rst = 1;


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


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


       Rst = 1;


end



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


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




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

你可能感兴趣的:(Testbench基本入门)