您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 质量控制/管理 > FPGA软件验证技术(下)
——Testbench的编写方法什么是Testbench测试平台(Testbench)指一段仿真代码,用来为设计产生特定的输入序列,也用来观测设计输出的响应。测试平台是系统的控制中心,验证的任务就是确定产生什么样的输入模式,以及获得期望的设计输出。在不改变所设计的硬件系统的前提下采用模块化的方法进行编码验证。把设计描述和功能验证描述分开。测试平台从来都不需要硬件实现tesbench基本框架测试平台是一个封闭的空间testbench基本框架testbench的目标验证HDL代码功能的正确性;1)待验证的模块加载到模拟验证环境;2)产生验证所需的激励。3)对输入激励码,构造出其对应的正确输出结果。4)提供一种机制,自动判断Design的正确性。如何编写testbench1)TestBench是个无输入输出的HDL顶层模块。2)其内部需要实例化DUT模块。3)需要定义被测模块内的连接线4)为被测顶层模块提供符合规范的输入激励。可写为激励模块或直接在Testbench中添加。5)观察设计输出和内部信号并与理想结果相比较。6)不需要只使用可综合的语句。可以使用系统任务语句实现。testbench书写结构(1)`timescale1ns/1psmoduletestbench();参数说明寄存器、线网类型变量的定义、说明;DUT实例化语句时钟信号定义、赋初值;定义置/复位信号的变化情形;用一个或多个initial语句块产生DUT的模拟激励向量用task等定义DUT外部时序接口endmoduleTestbench书写结构(2)`timescale1ns/100psmoduleTestBench();参数说明;寄存器、线网类型变量的定义、说明;DUT实例语句;时钟信号定义、赋初值;定义置/复位信号的变化情形;`include“产生输入激励码的HDL代码段”;endmodule常用信号的产生方式1)时钟信号的产生方式使用always语句产生。forever语句产生。2)复位信号产生在initial语句中赋值的方法产生。时钟信号1)使用always循环语句产生不断变化的时钟信号parameterPERIOD=10;regclk;initialclk=0;always#(PERIOD/2)Clk=~Clk;时钟信号2)使用forever语句实现initialbegin#20clk=1;foreverbegin#(PERIOD*0.5)clk=0;#(PERIOD*0.5)clk=1;endend通过修改延时时间可以改变时钟信号的占空比复位信号复位信号在验证中只考虑开始仿真时复位一次,根据不同的复位考虑复位时间的长短。复位信号直接在initial块中赋值即可。regrstb;initialbeginrstb=1’b0;#1000rstb=1’b1;end施加激励的方式行激励强制激励使用循环添加激励预设输入激励码向量方式使用task语句系统任务和系统函数行激励在initial语句中按顺序添加绝对延时激励reg[7:0]ts_data;Initialbegints_data=8’b0;#100Ts_data=8’h47;#100Ts_data=8’h1f;end优点:添加方便,简洁,易于理解;缺点:难于管理,不容易过程化。强制激励添加强制赋值的方式,添加激励源。1)使用assign和deassign语句initialbegin#10assigntop.dut.fsm1.state_reg=`init_state;#20deassigntop.dut.fsm1.state_reg;end2)使用force和release语句initialbegin#10forcetop.dut.counter.scan_reg.q=0;#20releasetop.dut.counter.scan_reg.q;end使用循环语句在initial语句块中用循环结构描述具有一定变化规则的输入激励信号initialbeginfor(i=0;i=255;i=i+1)@(negedgeclk)stimulus=i;#20$finish;end优点:1)每次循环迭代你可赋值一个新的激励向量信号间的时序关系是有规律的2)Testbench非常紧凑,易于管理预设输入激励码向量方式将所需的输入激励码表示为一定形式的向量表;输入激励码向量预存于文件中;使用时从文件中按一定的时序节拍读入文件中的输入激励码向量VerilogHDL提供的支持:$readmemb(“File_Name”,Test_Vector);从文件中读取二进制输入激励码向量$readmemh(“File_Name”,Test_Vector);从文件中读取十六进制输入激励码向量initialbegin$readmemh(ethernet2.txt,memh,0,15000000);//$readmemh(ts_over_ip_pkt.txt,memh,0,15000000);gmii_rx_dv=1'b0;gmii_rx_data=8'b0;shift1=8'b0;shift2=8'b0;shift3=8'b0;shift4=8'b0;shift5=8'b0;shift6=8'b0;shift7=8'b0;shift8=8'b0;lead_flag=1;cnt=0;wait(start)beginfor(cnt=0;cnt=15000000;cnt=cnt+1)begin@(posedgegmii_rx_clk)beginshift1=memh[cnt];shift2=shift1;shift3=shift2;shift4=shift3;shift5=shift4;shift6=shift5;shift7=shift6;shift8=shift7;endif((shift5==8'h55)&&(shift6==8'h55)&&(shift7==8'h55)&&(shift8==8'h55)&&(shift1==8'hd5)&&lead_flag)begingmii_rx_dv=1;gmii_rx_data=shift8;lead_flag=0;endelseif((shift5==8'h55)&&(shift6==8'h55)&&(shift7==8'h55)&&(shift8==8'h55)&&(shift1==8'hd5))begingmii_rx_dv=0;gmii_rx_data=8'h0;//time_gap=$random;//sentpacketsgap//#time_gap#120gmii_rx_dv=1;gmii_rx_data=shift8;#8;endelsebegingmii_rx_data=shift8;lead_flag=0;endendendend使用task语句使用task封装重复操作可以压缩重复操作,提高代码效率。taskwrite_cpu_bus;input[7:0]data_in;input[15:0]adr_in;beginCPU_ADR=16'b0;CPU_CS=1'b1;CPU_WE=1'b1;CPU_OE=1'b1;CPU_RW=1'b1;cpu_indata=8'b0;#40cpu_indata=data_in;CPU_ADR=adr_in;CPU_CS=1'b0;#8CPU_WE=1'b0;#48CPU_CS=1'b0;CPU_WE=1'b1;#48CPU_CS=1'b1;CPU_WE=1'b1;endendtasktaskwrite_psi;input[7:0]channel_id;for(psi_pkt_cnt=0;psi_pkt_cnt=189;psi_pkt_cnt=psi_pkt_cnt+1)beginif(psi_pkt_cnt==0)write_cpu_bus(8'h55,16'h0500);elseif(psi_pkt_cnt==1)write_cpu_bus(channel_id,16'h0500);elseif(psi_pkt_cnt==2)write_cpu_bus(8'h47,16'h0500);elsewrite_cpu_bus(psi_pkt_cnt,16'h0500);endendtask系统任务和系统函数是Verilog中预先定义好的,用于调试和编译预处理的任务或函数。以$开头,用于控制和检测仿真模拟过程主要有:(1)用于获取仿真时间的系统函数(2)支持文本输出(检测信号、显示信号)的系统任务(3)用于文件输入、输出操作的系统任务(4)用于暂停和退出仿真的系统任务(5)用于产生随机数的系统任务谢谢!
本文标题:FPGA软件验证技术(下)
链接地址:https://www.777doc.com/doc-2872523 .html