1、第第4 4章章ModelSimModelSim使用使用本章内容可参考本章内容可参考Verilog HDL Verilog HDL 数字设计与综合(第二版)数字设计与综合(第二版)4.1 ModelSim4.1 ModelSim简介简介 Modelsim仿真工具是Model公司开发的。它支持Verilog、VHDL以及他们的混合仿真,它可以将整个程序分步执行,使设计者直接看到他的程序下一步要执行的语句,而且在程序执行的任何步骤任何时刻都可以查看任意变量的当前值,可以在Dataflow窗口查看某一单元或模块的输入输出的连续变化等,比Quartus自带的仿真器功能强大的多,是目前业界最通用的仿真器之
2、一。HDL代码TestBench逻辑模拟修改修改HDL代码代码综合 Modelsim是专业的HDL语言仿真器,比Quartus自带的仿真器功能强大的多,能支持Testbench仿真。而Quartus simulator不支持Testbench,只支持波形文件.vwf仿真。对于ModelSim初学者来说,modelsim软件自带的教程是一个很好的选择,在Help-SE PDF Documentation-Tutorial里面。它从简单到复杂、从低级到高级详细地讲述了modelsim的各项功能的使用,简单易懂。4.2 ModelSim4.2 ModelSim运行模式运行模式 ModelsimMod
3、elsim运行方式有运行方式有4 4种种:用户图形界面模式交互式命令行模式 不显示modelsim的可视化界面,仅通过命令控制台输入的命令完成所有工作。Tcl和宏模式 编写可执行扩展名为do或者tcl语法文件批处理模式 其所有操作都在后台进行,用户看不到modelsim的界面,也不需要交互式输入命令。当工程很大,文件比较多时,用批处理比较方便。直接运行批处理文件,在后台调用modelsim,执行modelsim的脚本文件*.do,完成操作。功能仿真功能仿真(前仿真前仿真,代码仿真代码仿真)主旨在于验证电路的功能是否符合设计要求,其特点是不考虑电路门延迟与线延迟,主要是验证电路与理想情况是否一致
4、。可综合FPGA代码是用RTL级代码语言描述的,其输入为RTL级代码与Testbench.在设计的最初阶段发现问题,可节省大量的精力。4.3 ModelSim仿真仿真门级仿真和时序列仿真门级仿真和时序列仿真(后仿真后仿真)使用综合软件综合后生成的门级网表进行仿真,不加入时延文件的仿真就是门级仿真.可以检验综合后的功能是否满足功能要求,其速度比功能仿真要慢,比时序仿真要快.在门级仿真的基础上加入时延文件(.sdf)的仿真就是时序仿真,比较真实地反映了逻辑的时延与功能.综合考虑电路的路径延迟与门延迟的影响,验证电路能否在一定时序条件下满足设计构想的过程,是否存在时序违规。功能仿真需要的文件功能仿真
5、需要的文件1设计HDL源代码:可以使VHDL语言或Verilog语言。2测试激励代码:根据设计要求输入/输出的激励程序3仿真模型/库:根据设计内调用的器件供应商提供的模块而定,如:FIFO、ADD_SUB等 4.4 ModelSim仿真工作模式仿真工作模式 仿真步骤:以4 位计数器为例给出详细步骤1.启动modelsim软件先在c盘建立文件夹count4,在modelsim中选择File-Change Directory,在弹出的Choose folder对话框中设置目录路径为c:/count42.建立工程在modelsim中建立project,选择File-New-Project.在Proj
6、ect Name栏中填写你的项目名字,建议和你的顶层文件名字一致。Project Location是你的工作目录,你可通过Brose按钮来选择或改变。Ddfault Library Name可以采用工具默认的work。Workspace窗口的library中就会出现work库.3.为工程添加文件 工程建立后,选择Add Exsiting File后,根据相应提示将文件加到该Project中。这里是count4.v和其测试向量count_tp.v,源代码如下:12134.编译文件编译(包括源代码和库文件的编译)。编译可点击ComlileComlile All来完成。5.装载文件(1)双击libr
7、ay 中work中的count_tp装载(2)点击simulate start simulation按右图设置,点击ok146.开始仿真点击workspace下的sim,点击count_tp,选择add add to wave然后点run all,开始仿真157.退出仿真在仿真调试完成后退出仿真,在主窗口中选择simulateend simulation16补充补充:加testbench,仿真步骤跟前面相似,装载文件时双击count4在sim中点击count4,add add to wave对输入信号clk,reset编辑测试波形17点击run-all18(2)在modelsim内直接编写Te
8、stbenchModelsim提供了很多Testbench模板,可直接拿过来用可以减少工作量。点View-Source-Show Language Templates然后会出现一个加载工程,接着你会发现在刚才的文档编辑窗口左边出现了一个Language Templates窗口 展开Verilog项,双击Creat Testbench会出现一个创建向导选择Specify Design Unit工作库下的目标文件,点Next可以指定Testbench的名称以及要编译到的库等,此处我们使用默认设置直接点Finish。这时在Testbench内会出现对目标文件的各个端口的定义还有调用函数,以自己Tes
9、tbench内添加内容,然后保存为.v格式即可。按照前面的方法把Testbench文件也编译到工作库中。4.5 Verilog Testbench4.5 Verilog Testbench编写编写 Verilog Testbench是一种按照verilog来编写的HDL模型,只不过大量使用不可综合风格的仿真语句,比如延迟、赋值等等,通过使用testbench来验证行为级Verilog HDL模型是否正确。testbench三个目的:1.产生激励2.将激励加入被测模块(Unit under Test)并收集响应3.响应与期望比较设计组织设计组织虚线表示编译时检测输入文件是否存在及可读并允许生成输
10、出文件。简单的简单的test benchtest bench向要验证的设计提供向量,人工验证输出。向要验证的设计提供向量,人工验证输出。复杂的复杂的test benchtest bench是自检测的,其结果自动验证。是自检测的,其结果自动验证。stimulus要验证的设计简单的test bench复杂的test bench激励验证结果要验证的设计module TestBench_Name;参数说明;寄存器、线网类型变量的定义、说明;DUT 实例语句;时钟信号定义、赋初值;定义置/复位信号的变化情形;用一个或多个initial语句块产生DUT的模拟激励向量;用Task、function定义DUT
11、外部时序接口;endmoduleTestbenchTestbench架构架构输入激励寄存器、线网的设置输入激励寄存器、线网的设置 相对于被测试模块的输入激励设置为reg型,输出相应设置为wire类型,双向端口可设置中间变量inout_reg作为该inout的输出寄存,inout口在testbench中要定义为wire型变量,然后用输出使能控制传输方向。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_
12、dir_port_reg:1bz;用bi_dir_port_oe控制端口数据方向,并利用中间变量寄存器改变其值。等于两个模块之间用inout双向口互连。往端口写(就是往模块里面输入)。并行块并行块forkjoin块在测试文件中很常用。他们的并行特性使用户可以说明块在测试文件中很常用。他们的并行特性使用户可以说明绝对时间,并且可以并行的执行复杂的过程结构,如循环或任务。绝对时间,并且可以并行的执行复杂的过程结构,如循环或任务。module inline_ tb;reg 7:0 data_ bus;/instance of DUT initial fork data_bus=8b00;#10 da
13、ta_bus=8h45;#20 repeat(10)#10 data_bus=data_bus+1;#25 repeat(5)#20 data_bus=data_bus 1;#140 data_bus=8h0f;joinendmodule上面的两个repeat循环从不同时间开始,并行执行。象这样的特殊的激励集在单个的beginend块中将很难实现。包含文件包含文件包含文件用于读入代码的重复部分或公共数据。包含文件用于读入代码的重复部分或公共数据。module clk_gen(clk);output clk;reg clk;include common.txtinitial begin whil
14、e($time sim_end)begin clk=initial_clock;#(period/2)clk=!initial_clock;#(period/2);end$finish;endendmodule在上面的例子中,公共参数在一个独立的文件中定义。此文件在不同在上面的例子中,公共参数在一个独立的文件中定义。此文件在不同的仿真中可被不同的测试文件调用。的仿真中可被不同的测试文件调用。/common.txt/clock and simulator constantsparameter initial_clock=1;parameter period=15;parameter max_cy
15、c=100;parameter sim_end=period*max_cyc施加激励施加激励产生激励并加到设计有很多产生激励并加到设计有很多 种方法。一些常用的方法有:种方法。一些常用的方法有:从一个从一个initialinitial块中施加线激励块中施加线激励 从一个循环或从一个循环或alwaysalways块施加激励块施加激励 从一个向量或整数数组施加激励从一个向量或整数数组施加激励 记录一个仿真过程,然后在另一个仿真中回放施加激励记录一个仿真过程,然后在另一个仿真中回放施加激励线性激励线性激励线性激励有以下特性:线性激励有以下特性:只有变量的值改变时才列出只有变量的值改变时才列出易于定义
16、复杂的时序关系易于定义复杂的时序关系对一个复杂的测试,测试基准对一个复杂的测试,测试基准(test bench)(test bench)可能非常大可能非常大module inline_ tb;reg 7:0 data_ bus,addr;wire 7:0 results;DUT u1(results,data_ bus,addr);initial fork data_bus=8h00;addr=8h3f;#10 data_ bus=8h45;#15 addr=8hf0;#40 data_ bus=8h0f;#60$finish;joinendmodule循环激励循环激励从循环产生激励有以下特性
17、:从循环产生激励有以下特性:在每一次循环,修改同一组激励变量在每一次循环,修改同一组激励变量时序关系规则时序关系规则代码紧凑代码紧凑 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 1;i=i-1)/循环循环#50 stimulus=stim_arrayi;#30$finish;endendmodule矢量采样
18、矢量采样在仿真过程中可以对激励和响应矢量进行采样,作为其它仿真的激励在仿真过程中可以对激励和响应矢量进行采样,作为其它仿真的激励和期望结果。和期望结果。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)$fs
19、trobeb(STIMULUS,%b,in_vec);if(RESULTS!=0)#(period/2)forever#(period/2)$fstrobeb(RESULTS,%b,out_vec);join endendmodule矢量回放矢量回放保存在文件中的矢量反过来可以作为激励保存在文件中的矢量反过来可以作为激励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/Vecto
20、rs are loaded$readmemb(vec.txt,stim);for(i=0;i num_vecs;i=i+1)#50 data_bus=stimi;endendmodule/激励文件激励文件vec.txt001110000011100100111010001111000011000000101000000110000111100010111000.使用矢量文件输入使用矢量文件输入/输出的优点:输出的优点:激励修改简单激励修改简单 设计反复验证时直接使用工具比较矢量文件。设计反复验证时直接使用工具比较矢量文件。错误及警告报告错误及警告报告使用文本或文件输出类的系统任务报告错误及警告
21、使用文本或文件输出类的系统任务报告错误及警告always(posedge par_err)$display(error-bus parity errors detected);always(posedge cor_err)$display(warning-correctable error detected);一个更为复杂的一个更为复杂的test bench可以:可以:不但能报告错误,而能进行一些动作,如取消一个激励块并跳转不但能报告错误,而能进行一些动作,如取消一个激励块并跳转到下一个激励。到下一个激励。在内部保持错误跟踪,并在每次测试结束时产生一个错误报告。在内部保持错误跟踪,并在每次测试
22、结束时产生一个错误报告。强制激励强制激励在过程块中,可以用两种持续赋值语句驱动一个值或表达式到一个信号。在过程块中,可以用两种持续赋值语句驱动一个值或表达式到一个信号。过程持续赋值通常不可综合,所以它们通常用于测试基准描述。过程持续赋值通常不可综合,所以它们通常用于测试基准描述。对每一种持续赋值,都有对应的命令停止信号赋值。对每一种持续赋值,都有对应的命令停止信号赋值。不允许在赋值语句内部出现时序控制。不允许在赋值语句内部出现时序控制。对一个寄存器使用对一个寄存器使用assign和和deassign,将覆盖所有其他在该信号上的赋值。,将覆盖所有其他在该信号上的赋值。这个寄存器可以是这个寄存器可
23、以是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
24、.q=0;#20 release top.dut.counter.scan_ reg.q;end强制激励强制激励可以强制可以强制(force)并释放一个信号的指定位、部分位或连接,但位的指定不能并释放一个信号的指定位、部分位或连接,但位的指定不能是一个变量(例如是一个变量(例如out_veci)不能对不能对register的一位或部分位使用的一位或部分位使用assign和和deassign对同一个信号,对同一个信号,force覆盖覆盖assign。后面的后面的assign或或force语句覆盖以前相同类型的语句。语句覆盖以前相同类型的语句。如果对一个信号先如果对一个信号先assign然后然后f
25、orce,它将保持,它将保持force值。在对其进行值。在对其进行release后,后,信号为信号为assign值。值。如果在一个信号上如果在一个信号上force多个值,然后多个值,然后release该信号,则不出现任何该信号,则不出现任何force值。值。在上面两个例子中,在在上面两个例子中,在 net或或register上所赋的常数值,覆盖所有在时刻上所赋的常数值,覆盖所有在时刻10和时刻和时刻20之间可能发生在该信号上的其他任何赋值或驱动。如果所赋值是一个表达式,之间可能发生在该信号上的其他任何赋值或驱动。如果所赋值是一个表达式,则该表达式将被持续计算。则该表达式将被持续计算。建立时钟建
26、立时钟例例1:虽然有时候在设计中给出时钟,但通常时钟是测试基准中建立。:虽然有时候在设计中给出时钟,但通常时钟是测试基准中建立。下面介绍如何产生不同的时钟波形。同时给出用门级和行为级描述方法下面介绍如何产生不同的时钟波形。同时给出用门级和行为级描述方法下面是一个简单对称时钟的例子:下面是一个简单对称时钟的例子:reg ck;always begin#(period/2)ck=0;#(period/2)ck=1;endreg go;wire ck;nand#(period/2)u1(ck,ck,go);initial begin go=0;#(period/2)go=1;end注意:注意:在一些
27、仿真器中,时钟与设计使用相同的抽象级描述时,仿真性能会好一些。产生的波形(假定产生的波形(假定period为为20)建立时钟建立时钟例例2:有启动延时的对称时钟的例子:有启动延时的对称时钟的例子:reg ck;initial begin ck=0;#(period)forever#(period/2)ck=!ck;endreg go;wire ck;nand#(period/2)u1(ck,ck,go);initialbegin go=0;#(period)go=1;end注意:注意:在行为描述中,在时间0将CK初始化为0;而在结构描述中,直到period/2才影响CK值。当go信号在时间0初
28、始化时,CK值到period/2才变化。可以使用特殊命令force和release立即影响CK值。产生的波形(假定产生的波形(假定period为为20)建立时钟建立时钟例例3:有不规则启动延时的不对称时钟的例子:有不规则启动延时的不对称时钟的例子:注意:注意:在行为描述中,CK值立刻被影响;而在结构描述中,在传播延时后才输出正确波形。产生的波形(假定产生的波形(假定period为为20)reg ck;initial begin#(period+1)ck=1;#(period/2 1)forever begin#(period/4)ck=0;#(3*period/4)ck=1;endendreg
29、 go;wire ck;nand#(3*period/4,period/4)u1(ck,ck,go);initial begin#(period/4+1)go=0;#(5*period/4 1)go=1;end使用使用tasktask在在test bench中使用中使用task可以压缩重复操作,提高代码效率可以压缩重复操作,提高代码效率。module bus_ctrl_tb;reg 7:0 data;reg data_valid,data_rd;cpu u1(data_valid,data,data_rd);initial begin cpu_driver(8b0000_0000);cpu_d
30、river(8b1010_1010);cpu_driver(8b0101_0101);end task cpu_driver;input 7:0 data_in;begin#30 data_valid=1;wait(data_rd=1);#20 data=data_ in;wait(data_rd=0);#20 data=8hzz;#30 data_valid=0;end endtaskendmodule 使用使用tasktask产生的波形产生的波形4.5 4.5 系统任务和系统函数系统任务和系统函数 系统任务和系统函数是Verilog中预先定义好的,用于调试和编译处理的任务和函数。以$开头,
31、用于控制和检测仿真模拟过程。主要有:用于获取仿真时间的系统函数支持文本输出(信号检测和显示)的系统任务用于文件输入、输出操作的系统任务用于暂停和退出仿真的系统任务1.用于产生随机数的系统任务4.64.6系统任务和系统函数系统任务和系统函数$time,$realtime,$stime$time,$realtime,$stime:返回当前仿真时间:返回当前仿真时间$time返回一个64位的整数时间值$realtime返回的结果是实数时间值,是更为精确的仿真时间$返回一个32位整数时间值。(对于大于232的时间,返回模为232的值使用它可以节省显示和打印空间)1.这些函数的返回值使用调用模块中的ti
32、mescale定义的模块仿真时间尺度为单位显示任务:用于仿真模拟期间的信息显示显示任务:用于仿真模拟期间的信息显示$display在终端屏幕上输出参数列表中的信号当前值。$monitor:持续监控和显示指定任务的参数值。$write:功能同$display,但执行完不自动换行。$strobe:用于在指定时刻输出显示仿真数据。$display$display语法格式为:$display(“format_specifiers,”);$display输出时会自动换行:$display($time,“%bt%ht%dt%o”,sig1,sig2,sig3,sig4);$display($time,“s
33、ig1=%b,sig2=%h,sig3=%d,sig4=%o”);$display($time,“%bt”,sig1,“%ht”,sig2,“%dt”,sig3,“%ot”,sig4);$display支持二进制、八进制、十六进制和十进制。缺省基数为十进制。$display(sig1,sig2,sig3,sig4);$displayb(sig1,sig2,sig3,sig4);$displayh(sig1,sig2,sig3,sig4);$displayo(sig1,sig2,sig3,sig4);$display$display格式符格式符$strobe$strobe选通任务$strobe语
34、法格式为:$strobe(/$strobe/$strbeo/$strbeh);选通监视,提供一种显示数据的机制,在所有同一时间单元内赋值语句执行完毕后才执行。定义使用时的参数定义与$display有相同的参数列表格式。不同的是:$display显示的变量值是执行到该语句时变量的值,而$strobe显示的是执行该语句的仿真时刻的所有语句执行完后的结果。(=)举例initialbegina=0;$display(a);/displays 0$strobe(a);/displays 1.a=1;/.因为这条语句end$monitor$monitor 当一个或多个指定的线网或寄存器列表改变值的时候,写
35、出一行文本.这个命令用于在测试设备中监控仿真行为.语法$monitor(“format_specifiers,”);$monitoron;打开监控标志$monitoroff;关闭监控标志 持续监控和显示指定任务的参数值 持续检测(参数列表中)一个或多个信号的变化,每当被监测的信号值发生变化时,就在当前时钟结束后显示该信号值 参数定义方式与$display同$monitor/$monitorb/$monitoro/$monitorh持续监视和显示指定参数值。$monitor($time,“a=%d,b=%d”,a,b);将monitor写入到initial模块中科技在整个仿真过程中对指定的变量值进行监测。
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。