VivadoHLS工程testbench的三个要素
HLS中指针作为Top函数参数的处理方法
Vivado HLS中指针作为top函数参数的处理方法指针作为C语言精华,对于软件设计者比较好理解,但是在xilinxvivado HLS 高级语言综合的设计中,由于其综合后对应的硬件元素难以用软件的概念解释,常常令程序设计者和VHLS工具使用者头痛。
本文采用浅显易懂的描述方式,结合具体的c代码例子,详细描述了常用三种指针的设计类型,以及其作为顶层函数参数时,采用不同的编码风格和HLS约束策略,满足设计者对指针作为RTL 接口的需求。
1.基本指针类型基本指针类型指的是指针没有运算或者没有多次的存取(读写)。
指针作为top函数的参数时,指针综合为wire型或者握手协议类型接口。
如下例子1-1:voidpointer_basic (dio_t *d) {staticdio_tacc = 0;acc += *d;*d = acc;}例子1-1 基本类型指针作为顶层函数参数在这个例子中,只是简单的读写指针指向的变量值,并没有对指针做偏移或者指针(地址)运算,其接口综合为线型的RTL接口。
2.指针运算类型。
指针作为top层函数参数,并且函数中有对指针运算时,我们称之为指针运算类型。
指针运算常常限制指针可能综合的接口类型。
如下例中,指针做了偏移运算用于累加数据,从第二个值开始读出累加,并将每次累加结果写入上一个地址中。
voidpointer_arith (dio_t *d) {staticintacc = 0;int i;for (i=0;i<4;i++) {acc += *(d+i+1);*(d+i) = acc;}}例子1-2 指针运算类型作为顶层函数参数下面代码例子1-3是这个指针运算类型仿真的testbench。
因为函数pointer_arith内部的for循环进行数据累加,testbench通过数组d[5]分配了地址空间并对数组赋值。
int main () {dio_t d[5], ref[5];int i, retval=0;FILE *fp;// Create input datafor (i=0;i<5;i++) {d[i] = i;ref[i] = i;}// Call the function to operate on the datapointer_arith(d);// Save the results to a filefp=fopen("result.dat","w");printf(" Din Dout\n", i, d);for (i=0;i<4;i++) {fprintf(fp, "%d \n", d[i]);printf(" %d %d\n", ref[i], d[i]);}fclose(fp);// Compare the results file with the golden resultsretval = system("diff --brief -w result.dat result.golden.dat");if (retval != 0) {printf("Test failed!!!\n");retval=1;} else {printf("Test passed!\n");}// Return 0 if the testreturnretval;}例子1-3 指针运算类型作为顶层函数参数的testbench在C编译环境下仿真上面例子1-3的代码,结果如下:Din Dout0 11 32 63 10Test passed!指针运算带来的问题是,通常情况下,指针偏移是不规则的,不能按顺序存取指针数据。
testbench(框架—基础—进阶)
--------------------------------------project-------------------------------------------------------此模块为yuv444转yuv422模块,由输入24bit数转8bit输出,本笔记都以此工程为基础,都仿真测试过module yuv444to422(input ccd_clk,input sys_clk,input resetn,input HD,input VD,input [23:0] yuv,input yuv_trans_done,output clk_out,output reg [7:0] data_out,output HD_out,output VD_out,output reg [11:0] v_cnt);assign clk_out = ~ccd_clk;assign HD_out = HD;// ;hd1[1]assign VD_out = VD;//v_cnt_out;//;vd1[1]///////////////////1280*1024-->1280*720////////////reg [1:0] hs_edge;always@(posedge ccd_clk)beginif(!resetn)hs_edge <= 2'b00;elsehs_edge<= {hs_edge[0],HD};endalways@(posedge ccd_clk)beginif(!resetn)v_cnt <= 12'b0;else if(!VD)v_cnt <=0;else if(hs_edge==2'b01)v_cnt <= v_cnt +1;endreg v_cnt_out;always@(posedge sys_clk)beginif(!resetn)v_cnt_out <= 1'd0;else if ((v_cnt >= 12'd179) && (v_cnt <= 12'd899)) v_cnt_out <= 1'd1;else v_cnt_out <= 1'd0;end*/////////////////////////////reg [1:0]cnt1;always@(posedge ccd_clk)beginif(!resetn)cnt1<=0;else if(yuv_trans_done)cnt1<=cnt1+1;endalways@(posedge ccd_clk)beginif(!resetn)begindata_out <= 8'b0;endelse if (HD)begincase(cnt1)2'b0:data_out <= yuv[23:16];2'b1:data_out <= yuv[15:8]; //8'h80;//2'd2:data_out <= yuv[23:16];2'd3:data_out <= yuv[7:0]; //8'h80;//endcaseendendmodule--------------------------------------------testbench------------------------------------------- `timescale 1 ns/ 1 ps`include "D:/tangate_quartus/yuv444to422/yuv444to422.v"module yuv444to422_vlg_tst();reg HD;reg VD;reg ccd_clk;reg resetn;reg sys_clk;reg [23:0] yuv;reg yuv_trans_done;// wireswire HD_out;wire VD_out;wire clk_out;wire [7:0] data_out;wire [11:0] v_cnt;yuv444to422 i1 (.HD(HD),.HD_out(HD_out),.VD(VD),.VD_out(VD_out),.ccd_clk(ccd_clk),.clk_out(clk_out),.data_out(data_out),.resetn(resetn),.sys_clk(sys_clk),.v_cnt(v_cnt),.yuv(yuv),.yuv_trans_done(yuv_trans_done));//------------------------------------------------------------------------------------- parameter n = 10;//-------------------------------------------------------------------------------------initialbeginHD = 1'b0; // time 0 时刻VD = 1'b0;repeat(n)begin# 200 VD = 1'b1; // time 200repeat(10*n)begin#100 HD = 1'b1; //time 300#100 HD = 1'b0; //time 700end#100 VD = 1'b0;endend//------------------------------------------------initialbeginyuv_trans_done = 1'b0;#30 yuv_trans_done = 1'b1;end//----------------------------------------------/*initialbeginresetn = 1'b0;#30 resetn = 1'b1;end*///---------------------------------------------initialbeginsys_rst (100);//复位100个时间单位endtask sys_rst ;input [10:0] rst_time; //调用task的时候,将参数赋值给rst_time beginresetn = 0;#rst_time;resetn = 1;endendtask//-----------------------------------------------------alwaysbegin#10 ccd_clk = 1'b0;#10 ccd_clk = 1'b1;endinitialbeginyuv = 24'b0;forever @(posedge ccd_clk) #20 yuv = $random;end//-----------------------------------------------------------initialbegin#10000 $stop(2);end//------------------------------ok---------------------------------/*initialbegin#3000begin$display("current scope is %m");$display("the signal is %s",data_out);$display("the time is %t",$time) ;$display("data_out has %c ascii character value",data_out);$display("data_out=%h hex %d decimal", data_out, data_out);$display("data_out=%o otal %b binary", data_out, data_out);endend*///--------------------------------------ok------------------------------------------//always @(data_out) $display("Output changed at %t to %b",$time,data_out); //---------------------------------ok---------------------------------------------------//always @(data_out) $strobe("Output changed at %t to %b",$time,data_out); //-------------------------------ok----------------------------------------------------//initial//$monitor ("at time is %t and the signal is %b\n",$time , VD_out) ;//----------------------------------ok------------------------------------//initial// $monitor ("%d is changed at %t",data_out,$time);//yuv444to422_vlg_tst. //-----------------------------------ok--------------------------------------/* reg [23:0] buffer;initialbuffer = 24'b0000_1110_0001_1011_0101_1100;always @ ( posedge ccd_clk) #10 {yuv,buffer} = {buffer,yuv};*///-------------------------------------ok---------------------------------------------/*always @ (ccd_clk)begin$timeformat(-9,1,"ns",0);$display ("time clk HD VD v_cnt data_out ");$monitor("%t %b %b %b %b %b ", $realtime, clk_out, HD_out, VD_out, v_cnt, data_out);end*///--------------------------------write ok--------------------------------------/*initialbegin : blockinteger file_id;file_id = $fopen("D:/tangate_quartus/yuv444to422/data_out.txt");//1.打开文件//$fmonitor只要有变化就一直记录自动换行无需加\n//格式:$fmonitor(file_id, "%format_char", parameter);$fmonitor(file_id, "%m: %t data_out=%d v_cnt=%h___tangate", $time, data_out, v_cnt);//$fwrite需要触发条件才记录,只记录一行数据,换行需加\n,注意反斜杠的方向$fwrite(file_id, "%m: time is %t**data_out=%d**v_cnt=%h\n", $time, data_out, v_cnt);//2.写入文件//$fdisplay需要触发条件才记录,只记录一行数据,自动换行无需加\n//格式:$fdisplay(file_id, "%format_char", parameter);$fdisplay (file_id, "%m: %t data_out=%d v_cnt=%h___great man", $time, data_out, v_cnt);$fclose("D:/tangate_quartus/yuv444to422/data_out.txt"); //3.关闭文件end*///-----------------------------------read ok----------------------------------------------begin : blockinteger file_id;file_id = $fopen("D:/tangate_quartus/yuv444to422/data_out.txt");//1.打开文件$fread( "D:/tangate_quartus/yuv444to422/data_out.txt", $time, data_out, v_cnt);//2.读取文件$fclose("D:/tangate_quartus/yuv444to422/data_out.txt"); //3.关闭文件endendmoduleTestbench 学习笔记(框架)为什么C不能取代verilog和VHDL作为硬件描述语言?因为C缺少了硬件描述最基本的三个思想:连通性(Connectivity),时间性(Time)和并行性(Concurrency)。
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.testbench总体代码结构`timescale 1ns/1ps //时间精度`define clk_perilod 20 //时钟周期可变module test_file_tb;//==================<端⼝>==================================================reg clk ; //时钟,50Mhzreg rst_n ; //复位,低电平有效reg [XX:0] in ; //wire [XX:0] out ; ////--------------------------------------------------------------------------//-- 模块例化//--------------------------------------------------------------------------my_design u_my_design(.clk (clk ),.rst_n (rst_n ),.in (in ),.out (out ));//----------------------------------------------------------------------//-- 时钟信号和复位信号//----------------------------------------------------------------------initial beginclk = 0;forever#(`Clock/2) clk = ~clk;endinitial beginrst_n = 0; #(`Clock*20+1);rst_n = 1;end//----------------------------------------------------------------------//-- 设计输⼊信号//----------------------------------------------------------------------initial beginin = 0;#(`Clock*20+2); //初始化完成$stop;endendmodule在这⾥插⼊代码⽚2.时钟激励的编写`timescale 1ns/1ps //时间精度`define Clock 20 //时钟周期//========================================================================== //== ⽅法⼀,50%占空⽐//========================================================================== initial beginclk = 0;forever#(`Clock/2) clk = ~clk;end//========================================================================== //== ⽅法⼆,50%占空⽐//========================================================================== initial beginclk = 0;always#(`Clock/2) clk = ~clk;end//========================================================================== //== ⽅法三,产⽣固定输⼊的时钟脉冲//========================================================================== initial beginclk = 0;repeat(6)#(`Clock/2) clk = ~clk;end//========================================================================== //== ⽅法四,⾮50%占空⽐//========================================================================== initial beginclk = 0;forever begin#((`Clock/2)-2) clk = 0;#((`Clock/2)+2) clk = 1;endend3.复位信号`timescale 1ns/1ps //时间精度`define Clock 20 //时钟周期//========================================================================== //== ⽅法⼀,异步复位//========================================================================== initial beginrst_n = 0; #(`Clock*20+1);rst_n = 1;end//========================================================================== //== ⽅法⼆,同步复位//========================================================================== initial beginrst_n = 0; #(`Clock*20);rst_n = 1;end4.task使⽤//========================================================================== //== 输⼊信号任务封装//========================================================================== 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];@(posedge data_en); send_data=1;#100;endendtask//调⽤⽅法:i_data(8'hXX);//========================================================================== //== 多输⼊信号任务封装//========================================================================== task more_input;input [ 7:0] a;input [ 7:0] b;input [31:0] times;output [ 8:0] c;beginrepeat(times) @(posedge clk) //等待 times 个时钟上升沿c=a+b;endendtask//调⽤⽅法:more_input(x,y,t,z); //按声明顺序5.repeat ,wait函数//==========================================//== repeat重复执⾏//==========================================initial beginstart = 1;repeat(5) @(posedge clk) //等待5个时钟上升沿start = 0;endinitial beginrepeat(10)begin...//执⾏10次endend//===========================================//== wait为电平触发//==========================================initial beginstart = 1;wait(en); //等待en==1start = 0;end6.随机数产⽣$random //产⽣随机数$random % n //产⽣范围 {-n,n} 的随机数{$random} % n //产⽣范围 { 0,n} 的随机数7.⽂本输⼊输出reg [a:0] data_mem [0:b]; //定义位宽为(a+1)深度为(b+1)的存储器$readmemb/$readmemh("<读⼊⽂件名>",<存储器名>);$readmemb/$readmemh("<读⼊⽂件名>",<存储器名>,<起始地址>);$readmemb/$readmemh("<读⼊⽂件名>",<存储器名>,<起始地址>,<结束地址>);$readmemb/*------------------------------------------------------------------------*\读取⼆进制数据,读取⽂件内容只能包含:空⽩位置,注释⾏,⼆进制数数据中不能包含位宽说明和格式说明,每个数字必须是⼆进制数字。
Verilog十大基本功3(testbench的设计iout类型端口信号处理)
Verilog十大基本功3(testbench的设计iout类型端口信号处理)需求说明:Verilog设计基础内容:testbench的设计 iout类型端口信号处理来自:时间的诗原文:/times_poem/article/details/52037380续Verilog十大基本功2(testbench的设计文件读取和写入操作源代码)3 testbench 的技巧1)如果激励中有一些重复的项目,可以考虑将这些语句编写成一个 task,这样会给书写和仿真带来很大方便。
例如,一个存储器的 testbench 的激励可以包含 write, read 等 task。
2)如果DUT 中包含双向信号(inout),在编写testbench 时要注意。
需要一个 reg 变量来表示其输入,还需要一个 wire变量表示其输出。
3)如果initial 块语句过于复杂,可以考虑将其分为互补相干的几个部分,用数个 initial 块来描述。
在仿真时,这些initial 块会并发运行。
这样方便阅读和修改。
4)每个testbench 都最好包含$stop 语句,用以指明仿真何时结束。
5)加载测试向量时,避免在时钟的上下沿变化,比如数据最好在时钟上升沿之前变化,这也符合建立时间的要求。
4 一个简单的例子DUT:[plain] view plain copy1.module counter (2.clk,3.reset,4.enable,5.count6.);7.8.input clk;9.input reset;10.input enable;11.12.output [3:0] count;13.reg [3:0] count;14.15.always @ (posedge clk)16.if (reset == 1'b1) begin17.count <= 0;18.end else if ( enable == 1'b1) begin19.count <= count + 1;20.end21.endmoduletestbench:[plain] view plain copy1.module counter_tb;2.reg clk;3.reg reset;4.reg enable;5.wire [3:0] count;6.7.counter U0 (8..clk (clk),9..reset (reset),10..enable (enable),11..count (count)12.);13.14.initial begin15.clk = 0;16.reset = 0;17.enable = 0;18.end19.20.always #5 clk = ! clk;21.22.initial begin23.$dumpfile ("counter.vcd");24.$dumpvars;25.end26.27.initial begin28.$display("\t\ttime,\tclk,\treset,\tenable,\tcount");29.30.$monitor("‰d,\t‰b,\t‰b,\t‰b,\t‰d",$time, clk,res et,enable,count);31.end32.33.initial #100 $finish;34.//Rest of testbench code after this line35.endmodule5 双向端口这个没用过,从网上找的,如果有问题,大家再讨论吧芯片外部引脚很多都使用inout 类型的,为的是节省管腿。
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设计的早期阶段进行全面的功能验证和性能评估。
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语法深度解析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设计中不可或缺的一部分。
4.2.Verilog Testbench与仿真
Verilog Testbench与仿真Verilog Testbench与仿真为通过软件验证Verilog语言设计实例的逻辑功能,需要编写Testbench,也称为测试模块,并通过仿真软件ModelSim进行仿真。
1.Testbench功能产生模拟激励(波形);将产生的激励加入到被测试模块;将输出响应与期望进行比较。
2. Testbench结构Module test_bench信号或变量定义声明initial、always产生激励信号例化待测试模块监控和比较输出响应endmodule组合逻辑的仿真//待测模块2选1数据选择器module mux21 (a,b,s,y);input a,b;input s;output y;assign y =(s==0)?a :b;endmodule//测试模块(testbench )`timescale 1ns / 1ps module mux21_tp;reg a,b,s;wire y;mux21 u0(.a(a),.b(b),.s(s),.y(y));initial begina=0;b=0;s=0;#5 s=1;#5 a=1;s=0;#5 s=1;#5 a=0;b=1;s=0;#5 s=1;#5 a=1;b=1;s=0;#5 s=1;end initial$monitor ($time,,,"a=%b b=%b s=%b y=%b",a,b,s,y);endmoduleTestbench待测模块wire y reg a,b,soutput y wire a,b,s//测试模块(test bench )`timescale 1ns / 1ps module mux21_tp;reg a,b,s;wire y;mux21 u0(.a(a),.b(b),.s(s),.y(y));initial begina=0;b=0;s=0;组合逻辑的仿真(1)Verilog HDL 仿真编译指令“`”开头,编译指定某种操作` timescale [时间的基准单位]/[时间的精度]`timescale 10ns / 1ns 缺省:`timescale 1ns / 1ns时间单位符号有s 、ms 、ns 、ps 和fs ,分别表示为秒、10-3s 、10-6s 、10-9s 、10-12s 、10-15s 。
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 testbench文件的编写要点
文章标题:深入探讨Verilog Testbench文件的编写要点在数字电路设计中,Verilog是一种常用的硬件描述语言,用于描述电子系统的行为。
而Testbench文件则是用来验证Verilog设计的功能和正确性的关键组成部分。
在本文中,我们将深入探讨Verilog Testbench文件的编写要点,以便读者更好地理解和掌握这一重要的技术。
一、Verilog Testbench文件的基本结构在编写Verilog Testbench文件时,需要遵循一定的基本结构,以确保测试的全面性和准确性。
Testbench文件应包括对被测试模块的实例化和初始化,并且需要定义时钟和输入信号的周期和时序关系。
Testbench文件中应包括对被测试模块输出信号的监控和比对,以验证其正确性和稳定性。
Testbench文件还应包括测试结束条件的判断和输出。
二、Verilog Testbench文件的编写要点在编写Verilog Testbench文件时,需要注意一些重要的要点,以确保测试的高效性和准确性。
需要对测试用例进行全面的设计和考虑,覆盖被测试模块的所有功能和状态。
需要对输入信号的生成和时序进行合理的设计和控制,确保测试能够完整而准确地进行。
对输出信号的监控和比对也需要有严格的设计和实现,以确保测试结果的准确性和可靠性。
三、个人观点和理解在我看来,Verilog Testbench文件的编写是Verilog验证工作中至关重要的一环。
一个好的Testbench文件可以大大提高验证的效率和准确性,而一个不好的Testbench文件则可能导致验证工作陷入困境。
我们需要将编写Testbench文件作为验证工作中的重点和难点来认真对待,不断总结和积累经验,以提高自己的测试能力和水平。
总结回顾在本文中,我们深入探讨了Verilog Testbench文件的编写要点,包括基本结构和编写要点,并共享了个人观点和理解。
通过深入理解和研究Verilog Testbench文件的编写要点,我们可以更好地应用这一技术,提高验证工作的效率和准确性。
testbench 的编写及使用方法思考与体会
【导言】1. 什么是 testbench?2. testbench 的作用和优势【testbench 编写】3. testbench 编写的基本步骤4. testbench 编写的注意事项5. testbench 编写过程中的实际问题与解决方法【testbench 使用方法】6. testbench 的使用流程7. testbench 的结果分析和验证8. testbench 使用过程中的常见错误及解决办法【结语】9. testbench 的编写与使用思考10. testbench 的未来发展预期【导言】1. 什么是 testbench?Testbench 是指在数字电路设计中对被测电路模块进行验证的仿真测试工具。
它是一种独立的模块化设计,用于测试另一个模块或芯片的功能和性能。
在数字电路设计中,testbench 是非常重要的工具,可以帮助设计人员验证电路的正确性和稳定性。
2. testbench 的作用和优势testbench 主要用于验证设计的功能和性能是否符合预期,并且检测是否有潜在的bug存在。
它可以模拟各种工作条件和异常情况,帮助设计人员有效地发现和解决问题。
testbench 的优势在于能够大大提高验证的效率和准确性,节省了大量的人力和时间成本。
【testbench 编写】3. testbench 编写的基本步骤要编写一个高质量的 testbench,需要遵循以下基本步骤:(1)分析被测电路的功能和接口,确定测试的重点和目标;(2)编写测试数据生成模块,包括设计测试用例和对输入信号进行生成;(3)编写时序控制模块,用于控制测试数据的输入和时序顺序;(4)编写仿真结果分析模块,用于对仿真结果进行验证和分析;(5)整合以上模块,编写完整的 testbench。
4. testbench 编写的注意事项在编写 testbench 的过程中,需要注意以下几点:(1)保证测试用例的全面性和充分性,覆盖各种工作条件和异常情况;(2)时序控制模块的设计要符合被测电路的时序要求,保证测试数据的输入顺序和时序正确;(3)仿真结果分析模块要设计完善,能够对仿真结果进行准确的验证和分析;(4)编写的 testbench 要符合规范,可读性强,方便他人理解和维护。
(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。
如上所属,测试文件经常同时包含附加功能,如结果的可视化显示和内建错误检测。
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-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 支持的文本输出的系统任务显示任务:用于仿真模拟期间显示信息。
Verilog十大基本功2(testbench的设计文件读取和写入操作源代码)
Verilog十大基本功2(testbench的设计文件读取和写入操作源代码)需求说明:Verilog设计基础内容:testbench的设计读取文件写入文件来自:时间的诗原文:/times_poem/article/details/52036592十大基本功之 testbench1. 激励的产生对于 testbench 而言,端口应当和被测试的 module 一一对应。
端口分为 input,output 和 inout 类型产生激励信号的时候,input 对应的端口应当申明为 reg,output 对应的端口申明为 wire,inout 端口比较特殊,下面专门讲解。
1)直接赋值一般用 initial 块给信号赋初值,initial 块执行一次,always 或者forever 表示由事件激发反复执行。
举例,一个 module[plain] view plain copy1.`timescale 1ns/1ps2.3.module exam();4.reg rst_n;5.reg clk;6.reg data;7.8.initial9.begin10.clk = 1'b0;11.rst = 1'b1;12.#1013.rst = 1'b0;14.#50015.rst = 1'b1;16.end17.18.always19.begin20.#10 clk = ~clk;21.end22.23.endmodule大家应该注意到有个#符号,该符号的意思是指延迟相应的时间单位。
该时间单位由 timscale 决定.一般在testbench 的开头定义时间单位和仿真精度,比如`timescale 1ns/1ps前面一个是代表时间单位,后面一个代表仿真时间精度。
以上面的例子而言,一个时钟周期是 20 个单位,也就是 20ns。
而仿真时间精度的概念就是,你能看到1.001ns 时对应的信号值,而假如 timescale 1ns/1ns,1.001ns 时候的值就无法看到。
Vivado HLS工程testbench的三个要素
编写高效Vivado HLS工程testbench的三个要素在C程序的设计中,任何一个C程序的顶层都是main()函数。
而在vivado HLS的设计中,只要函数的层次在main()函数以下,都可以被综合。
但是每个vivado HLS工程只能指定一个top层函数作为输出RTL模块的顶层,其它和这个函数层次平行,不需要被综合的函数都可以作为testbench来使用。
这样就带来一个问题,如何编写vivado HLS工程的testbench更高效,或者说能更好的让HLS工具自动重用C testbench 验证产生的RTL代码就变得非常重要。
通常,在Vivado HLS中,好的C testbench设计原则是testbench设计和需要实现的算法函数分别保存在不同的文件中,并且充分利用头文件。
Testbench 常常包含了一些HLS综合不支持的操作,比如通过文件的读写取得仿真数据并保存结果,或者打印一些测试结果进行分析。
在头文件中,完成对testbench中所有的数据类型和函数的定义,以及包含共享的设计文件和函数库。
Vivado HLS中,只能指定一个top层函数用于综合,top层函数可以包含多个子函数。
当需要综合多个并行层次的函数时,可以编写一个wrapper函数作为top层函数,将需要综合的多个并行函数封装起来。
C testbench的目不仅是要验证需要综合的top函数功能正确(C编译器验证环境),同时重用C testbench作为综合产生RTL代码的仿真激励,HLS工具自动调用C testbench来验证RTL功能的一致性(C编译器和RTL仿真器的协同仿真环境)。
这样,编写一个好的风格testbench可以很好的提高设计的验证效率,如果在HLS综合前和综合过程中,需要修改综合函数的代码,可以用testbench验证,确保需要综合的C算法功能正确。
Vivado HLS中推荐高效的testbench具有如下三个特征:1.Testbench代码和需要综合的C算法代码保存在不同的文件中(例子1-1)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编写高效Vivado HLS工程testbench的三个要素在C程序的设计中,任何一个C程序的顶层都是main()函数。
而在vivado HLS的设计中,只要函数的层次在main()函数以下,都可以被综合。
但是每个vivado HLS工程只能指定一个top层函数作为输出RTL模块的顶层,其它和这个函数层次平行,不需要被综合的函数都可以作为testbench来使用。
这样就带来一个问题,如何编写vivado HLS工程的testbench更高效,或者说能更好的让HLS工具自动重用C testbench验证产生的RTL代码就变得非常重要。
通常,在Vivado HLS中,好的C testbench设计原则是testbench设计和需要实现的算法函数分别保存在不同的文件中,并且充分利用头文件。
Testbench 常常包含了一些HLS综合不支持的操作,比如通过文件的读写取得仿真数据并保存结果,或者打印一些测试结果进行分析。
在头文件中,完成对testbench中所有的数据类型和函数的定义,以及包含共享的设计文件和函数库。
Vivado HLS中,只能指定一个top层函数用于综合,top层函数可以包含多个子函数。
当需要综合多个并行层次的函数时,可以编写一个wrapper函数作为top层函数,将需要综合的多个并行函数封装起来。
C testbench的目不仅是要验证需要综合的top函数功能正确(C编译器验证环境),同时重用C testbench作为综合产生RTL代码的仿真激励,HLS工具自动调用C testbench来验证RTL功能的一致性(C编译器和RTL仿真器的协同仿真环境)。
这样,编写一个好的风格testbench可以很好的提高设计的验证效率,如果在HLS综合前和综合过程中,需要修改综合函数的代码,可以用testbench验证,确保需要综合的C算法功能正确。
Vivado HLS中推荐高效的testbench具有如下三个特征:
1.Testbench代码和需要综合的C算法代码保存在不同的文件中(例子1-1)。
输入多个不同的数据,对需要综合的Top层函数执行多次的处理和验证。
还可以进行top函数多样性的测试。
Testbench和C设计分开不同的文件使得HLS工程非常清晰,它们分别作为test bench文件和source文件加入HLS的project中。
(Testbench和要综合实现的设计文件分别保存不是HLS强制的,也可以保存在同一个文件中,如果保存为同一个文件,在HLS工程,需要指定这个文件既是testbench文件也是source文件)。
需要综合的top层函数文件
作为testbench的Main()函数文件和仿真数据文件
例子1-1 testbench函数和要综合的top函数保存在不同文件中
2.Testbench具有自测试功能,testbench调用需综合的top函数,仿真输出结果与已知正确的数值进行对比。
已知正确的数值可以通过文件读入(例子2-1),也可以由testbench的其它部分的仿真代码产生(例子2-2)。
仿真数据和保存的Golden数据比较
例子2-1: testbench仿真数据与保存的Golden数据比较Golden函数产生仿真的golden数据
需要综合的 top function
例子2-2: testbench仿真数据与Goden函数输出的数据比较
3.Main()函数作为testbench函数(例子3-1),如果仿真top函数正确,main()函数返回0值;如果仿真不通过,返回任意非0的值即可(例子3-2)。
(之所以要求仿真正确返回0值,是因为HLS工具自动进行RTL验证时,如果testbench返回0值,HLS认为仿真正确,而返回其它值时,HLS报告仿真失败)。
Main()函数作为testbench
例子3-1: Main函数作为testbench
与Golden结果一致,返回“0”,否则,返回非“0”值
例子3-2: Testbench函数的返回值
综上所述,掌握三个基本的VivadoHLS工程testbench编写原则,可以轻松书写VHLS高效的testbench仿真激励。
首先,testbench和要综合的顶层函数分别保存在不同的文件中,使得vivadoHLS工程简洁清楚;其次,testbench具有自测试功能,通过调用Golden函数或者已保存好的golden数据,与仿真的结果进行比较,使得HLS自动重用C testbench来验证RTL仿真变得简单;最好,数据比较一致返回“0”值,错误不一致时返回任意非“0”值即可。
(注:文档可能无法思考全面,请浏览后下载,供参考。
可复制、编制,期待你的好评与关注)。