




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
任务1.1
VerilogHDL标准
任务1.2电路设计
任务1.3电路仿真任务1.1
VerilogHDL标准VerilogHDL目前有三个标准:IEEE1364-1995、IEEE1364-2001和IEEE1364-2005。这三个标准分别发布于1995年、2001年、2005年,相应的标准可简称为Verilog-1995、Verilog-2001和Verilog-2005。VerilogHDL语言最初是于1983年由GatewayDesignAutomation公司为其模拟器产品开发的硬件建模语言。由于该公司的模拟、仿真器产品广泛使用VerilogHDL,因此该语言作为一种便于使用且实用的语言逐渐为众多设计者所接受。开放Verilog国际组织是促进VerilogHDL发展的国际性组织。1992年OVI决定致力于推广Verilog标准成为IEEE标准并于1995年获得成功(称之为IEEE1364-1995)。与Verilog-1995相比,Verilog-2001加入了很多有用的特性,这些特性可以提高设计的生产效率、综合能力和验证效率。新特性包括:增加generate语句,简化模块多次实例化或者选择实例化;增强对多维数组的支持;增强文件I/O的操作;增加对task和function重入的支持;增加always@(*);增加新的端口声明方式;等等。与Verilog-2001相比,Verilog-2005增加了Verilog-AMS,支持对集成的模拟和混合信号系统的建模,把寄存器类型改名为变量类型。2009年,IEEE1364-2005和IEEE1800-2005两个部分合并成IEEE1800-2009。IEEE1800-2005和IEEE1800-2009都是SystemVerilog语言标准。SystemVerilog是硬件描述验证语言,是硬件描述语言和硬件验证语言的一个集成。本书所有代码均符合VerilogHDL的IEEE1364-2001标准。关于VerilogHDL标准更多的内容和细节,请读者自行查阅上述VerilogHDL标准。任务1.2 电
路
设
计HDL,全称硬件描述语言,用来描述电路。采用HDL编写电路描述文件时,可用综合工具生成电路网表文件。电路设计完成后,通常需要查看综合后的电路。本书使用的综合工具软件是Vivado14。该版本支持VerilogHDL的IEEE1364-2001标准。另外,本书部分项目也用到了QuartusⅡ13软件。关于Vivado14和QuartusⅡ13软件的安装和详细使用说明,本书不展开介绍,感兴趣的读者可自行查阅相关资料。在电路设计过程中,可能会结合使用HDL和C语言。HDL与C语言两者有本质区别,如图1-1所示。C语言是软件语言,编译后生成机器语言程序(机器语言程序是一系列指令),并使CPU执行,并不生成硬件电路,CPU处理软件指令需要取址、译码、执行,代码是串行执行的。HDL是硬件描述语言,综合后生成硬件电路,代码是并行执行的。在电路设计过程中,通常将C语言和HDL语言结合使用,具体表现在:(1)在电路设计中,C语言可以进行先期的算法验证,待算法验证后再使用HDL语言来实现,也就是使用C语言辅助硬件设计。(2) C语言与VerilogHDL硬件描述语言相似,在完全理解了两种语言的语法和功能,并具备了软件思维和硬件思维之后,很容易将C语言的程序转成VerilogHDL语言的程序。一、设计举例【例1-1】
使用HDL语言描述一个非门。上述代码中,将输出Y描述为输入A取反,可以使用综合工具查看生成的电路。综合的电路如图1-2所示。【例1-2】
使用HDL语言描述一个D触发器。上述代码中,复位时将q的值赋为0,在clk上升沿将d赋值给q。综合的电路如图1-3所示。上述电路设计涉及的知识点有:module结构及其相关知识点、assign连续赋值语句、always过程语句。(1) module结构。module和endmodule是VerilogHDL的关键字,用来说明模块。每个模块都可以理解为一颗特定功能的芯片。VerilogHDL程序是由模块构成的,每个模块的内容都嵌在module和endmodule两个语句之间。每个模块可实现特定的功能,且可进行层次嵌套。因此,可将大型的数字电路设计分割成不同的小模块来实现特定的功能,最后通过顶层模块调用子模块来实现整体功能。(2)端口属性。每个模块需进行端口列表声明,说明输入/输出端口属性,并对模块的功能进行描述。input和output是VerilogHDL的关键字,用来说明模块的端口属性。端口属性分别为input(输入)、output(输出)和inout(输入/输出)。另外,每个模块需进行端口列表声明,说明这些端口的输入、输出属性。(3)信号类型。wire、reg是VerilogHDL语言的关键字,用来说明模块内部信号的属性,包括线网类型、寄存器类型等。在设计过程中,需要注意的是,wire通常用来说明在assign语句中被赋值的变量;reg通常用来说明在initial语句或always语句中被赋值的变量。(4)注释语句。可以用/*…*/和//…对VerilogHDL程序的任何部分作注释。一个有使用价值的源程序都应当加上必要的注释,以增强程序的可读性和可维护性。(5)书写格式。VerilogHDL程序的书写格式自由,一行可以写几个语句,也可以一个语句分写多行。除了endmodule语句外,VerilogHDL程序中每个语句和数据定义的最后必须有分号。(6) assign连续赋值语句。assign是VerilogHDL语言的关键字,用来说明模块内部信号的连接关系。语句“assignY = ~A;”的功能是:当A = 1时,Y = 0;当A = 0时,Y = 1。assign语句常用于实现简单的组合逻辑电路。(7) always过程语句。always是VerilogHDL语言的关键字,用来说明模块的行为。always语句常用于实现时序逻辑电路和复杂的组合逻辑电路。二、查看电路图代码设计完成后,可以使用综合工具查看电路图。例如,QuartusⅡ、Vivado、DesignCompiler等都可用于查看综合后的电路图。Vivado设计套件是FPGA厂商Xilinx公司2012年发布的集成设计环境,包括高度集成的设计环境和新一代从系统到IC级的工具。本书使用的集成开发环境是Vivado2014.4。QuartusⅡ是Altera公司的综合性PLD/FPGA开发软件。本书使用的集成开发环境是QuartusⅡ13.1。Vivado和QuartusⅡ均支持原理图、VHDL、VerilogHDL等多种设计输入形式,内嵌自有的综合器以及仿真器,可完成从设计输入到硬件配置的完整设计流程。下面以Vivado为例来说明查看综合后的电路图的步骤。1.创建新工程(1)打开“Vivado2014.4”设计开发软件,选择“CreateNewProject”,如图1-4所示。(2)在弹出的创建新工程的界面中,点击“Next”按钮,开始创建新工程,如图1-5所示。(3)在“ProjectName”界面中,将工程名称修改为“sw_led_vavido”,并设置好工程存放路径。同时勾选上创建工程子目录的选项。这样整个工程文件都将存放在创建的“sw_led_vavido”子目录中。然后,点击“Next”按钮,如图1-6所示。(4)在选择工程类型的界面中,选择RTL工程。由于本工程需要创建源文件,因此,无须将“Donotspecifysourcesatthistime”(不指定添加源文件)勾选上。然后,点击“Next”按钮,如图1-7所示。(5)在创建或添加Verilog源文件界面中,暂时先不新建或添加源文件。点击“Next”按钮,如图1-8所示。(6)在创建或添加约束文件界面中,暂时先不新建或添加约束文件。点击“Next”按钮,如图1-9所示。(7)在器件板卡选型界面中,不选择任何器件,直接点击“Next”按钮。(8)在新工程总结界面中,检查工程创建是否有误。没有问题,则点击“Finish”按钮,完成新工程的创建。2.添加和编辑源文件(1)点击“ProjectManager”目录下的“AddSources”,如图1-10所示。(2)选择添加源文件。点击“Next”按钮,如图1-11所示。(3)点击“CreateFile…”,创建新文件。在弹出的对话框中输入文件名“sw_led_vivado”,点击“OK”按钮进行新建,如图1-12所示。(4)在弹出的模块定义对话框中,保持默认,点击“OK”按钮后,在弹出的模块保存对话框中点击“Yes”按钮,完成源文件的创建。(5)双击“sw_led_vivado.v”,在出现的源文件编辑框中完成源文件的编辑,如图1-13所示。3.查看RTL电路图RTL原理图不是设计开发描述工具,而是综合器输出的一个结果。在FPGA应用开发过程中,可以通过“RTLANALYSIS→Schematic”查看电路图,如图1-14所示。图1-3就是通过这种方法查看D触发器的电路图。
“RTLANALYSIS→Schematic”功能在自顶向下的层级设计中,常用于检查模块端口间的连接是否正确,是一个比较实用的工具。在本书的后续章节中会使用这一工具给出电路原理图,说明模块间的连接关系;同时,在电路图的设计过程中,也常用这个工具来排查错误,尤其是模块间的连接错误。另外,使用其他综合工具也可以查看电路图,如QuartusⅡ、DesignCompiler等。但在其他综合工具中查看的电路图与Vivado中的电路图在外观上不太一致,如例1-2,在QuartusⅡ中查看到的电路图如图1-15所示。任务1.3 电
路
仿
真HDL语言描述的电路功能是否正常,可以使用仿真来验证。本书中的项目使用的仿真工具软件是ModelSim10.0,该版本支持VerilogHDL的IEEE1364-2001标准。本任务详细介绍了Verilog的仿真技术。因为可综合的语法是Verilog语法的一个子集,所以读者要全面了解VerilogHDL的强大功能,就必须详细全面地了解VerilogHDL语法,且为了配合对各种语法进行仿真分析,还需要借助ModelSim软件。ModelSim是一种功能强大的仿真软件,不仅支持向量波形文件的仿真,还支持文本文件的仿真。一、仿真举例【例1-3】
使用HDL语言对非门进行验证。//显示输出,aa或yy有变化时才打印信息上述代码可以实现对非门的仿真,仿真图形如图1-16所示。【例1-4】
使用HDL语言对D触发器进行验证。上述代码可以实现对D触发器的仿真,仿真图形如图1-18所示。上述电路仿真涉及的知识点有testbench、模块例化、initial过程语句、延时仿真、多变量处理、循环语句、系统函数、仿真软件force功能等。下面对这些知识点进行说明。(1) testbench。testbench是一种验证手段。任何设计都会有输入/输出,但是在软环境中没有激励输入,也不会对设计的输出的正确性进行评估,因此testbench就应运而生了。testbench是一种“虚拟平台”,俗称测试台,模拟实际环境的输入激励和输出校验的产生,可以对设计从软件层面上进行分析和校验。测试台mynot_tb的主要功能是为mynot模块提供输入激励信号;测试模块mydff_tb的主要功能是为mydff模块提供输入激励信号。(2)模块例化。测试台调用设计代码称为例化。非门测试的例化语句形式为其中,A和Y为设计代码中的端口信号名,aa和yy为测试代码中相对应的信号名。通过为aa增加激励,可以观察输出yy的响应。这种例化方式称为名称关联例化。D触发器测试的例化语句形式为mydffUU(clk,rst,d,q);其中,clk、rst、d、q均为测试模块中的信号,而没有出现设计模块中的信号名,这种例化的信号传递是由信号在端口中的位置决定的。这种例化方式称为位置关联例化。应注意测试台中的变量声明与被例化的设计模块中的端口类型说明。例如,测试模块mynot_tb中aa为reg类型,而在设计模块mynot中A为wire类型。测试模块mydff_tb和设计模块mydff,其中的端口类型也是类似的,测试模块mydff_tb中的clk、rst、d等变量均定义成了reg类型,而在设计模块中这些相应的端口均为wire类型。(3) initial过程语句。initial是VerilogHDL语言的关键字,用来为输入信号添加激励。在测试台mynot_tb中,为aa赋值20次,每次间隔10个时间单位,所赋的值是随机产生的。(4)延时仿真。#N表示的是延时N个时间单位。时间单位通过 'timescale进行说明。在测试台mynot_tb中,repeat(20)#10aa=($random)%2;就是重复20次操作,每次操作的间隔为10个时间单位。(5)多变量处理。当需要为多个变量设置激励时,虽然可以将所有激励写在一个initial语句块或一个always语句块中,但当设计输入信号多且变化情况也多时,则信号激励的产生会不太清晰,甚至会造成逻辑混乱。因此,建议为每个变量单独设置激励,即一个变量的激励设置仅在一个initial语句块或一个always语句块中处理。在测试台mydff_tb中,clk、rst、d都是进行单独设置激励的。(6)循环语句。forever和repeat用于执行循环,前者表示循环次数无限;后者表示循环次数有限,且在其后括号中说明循环次数。循环语句在仿真中较常用,使用循环语句设置激励比较高效实用。(7)系统函数。调用系统函数时应在函数名前加 $。下面对例中的系统函数的作用进行说明。stop函数用来停止仿真。monitor和display函数用来显示当前变量值。monitor与display的区别是:前者是待显示变量有变化时就会显示该变量的值,而display只显示一次。realtime函数用于显示当前仿真时间。(8)仿真软件force功能。对于初学者,在ModelSim软件中,除了编写测试台仿真外,也可以直接使用软件中的force按钮产生激励进行仿真。使用force按钮产生激励的优点是不用写测试台程序,可以直接针对设计的输入设置相应的激励,然后直接观察设计的仿真结果。这种方法在一些简单设计中比较直观,减少了初学者编写测试台的干扰,对初学者学习语法和理解设计代码有一定的帮助。但对于熟悉HDL语言的开发者来说,建议在测试台上进行仿真。二、基于ModelSim的仿真步骤1.创造ModelSim工程(1)点击“开始→程序→ModelSimSE-6410.0c”或双击桌面上的快捷方式,打开ModelSim软件。(2)点击“File→New→Project”,出现如图1-19所示的界面,在“ProjectName”中输入建立的工程名字“MyPrj”,在“ProjectLocation”中输入工程保存的路径为“D:/BOOK_HDL”。注意:ModelSim不能为一个工程自动建立一个目录,创建者应自己在ProjectLocation中输入路径来为工程建立目录,使用自己创建的目录;在“DefaultLibraryName”中设置设计编译后存放的目标库,使用默认值。(3)编译设计文件后,在Workspace窗口的Library中会出现work库。完成各项设置后,点击“OK”按钮。2.添加工程文件在如图1-20所示的界面中,可以点击不同的图标来为工程添加不同的项目。点击“CreateNewFile”可以为工程添加新建的文件,点击“AddExistingFile”为工程添加已经存在的文件,点击“CreateSimulation”为工程添加仿真,点击“CreateNewFolder”可以为工程添加新的目录。这里我们点击“CreateNewFile”。(1)点击“CreateNewFile”,出现如图1-21所示的界面。(2)在“FileName”框中输入“MyFile”。在“Addfileastype”下拉框中选择“Verilog”,如图1-21所示,点击“OK”按钮。(3)打开“MyFile.v”文件,录入设计代码和测试代码,代码文件如下所示。【例1-5】
计数器的设计代码和测试代码。上述设计代码和测试代码均写在一个文件中。实际开发过程中,也可以将设计代码和测试代码分别写入两个不同名称的文件。录入代码后,如图1-22所示。3.编译工程通过图1-23可以看出,在Workspace窗口中的“Project”选项卡里,“MyFile.v”文件状态栏有问号,这表示该文件未曾编译或者编译后又进行了修改。对文件的编译过程如下:(1)选择“Compile→CompileSelected”或者“Compile→CompileAll”,如图1-23所示。(2)在命令窗口中将出现“#CompileofMyfile.vwassuccessful.”,且在状态栏后有一对号,表示编译成功,如图1-24所示。如果编译出错,则可以双击错误弹出错误的提示信息,然后根据提示进行排错。排错后再次编译,如果编译还出错,就继续排错,直到编译成功为止。4.仿真(1)选择“Library”标签,出现如图1-25所示的界面。(2)展开“work”库,并选中其中的“counter_tb”,即顶层测试模块,也是所要仿真的对象。选中后单击右键,选择“Simulationwithoutoptimization”后,弹出如图1-26所示的界面,在该界面中可以看到sim标签页和Wave标签页,表明仿真设置成功。(3)为了观察波形窗口,需要为该窗口添加需要观察的对象,首先,在主窗口勾选“View→debugWindows→Objects”,打开信号列表窗口如图1-27所示,在该窗口中点击“Add→ToWave→SignalsinRegion”,在波形窗口中就可以看到clk、rst和cnt信号。(4)在主窗口中输入“run1μs”后回车,表示运行仿真1μs,仿真时CPU的利用率一直为100%,如果仿真较慢,则还可以观察状态栏里的当前仿真时间。(5)仿真完成后,点击Wave标签页,可以看到仿真波形。5.功能仿真结果分析首先,给Wave窗口增加一个cnt,并将其中一个cnt设置成无符号十进制,即“unsigned”,另一个cnt设置成模拟信号输出,即“Analog”,设置界面如图1-28所示。按图1-28所示,将“Radix”设置为“unsigned”,将“Format”设置为“Analog”。设置完成后,仿真波形如图1-29所示。根据仿真结果可知,该设计实现了一个0~15的计数器。如果外加DAC器件将数字量变成模拟量,该设计则很容易产生一个锯齿波。三、结构化过程语句InitialInitial语句通常用于仿真过程中对输入信号执行一次添加激励的操作。所有在initial语句内的语句构成了一个initial块。initial块从仿真0时刻开始执行,在整个仿真过程中只执行一次。如果一个模块中包括了若干个initial块,则这些initial块从仿真0时刻开始并发执行,且每个initial块的执行是各自独立的。initial块的使用类似于always块(always语句将在“任务4.1”中进行详细描述),块内使用的语句必须是行为语句,应用于always块内的语句均可应用于initial块。在一个模块内,可同时包括若干个initial块和若干个always块,所有这些块均从仿真0时刻开始并发执行,且每个块的执行是各自独立的。如果在initial块内包含了多条行为语句,则需要将这些语句组成一组,使用关键字begin和end(或者fork和join)将它们组合为一个块语句;如果块内只有一条语句,则无须使用关键字begin和end(或者fork和join)。这一点类似于C语言中的复合语句{}。initial语句的格式如下:由于initial块语句在整个仿真期间只能执行一次,因此,它一般用于初始化、信号监视、生成仿真波形等。下面举例说明initial语句的使用。【例1-6】initial块语句举例。程序说明:(1)程序中各变量的波形图如图1-30所示。从图1-30中的仿真波形可以看出,多个initial块都是从仿真0时刻开始并发执行的。(2)程序中,一个initial语句仅对应着一个变量的赋值,使程序简洁易懂。(3)块内的语句按顺序执行,即只有上面一条语句执行完后,下面的语句才能执行。(4)每条语句的延时时间是相对于前一条语句的仿真时间而言的。(5)直到最后一条语句执行完,程序流程控制才跳出该initial语句块。(6)在仿真过程中,如果某条语句前面存在延时,那么对这条语句的仿真将会停顿下来,经过指定的延时时间之后再继续执行(可结合代码和波形图进行理解)。(7)在程序的for语句中加入延时,是为了看清楚初始化过程。(8)在VerilogHDL中,可以给每个顺序块和并行块取一个名字,只需将名字加在关键词begin或fork后面即可。这样做的原因有以下几点:①
可以在块内定义局部变量,即只在块内使用的变量,本例为变量t。②
可以允许块被其他语句调用,如被disable语句调用。③
在Verilog语言里,所有的变量都是静态的,即所有的变量都只有一个唯一的存储地址,因此,进入或跳出块并不影响存储在变量内的值。基于以上原因,块名就提供了一个可在任何仿真时刻确认变量值的方法。(9)本例中,可使用fork…join替换begin…end,读者可以学习体会两者的区别。fork…join语句块中,所有语句均是并行的,每条语句的执行时刻仅与该语句前面的延时相关,与其他语句的延时无关。(10)从本例可以看出,initial语句的用途之一,是初始化各变量;initial语句的另一用途,是用initial语句来生成激励波形作为电路的测试仿真信号,如图1-30中的x即可用作电路的激励信号。initial块常用于测试文件的编写,用来产生仿真测试信号和设置信号记录等仿真环境。四、延时仿真设计电路时,描述的电路都是无延时的。而在实际的电路中,任何一个逻辑门都具有延时,Verilog允许用户通过延时语句来说明逻辑电路中的延时。通常,在测试激励块中都需要使用延时,下面将对延时作进一步说明。信号在电路中传输会有传播延时,如线延时、器件延时等。所谓延时就是对延时特性的HDL描述,举例如下:assign#2B=A;表示B信号在2个时间单位后得到A信号的值,如图1-31所示。在VerilogHDL中,所有延时都必须根据时间单位进行定义,定义的方法是在module前添加如下语句:`timescale1ns/100ps其中,`timescale是VerilogHDL提供的编译预处理命令,1 ns表示时间单位是1 ns,100 ps表示时间精度是100ps。根据该命令,编译工具才可以认知 #2为2 ns。在VerilogHDL的IEEE标准中,没有规定时间单位的缺省值,由各仿真工具确定。因此,在编写代码时必须确定时间单位。在Verilog中,时序控制起着非常重要的作用,它使得设计者可以指定赋值发生的时刻,进而控制仿真时间的推进过程。基于延时的时序控制出现在表达式中,它指定了语句开始执行到执行完成之间的时间间隔。延时值可以是数字、标识符或表达式,但需要在延时值加上关键字 #。`timescale命令用来说明跟在该命令后的模块的时间单位和时间精度。使用`timescale命令可以在同一个设计里包含采用了不同的时间单位的模块。例如,一个设计中包含了两个模块,其中一个模块的时间延时单位为ns,另一个模块的时间延时单位为ps,EDA工具仍然可以对这个设计进行仿真测试。`timescale命令的格式如下:`timescale<时间单位>/<时间精度>在这条命令中,时间单位参量用来定义模块中仿真时间和延时时间的基准单位。时间精度参量用来声明该模块的仿真时间的精确程度,该参量被用来对延时时间值进行取整操作(仿真前),因此,该参量又被称为取整精度。如果在同一个程序设计里,存在多个`timescale命令,则用最小的时间精度值来决定仿真的时间单位。另外,时间精度要和时间单位一样精确,时间精度值不能大于时间单位值。在 `timescale命令中,用于说明时间单位和时间精度参量值的数字必须是整数,其有效数字为1、10、100,单位为秒(s)、毫秒(ms)、微秒(μs)、纳秒(ns)、皮秒(ps)等。这几种单位的意义见表1-1的说明。下面举例说明`timescale命令的用法。【例1-7】`timescale命令的用法举例。程序运行结果如图1-32所示。程序说明:(1) `timescale命令定义了模块test的时间单位为10 ns、时间精度为1 ns。在这个命令之后,模块中所有的时间值都是10 ns的倍数,并且可表达为带一位小数的实型数,这是因为 `timescale命令定义的时间精度为时间单位的1/10。(2)参数d = 1.37,根据时间精度,d的值应为1.4(四舍五入),再根据时间单位,d所代表的时间为14ns(即1.4 × 10 ns)。(3) #dset = 0;中,d为延时值,#d表示延时d秒,整个句子表达的意思是延时d秒后再将set赋值为0。延时值可以是数字、标识符或表达式,表示延时时需要在延时值前加上关键字 #。(4)本例的仿真过程为:在仿真时刻为14 ns时,寄存器set被赋值0;在仿真时刻为28ns时,寄存器set被赋值1。五、仿真常用系统函数和任务VerilogHDL语言中有以下系统函数和任务:$bitstoreal、$rtoi、$display、$setup、$finish、$skew、$hold、$setuphold、$itor、$strobe、$period、$time、$printtimescale、$timefoemat、$realtime、$width、$realtobits、$write、$recovery等。VerilogHDL语言中的每个系统函数和任务前面都应用一个标识符 $ 来加以确认。这些系统函数和任务提供了非常强大的功能,有兴趣的读者可以参阅相关书籍。下面仅对一些常用的系统函数和任务进行介绍。1.系统任务$display、$write和$strobe格式:这三个函数和系统任务的作用是用来输出信息,即将参数p2~pn按参数p1给定的格式输出。参数p1通常称为“格式控制”,参数p2~pn通常称为“输出表列”。这三个任务的作用基本相同。$display在输出后自动地进行换行,$write则不是这样,如果想在一行里输出多个信息,可以使用$write;$strobe是在同一仿真时刻的其他语句执行完成之后才执行。在$display、$write和$strobe中,其输出格式控制是用双引号括起来的字符串,它包括两种信息:格式说明和普通字符。(1)格式说明由“%”和格式字符组成,它的作用是将输出的数据转换成指定的格式输出。格式说明总是由“%”字符开始的,对于不同类型的数据用不同的格式输出。表1-2中给出了常用的几种输出格式。(2)普通字符即需要原样输出的字符。其中一些特殊的字符可以通过表1-3中的转换序列来输出。表1-3中的字符形式用于格式字符串参数中,用来显示特殊的字符。在 $display和 $write的参数列表中,其“输出表列”是需要输出的一些数据,可以是表达式。下面举几个示例进行说明。【例1-8】$display应用举例。
其输出结果如图1-33所示。程序说明:(1)使用 $display时,输出列表中数据的显示宽度是自动按照输出格式进行调整的。因此,在显示输出数据并经过格式转换以后,总是用表达式的最大可能值所占的位数来显示表达式的当前值。在用十进制数格式输出时,输出结果前面的0值用空格来代替。对于其他进制,输出结果前面的0仍然显示出来。对于一个位宽为7位的值,如按照十六进制数输出,则输出结果占2个字符的位置,如按照十进制数输出,则输出结果占3个字符的位置。这是因为这个表达式的最大可能值为7F(十六进制)或127(十进制)。因此,可以通过在%和表示进制的字符中间插入一个0,自动调整显示输出数据宽度的方式,使输出时总是用最少的位数来显示表达式的当前值。例如:$display("hex:%0h,decimal:%0d",a,a);(2)如果输出列表中表达式的值包含有不确定的值或高阻值时,其结果输出应遵循一定的规则。下面分别针对十进制、八进制/十六进制、二进制进行说明。①
在输出格式为十进制的情况下:如果表达式值的所有位均为不定值,则输出结果为小写的x。如果表达式值的所有位均为高阻值,则输出结果为小写的z。如果表达式值的部分位为不定值,则输出结果为大写的X。如果表达式值的部分位为高阻值,则输出结果为大写的Z。②
在输出格式为十六进制和八进制的情况下:每4位二进制数为一组,代表一位十六进制数;每3位二进制数为一组,代表一位八进制数。如果表达式值相对应的一位八进制(十六进制)数的所有位均为不定值,则该位八进制(十六进制)数的输出结果为小写的x。如果表达式值相对应的一位八进制(十六进制)数的所有位均为高阻值,则该位八进制(十六进制)数的输出结果为小写的z。如果表达式值相对应的一位八进制(十六进制)数的部分位为不定值,则该位八进制(十六进制)数输出结果为大写的X。如果表达式值相对应的一位八进制(十六进制)数的部分位为高阻值,则该位八进制(十六进制)数输出结果为大写的Z。③
对于二进制输出格式,表达式值的每一位的输出结果为0、1、x、z。选通显示($strobe)与 $display作用大同小异。如果许多其他语句与 $display任务在同一时刻执行,那么,这些语句与 $display任务的执行顺序是不确定的。如果使用 $strobe,该语句总是在同一时刻的其他语句执行完成之后才执行。因此,它可以确保所有在同一时刻赋值的其他语句执行完成后,才显示数据。【例1-9】$strobe应用举例。输出结果如下:#$display:val=0#$strobe:val=1程序说明:(1)由于val<=1;是非阻塞赋值,要在此仿真时刻最后才完成赋值,因此,非阻塞语句的赋值在所有的$display命令执行以后才更新数值;由于$display在val=0;语句之后,所以显示的val值,为此刻的值0。(2) $strobe语句总是在同一时刻的其他语句执行完成之后才执行,它显示val非阻塞赋值完成后的值1。因此,建议读者用$strobe系统任务来显示用非阻塞赋值的变量的值。2.系统任务 $monitor格式:任务 $monitor提供了监控和输出参数列表中的表达式或变量值的功能,其参数列表中输出控制格式字符串和输出表列的规则和 $display的一样。当启动一个带有一个或多个参数的$monitor任务时,仿真器则建立一个处理机制,使得每当参数列表中的变量或表达式的值发生变化时,整个参数列表中的变量或表达式的值都将输出显示。如果同一时刻,有多于一个的参数值发生变化,在该时刻也只输出显示一次。$monitoron和 $monitoroff任务是通过打开和关闭监控标志来控制监控任务 $monitor的启动和停止。其中,$monitoroff任务用于关闭监控标志,停止监控任务 $monitor;$monitoron用于打开监控标志,启动监控任务 $monitor。通常在调用 $monitoron启动 $monitor时,不管 $monitor参数列表中的值是否发生变化,总是立刻输出显示当前时刻参数列表中的值,这些值可用于在监控的初始时刻设定初始比较值。在缺省情况下,控制标志在仿真的起始时刻就已经打开了。在多模块调试的情况下,许多模块中都调用了 $monitor,因为任何时刻只能有一个 $monitor起作用,因此,需配合 $monitoron与 $monitoroff使用,把需要监视的模块用 $monitoron打开,在监视完毕后及时用 $monitoroff关闭,以便把 $monitor让给其他模块使用。$monitor与 $display的不同处还在于 $monitor往往在initial块中被调用,只要不调用 $monitoroff,$monitor便可不间断地对所设定的信号进行监视。3.时间度量系统函数$time在VerilogHDL中有两种类型的时间系统函数:$time和 $realtime。用这两个时间系统函数可以得到当前的仿真时刻。系统函数 $time可以返回一个用64比特整数表示的当前仿真时刻值,该时刻以模块的仿真时间尺度为基准。$realtime和 $time的作用一样,只是 $realtime返回的时间数字是一个实型数,该数字也是以仿真时间尺度为基准的。下面举例说明。【例1-10】$monitor和$time应用举例。输出结果如下:程序说明:(1)在这个例子中,模块monit设置为在时刻为14 ns时设置寄存器data为0,在时刻为28 ns时设置寄存器data为1,在42ns时设置寄存器data为0,在56 ns时设置寄存器data为1。但是,由 $time记录的data变化时刻却和预想的不一样。(2) $time显示时刻受时间尺度比例的影响。在本例中,时间单位是10 ns,因为 $time输出的时刻是时间单位的倍数,即14 ns、28 ns、42 ns和56 ns输出为1.4、2.8、4.2和5.6。又因为 $time是输出整数,所以在将经过尺度比例变换的数字输出时,需要先进行取整。在本例中,1.4、2.8、4.2和5.6经取整后为1、3、4和6。注意:时间精度并不影响数字的取整。(3)若将例子中 $monitor($time,"data=",data); 改为$monitor($realtime,"data=",data);,则输出结果如下:从输出结果可以看出,$realtime将仿真时刻经过尺度变换以后输出,不需进行取整操作。所以,$realtime返回的时刻是实型数。(4)可以使用$monitor($time,"%0tdata=%0d",$time,data); 来去掉输出中的空格,也可以在格式符中使用具体的数值来规定输出占据的位宽。若读者想了解更多格式符的使用方法,可自行查阅相关资料。4.系统任务$finish和$stop1) $finish格式:系统任务$finish的作用是退出仿真器,返回主操作系统,也就是结束仿真过程。任务$finish可以带参数,根据参数的值输出不同的特征信息。如果不带参数,则默认$finish的参数值为1。下面给出了对于不同的参数值,系统输出的特征信息:0表示不输出任何信息;1表示输出当前仿真时刻和位置;2表示输出当前仿真时刻、位置和在仿真过程中所用memory及CPU时间的统计。2) $stop格式:$stop任务的作用是把EDA仿真器设置成暂停模式,在仿真环境下给出一个交互式的命令提示符,将控制权交给用户。这个任务可以带有参数表达式,根据参数值(0,1或2)的不同,输出不同的信息,参数值越大,输出的信息越多。5.系统任务$readmemb和$readmemh在VerilogHDL程序中有两个系统任务$readmemb和$readmemh,用来从文件中读取数据到存储器中。这两个系统任务可以在仿真的任何时刻执行使用,其共有以下六种使用格式:(1) $readmemb("<数据文件名>",<存储器名>);(2) $readmemb("<数据文件名>",<存储器名>,<起始地址>);(3) $readmemb("<数据文件名>",<存储器名>,<起始地址>,<结束地址>);(4) $readmemh("<数据文件名>",<存储器名>);(5) $readmemh("<数据文件名>",<存储器名>,<起始地址>);(6) $readmemh("<数据文件名>",<存储器名>,<起始地址>,<结束地址>);规则如下:(1)第一个变量是一个ASCII文件的名字,这个文件可以只包含空白位置(空格、换行、制表格tab和form-feeds)、Verilog注释(//形式的和/*…*/形式的都允许)、hex地址值以及二进制或十六进制数字。数字中不能包含位宽说明和格式说明,对于$readmemb系统任务,每个数字必须是二进制数字;对于$readmemh系统任务,每个数字必须是十六进制数字。数据值必须和存储器数组的宽度相同,而且用空白分隔。(2)第二个变量是存储器数组的名字。(3)当数据文件被读取时,每一个被读取的数字都被存放到地址连续的存储器单元中。存储器单元的存放地址范围由系统任务声明语句中的起始地址和结束地址来说明,每个数据的存放地址在数据文件中进行说明。(4)地址值是带前缀@的十六进制且允许大写和小写的数字。在字符“@”和数字之间不允许存在空白位置。可以在数据文件里出现多个地址。当系统任务遇到一个地址说明时,系统任务将该地址后的数据存放到存储器中相应的地址单元中。下面举例说明系统任务$readmemb和$readmemh的应用。【例1-11】
系统任务$readmemb和$readmemh应用举例。程序使用的文件“Mem.txt”如图1-34所示。程序运行结果如图1-35所示。关于系统任务 $readmemb和 $readmemh的进一步说明:(1)如果系统任务声明语句和数据文件中都没有进行地址说明,则缺省的存放起始地址为该存储器定义语句中的起始地址。数据文件里的数据被连续存放在该存储器中,直到该存储器单元存满或数据文件里的数据存完为止。(2)如果系统任务中说明了存放的起始地址,没有说明存放的结束地址,则数据从起始地址开始存放,存放到该存储器定义语句中的结束地址为止。(3)如果在系统任务声明语句中,起始地址和结束地址都进行了说明,则数据文件里的数据按该起始地址开始存放到存储器单元中,直到该结束地址,而不考虑该存储器的定义语句中的起始地址和结束地址。(4)如果地址信息在系统任务和数据文件里都进行了说明,那么数据文件里的地址必须在系统任务中地址参数声明的范围之内。否则将提示错误信息,并且装载数据到存储器中的操作被中断。(5)如果数据文件里的数据个数和系统任务中起始地址及结束地址暗示的数据个数不相同,会提示错误信息。6.系统任务 $fopen和 $fclose$fopen是打开一个文件进行写操作的系统函数,用 $fdisplay、$fmonitor等系统任务将文本写入到文件。$fclose是关闭一个文件的系统任
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 提高成绩的复习策略试题及答案
- 2024年高校辅导员招聘考试试题及答案全景图
- 农业职业经理人要知道的事试题及答案
- 2024年农业职业经理人考试重点提示试题及答案
- 2024年农艺师考试不同阶段的心理调节技巧试题及答案
- 启动工作计划福建事业单位考试试题及答案
- 福建事业单位考试的结构性思维培养与应用试题及答案
- 农业职业经理人与政策导向试题及答案
- 晓师附小面试题及答案
- 规律掌握园艺师考试内容试题及答案
- 《上一堂朴素的语文课》读书交流1
- 建筑工程屋面及防水工程施工技术培训讲义
- 企业管理与领导力的战略与实践
- 工程经济与项目管理(慕课版)
- 宗亲会活动方案
- 测绘生产成本费用定额2022
- 阴道裂伤的健康宣教
- 某国企2023年度经营管理工作总结和2024年工作思路
- 大于号小于号等于号田字格描红
- 摄影个人作品集
- 大学军事理论课教程第四章现代战争第二节 新军事革命
评论
0/150
提交评论