modelsim软件使用.ppt
逻辑设计与FPGA,仿真软件Modelsim的基本知识,福州大学微电子系,仿真与验证,1、编写测试验证程序1.1、测试验证程序有三个主要目的1.2、典型的测试验证程序形式2、激励波形产生2.1、值序列2.2、重复模式3、测试验证程序实例3.1、解码器 3.2、触发器,Verilog模块的测试,目的:如何编写的测试文件,对所做的设计进行完整的测试和验证。掌握组织模块测试的常用方法学会编写常用的测试代码。,模块的测试,1、编写测试验证程序,测试验证程序用于测试和验证设计的正确性。Verilog HDL提供强有力的结构来编写测试验证程序。,1、编写测试验证程序,1.1、测试验证程序有三个主要目的:1)产生模拟激励(波形);2)将输入激励加入到测试模块并收集其输出响应;3)将响应输出与期望值进行比较。,1.2、典型的测试验证程序形式,module Test_Bench;(不做端口声明)/通常测试验证程序没有输入和输出端口。Local_reg_and_net_declarations(端口声明)Generate_waveforms_using_initial_&_always_statemen(产生激励波形)Instantiate_module_under_test(例化被测模块)Monitor_output_and_compare_with_expected_values(输出监控或直接波形输出)endmodule测试时,通过在测试验证程序中进行实例化,将激励自动加载于测试模块。,1.2、典型的测试验证程序形式,测试模块常见的形式:module XX_tb;reg;/被测模块输入变量类型定义wire;/被测模块输出变量类型定义initial begin;end/产生测试信号always begin;end/产生测试信号tsint m(.in1(ina),.in2(inb),.out1(outa),.out2(outb);/被测模块的实例引用initial begin.;.;end/记录输出和响应endmodule,1.2、典型的测试验证程序形式,测试模块中常用的过程块:,always,所有的过程块都在0时刻同时启动;它们是并行的,在模块中不分前后。initial块 只执行一次。always块 只要符合触发条件可以循环执行。,1.2、典型的测试验证程序形式,如何描述激励信号:module t;reg a,b,sel;/被测模块的输入信号用寄存器赋值wire out;/被测模块的输出信号/引用多路器实例 mux2 m(out,a,b,sel);/加入激励信号 initial begin a=0;b=1;sel=0;#10 b=0;#10 b=1;sel=1;#10 a=1;#10$stop;end,1.2、典型的测试验证程序形式,如何观察被测模块的响应:在initial 块中,用系统任务$time 和$monitor$time 返回当前的仿真时刻$monitor 只要在其变量列表中有某一个或某几个变 量值发生变化,便在仿真单位时间结束时显示其变 量列表中所有变量的值。例:initial begin$monitor($time,“out=%b a=%b b=%b sel=%b”,out,a,b,sel);end,2、激励波形产生,有两种产生激励值的主要方法:产生值序列,即在确定的离散时间间隔加载激励。2)产生重复模式的波形。,2.1、值序列,A1、产生值序列的最佳方法是使用initial语句。initialbegin Reset=0;#100 Reset=1;#80 Reset=0;#30 Reset=1;end产生的波形如图所示。Initial语句中的赋值语句用时延控制产生波形。此外,语句内时延也能够按如下实例所示产生波形。,因为使用的是阻塞性过程赋值,上面语句中的时延是相对时延。,2.1、值序列,B、若要重复产生一个值序列,可以使用always语句替代initial语句。Parameter REPEAT_DELAY=35;Integer CoinValue;alwaysbeginCoinValue=0;#7 CoinValue=25;#2 CoinValue=5;#8 CoinValue=10;#6 CoinValue=5;#REPEAT_DELAY;end,这是因为initial语句只执行一次而always语句会重复执行,2.2、重复模式,A、重复模式的生成通过使用如下的连续赋值形式加以简化:assign#(PERIOD/2)Clock=Clock;但是这种做法并不完全正确。问题在于Clock是一个线网(只有线网能够在连续赋值中被赋值),它的初始值是z,并且,z等于x,x等于x。因此Clock的值永远固定为值x。现在需要一种初始化Clock方法。可用initial语句实现。initial Clock=0;但是现在Clock必须是寄存器数据类型(因为只有寄存器数据类型能够在initial语句中被赋值),因此连续赋值语句需要被变换为always语句。always#(PERIOD/2)Clock=Clock;,2.2、重复模式,B1、下面是一个完整的时钟产生器模块。Module Gen_Clk_A(Clk_A);output Clk_A;reg Clk_A;parameter tPERIOD=10;initialClk_A=0;always#(tPERIOD/2)Clk_A=Clk_A;endmodule,2.2、重复模式,B2、下面给出了产生周期性时钟波形的另一种可选方式。Module Gen_Clk_B(Clk_B);output Clk_B;reg Start;initialbeginStart=1;#5 Start=0;endnor#2(Clk_B,Start,Clk_B);endmodule,initial语句将Start置为1,这促使或非门的输出为0(从x值中获得)。5个时间单位后,在Start变为0时,或非门反转产生带有周期为4个时间单位的时钟波形。,2.2、重复模式,B3、如果要产生高低电平持续时间不同的时钟波形,可用always语句建立模型。Module Gen_Clk_C(Clk_C);Parameter tON=5,tOFF=10;Output Clk_C;Reg Clk_C;always begin#tON Clk_C=0;#tOFF Clk_C=1;end endmodule,3、测试验证程序实例,out,module mux2_m(out,a,b,sl);input a,b,sl;output out;wire sela,nsl,selb not u1(ns1,sl);and#1 u2(sela,a,nsl);and#1 u3(selb,b,sl)or#2 u4(out,sela,selb)endmodule,3、测试验证程序实例,module t;reg a,b,sel;wire out;mux2_m tt(out,a,b,sel);/引用多路器实例initial begin a=0;b=1;sel=0;#10 b=0;#10 b=1;sel=1;#10 a=1;#10$stop;end/加入激励信号initial begin$monitor($time,“out=%b a=%b b=%b sel=%b”,out,a,b,sel);endendmodule,3、测试验证程序实例,下例是D触发器及其测试模块。module MSDFF(D,C,Q,Qbar);input D,C;output Q,Qbar;reg Q;always(posedge C)Q=D;assign Qbar=Q;endmodule,3、测试验证程序实例,module Test;reg D,C;wire Q,Qb;MSDFF MSDFFM1(D,C,Q,Qb);always#5 C=C;initialbeginD=0;C=0;#40 D=1;#40 D=0;#40 D=1;#40 D=0;$stop;endinitial$monitor(“Time=%t:C=%b,D=%b,Q=%b,Qb=%b,$time C,D,Q,Qb);endmodule,在此测试验证模块中,触发器的两个输入和两个输出结果均设置了监控,故只要其中任何值发生变化就输出指定变量的值。,Modelsim软件使用,4.1 ModelSim简介 4.2 ModelSim的安装4.3 ModelSim的使用4.4 从例子开始学习ModelSim,4.1 ModelSim简介,ModelSim为HDL仿真工具,我们可以利用该软件来实现对所设计的VHDL或Verilog程序进行仿真,支持IEEE常见的各种硬件描述语言标准。可以进行两种语言的混合仿真。ModelSim常见的版本分为ModelSim XE和ModelSim SE两种,ModelSim版本更新很快,但功能基本一致。,4.1 ModelSim简介,本节将对ModelSim6.2b版本进行介绍,有关更深入地教程,还是参考ModelSim附带的文档。在网址/上也可以找到深入的教程,在该页面上注册以后,会在电子邮件中收到发过来的密码,根据邮件地址和密码登陆后,会有一些高级教程和使用要点(Application Notes)下载。,4.1 ModelSim简介,如果ModelSim是和ISE一起使用的话,你需要编译Xilinx的一些库文件,这些库文件包括unisim、simprim、xilinxcorelib、aim、pls、cpld等,有了这些库文件,可以在ISE中生成设计的行为仿真(将设计转换为RTL描述后进行的仿真)、转换后仿真(将设计转换为Xilinx器件的基本模块来实现后进行的仿真)、映射后仿真(将设计用Xilinx的具体器件的具体模块实现后进行的仿真,仿真中包含了器件的延时,但由于没有布局布线无法提取出互连线的信息,因此仿真中不包含互连线的延时、电容、电阻等信息)。,4.1 ModelSim简介,布局布线后仿真(将设计用Xilinx具体器件进行布局布线后,提取出互连线的信息,进行的仿真)的各种模型,然后在ModelSim中对这些模型进行仿真,由于ISE和ModelSim已经实现了无缝连接,在ISE中只需设置一个可视的波形文件,然后点几下鼠标就可以实现各种仿真。同时,也可以使用ModelSim的XE(Xilinx Edition)版本,由于该版本是Xilinx版,其中自然就集成了Xilinx的各种库文件,使用时就不需要考虑库文件方面的问题了。对于ISE不同版本集成了不同版本的ModelSim,虽然是集成,还是需要单独进行安装的。,4.2 ModelSim的安装,安装说明:1.运行setup,安装程序。选择“Full product”选项。当询问security key的时候,选择 NO。当你看见“License Wizard”对话框时候,选择“close”。2.运行keygen,生成license.dat,把它拷贝到 c:flexlm 目录。3.设置环境变量:LM_LICENSE_FILE=c:flexlmlicense.dat(选择我的电脑按右键,选“属性”,再选“高级”,可以看到环境变量按钮)4.运行ModelSim,OK。,4.3 ModelSim的使用说明,接下去我们来从一个简单的例子学习ModelSim的简单使用。,4.3.1 ModelSim 用户界面特征,有九个窗口:main,source,objects,active process,locals,dataflow,wave,watch,和list 窗口Main 窗口 ModelSim 这是设计加载前的提示符 能浏览帮助,编辑库,编辑源代码而不用调用一个设计 VSIM 设计加载后显示的提示符 告诉我们仿真器的行为动作 命令 信息 声明,4.3.2 ModelSim实现方法,交互式的命令行(Cmd)唯一的界面是控制台的命令行,没有用户界面 用户界面(UI)能接受菜单输入和命令行输入 课程主要讨论 批处理模式 从DOS或UNIX命令行运行批处理文件 不讨论,4.3.3基本仿真步骤,1 创建一个工程2 编写源代码和测试程序3 编译源代码和测试程序-所有HDL代码必须经过编译才能进行仿真-Verilog和VHDL的编译命令不同4 启动仿真器5 运行仿真器,创建一个工程,1,UI)选择主窗口中的菜单:File-New Project 输入项目名称:MUX24 项目保存的目录 默认的库名:work,2 编写源代码和测试程序,在Project下点击右键:选择Add to Project 选New File 输入文件名(注意不要加后缀.v)在Add file as type中务必要选Verilog 同样的方法加入相应的测试文件。,3 编译源代码(Verilog),UI)Compile-Compile all在Project下点击右键:选择compilecompile allCmd)vlog-work.v.v文件按列出的顺序编译编译顺序无关紧要缺省编译到work库中例:vlog my_design.v注意:当项目中涉及的设计文件被改变时必须重新编译。,编译,出错信息,4 启动仿真器,UI)Simulate-SimulateCmd)vsim-lib VHDLvsim top_entity top_architecture仿真Entity/Architecture对也可以选择一个ConfigurationVerilogvsim top_level1 top_level2仿真多个顶层Modules,启动仿真器(UI),选择顶层module或entity/architecture,选择仿真精度,选择库,vsim命令参数,参数-t 指定仿真时间精度单位可以是 fs,ps,ns,ms,sec,min,hr如果使用了 Verilog中的timescale编译指令,仿真将使用所有设计文件中最小的时间精度该参数是可选的(默认值是ns)-sdfmin|-sdftyp|-sdfmax=标注SDF文件该参数是可选的实例名也是可选的;如果没有指定,SDF将用于顶层设计,5 运行仿真器,UI)RunCmd)run 可按指定时间步长运行仿真器,运行仿真器,run命令参数,可选参数-指定运行的时间步长单位可以是fs,ps,ns,ms,sec-step执行到下一个HDL表达式-continue在 step或断点之后继续执行余下的仿真-all运行仿真器,直到不再有事件发生,run命令例子,run 1000从当前位置开始,仿真器运行1000个时间单位run 2500 ns从当前位置开始,仿真器运行2500nsrun 3000仿真器运行到3000个时间单位的时刻停止,4.3.3仿真器的激励,测试平台(Testbench)可用Verilog或VHDL编写用于非常复杂的仿真和交互式仿真force命令用于简单模块的仿真直接从命令控制台输入可以使用.DO文件(宏文件),DO文件,DO文件是自动运行仿真步骤的宏文件建库编译仿真强制仿真器激励可以运用于所有ModelSim模式UI)Tools-Execute MarcoCmd)do.do可以调用其他DO文件,cd c:mydirvlib workvlog counter.vvsim counterview*add wave/*add list/*do run.do,DO文件例子,用ModelSim进行仿真,演 示,4.4从例子开始学习ModelSim,例子是一个分频电路的设计。分频电路:是将较高频率的时钟分频,得到较低频率的时钟,分频电路的使用较为广泛。例如,我们要编写一个显示时间的电路就需要一个分频器,将晶振的频率分频得到1Hz的时钟信号。分频有几种方法,对于较为规则的分频,如2分频、4分频、8分频等可以调用ISE本身的库函数来实现;对于较不规则的分频,我们也有两种方法,一种是利用计数器的某一位来作为分频输出,一种是计数器计数到某一数值时,分频时钟信号翻转来实现分频。两种方法都可以从其仿真结果得到。,图形界面对设计进行仿真,Modelsim快速上手四部曲分别是:创建工程、添加Verilog代码文件、编译、仿真。下面简单给出这四步:初学者可以按照如下步骤开始:1、运行ModelSim,方法是点击开始-程序-ModelSim SE 6.2b-ModelSim或双击桌面上的快捷方式,会出现界面,如果上一次使用ModelSim建立过工程,这时候会自动打开上一次所建立的工程;,图形界面对设计进行仿真,图形界面对设计进行仿真,2、点击File-New-Project,会出现如图4-3-2所示的界面,在Project Name中我们输入建立的工程名字为DivClkSimu,在Project Location中输入工程保存的路径为D:/yuProj/modelsim/DivClk,注意ModelSim不能为一个工程自动建立一个目录,这里我们最好是自己在Project Location中输入路径来为工程建立目录,在Default Library Name中为我们的设计编译到哪一个库中,这里我们使用默认值,这样,在我们编译设计文件后,在Workspace窗口的Library中就会出现work库。这里我们输入完以后,点击OK;,图形界面对设计进行仿真,新建工程窗口,图形界面对设计进行仿真,3、这时有对话框图所示,提示我们给定的工程路径不存在,是否建立该路径,我们的目的就是为工程建立一个新目录,因此,点击确定;,确认建立新的工程目录,图形界面对设计进行仿真,4、这时候出现如图所示的界面,可以点击不同的图标来为工程添加不同的项目,点击Create New File可以为工程添加新建的文件,点击Add Existing File为工程添加已经存在的文件,点击Create Simulation为工程添加仿真,点击Create New Folder可以为工程添加新的目录。这里我们点击Create New File;,5、出现界面如图,我们在File Name中输入DivClk作为文件的名称,Add file as type为输入文件的类型为VHDL、Verilog、TCL或text,这里我们设置Verilog,Folder为新建的文件所在的路径,Top Level为在我们刚才所设定的工程路径下。点击OK;并在Add items to the Project窗口点击Close关闭该窗口;,图形界面对设计进行仿真,图形界面对设计进行仿真,6、这时候在Workspace窗口中出现了Project选项卡,在其中有DivClk.v,其状态栏有一个问号,表示未编译,我们双击该文件,这时候出现窗口edit-DivClk.v的编辑窗口,在其中输入我们的设计文件如下:,图形界面对设计进行仿真,module div(clk_i,clk_o,reset);parameter DIV_N=4;input clk_i,reset;output clk_o;reg clk_o;integer count;always(negedge reset or posedge clk_i)begin if(!reset)count=0;else if(count=3)count=0;else count=count+1;endalways(negedge reset or posedge clk_i)begin if(!reset)clk_o=0;else begin if(count=(DIV_N/2-1)clk_o=0;else clk_o=1;endendendmodule,图形界面对设计进行仿真,7、点击File-Save,并退出该窗口(File-Close);8、在WorkSpace窗口的DivClk.v上点击右键,选择Compile-Compile All,如图所示;,图形界面对设计进行仿真,9、在脚本窗口中将出现一行绿色字体Compile of DivClk.v was successful.,说明文件编译成功,在该文件的状态栏后有一绿色的对号,表示编译成功;10、下面我们开始仿真,点击菜单Simulate-Simulate,会出现如下图所示的界面,我们展开Design选项卡下的work库,并选中其中的div,这时候在Simulate中出现了work.div表示我们所要仿真的对象,Resolution为仿真的时间精度,这里我们使用默认值,点击OK;,图形界面对设计进行仿真,选择仿真对象,图形界面对设计进行仿真,11、为了观察波形窗口,我们点击菜单View-debug windows-Wave;12、这时候出现的Wave窗口为空,里面什么都没有,我们 要为该窗口添加我们需要观察的对象,首先在workspace窗口中右击instance的中例化模块div,选择add-add to wave可得如下图所示,这时候在波形窗口中就可以看到所有的信号了。,图形界面对设计进行仿真,信号窗口,图形界面对设计进行仿真,13、下面我们就开始仿真了,在主窗口中输入命令对信号进行驱动,对时钟信号输入驱动:force clk_i 0 0,1 10-r 20对reset信号输入驱动:force reset 0 0,1 3 其中force为命令,clk表示为clk信号驱动,0 0表示在零时刻该值为0,1 10表示在10ns处值为1,-r 20表示从20ns处开始重复(repeat),可以看出我们这里的输入时钟为50MHz,即周期为20ns;,采用testbench实现仿真,include“DivCLK.v”module testdiv;reg clk_i;reg reset;wire clk_o;always#10 clk_i=clk_i;initialbegin#0 reset=0;clk_i=0;#5 reset=1;#2000$stop;enddiv div1(.clk_i(clk_i),.clk_o(clk_o),.reset(reset);endmodule,图形界面对设计进行仿真,图形界面对设计进行仿真,14、以十进制查看counter信号波形,在波形窗口中,右键点击counter信号,点击Radix-Decimal,该信号的值就以十进制显示了;15、开始仿真,在主窗口中输入run 3us,表示运行仿真3微秒,这时候如果你的机器配置较低那就要等几分钟时间了,这时候你可以看看CPU的利用率一直为100,仿真是比较占资源,并且以后对波形的操作机器反应也很慢,如果仿真很慢你可以看看状态栏的当前仿真时间是多少;,图形界面对设计进行仿真,16、这时候点击按钮(在当前波形窗口中显示所有波形),点击 可以在波形窗口添加竖线,点击可以 调整选定竖线在选定信号的变化处,调整完毕,我们可以在波形窗口看到如图所示的窗口,可以看到分频得到的时钟占空比为1(即一个周期内容为1时间等于波形为0的时间),分频后周期为80ns;点击中间键拉出需要显示的区域,图形界面对设计进行仿真,仿真波形窗口,图形界面对设计进行仿真,17、退出仿真,在主窗口中点击Simulate-End Simulation,会出现对话框,提示我们是否确认退出仿真,我们点击是退出仿真;18、仿真结果分析,这里我们的输入时钟为50MHz,周期 为20ns,通过分频语句得到频率为12.5MHz,周期为80ns的时钟,使用时可以调整分频语句if(count=3)then中的值及位宽来调整分频后的时钟频率。设我们需要从周期为T(ns)的时钟得到周期为X(ns)的脉冲,可以用如下的方法计算出此处应有的值:(X/T)/2)-1,例如此处我们要从周期为20ns的时钟得到周期为1000ns(1us)的脉冲,(X/T)/2)-1=(1000/20)/2-1)=24=(11000)Bin因此可以得到该式中的值。,