北大数字集成电路课件--15_Verilog-testbench的写法
verilogtestbench写法
verilogtestbench写法Verilog测试平台(testbench)技术(⼀) 收藏对设计进⾏功能仿真和时序仿真时,需要给待测模块提供激励输⼊。
对于由Verilog语⾔描述的设计模块,最好的⽅法⾃然同样是⽤Verilog语⾔对待测模块施加激励和检测模块的输出响应。
实际应⽤中,Verilog测试平台(testben ch)就是⽤来提供上述功能的。
Verilog测试平台是⼀个例化的待测(MUT)Verilog 模块,给它施加激励并观测其输出。
由于测试平台是⽤Verilog语⾔描述的,因此可以应⽤到不同的仿真环境中。
待测模块和与之对应的测试平台组成⼀个仿真模型,应⽤这个模型可以在不同的测试环境中⽤相同的激励对待测模块进⾏调试。
下⾯就对不同电路类型分别介绍verilog测试平台的语⾔结构。
⼀、测试平台1.组合电路测试设计组合电路的测试平台时,待测模块及其功能决定了激烈的选择与测试次数。
对于⼀个已有的待测模块,测试平台中需要声明与待测模块输⼊输出端⼝对应的变量。
与输⼊端⼝相连接的变量定义为reg,与输出端⼝相连接的变量定义为wire,例化时将测试平台中声明的变量与待测模块的输⼊输出端⼝相关联。
使⽤initial语句控制程序运⾏,initial语句是⼀种过程结构,在initial块中可使⽤延迟控制语句来控制initial块中的程序流动。
这⾥对⼀个简单的算术逻辑单元(ALU)为例进⾏测试,下⾯是该单元Verilog 描述。
/***************************************************************** ********///多动能ALU的Verilog代码'timescale 1ns/100psmodule alu_4bit(a,b,f,oe,y,p,ov,a_gt_b,a_eg_b,a_lt_b);input [3:0] a,b;input [1:0] f;input oe;input [3:0] y;output p,ov,a_gt_b,a_eg_b,a_lt_b; reg [4:0] im_y;always @(a or b or f)beginov=1'b0;im_y=0;case(f)2'b00:beginim_y=a+b;if(im_y>5'b01111)ov=1'b1;end2'b01:beginim_y=a-b;if(im_y>5'b01111)ov=1'b1;end2'b10:im_y[3:0]=a&b;2'b11:im_y[3:0]=a^b;default:im_y[3:0]=4'b0000;endcaseendalways @(a or b)beginif(a>b){a_gt_b,a_ge_b,a_lt_b}=3'b100;else if(a{a_gt_b,a_ge_b,a_lt_b}=3'b001;else{a_gt_b,a_ge_b,a_lt_b}=3'b010;endassign p=^im_y[3:0];assign y=oe?im_y[3:0]:4'bz;endmodule/***************************************************************** ********/模块alu_4bit是四功能的算术逻辑单元,输⼊包括数据信号a、b和功能信号f,输出包括数据信号y和ALU⽣成的奇偶校验信号p、溢出信号ov及⽐较信号。
Verilog仿真文件testbench编写样例
Verilog 仿真文件testbench编写样例`timescale 1ns/100psmodule testbench;localparam DATA_WIDTH = 32;localparam CLK_100_PERIOD = 5;localparam CLK_200_PERIOD = 2.5;localparam SIM_TIME = 150000;localparam ;localparam ;reg clk_100, clk_200;wire clk;assign clk = clk_100;alwaysbeginclk_100 = 0;forever #CLK_100_PERIOD clk_100 = ~clk_100;endalwaysbeginclk_200 = 0;forever #CLK_200_PERIOD clk_200 = ~clk_200;endreg rstn;integer fp_testin;integer fp_matlab_out;integer fp_sim_out;integer fp_outdiff;reg signed [DATA_WIDTH/2-1:0] matlab_in_re, matlab_in_im;reg signed [DATA_WIDTH/2-1:0] matlab_out_re, matlab_out_im;reg signed [DATA_WIDTH/2-1:0] matlab_diff_re, matlab_diff_im;reg signed [DATA_WIDTH/2-1:0] matlab_diff_re2, matlab_diff_im2;reg signed [DATA_WIDTH/2-1:0] max_diff_re, max_diff_im;initial beginmax_diff_re = 0;max_diff_im = 0;rstn = 0;#500rstn = 1;#SIM_TIMEsim_finish();$stop();endtask sim_finish;beginif(fp_testin!=0)$fclose(fp_testin);if(fp_matlab_out!=0)$fclose(fp_matlab_out);if(fp_sim_out)$fclose(fp_sim_out);if(fp_outdiff!=0)$fclose(fp_outdiff);endendtaskinitialbeginfp_testin = 0;fp_testin=$fopen("txt_file/input_data.txt"," r");if(fp_testin==0)begin$display("input_data.txt open failed!"); sim_finish();$stop();endelse begin$fscanf(fp_testin,"%d, %d\n",matlab_in_re,matlab_in_im); endfp_matlab_out = 0;fp_matlab_out =$fopen("txt_file/matlab_out.txt"," r");if(fp_matlab_out==0)begin$display("fp_matlab_out.txt openfailed!");sim_finish();$stop();endelse begin$fscanf(fp_matlab_out,"%d, %d\n",matlab _out_re,matlab_out_im);endfp_sim_out = 0;fp_sim_out =$fopen("txt_file/modelsim_out.txt",&quo t;w");if(fp_sim_out == 0)begin$display("modelsim_out_re.txt openfailed!");sim_finish();$stop();endfp_outdiff = 0;fp_outdiff =$fopen("text_file/outdiff.txt","w& quot;);if(fp_outdiff==0)begin$display("outdiff.txt open failed!"); sim_finish();$stop();endendalways @(posedge clk)beginif(stest_wvalid && stest_wready) //ready to changebeginif(~$feof(fp_testin))$fscanf(fp_testin,"%d, %d\n",matlab_in_re,matlab_in_im); endelsebeginmatlab_in_re <= matlab_in_re;matlab_in_im <= matlab_in_im;endendalways @(posedge clk_100)beginif(mfc_wready && mfc_wvalid)beginmatlab_diff_re <= mfc_wdata_re - matlab_out_re; matlab_diff_im <= mfc_wdata_im - matlab_out_im; matlab_diff_re2 <= matlab_out_re - mfc_wdata_re ; matlab_diff_im2 <= matlab_out_im - mfc_wdata_im ; if(max_diff_re < matlab_diff_re)beginmax_diff_re <= matlab_diff_re;$display("max_diff_re:%dmax_diff_im:%d\n",max_diff_re,max_diff_im); endelse if(max_diff_re < matlab_diff_re2)beginmax_diff_re <= matlab_diff_re2;$display("max_diff_re:%dmax_diff_im:%d\n",max_diff_re,max_diff_im); endif(max_diff_im < matlab_diff_im)beginmax_diff_im <= matlab_diff_im;$display("max_diff_re:%dmax_diff_im:%d\n",max_diff_re,max_diff_im); endelse if(max_diff_im < matlab_diff_im2)beginmax_diff_im <= matlab_diff_im2;$display("max_diff_re:%dmax_diff_im:%d\n",max_diff_re,max_diff_im); end$fscanf(fp_matlab_out,"%d, %d\n",matlab _out_re,matlab_out_im);$fwrite(fp_sim_out, "%d, %d\n",mfc_wdata_re,mfc_wdata_im);$fwrite(fp_outdiff,"%d, %d\n",matlab_diff_re,matlab_diff_i m);endendendmodule。
VerilogHDL及其Testbench编写方法
Verilog HDL及其Testbench总结(欢迎批评指正:jackhuan@)1 Verilog HDL的基本观点1) 观点1:module内每个基本模块之间是并行运行的。
2) 观点2:每个模块相当于一个连续赋值的过程。
3) 观点3:方程和任务是共享代码的最基本方式。
4) 观点4:同语言可用于生成模拟激励和指定测试的验证约束条件。
5) 观点5:库的概念相当于Visual C++中的DLL概念。
6) 观点6:文件与文件之间的关系可以使用C++中的*.h和*.cpp之关系理解。
2 设计建模的三种方式1) 行为描述方式。
过程化结构,每个结构之间是并行的。
2) 数据流方式。
连续赋值语句方式,每个赋值语句之间是并行的,且赋值语句和结构之间是并行的。
3) 结构化方式。
门和模块实例化语句。
3 两者数据类型1) 线网数据类型wire:表示构件间的物理连线;2) 寄存器数据类型reg:表示抽象的数据存储元件。
4 几个概念1) 模块(module)。
模块是Verilog HDL的基本描述耽误,用于描述某个设计的功能或结构及其与其它模块通信的外部端口。
一个设计的结构可以使用开关级原语、门级原语和用户定义的原语方式描述;数据流行为使用使用连续赋值语句进行描述;时序行为使用过程结构描述。
模块的声明部分和语句可以散布在模块中的任何地方,但变量、寄存器、线网和参数说明必须在使用前出现。
2) 只有寄存器类型数据(reg/integer)能够在initial和always语句中被赋值。
3) 阻塞性和非阻塞性赋值。
理解这两个概念在学习verilog HDL中非常重要。
决定了时序的正确与否。
阻塞性赋值的概念是在该条赋值语句执行完成后再执行后面的语句,也就是说在执行该语句时,后面的语句是挂起的。
而非阻塞性赋值的结果在何时执行是不知道的,但是可以预见在某个时间步内该语句一定能够执行完成,从这个意义上来看,非阻塞性赋值的语句类似于并行语句,稍有处理不当,会引发多驱动源问题。
Verilog中inout类型的数据的使用和testbench仿真写法
Verilog inout 双向口使用和仿真芯片外部引脚很多都使用inout类型的,为的是节省管腿。
一般信号线用做总线等双向数据传输的时候就要用到INOUT类型了。
就是一个端口同时做输入和输出。
inout在具体实现上一般用三态门来实现。
三态门的第三个状态就是高阻' Z'。
当inout端口不输出时,将三态门置高阻。
这样信号就不会因为两端同时输出而出错了,更详细的内容可以搜索一下三态门tri-state的资料.1 使用inout类型数据,可以用如下写法:inout data_inout;input data_in;reg data_reg;//data_inout的映象寄存器reg link_data;assign data_inout=link_data?data_reg:1’bz;//link_data控制三态门//对于data_reg,可以通过组合逻辑或者时序逻辑根据data_in对其赋值.通过控制link_data的高低电平,从而设置data_inout是输出数据还是处于高阻态,如果处于高阻态,则此时当作输入端口使用.link_data可以通过相关电路来控制.2 编写测试模块时,对于inout类型的端口,需要定义成wire类型变量,而其它输入端口都定义成reg类型,这两者是有区别的.当上面例子中的data_inout用作输入时,需要赋值给data_inout,其余情况可以断开.此时可以用assign语句实现:assign data_inout=link?data_in_t:1’bz;其中的link ,data_in_t是reg类型变量,在测试模块中赋值.另外,可以设置一个输出端口观察data_inout用作输出的情况:Wire data_out;Assign data_out_t=(!link)?data_inout:1’bz;else,in RTLinout use in top module(PAD)dont use inout(tri) in sub module也就是说,在内部模块最好不要出现inout,如果确实需要,那么用两个port实现,到顶层的时候再用三态实现。
Verilog测试平台的简介(Testbenches)PPT
#15 start = 1;
end
Designing Your Testbench
You can make your testbench as simple or as comolex as you want. A comolex testbench would perform response berifivation “on-the-fly”.
Chapter 15:Introduction to Verilog Testbenches
Objectives In this section,you will learn about designing a testbench: ▪ Creating clocks ▪ Including files ▪ Strategic use of tasks and concurrent statements ▪ Controlling and observing the design ▪ Reporting warnings and errors
end
end
reg start;
nand #10 (clk,clk,start);
initial begin
#10 start = 0;
#10 start = 1;
end
Creating Clocks
Example 3
Here are examples of an asymmetric clock with delayed startup:
You can define the clock in either the design or its testbench. You can define the clock either behaviorally or structurally. Here are examples of a symmetric clock:
testbench
输出格式化时间信息
对#延迟,Verilog将延迟值舍入最近(四舍五入)时间精度值。 例如,上面的例子修改为:
`timescale 1ns/ 100ps not #9.49 n1 (o1, in1);
`timescale 1ns/ 100ps not #9.42 n1 (o1, in1);
结果为:
time realtime in1 o1 0 0 9 0 10 1 19 1 10.00ns 1 19.50ns 19 10 x 9.50ns 9 0.00ns stime 0
$display ($ time, “%b \t %h \t %d \t %o”, sig1, sig2, sig3, sig4); $display ($ time, “%b \t”, sig1, “%h \t”, sig2, “% d \t”, sig3, “%o”, sig4);
$display支持二进制、八进制、十进制和十六进制。缺省基数为十进制。
rval); $display("rval=%o otal %b binary", rval, rval); $display("rval has %c ascii character value",rval); $display("pd strength value is %v",pd); $display("current scope is %m"); $display("%s is ascii value for 101",101); $display("simulation time is %t",$time); end endmodule
(verilog和vhdl)Testbench编程指南
(verilog和vhdl)Testbench编程指南TestBench编程指南如今数字设计的规模变得越来越庞大,设计的复杂程度也越来越高,这就使得设计的验证变得越来越困难,而且费时费力。
为了应对这种挑战,验证工程师依靠各种验证工具和方法。
对于大型设计,如几百万门的设计,通常采用一整套正式的验证工具。
然而,对于小一些的设计,设计工程师发现往往采用带TestBench的HDL仿真工具是最好的途径。
TestBench已经变成验证高级语言设计的一种标准的方法。
通常,TestBench执行以下任务:z例化设计,使其可测试(DUT-design under test);z通过将测试向量应用到模型来仿真例化后的可测试的设计;z将结果输出到终端,或者输出波形窗口;z将真实的结果和期望的结果进行比较;一般,TestBench采用工业标准的VHDL或者Verilog硬件描述语言来编写。
TestBench调用功能设计,然后仿真。
复杂的测试文件执行附加功能――例如,他们包含逻辑以决定合适的设计激励或者比较真实的结果和期望的结果。
以下章节将讨论一个组织良好的测试文件的组成,以及例举了一个带有自检的测试文件(自动将真实的结果和预期的结果进行比较)。
下图是一个标准的HDL验证的流程。
自从测试文件可以用VHDL或者Verilog编写以来,测试验证流程就可以在平台和供应商的工具交叉进行。
同时,由于VHDL和Verilog都是标准的公用的语言,所以用VHDL或者是Verilog描述的验证可以很简单的被再使用。
图1. HDL验证流程测试文件构成:测试文件可以采用VHDL或者Verilog语言编写。
由于测试文件只是用来仿真的,他们就不被用于综合的RTL语言子集的语法所约束。
相反,所有行为结构都可以被使用。
这样,测试文件可以被写的更通用,更易于维护。
所有的测试文件都包含以下基本内容,如表1。
如上所属,测试文件经常同时包含附加功能,如结果的可视化显示和内建错误检测。
Testbench文件编写纪要(Verilog)
Testbench⽂件编写纪要(Verilog)之前在使⽤Verilog做FPGA项⽬中、以及其他⼀些不同的场合下,零散的写过⼀些练⼿性质的testbench⽂件,开始⼏次写的时候,每次都会因为⼀些基本的东西没记住、写的很不熟练,后⾯写的时候稍微熟练了⼀点、但是整体编写下来⽐较零碎不成体系,所以在这⾥简要记录⼀下⼀般情况下、针对⼩型的verilog模块进⾏测试时所需要使⽤到的testbench⽂件的编写要点。
本⽂主要参考了在⽹上找到的Lattice公司的“A Verilog HDL Test Bench Primer”⼿册中的有关内容。
谢谢!模块实例化、reg&wire声明、initial和always块的使⽤需要测试的模块(Verilog-module)被称为DUT(Design Under Test),在testbench中需要对⼀个或者多个DUT进⾏实例化。
Testbench中的顶层module不需要定义输⼊和输出。
Testbench中连接到DUT instance的输⼊的为reg类型、连接到DUT instance的输出的为wire类型。
对于DUT的inout类型变量,在testbench中需要分别使⽤reg、wire类型的变量进⾏调⽤。
例如,对于下⾯这样⼀个待测试module:module bidir_infer (DATA, READ_WRITE);input READ_WRITE ;inout [1:0] DATA ;reg [1:0] LATCH_OUT ;always @ (READ_WRITE or DATA) beginif (READ_WRITE == 1)LATCH_OUT <= DATA;endassign DATA = (READ_WRITE == 1) ? 2'bZ : LATCH_OUT;endmodule为其设计的testbench⽂件可以是:module test_bidir_ver;reg read_writet;reg [1:0] data_in;wire [1:0] datat, data_out;bidir_infer uut (datat, read_writet);assign datat = (read_writet == 1) ? data_in : 2'bZ;assign data_out = (read_writet == 0) ? datat : 2'bZ;initial beginread_writet = 1;data_in = 11;#50 read_writet = 0;endendmodule和普通的Verilog模块中⼀样、使⽤assign对wire类型的变量进⾏赋值。
verilog testbench例子
Verilog Testbench例子Verilog是一种硬件描述语言,用于描述数字系统。
在Verilog中,testbench是用于验证设计的一部分。
它是一个独立的模块,用于提供输入信号并验证设计的输出信号。
在本文中,我们将介绍一个Verilog testbench的例子,以帮助读者更好地理解Verilog设计和验证的流程。
1. 确定测试目标在编写Verilog testbench之前,首先需要确定测试的目标。
这包括对设计的功能和性能的需求,并确定测试中需要关注的重点。
测试目标的确定将有助于后续测试用例的编写和验证结果的分析。
2. 编写testbench框架testbench通常包括以下几个部分:- 时钟信号生成器:用于生成时钟信号,驱动设计的时序逻辑。
- 信号生成器:用于生成各种输入信号,模拟实际工作状态下的输入情况。
- 仿真模型:绑定被测设计的接口,将输入信号传递给设计,并验证设计的输出信号是否符合预期。
下面是一个简单的testbench框架的例子:```verilog`timescale 1ns / 1nsmodule tb_example;// Define signalsreg clk;reg rst;reg [7:0] data_in;wire [7:0] data_out;// Instantiate design under test (DUT) example_dut dut(.clk(clk),.rst(rst),.data_in(data_in),.data_out(data_out));// Clock generatoralways#5 clk = ~clk;// Stimulus generatorinitial beginrst = 1;#10 rst = 0;#20 data_in = 8'hFF;#20 data_in = 8'h00;// Add more stimulus hereend// Check outputsalways (posedge clk) begin// Add output check hereendendmodule```3. 编写测试用例编写测试用例是testbench编写的关键步骤之一。
北大数字集成电路课件--15_Verilog-testbench的写法
矢量回放
• 保存在文件中的矢量反过来可以作为激励
module read_file_tb; parameter num_vecs = 256; reg [7:0] data_bus; reg [7:0] stim [num_vecs-1:0]; integer i; DUT u1 (results, data_bus) initial begin // Vectors are loaded $readmemb ("vec. txt", stim); for (i =0; i < num_vecs ; i = i + 1) #50 data_bus = stim[i]; end endmodule // 激励文件 激励文件vec.txt 00111000 00111001 00111010 00111100 00110000 00101000 00011000 01111000 10111000 . .
循环激励
• 从循环产生激励有以下特性: 从循环产生激励有以下特性: 在每一次循环, 在每一次循环,修改同一组激励变量 时序关系规则 代码紧凑
module loop_tb; reg clk; reg [7:0] stimulus; wire [7:0] results; integer i; DUT u1 (results, stimulus); always begin // clock generation clk = 1; #5 clk = 0; #5 end initial begin for (i = 0; i < 256; i = i + 1) @( negedge clk) stimulus = i; #20 $finish; end endmodule
组合-时序逻辑电路Verilog-Testbench代码_带仿真代码和波形_
组合-时序逻辑电路Verilog-Testbench代码_带仿真代码和波形_1组合逻辑电路--基本门电路1.1基本门电路1.1.1结构化描述⽅式代码如下View Code1 module logics2 (3 input iA,4 input iB,5 output oAnd,6 output oOr,7 output oNot8 );910 and and_inst(oAnd,iA,iB);11 or or_inst(oOr,iA,iB);12 not not_inst(oNot,iA);1314 endmodule最底层的是门级原语and or not RTL级视图testbench如下View Code1 `timescale 1 ns/ 1 ns2 module logics_tb();34 reg ia;5 reg ib;67 wire oAnd;8 wire oOr;9 wire oNot;1011 initial12 begin13 ia=0;14 #40 ia=1;15 #40 ia=0;16 #40 ia=1;17 #40 ia=0;18 end1920 initial21 begin22 ib=0;23 #40 ib=0;24 #40 ib=1;25 #40 ib=1;26 #40 ib=0;27 end2829 logics logics_inst30 (31 .iA(ia),32 .iB(ib),33 .oAnd(oAnd),34 .oOr(oOr),35 .oNot(oNot)36 );37RTL级仿真图形如下GATE级仿真图如下可见RTL级仿真是理想的,GATE级仿真考虑了延迟和信号开始的不确定。
1.1.2采⽤流描述⽅法代码如下View Code1 module logics2 (3 input iA,4 input iB,5 output oAnd,6 output oOr,7 output oNot8 );910 assign oAnd=iA&iB11 assign oOr=iA|iB;12 assign oNot=~iA;1314 endmoduleRTL级视图,仿真图形同上。
verilog testbench语法
verilog testbench语法摘要:一、Verilog 简介二、Verilog Testbench 的作用三、Verilog Testbench 语法1.模块声明2.信号声明3.初始化语句4.循环语句5.断言和读取语句6.函数和任务声明7.子模块和测试序列四、Verilog Testbench 实例1.简单实例2.复杂实例五、Verilog Testbench 应用场景六、总结正文:一、Verilog 简介Verilog 是一种硬件描述语言,用于描述数字电路和模拟混合信号电路。
它被广泛应用于电子设计自动化(EDA)领域,可以用来设计、验证和仿真数字电路。
二、Verilog Testbench 的作用Verilog Testbench 是一个用于验证Verilog 代码的工具,它可以模拟真实环境中的测试信号,并检查电路的行为是否符合预期。
Testbench 可以帮助我们发现代码中的错误,提高设计质量。
三、Verilog Testbench 语法1.模块声明一个Testbench 模块使用`module`关键字声明,例如:```module tb_example();```2.信号声明在Testbench 中,需要声明待测试模块的输入输出信号。
例如:```reg [7:0] A, B;wire C;```3.初始化语句初始化语句用于设置信号的初始值。
例如:```initial beginA = 8"h00;B = 8"h01;end```4.循环语句Testbench 中可以使用`for`、`forever`和`while`等循环语句。
例如:```initial beginfor (A = 8"h00; A < 8"hFF; A = A + 8"h01) begin// 测试代码endend```5.断言和读取语句断言语句用于检查信号之间的关系是否满足预期。
verilog,testbench
Testbench专题所谓testbench,即测试平台,详细的说就是给待验证的设计添加激励,同时观察输出响应是否符合设计要求。
也许我们会把把程序开发出来算作一个工程项目的重大的比例,这在今天的FPGA设计中,并不是如此,往往在仿真验证上的工作量占到一半以上。
试想这么一个测试,一个16位的输入总线,它可以有多少种组合?如果每次随机产生一种输入,用波形的去画一画,眼花!波形是最直观的测试手段,但不是唯一手段。
一个完整的测试平台如下图所示,它是分结构组成的,其中对设计测试结果的判断不仅可以通过观察对比波形得到,而且可以灵活使用脚本命令将有用的输出信息打印到终端或者产生文本进行观察,也可以写一段代码让它们自动比较输出结果。
TB的设计是多种多样,可以使用灵活的VERILOG的验证脚本,但是它也是基于硬件语言但是又服务于软件测试的语言,有时并行有时顺序,只有掌握这些关键点,才能很好服务测试。
技巧1Tb中的例化应该把INPUT转换成REG,因为待测设计的输入值是由TB 决定的。
相应的OUTPUT 就应该转换成WIRE,因为待测设计的输出值不是由tb决定的。
这里需要注意Inout端口,在例化中也是一个wire型。
技巧2时钟产生第一种:parameter PERIOD=XX; Initial beginClk=0;Forever#( PERIOD /2) clk =~clk; End第二种parameter PERIOD=XX;always begin#( PERIOD /2) clk=0;# (PERIOD /2) clk=1;End技巧3复位信号Initial beginReset_task(XX);//注意时间尺度…….EndTask reset_task;Input [15:0]reset_time;BeginReset=0;# reset_time;Reset =1;End技巧4变量的定义在编写testbench时,关于变量的定义常犯的错误就是将一个定义的全局变量应用到了两个不同的always块中(如例1所示),那么由于这两个always块独立并行的工作机制,很可能会导致意想不到的后果。
verilog testbench语法
verilog testbench语法摘要:1.Verilog Testbench 简介2.Testbench 结构3.编写Testbench 的注意事项4.Testbench 常用技巧与策略5.UVM 与Verilog Testbench 的区别正文:Verilog Testbench 是一种用于验证数字电路设计的测试工具,通过模拟和仿真来检查电路功能是否符合预期。
Testbench 主要由三个部分组成:驱动模块、监控模块和测试模块。
在本文中,我们将详细讨论Testbench 的语法、结构以及编写Testbench 时需要注意的要点。
1.Verilog Testbench 简介Verilog Testbench 是基于文本的测试工具,它使用Verilog 编程语言编写。
通过描述性文本和激励信号,Testbench 可以模拟数字电路的行为,并在仿真过程中检查电路的响应是否正确。
Testbench 主要用于验证电路设计的功能、时序和性能。
2.Testbench 结构一个典型的Testbench 结构包括以下几个部分:- 驱动模块:负责产生输入信号,用于刺激被测电路。
- 监控模块:用于捕获被测电路的输出信号,并与预期值进行比较。
- 测试模块:根据输入信号和输出信号的比较结果,判断电路设计的正确性。
3.编写Testbench 的注意事项- 确保Testbench 与被测模块的接口匹配,包括输入信号、输出信号和参数。
- 使用适当的时钟信号和复位信号,确保仿真过程中电路状态的正确切换。
- 编写清晰的注释,便于理解和维护。
- 合理使用宏定义和参数化,提高Testbench 的可复用性。
- 验证电路的边界条件,确保测试的全面性。
4.Testbench 常用技巧与策略- 使用事件驱动的仿真算法,提高仿真速度。
- 采用分阶段测试策略,逐步验证电路的各个功能模块。
- 使用随机化测试,提高测试覆盖率。
- 结合断言和检查点,确保电路的正确性。
Verilog-HDL-如何编写TESTBENCH
08:292主要内容Verilog 对验证的支持系统函数和系统任务如何编写模块的TESTBENCH08:293系统任务和系统函数是Verilog中预先定义好的,用于调试和编译预处理的任务或函数。
以$开头,用于控制和检测仿真模拟过程主要有:(1)用于获取仿真时间的系统函数(2)支持文本输出(检测信号、显示信号)的系统任务(3)用于文件输入、输出操作的系统任务(4)用于暂停和退出仿真的系统任务(5)用于产生随机数的系统任务08:294获取当前仿真时间的系统函数$time,$realtime,$stime:返回当前仿真时间。
$time返回一个64位的整数时间值,$realtime返回的结果是实数时间值,是更为精确的仿真时间 $stime返回一个32位整数时间值。
(对大于232的时间,返回模232的值。
使用它可以节省显示及打印空间。
)这些函数的返回值使用调用模块中`timescale 定义的模块仿真时间尺度为单位08:295例..\..\verilog_example\Dec2x4.v..\..\verilog_example\Dec_Test.v # At time 0, input is 0,0,0, output is,xxxx # At time 4, input is 0,0,0, output is,1111# At time 10, input is 0,0,1, output is,1111# At time 13, input is 0,0,1, output is,0111# At time 20, input is 1,0,1, output is,0111# At time 23, input is 1,0,1, output is,0101# At time 26, input is 1,0,1, output is,1101# At time 30, input is 1,1,1, output is,1101# At time 33, input is 1,1,1, output is,1100# At time 36, input is 1,1,1, output is,1110# At time 40, input is 0,1,1, output is,1110# At time 44, input is 0,1,1, output is,1011# At time 50, input is 0,0,1, output is,1011# At time 54, input is 0,0,1, output is,011108:296Verilog 支持的文本输出的系统任务显示任务:用于仿真模拟期间显示信息。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
于敦山
北大微电子学系
Bench使用简介 第十五章 Verilog Test Bench使用简介
学习内容: 学习内容: • 用一个复杂的 用一个复杂的test bench复习设计的组织与仿真 复习设计的组织与仿真 • 建立 建立test bench通常使用的编码风格及方法 通常使用的编码风格及方法
数组激励
• 从数组产生激励有以下特性: 从数组产生激励有以下特性: 在每次反复中, 在每次反复中,修改同一组激励变量 激励数组可以直接从文件中读取
module array_ tb; reg [7: 0] data_ bus, stim_ array[ 0: 15]; // 数 组 integer i; DUT u1 (results, stimulus); initial begin // 从数组读入数据 #20 stimulus = stim_array[0]; #30 stimulus = stim_array[15]; // 线激励 #20 stimulus = stim_array[1]; for (i = 14; i > 1; i = i - 1) // 循环 #50 stimulus = stim_array[i] ; #30 $finish; end endmodule
在上面的例子中,公共参数在一个独立的文件中定义。 在上面的例子中,公共参数在一个独立的文件中定义。此文件在不同 的仿真中可被不同的测试文件调用。 的仿真中可被不同的测试文件调用。
施加激励
种方法。一些常用的方法有: 产生激励并加到设计有很多 种方法。一些常用的方法有: • 从一个 从一个initial块中施加线激励 块中施加线激励 • 从一个循环或 从一个循环或always块施加激励 块施加激励 • 从一个向量或整数数组施加激励 • 记录一个仿真过程,然后在另一个仿真中回放施加激励 记录一个仿真过程,
包含文件
• 包含文件用于读入代码的重复部分或公共数据。 包含文件用于读入代码的重复部分或公共数据。
module clk_gen (clk); output clk; reg clk; `include "common.txt" initial begin while ($ time < sim_end) begin clk = initial_clock; #(period/2) clk = !initial_clock; #(period/2); end $finish; end endmodule // common. txt // clock and simulator constants parameter initial_clock = 1; parameter period = 15; parameter max_cyc = 100; parameter sim_end = period * max_cyc
并行块
• fork…join块在测试文件中很常用。他们的并行特性使用户可以说明 块在测试文件中很常用。 块在测试文件中很常用 绝对时间,并且可以并行的执行复杂的过程结构,如循环或任务。 绝对时间,并且可以并行的执行复杂的过程结构,如循环或任务。
module inline_ tb; reg [7: 0] data_ bus; // instance of DUT initial fork data_bus = 8'b00; #10 data_bus = 8'h45; #20 repeat (10) #10 data_bus = data_bus + 1; #25 repeat (5) #20 data_bus = data_bus << 1; #140 data_bus = 8'h0f; join endmodule 上面的两个repeat循环从不同时间开始,并行执行。 象这样的特殊的激励集在单个的be
在上面两个例子中, 上所赋的常数值, 在上面两个例子中,在 net或register上所赋的常数值,覆盖所有在时刻 和时刻 或 上所赋的常数值 覆盖所有在时刻10和时刻 20之间可能发生在该信号上的其他任何赋值或驱动。如果所赋值是一个表达式, 之间可能发生在该信号上的其他任何赋值或驱动。 之间可能发生在该信号上的其他任何赋值或驱动 如果所赋值是一个表达式, 则该表达式将被持续计算。 则该表达式将被持续计算。 • • • • • • 可以强制(force)并释放一个信号的指定位、部分位或连接,但位的指定不能 并释放一个信号的指定位、部分位或连接, 可以强制 并释放一个信号的指定位 是一个变量(例如out_vec[i]) 是一个变量(例如 ) 不能对register的一位或部分位使用 的一位或部分位使用assign和deassign 不能对 的一位或部分位使用 和 对同一个信号, 覆盖assign。 对同一个信号,force覆盖 覆盖 。 后面的assign或force语句覆盖以前相同类型的语句。 语句覆盖以前相同类型的语句。 后面的 或 语句覆盖以前相同类型的语句 如果对一个信号先assign然后 如果对一个信号先 然后force,它将保持force值。在对其进行release后, ,它将保持 值 在对其进行 后 然后 信号为assign值。 信号为 值 如果在一个信号上force多个值,然后 多个值, 该信号, 如果在一个信号上 多个值 然后release该信号,则不出现任何 该信号 则不出现任何force值。 值
Time | data_ bus 0 | 8’b0000_0000 10 | 8’b0100_0101 30 | 8’b0100_0110 40 | 8’b0100_0111 45 | 8’b1000_1110 50 | 8’b1000_1111 60 | 8’b1001_0000 65 | 8’b0010_0000 70 | 8’b0010_0001 80 |
强制激励
• 在过程块中,可以用两种持续赋值语句驱动一个值或表达式到一个信号。 在过程块中,可以用两种持续赋值语句驱动一个值或表达式到一个信号。 – 过程持续赋值通常不可综合,所以它们通常用于测试基准描述。 过程持续赋值通常不可综合,所以它们通常用于测试基准描述。 – 对每一种持续赋值,都有对应的命令停止信号赋值。 对每一种持续赋值,都有对应的命令停止信号赋值。 – 不允许在赋值语句内部出现时序控制。 不允许在赋值语句内部出现时序控制。 对一个寄存器使用assign和deassign,将覆盖所有其他在该信号上的赋值 。 对一个寄存器使用 和 ,将覆盖所有其他在该信号上的赋值。 这个寄存器可以是RTL设计中的一个节点或测试基准中在多个地方赋值的 这个寄存器可以是 设计中的一个节点或测试基准中在多个地方赋值的 信号等。 信号等。 initial begin #10 assign top.dut.fsm1.state_reg = `init_state ; #20 deassign top.dut.fsm1.state_reg ; end 在register和net上(例如一个门级扫描寄存器的输出)使用 和 上 例如一个门级扫描寄存器的输出)使用force和release, 和 , 将覆盖该信号上的所有其他驱动。 将覆盖该信号上的所有其他驱动。 initial begin #10 force top. dut. counter. scan_ reg. q = 0 ; #20 release top. dut. counter. scan_ reg. q ; end
矢量回放
• 保存在文件中的矢量反过来可以作为激励
module read_file_tb; parameter num_vecs = 256; reg [7:0] data_bus; reg [7:0] stim [num_vecs-1:0]; integer i; DUT u1 (results, data_bus) initial begin // Vectors are loaded $readmemb ("vec. txt", stim); for (i =0; i < num_vecs ; i = i + 1) #50 data_bus = stim[i]; end endmodule // 激励文件 激励文件vec.txt 00111000 00111001 00111010 00111100 00110000 00101000 00011000 01111000 10111000 . .
矢量采样
• 在仿真过程中可以对激励和响应矢量进行采样,作为其它仿真的激 在仿真过程中可以对激励和响应矢量进行采样, 励和期望结果。 励和期望结果。
module capture_tb; parameter period = 20 reg [7:0] in_vec, out_vec; integer RESULTS, STIMULUS; DUT u1 (out_ vec, in_ vec); initial begin STIMULUS = $fopen("stimulus. txt") ; RESULTS = $fopen("results. txt") ; fork if (STIMULUS != 0 ) forever #( period/2) $fstrobeb (STIMULUS, "%b", in_vec); if (RESULTS != 0 ) #( period/2) forever #( period/2) $fstrobeb (RESULTS, "%b", out_vec); join end endmodule
• 使用矢量文件输入 输出的优点: 使用矢量文件输入/输出的优点: 输出的优点 – 激励修改简单 – 设计反复验证时直接使用工具比较矢量文件。 设计反复验证时直接使用工具比较矢量文件。
错误及警告报告
• 使用文本或文件输出类的系统任务报告错误及警告