怎样写testbench
verilogtestbench写法
Verilog测试平台(testbench)技术(一) 收藏对设计进行功能仿真和时序仿真时,需要给待测模块提供激励输入。
对于由V erilog语言描述的设计模块,最好的方法自然同样是用Verilog语言对待测模块施加激励和检测模块的输出响应。
实际应用中,Verilog测试平台(testbench)就是用来提供上述功能的。
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<b){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及比较信号。
如何编写testbench的总结(非常实用的总结)
如何编写testbench的总结(⾮常实⽤的总结)1.激励的设置相应于被测试模块的输⼊激励设置为reg型,输出相应设置为wire类型,双向端⼝inout在测试中需要进⾏处理。
⽅法1:为双向端⼝设置中间变量inout_reg作为该inout的输出寄存,inout⼝在testbench中要定义为wire型变量,然后⽤输出使能控制传输⽅向。
eg:inout [0:0] bi_dir_port;wire [0:0] bi_dir_port;reg [0:0] bi_dir_port_reg;reg bi_dir_port_oe;assign bi_dir_port=bi_dir_port_oe?bi_dir_port_reg:1'bz;⽤bi_dir_port_oe控制端⼝数据⽅向,并利⽤中间变量寄存器改变其值。
等于两个模块之间⽤inout双向⼝互连。
往端⼝写(就是往模块⾥⾯输⼊)⽅法2:使⽤force和release语句,这种⽅法不能准确反映双向端⼝的信号变化,但这种⽅法可以反映块内信号的变化。
具体如⽰:module test();wire data_inout;reg data_reg;reg link;#xx; //延时force data_inout=1'bx; //强制作为输⼊端⼝...............#xx;release data_inout; //释放输⼊端⼝endmodule从⽂本⽂件中读取和写⼊向量1)读取⽂本⽂件:⽤ $readmemb系统任务从⽂本⽂件中读取⼆进制向量(可以包含输⼊激励和输出期望值)。
$readmemh ⽤于读取⼗六进制⽂件。
例如:reg [7:0] mem[1:256] // a 8-bit, 256-word 定义存储器meminitial $readmemh ( "mem.data", mem ) // 将.dat⽂件读⼊寄存器mem中initial $readmemh ( "mem.data", mem, 128, 1 ) // 参数为寄存器加载数据的地址始终2)输出⽂本⽂件:打开输出⽂件⽤?$fopen 例如:integer out_file; // out_file 是⼀个⽂件描述,需要定义为 integer类型out_file = $fopen ( " cpu.data " ); // cpu.data 是需要打开的⽂件,也就是最终的输出⽂本设计中的信号值可以通过$fmonitor, $fdisplay,2. Verilog和Ncverilog命令使⽤库⽂件或库⽬录ex). ncverilog -f run.f -v lib/lib.v -y lib2 +libext+.v //⼀般编译⽂件在run.f中, 库⽂件在lib.v中,lib2⽬录中的.v⽂件系统⾃动搜索使⽤库⽂件或库⽬录,只编译需要的模块⽽不必全部编译3.Verilog Testbench信号记录的系统任务:1). SHM数据库可以记录在设计仿真过程中信号的变化. 它只在probes有效的时间内记录你set probe on的信号的变化.ex). $shm_open("waves.shm"); //打开波形数据库$shm_probe(top, "AS"); // set probe on "top",第⼆个参数: A -- signals of the specific scropeS -- Ports of the specified scope and below, excluding library cellsC -- Ports of the specified scope and below, including library cellsAS -- Signals of the specified scope and below, excluding library cellsAC -- Signals of the specified scope and below, including library cells还有⼀个 M ,表⽰当前scope的memories, 可以跟上⾯的结合使⽤, "AM" "AMS" "AMC"什么都不加表⽰当前scope的ports;$shm_close //关闭数据库2). VCD数据库也可以记录在设计仿真过程中信号的变化. 它只记录你选择的信号的变化.ex). $dumpfile("filename"); //打开数据库$dumpvars(1, top.u1); //scope = top.u1, depth = 1第⼀个参数表⽰深度, 为0时记录所有深度; 第⼆个参数表⽰scope,省略时表当前的scope.$dumpvars; //depth = all scope = all$dumpvars(0); //depth = all scope = current$dumpvars(1, top.u1); //depth = 1 scope = top.u1$dumpoff //暂停记录数据改变,信号变化不写⼊库⽂件中$dumpon //重新恢复记录3). Debussy fsdb数据库也可以记录信号的变化,它的优势是可以跟debussy结合,⽅便调试.如果要在ncverilog仿真时,记录信号, ⾸先要设置debussy:a. setenv LD_LIBRARY_PATH :$LD_LIBRARY_PATH(path for debpli.so file (/share/PLI/nc_xl//nc_loadpli1))b. while invoking ncverilog use the +ncloadpli1 option.ncverilog -f run.f +debug +ncloadpli1=debpli:deb_PLIPtrfsdb数据库⽂件的记录⽅法,是使⽤$fsdbDumpfile和$fsdbDumpvars系统函数,使⽤⽅法参见VCD注意: 在⽤ncverilog的时候,为了正确地记录波形,要使⽤参数: "+access+rw", 否则没有读写权限在记录信号或者波形时需要指出被记录信号的路径,如:tb.module.u1.clk.………………………………………………………………………………………………………关于信号记录的系统任务的说明:在testbench中使⽤信号记录的系统任务,就可以将⾃⼰需要的部分的结果以及波形⽂件记录下来(可采⽤sigalscan⼯具查看),适⽤于对较⼤的系统进⾏仿真,速度快,优于全局仿真。
Testbench写法总结
outer_port_tb_wire,inner_port_tb_wire);
end
else
begin
$display("\n **** time=%t ****",$time);
$display("ERROR! out_en=%d",out_en_tb);
$display("ERROR! outer_port_tb_wire != inner_port_tb_wire" );
$display("ERROR! outer_port_tb_wire=%d, inner_port_tb_wire=%d",
outer_port_tb_wire,inner_port_tb_wire);
end
end
endmodule
验证该双向端口的testbench结构如图2所示。
这是一个self-checking testbench,可以自动检查仿真结果是否正确,并在Modelsim控制台上打印出提示信息。图中Monitor完成信号采样、结果自动比较的功能。
testbench的工作过程为
1)out_en=1时,双向端口处于输出状态,testbench给inner_port_tb_reg信号赋值,然后读取outer_port_tb_wire的值,如果两者一致,双向端口工作正常。
module tb();
reg[7:0] inner_port_tb_reg;
wire[7:0] inner_port_tb_wire;
reg[7:0] outer_port_tb_reg;
wire[7:0] outer_port_tb_wire;
简单的Testbench设计
//被测设计的输入信号,对应测试脚本的输出信号(注意要定义成 reg) reg clk; reg rst_n; //被测设计的输出信号,对应测试脚本的输入信号(注意要定义成 wire) wire led; //例化待测模块 Led led_test
简单的 Testbench nch 是一种验证的手段。首先,任何设计都是会有输入输出的。 但是在软环境中没有激励输入,也不会对你设计的输出正确性进行评估。那 幺此时便有一种,模拟实际环境的输入激励和输出校验的一种“虚拟平台”的 产生。在这个平台上你可以对你的设计从软件层面上进行分析和校验,这个 就是 testbench 的含义。 简单的 Testbench 设计 //timescale 仿真时间单位/时间精度(时间精度不能比时间单位还要 大) timescale 1ns/1ps //定义一个无输入无输出的 Moudle module Led_clg_tst();
( .clk(clk), .rst_n(rst_n), .led(led) ); //使用 Initail 生成 rst_n 激励 initial begin //监控 Led 信号变化
monitor(monitor(time,”led value= %b\n”,led); end //使用 alwasys 模拟产生 25M 的时钟信号 always #20 clk = ~clk; endmodule
我的testbench书写总结
占空比为 50%的时钟`timescale 1ns/1ns //定义时间的尺度和精度,其中精度和小树部分挂钩parameter period=4’d10;reg clk; //时钟是输入给DUT的信号必须声明为reg类型initialbeginclk=1’b0; //定义clk的初始状态为低电平forever#( period/2) clk=~clk;endparameter period=4’d10;reg clk;initialbeginclk=1’b0; //定义clk的初始状态为低电平endalways #( period/2) clk=~clk;占空比非50%的时钟信号parameter HIGH_TIME=4,LOW_TIME=6;reg clk;initialbeginclk=1’b0; //定义clk的初始状态为低电平endalwaysbegin# LOW_TIME clk=1’b1;//0~LOW_TIME为低电平# HIGH_TIME clk=1’b0; //从low_time~(low_time+high_time)为高电平end固定数目的时钟信号parameter PulseCount=4,PERIOD=10;reg clk;initialbeginclk=1’b0; //定义clk的初始状态为低电平repeat(PulseCount) //相对于下面的语句重复执行4次#(PERIOD/2) clk=~clk;End//先低电平半个周期,然后再产生两个完整周期的脉冲,结束时clk为低电平parameter Phase_Shift=2;PERIOD=10;reg source_clk;wire derive_clk;//这里是wire好像没有多大用处,要是能用reg就有用了//用initial语句生成源时钟initialbeginclk=1’b0; //定义clk的初始状态为低电平forever#( PERIOD/2) source_clk=~source_clk;EndAssign #Phase_Shift derive_clk=source_clk; //生成派生时钟,要延后2ns2,对于仿真器,reg在没有赋初始值的情况下默认的值为’X’即不定值,而wire的默认值为’Z’即高阻态。
vivadotestbench写法
主题:vivadotestbench编写方法内容:1. 什么是vivadotestbench?vivadotestbench是一个用于编写Verilog的测试台,用于对Verilog 模块进行仿真和验证。
它可以帮助工程师们在Verilog设计的早期阶段进行功能验证和性能评估,以确保设计的稳定性和正确性。
2. vivadotestbench的基本结构vivadotestbench通常包含以下基本结构:模块实例化、时钟和复位初始化、输入数据生成、仿真控制和输出检测。
这些基本结构构成了一个完整的测试台,可以用于对Verilog模块进行全面的验证和测试。
3. vivadotestbench的编写步骤编写vivadotestbench的步骤可以分为以下几个部分:3.1 模块实例化:首先需要实例化待测模块,并且连接时钟、复位信号和输入输出端口。
3.2 时钟和复位初始化:在测试台中需要为待测模块提供时钟信号,并对复位信号进行初始化。
3.3 输入数据生成:根据待测模块的输入端口,生成相应的测试数据,并将其输入到待测模块中。
3.4 仿真控制:控制仿真的开始、暂停和结束,以及执行仿真的时长和步长等。
3.5 输出检测:对待测模块的输出进行检测和比对,以验证其正确性和稳定性。
4. vivadotestbench的常见问题及解决方法在编写vivadotestbench的过程中,可能会遇到一些常见的问题,例如时序约束不准确、测试数据生成不完整、输出检测逻辑错误等。
针对这些问题,可以采取一些解决方法,如优化时序约束、增加测试数据生成的覆盖率、修正输出检测逻辑等。
5. vivadotestbench的优点和应用场景vivadotestbench具有易用性好、灵活性强、功能全面等优点,适用于对Verilog模块进行全面的仿真和验证。
它可以帮助工程师们提高设计的稳定性和正确性,加快设计的上线速度,降低设计的风险和成本。
结论:vivadotestbench是一个强大的Verilog测试台,可以帮助工程师们在Verilog设计的早期阶段进行全面的功能验证和性能评估。
(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类型的变量进⾏赋值。
(完整版)实例解读Testbench编写方法
实例解读Testbench编写方法前言:在进行quartusII设计时,不少人刚开始觉得仿真极其不方便,还需要编写测试文件,浪费时间精力。
不过小编想告诉大家,其实testbench编写很容易学,不外乎wait for 语句的堆叠就可以了,至于高深的用法,对一般程序都涉及不到,没必要弄得那么复杂。
下面看看实例吧,将详细说明testbench的编写:我们可以通过Quartus自动生成一个Testbench的模板,选择Processing —〉 Start -〉Start Test Bench Template Writer,等待完成后打开刚才生成的Testbench,默认是保存在sim ulation\modelsim文件夹下的.vt格式文件.打开vt文件后可以看到Quartus已经为我们完成了一些基本工作,包括端口部分的代码和接口变量的声明,我们要做的就是在这个做好的模具里添加我们需要的测试代码.一个最基本的Testbench包含三个部分,信号定义、模块接口和功能代码.‘timescale 1ns/ 1ps表示仿真的单位时间为1ns,精度为1ps.想要进行仿真首先要规定时间单位,而且最好在Testbench里面统一规定时间单位,而不要在工程代码里定义,因为不同的模块如果时间单位不同可能会为仿真带来一些问题,而timescale本身对综合也就是实际电路没有影响。
其实Testbench本身可以看做一个模块或者设备(本例中的模块名为add_vlg_tst),和你自己编写的模块进行通信。
通过Testbench模块向待测模块输出信号作为激励,同时接收从待测模块输出的信号来查看结果.因此,在待测模块中的reg型信号在Testbench中就变成了wire,待测模块中的wire型信号在Testb ench中则对应为reg型。
那么inout怎么办呢,inout型信号也要设成wire,同时要用一个reg型信号作为输出寄存器,同时设置一个三态门,由一个使能信号控制,如:assign inout_sig = out_en ? out_reg : 1’bz;处理完接口和声明之后,需要自己设置一些激励信号,激励信号的内容就是肯能会输入到待测模块中的波形.下面我们就来写一个简单的测试程序.实例:60进制计数器源代码:library ieee;use ieee.std_logic_1164。
verilog testbench语法
Verilog Testbench语法深度解析1. 什么是Verilog Testbench?Verilog Testbench是一种用于验证Verilog硬件描述语言(HDL)设计的测试环境。
它可以模拟设计的功能,并验证其正确性。
Testbench通常包括测试向量生成、时序控制、错误检测和报告等功能,用于对设计的每个功能进行全面的测试。
2. Verilog Testbench的基本结构Verilog Testbench通常包括模块实例化、时钟生成、信号驱动、仿真结束条件等基本结构。
下面我们分别来详细解析一下这些基本结构:2.1 模块实例化模块实例化是将被测试的Verilog设计模块实例化到Testbench中进行仿真。
在Testbench中,需要为被测设计的每个模块实例化一个对应的实例,并连接所需的输入和输出信号。
如果我们要测试一个简单的加法器模块,那么Testbench中就需要实例化这个加法器,并为其提供输入信号。
2.2 时钟生成时钟是数字电路中非常重要的一部分,它的稳定性和频率对设计的正确性有很大影响。
因此在Testbench中,通常需要生成一个时钟信号,并为被测设计提供时钟。
时钟的生成需要考虑到时钟周期、占空比、起始相位等因素。
2.3 信号驱动在Verilog Testbench中,需要为被测设计提供输入信号,并对其进行驱动。
这些输入信号可以是测试用的模拟信号,也可以是从文件读取的数据。
对于复杂的设计,输入信号的生成可能需要一定的算法和规则。
2.4 仿真结束条件仿真结束条件是指在Testbench中指定了仿真运行的结束条件。
通常情况下,仿真会在满足了所有测试用例,并且通过了所有检查点之后结束。
在Testbench中需要注意设置好仿真的结束条件,以避免不必要的浪费。
3. Verilog Testbench的个人观点对于Verilog Testbench,我个人认为它是Verilog设计中不可或缺的一部分。
testbench万能模版
`timescale 1ns/1ps // 定义时间单位和精度//定义仿真时间initial begin#10000 finish;end//设计顶层模块testbenchmodule testbench;//定义内部的信号变量以及类型wire [7:0]count; //线型定义输出端,连接各模块的输出端口,用线连接没有记忆reg clk; //寄存器定义激励信号,连接各模块的输入端口,具有记忆功能reg reset; //两个最基本的激励信号//固定参数的赋值,状态的编码/***parameter tpd_reset_to_count = 3 ;parameter tpd_clk_to_count = 2 ; **///变量初始化/**initial begina=b;b=c;c=d;end **///时钟设置always #500 clk=~clk;initialbeginclk =1;reset=0; //一般是低电平复位#100clk =0;reset=1;end//调用函数用modelsim生成fsdb文件initialbegin$fsdbDumpfile("wave_test.fsdb");$fsdbDumpvars(0);end//调用模块与顶层模块的各个端口的连接(一一对应时自动连接)filename u1(.cp(clk),.clr(reset),.RSTSM(),.DQ_IN(),.MASTER_CNT(),.SLA VE_CNT());//调用输出图像的函数integer fid;initialbeginfid=$fopen("report.txt","w+");#1000000$fclose(fid);endalways @ (posedge clk negedge reset) $display(fid,"timerh=%d",timerh);endmodule //结束顶层模块。
编写testbench的一些技巧
编写testbench的⼀些技巧1 Testbench的结构1) 单顶层结构⼀种结构是testbench 只有⼀个顶层,顶层再把所有的模块实例化进去。
打个⽐⽅,类似树结构,只有⼀个模块有⼦节点⽽没有⽗节点,其它模块都有⽗节点。
如下图结构所⽰:测试模块是⼀些接⼝模型,接⼝模型还可能包含了⼀些激励在内。
测试模块和DUV之间通过端⼝映射进⾏互连。
2) 多顶层结构另外⼀种结构是多顶层结构,如下图所⽰:在这种结构中,有⼀个顶层是作为测试向量模块,⼀个或多个顶层是⼀些公⽤⼦程序,这些⼦程序由于完成⼀些通⽤的功能被封装成任务、函数等被公⽤。
还有⼀个叫harness的顶层,该顶层由DUV和⼀些接⼝模型构成⼀个狭义上的测试平台,其它模块可以调⽤BFM⾥⾯的task 或event 等,向DUV施加激励。
注意这些顶层之间是没有端⼝映射的,它们之间的互相调⽤和访问是通过层次路径名的⽅式来访问,上图的虚线表⽰层次路径名的访问。
下⾯举例说明层次路径是如何访问的。
由于⼤部分⼈对C都有所认识,在这⾥作个⽐较,便于了解。
Verilog HDL的顶层类似于C的结构体,⽽实例化的模块、任务、函数、变量等就是结构体⾥的成员,可以通过句点( . )隔开的⽅式访问结构体⾥⾯的每⼀个成员。
如:顶层harness 实例化进来的模块BFM1 ⾥⾯有⼀个任务SEND_DATA , 该任务可以产⽣激励输⼊到DUV,在testcase ⾥调⽤该任务就可写为:initialbegin……harness . BFM1 . SEND_DATA (……);end多顶层结构的可扩展和重⽤性⽐单顶层结构强得多。
层次路径的访问⽅式⾮常有⽤,在下⼀节会讲述更多的应⽤。
2 如何编写Testbench1) 何时使⽤initial和alwaysinitial和always 是2个基本的过程结构语句,在仿真的⼀开始即开始相互并⾏执⾏。
通常被动的检测响应使⽤always语句,⽽主动的产⽣激励使⽤initial语句。
VHDLRTL代码及testbench编写
VHDLRTL代码及testbench编写Background因为使⽤verilog⽐较多, 对VHDL不熟, 因此学习下VHDL语法, 并练习写了个简单的分频器和仿真. RTL design使⽤VHDL写⼀个简单的分频器, 话不多说, 代码如下:library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;--use ieee.std_logic_arith.all;-- entity clkdiventity clkdiv isport(-- clk_in: in bit; -- if clk_in is defined as bit type(not std_logic), rising_edge(clk_in) will generate compilation errorclk_in: in std_logic;clk_out: out std_logic;rst_n: in std_logic);end clkdiv;-- architecturearchitecture behavior of clkdiv is-- declare signalssignal cnt : std_logic_vector(7 downto 0);signal temp : std_logic;begin-- count processPROCESS_CNT: process(clk_in, rst_n)beginif(rst_n = '0') thencnt <= "00000000";--elsif(clk_in'event and clk_in='1') thenelsif rising_edge(clk_in) thenif(cnt = 9) thencnt <= "00000000";elsecnt <= cnt + 1;end if;end if;end process;-- divider processPROCESS_DIV: process(clk_in, rst_n)beginif(rst_n = '0') thentemp <= '0';--elsif((clk_in'event) and (clk_in = '1')) thenelsif rising_edge(clk_in) thenif(cnt < 5) thentemp <= '1';elsetemp <= '0';end if;end if;end process;-- assign clk_out = tempclk_out <= temp;end behavior;testbench simulation使⽤VHDL写testbenchlibrary ieee;use ieee.std_logic_1164.all;entity tb is -- testbench empty entity, no need to define portend tb;architecture behavior of tb iscomponent clkdiv -- declaration of test entity port(clk_in, rst_n: in std_logic;clk_out: out std_logic);end component;-- port input signalsignal clkin: std_logic;signal rst: std_logic;-- port output signalsignal clkout: std_logic;-- clock cycle definitionconstant clk_period: time :=20 ns;begin -- architecture beginb1: clkdivport map(clk_in=> clkin,rst_n => rst,clk_out => clkout);-- generate test clockclk_gen: processbeginclkin <= '0';wait for clk_period/2;clkin <= '1';wait for clk_period/2;end process;rst_gen: processbeginrst <= '0';wait for 15 ns;rst <= '1';wait;end process;end behavior; -- architecture end waveform viewing使⽤modelsim来进⾏仿真, 并查看波形。
书写testbench过程
书写testbench过程各种⽂件的说明:Netlist Files:HDL code經過合成後轉出的.v檔,或是類⽐電路跑HSPICE 的.sp檔Stimulus Files:HDL寫的testbench.v經過value change dump轉成.vcd,.vcd 再經過VTRAN轉成vector file (.vec).vec 是讓軟體⽤來餵給netlist當inputpattern⽤的Configuration File:⽤來設定軟體模擬時,要擷取哪些點的哪些訊息(如電壓或電流),以儲存在.out與.log(如果是⽤GUI介⾯,可以不需要這個檔案)?Technology file:NanoSim uses a tech. file in place of MOS models during simulation.out File :執⾏模擬後的產出檔案,供turboWave直接讀取以顯⽰電壓/電流波形.fsdb File:執⾏模擬後的產出檔案,供turboWave直接讀取以顯⽰電壓/電流波形.log File :模擬結果的輸出,裡⾯有耗電情況的report由於NanoSim是Transistor-level simulator,要執⾏NanoSim有幾種⽅式提供類⽐電路的spice netlist (.sp or .spi)與MOS spice module (含電壓/溫度規格) -- 類⽐模擬提供數位電路的gate-level netlist (.v),cell-base spice simulation module (not cell-base Verilog simulation module)與MOS spice module (含電壓/溫度規格) -- 數位模擬(官⽅使⽤說明)提供類⽐電路的spice netlist (.sp or .spi)與數位電路的gate-level netlist (.v),以VCS搭配NanoSim做類⽐與數位的混合模擬(官⽅使⽤說明)书写test bench之前要了解测试单元的设计规范,要很清楚规范并且要有测试⽂档(test bench 的结构和测试情况)以⼀个四位计数器为例,计数器程序如下://-----------------------------------------------------// Design Name : counter// File Name : counter.v// Function : 4 bit up counter// Coder : Deepak//-----------------------------------------------------module counter (clk, reset, enable, count);input clk, reset, enable;output [3:0] count;reg [3:0] count;always @ (posedge clk)if (reset == 1'b1) begincount <= 0;end else if ( enable == 1'b1) begincount <= count + 1;endendmoduletest plan 如下:本test bench是⾃动检测测试,我们的test bench 测试环境如下图所⽰:待测试的设计(DUT)是test bench中的⼀部分, 其中test bench 有clock generator, reset generator, enable logic generator, and compare logic, which basically calculate the expected count value of counter and compare the output of counter with calculated value.测试的情况(根据设计说明确定,应尽量使测试完全):Reset Test : We can start with reset de-asserted, followed by asserting reset for few clock ticks and deasserting the reset, See if counter sets its output to zero.Enable Test: Assert/deassert enable after reset is applied.Random Assert/deassert of enable and reset.Test bench设计过程:1. 通式,test bench也是⼀个模块,其中包括module名,⼀般是测试设计名加_tb;进⾏待测设计的例化;对初始端⼝的初始化;时钟的设计;测试结果的输出。
VHDL——如何写简单的testbench
use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;--use ieee.std_logic_unsigned.all;entity cnt6 isport(clr,en,clk :in std_logic;q :out std_logic_vector(2 downto 0) );end entity;architecture rtl of cnt6 issignal tmp :std_logic_vector(2 downto 0); beginprocess(clk)-- variable q6:integer;beginif(clk'event and clk='1') thenif(clr='0')thentmp<="000";elsif(en='1') thenif(tmp="101")thentmp<="000";elsetmp<=unsigned(tmp)+'1';end if;end if;end if;q<=tmp;-- qa<=q(0);-- qb<=q(1);-- qc<=q(2);end process;end rtl;二、六进制计数器testbench的代码signal en :std_logic:='0';signal clk :std_logic:='0';signal q :std_logic_vector(2 downto 0);constant clk_period :time :=20 ns;begininstant:cnt6 port map(clk=>clk,en=>en,clr=>clr,q=>q);clk_gen:processbeginwait for clk_period/2;clk<='1';wait for clk_period/2;clk<='0';end process;clr_gen:processbeginclr<='0';wait for 30 ns;clr<='1';wait;end process;en_gen:processbeginen<='0';wait for 50ns;en<='1';wait;end process;end rtl;--测试平台文件(testbench)的基本结构library ieee;use ieee.std_logic_1164.all;entity test_bench is --测试平台文件的空实体(不需要端口定义) end test_bench;architecture tb_behavior of test_bench iscomponent entity_under_test --被测试元件的声明port(list-of-ports-theri-types-and-modes);end component;begininstantiation:entity_under_test port map(port-associations);process() --产生时钟信号……end process;process() --产生激励源……end process;end tb_behavior;------------------------------------------------------------------- --简单计数程序源码library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;use ieee.std_logic_unsigned.all;entity sim_counter isport(clk :in std_logic;reset :in std_logic;count :out std_logic_vector(3 downto 0));end entity;architecture behavioral of sim_counter issignal temp :std_logic_vector(3 downto 0);beginprocess(clk,reset)beginif reset='1' thentemp<="0000";elsif clk'event and clk='1' thentemp<=temp+1;end if;end process;count<=temp;end behavioral;------------------------------------------------------------------- --简单计数程序,测试文件代码(testbench)library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;use ieee.numeric_std.all;entity counter_tb_vhd is --测试平台实体end counter_tb_vhd;architecture behavior of counter_tb_vhd is--被测试元件(DUT)的声明component sim_counterport(clk :in std_logic;reset :in std_logic;count :out std_logic_vector(3 downto 0));end component;--输入信号signal clk:std_logic:='0';signal reset :std_logic:='0';--输出信号signal count :std_logic_vector(3 downto 0);constant clk_period :time :=20 ns; --时钟周期的定义begindut:sim_counter port map(clk=>clk,reset=>reset,counter=>counter);clk_gen:processbeginclk='1';wait for clk_period/2;clk='0';wait for clk_period/2;end process;tb:process --激励信号beginwait for 20 ns;reset<='1';wait for 20 ns;reset<='0';wait for 200 ns;wait; --will wait forever;end process;end;--激励信号的产生方式--1.以一定的离散时间间隔产生激励信号的波形--2.基于实体的状态产生激励信号,也就是说基于实体的输出响应产生激励信号--两种常用的复位信号--1.周期性的激励信号,如时钟--2.时序变化的激励型号,如复位--eg.产生不对称时钟信号w_clk<='0' after period/4 when w_clk='1' else'1' after 3*period/4 when w_clk='0' else'0';--eg.产生堆成时钟信号,process语句clk_gen1:processconstan clk_period := 40 ns;beginclk='1';wait for clk_period/2;clk='0';wait for clk_period/2;end process;四、如果自己不想写这些testbench的这些固定格式,可以在quartus 里自动生成testbench文件的模板,然后往里面写信号就行了步骤:processing->start->start test bench template write这里需要注意的是要在仿真选项里选择一个仿真工具,然后才会生成testbench自动生成的testbench模板格式如下:-- Copyright (C) 1991-2008 Altera Corporation-- Your use of Altera Corporation's design tools, logic functions-- and other software and tools, and its AMPP partner logic-- functions, and any output files from any of the foregoing-- (including device programming or simulation files), and any-- associated documentation or information are expressly subject-- to the terms and conditions of the Altera Program License-- Subscription Agreement, Altera MegaCore Function License-- Agreement, or other applicable license agreement, including,-- without limitation, that your use is for the sole purpose of-- programming logic devices manufactured by Altera and sold by-- Altera or its authorized distributors. Please refer to the-- applicable agreement for further details.-- ***************************************************************************-- This file contains a Vhdl test bench template that is freely editable to-- suit user's needs .Comments are provided in each section to help the user -- fill out necessary details.-- ***************************************************************************-- Generated on "03/13/2011 20:05:04"-- Vhdl Test Bench template for design : cnt6---- Simulation tool : ModelSim (VHDL)--LIBRARY ieee;USE ieee.std_logic_1164.all;ENTITY cnt6_vhd_tst ISEND cnt6_vhd_tst;ARCHITECTURE cnt6_arch OF cnt6_vhd_tst IS-- constants-- signalsSIGNAL clk : STD_LOGIC;SIGNAL clr : STD_LOGIC;SIGNAL en : STD_LOGIC;SIGNAL q : STD_LOGIC_VECTOR(2 DOWNTO 0);COMPONENT cnt6PORT (clk : IN STD_LOGIC;clr : IN STD_LOGIC;en : IN STD_LOGIC;q : OUT STD_LOGIC_VECTOR(2 DOWNTO 0));END COMPONENT;BEGINi1 : cnt6PORT MAP (-- list connections between master ports and signalsclk => clk,clr => clr,en => en,q => q);init : PROCESS-- variable declarationsBEGIN-- code that executes only onceWAIT;END PROCESS init;always : PROCESS-- optional sensitivity list-- ( )-- variable declarationsBEGIN-- code executes for every event on sensitivity list WAIT;END PROCESS always;END cnt6_arch;。
关于inout类型数据的testbench编写调试过程记录
我这两天用verilog编的ARM7与CPLD总线连接的程序,编完后用Jlink查看过ARM收发的数据,总线是好使的,就是说源模块代码没问题。
现在问题就出在编写testbench仿真总线inout口,能看到测试模块给源模块的总线输入数据,但是看不到总线输出数据。
在网上找了下资料,发现有建议用"assign DATA = (~nWE)?treg_DATA:16'hzzzz;assign DATA_OUT=(~nOE)?DATA:16'hzzzz;"这种方式,通过treg_DATA输入数据,DATA_OUT观察输出数据,但是试验了发现不行,总线输出仍然是高阻态。
后来在weizhiheng的这个帖子/bbs/thread-245831-1-1.html里找到另外一种方法,像这样reg [3:0] dirdata$inout$reg = 4'b0000;wire [3:0] dirdata = dirdata$inout$reg;通过dirdata 观察输出,但是发现也不行。
所以只能上网求助大家了。
我先粘贴源模块代码:module lpcbus(clk,ADDR,DATA,nOE,nWE,nCS,led);input clk,nOE,nWE,nCS;input [7:0] ADDR;inout [15:0] DATA;output led;reg [15:0]DATAOUT;wire link_bus;assign link_bus=!nOE;assign DATA=(link_bus)?DATAOUT:16'hzzzz; reg [25:0]cnt;always@(posedge clk) begincnt<=cnt+1;endassign led=cnt[25];reg [15:0]ram,ram2;always@(nWE or nCS or ADDR) begin if((nCS==0)&&(nWE==0)) begincase(ADDR)16'h55: beginram<=DATA;end16'h77: beginram2<=DATA;enddefault:begin endendcaseendendalways@(nOE or nCS or ADDR) begin if((nCS==0)&&(nOE==0)) begincase(ADDR)16'h66: beginDATAOUT<=ram;end16'h88: beginDATAOUT<=ram2;enddefault: begin endendcaseendelse beginDATAOUT<=16'hzzzz;endendendmodule功能及其简单,就是往0X55写数时,能从0x66里读出来,是用来测试总线用的,试验结果验证好用。
Verilog-testbench的写法
数字集成电路设计入门--从HDL到版图于敦山北大微电子学系第十五章Verilog Test Bench使用简介学习内容:•用一个复杂的test bench复习设计的组织与仿真•建立test bench通常使用的编码风格及方法设计组织虚线表示编译时检测输入文件是否存在及可读并允许生成输出文件。
test bench 组织stimulus要验证的设计简单的test bench•简单的test bench 向要验证的设计提供向量,人工验证输出。
•复杂的test bench 是自检测的,其结果自动验证。
复杂的test bench激励验证结果要验证的设计并行块•fork…join块在测试文件中很常用。
他们的并行特性使用户可以说明绝对时间,并且可以并行的执行复杂的过程结构,如循环或任务。
module inline_ tb;reg [7: 0] data_ bus;// instance of DUTinitial forkdata_bus = 8'b00;Time | data_ bus0 | 8’b0000_0000 10 | 8’b0100_0101 30 | 8’b0100_0110 40 | 8’b0100_0111 45 | 8’b1000_1110#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;joinendmodule上面的两个repeat循环从不同时间开始,并行执行。
象这样的特殊的激励集在单个的begin…end块中将很难实现。
50 | 8’b1000_1111 60 | 8’b1001_0000 65 | 8’b0010_0000 70 | 8’b0010_0001 80 | 8’b0010_0010 85 | 8’b0100_0100 90 | 8’b0100_0101 100 | 8’b0100_0110 105 | 8’b1000_1100 110 | 8’b1000_1101 120 | 8’b1000_1110 125 | 8’b0001_1100 140 | 8’b0000_1111包含文件•包含文件用于读入代码的重复部分或公共数据。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
怎样写testbench本文的实际编程环境:ISE 6.2i.03ModelSim 5.8 SESynplify Pro 7.6编程语言 VHDL在ISE中调用ModelSim进行仿真一、基本概念和基础知识Testbench不仅要产生激励也就是输入,还要验证响应也就是输出。
当然也可以只产生激励,然后通过波形窗口通过人工的方法去验证波形,这种方法只能适用于小规模的设计。
在ISE环境中,当前资源操作窗显示了资源管理窗口中选中的资源文件能进行的相关操作。
在资源管理窗口选中了testbench文件后,在当前资源操作窗显示的ModelSim Simulator中显示了4种能进行的模拟操作,分别是:Simulator Behavioral Model(功能仿真)、Simulator Post-translate VHDL Model(翻译后仿真)、Simulator Post-Map VHDL Model(映射后仿真)、Simulator Post-Place & Route VHDL Model(布局布线后仿真)。
如图1所示:图1l Simulator Behavioral Model 也就是所说的功能仿真、行为仿真、前仿真。
验证功能是否正确,这是设计的第一步。
功能仿真正确的程序不一定能被正确综合,也就是硬件实现。
有的在综合时报错误,有的虽然能综合但结果并不正确。
当然,功能仿真如果都不能通过,以后的步骤也就无法进行。
这是必做的仿真。
l Simulator Post-translate VHDL Model 也就是翻译后仿真。
对源程序进行编译后首先排除了语法错误,对一些像类属命令(Generic)、生成语句(Generate)等进行了展开。
不是必做的仿真。
l Simulator Post-Map VHDL Model也就是映射后仿真。
不同的器件内部结构也不尽相同,映射的作用就是将综合后产生的网表文件对应到实际的器件上去。
由于映射不包含布线,也就是要用什么类型的逻辑单元虽然已经确定但要用哪个位置的还没有确定,因此,映射后仿真不包含布线延时。
不是必做的仿真。
l Simulator Post-Place & Route VHDL Model也就是所说的布局布线后仿真、时序仿真、后仿真。
这是最完整的仿真,既包含逻辑延时又包含布线延时。
在做布局布线后仿真时要用到一个叫SDF的文件。
SDF文件包含设计中每个单元(Cell)的延时和时序约束数据。
通过加载这个文件就能得到完整的时序情况。
它是必做的仿真。
一般必须进行功能仿真和布局布线后仿真。
常见问题:为什么有的testbench在进行功能仿真时能正确进行,而在进行布局布线后仿真时就不能运行。
有两点要注意的地方:(1)、在做映射后仿真或布局布线后仿真时,都已经经过了综合工具的综合,源程序中的类属命令(Generic)、生成语句(Generate)等都已经进行展开。
例如,如果用Generic定义了一个参数width,综合工具进行综合时已经按照一个确定的width值进行了综合。
它生成的电路已经具有一个确定的结构,不能再随意调整。
所以在映射后仿真和布局布线后仿真的testbench中,往往不能出现Generic语句。
(2)映射后仿真和布局布线后仿真都要用到SDF文件,并且要将SDF文件关联到设计中的实例。
所以在映射后仿真和布局布线后仿真的testbench中,第一,要将你的设计声明成一个元件。
第二,实例化你设计的元件并且实例名要取为UUT(默认的,当然也可以改)。
关于断言语句在仿真中为了能得到更多信息,经常要用到断言语句(assert)。
其语法如下:Assert<条件>Report<消息>Severity<出错级别>;出错级别共有5种:l Notel Warningl Errorl Failurel Fatal在VHDL模型的模拟过程中,一旦断言语句的条件为假,则发送消息并将出错级别发送给模拟器。
通常可以设置一个中止模拟器运行的出错级别,一般默认的中止运行的出错级别为Failure。
我们来看一个例子:assert falsereport "********* " & IMAGE(DWIDTH) & "BIT DIVIDER SEQUENCE FINISHEDAT " & IMAGE(now) & " !" & " *********"severity note;断言的条件不是一个条件表达式,而直接是false。
这说明只要程序执行到这里断言就一定会成立,送出消息。
出错级别为note,在模拟器的输出窗口将会显示:and (s_ovi = '0')and (s_qutnt = conv_std_logic_vector(v_quot,DWIDTH))and (s_rmndr = conv_std_logic_vector(v_remd,DWIDTH))report "ERROR in division!"severity failure;断言的条件有4个并且是与的关系,只要其中一个条件不成立则整个表达式为假,断言成立。
如果断言成立将输出“ERROR in division!“这个消息。
并且通知模拟器出错级别为failure,这一般会停止模拟。
这个断言实际是在对结果进行验证。
二、实际testbench分析下面将详细分析一个实际的testbench,它是用来测试8051的ALU单元的除法功能的。
8位的除法器,被除数和除数的组合共有256×256=65536种。
我们采用的方法是穷举所有的输入组合,这样的代码覆盖率可以达到100%。
它的验证必须通过程序自动完成,否则通过人工方法工作量太大。
把要测试的程序当作一个元件,例如想象成一个74系列数字电路。
Testbench的作用是在被测试电路的输入端加上激励,然后比较被测试电路的输出和计算出来的期望值是否一致。
对我们这个例子来说,在要仿真的ALU输入端产生65536种输入组合,然后将ALU产生的对应输出值和testbench算出的期望值相比较,如果有错误产生则停止模拟并输出信息。
ALU的除法单元的输入有4个,分别是被除数、除数、进位、溢出位;输出也有4个,分别是商、余数、新的进位、新的溢出位。
1、testbench的输出s_dvdnd(被除数)、s_dvsor(除数)、s_cyo(进位)、s_ovo(溢出位)连接到ALU的输入acc_i(被除数)、ram_data_i(除数)、cy_i(进位)、ov_i (溢出位);2、testbench的输入s_qutnt(商)、s_rmndr(余数)、s_cyi(进位)、s_ovi(溢出位)连接到ALU的输出result_a_o(商)、 result_b_o(余数)、new_cy_o(进位)、new_ov_o (溢出位)。
3、总之,testbench驱动被测试单元,同时对被测试单元的输出进行验证。
4、assert (s_cyi((DWIDTH-1)/4) = '0')and (s_ovi = '0')and (s_qutnt = conv_std_logic_vector(v_quot,DWIDTH))and (s_rmndr = conv_std_logic_vector(v_remd,DWIDTH))report "ERROR in division!"severity failure;根据51指令系统规定,除法运算的cy位固定为0,如果除数为0则ov置1,否则置0。
程序中s_qutnt = conv_std_logic_vector(v_quot,DWIDTH)s_rmndr = conv_std_logic_vector(v_remd,DWIDTH)用来对运算结果进行比较。
conv_std_logic_vector()是类型转换函数。
――首先是对库的引用library IEEE;use IEEE.std_logic_1164.all;use IEEE.std_logic_arith.all;library work;use work.mc8051_p.all;library STD;use STD.textio.all;――定义结构体,testbench程序的结构体是空的。
因为testbench是用来仿真的,不存在--对外的接口,所以entity是空的。
但是必须要有,这是语法的要求。
entity TBX_mc8051_alu isend TBX_mc8051_alu;------------------------------------------------------------------------------- architecture TBX_ARCH_DIV of TBX_mc8051_alu is――定义元件,映射后仿真和布局布线后仿真要使用SDF文件,必须指定实例名。
要实例--化元件首先必须定义元件。
component mc8051_aluport (new_ov_o : out STD_LOGIC; ――新的ov位,输出ov_i : in STD_LOGIC := 'X'; ――ov位,输入new_cy_o : out STD_LOGIC_VECTOR ( 1 downto 0 ); ――新的cy位,输出acc_i : in STD_LOGIC_VECTOR ( 7 downto 0 ); ――acc,输入rom_data_i : in STD_LOGIC_VECTOR ( 7 downto 0 ); ――rom_data,输入cmd_i : in STD_LOGIC_VECTOR ( 5 downto 0 ); ――命令,输入ram_data_i : in STD_LOGIC_VECTOR ( 7 downto 0 ); ――ram_data,输入cy_i : in STD_LOGIC_VECTOR ( 1 downto 0 ); ――cy,输入result_b_o : out STD_LOGIC_VECTOR ( 7 downto 0 ); ――结果b,输出result_a_o : out STD_LOGIC_VECTOR ( 7 downto 0 ) -―结果a,输出);end component;――定义函数----------------------------------------------------------------------------- ---- IMAGE - Convert a special data type to string -- --This function uses the STD.TEXTIO.WRITE procedure to convert different -- -- VHDL data types to a string to be able to output the information via -- -- a report statement to the simulator. -- -- (VHDL'93 provides a dedicated predefinded attribute 'IMAGE) -- ----------------------------------------------------------------------------- ――定义了一个函数IMAGE,之所以有两个定义,是因为对IMAGE进行了重载,一个是把――time变量转换成string,另一个是把integer变量转换成stringfunction IMAGE (constant tme : time) return string isvariable v_line : line;variable v_tme : string(1 to 20) := (others => ' ');beginwrite(v_line, tme);v_tme(v_line.all'range) := v_line.all;deallocate(v_line);return v_tme;end IMAGE;function IMAGE (constant nmbr : integer) return string isvariable v_line : line;variable v_nmbr : string(1 to 11) := (others => ' ');beginwrite(v_line, nmbr);v_nmbr(v_line.all'range) := v_line.all;deallocate(v_line);return v_nmbr;end IMAGE;――定义过程,它产生所有的测试输入数据并将产生结果和期望值进行比较,如果有误――产生,模拟将停止并输出一个错误信息。