EDA原理及应用课件

上传人:博****1 文档编号:567490497 上传时间:2024-07-20 格式:PPT 页数:262 大小:570.02KB
返回 下载 相关 举报
EDA原理及应用课件_第1页
第1页 / 共262页
EDA原理及应用课件_第2页
第2页 / 共262页
EDA原理及应用课件_第3页
第3页 / 共262页
EDA原理及应用课件_第4页
第4页 / 共262页
EDA原理及应用课件_第5页
第5页 / 共262页
点击查看更多>>
资源描述

《EDA原理及应用课件》由会员分享,可在线阅读,更多相关《EDA原理及应用课件(262页珍藏版)》请在金锄头文库上搜索。

1、EDA原理及应用原理及应用马冬梅2019.1.17 内容:内容: 一、EDA设计导论 二、可编程逻辑器件设计方法 三、Verilog HDL语言基础 EDA技术综述;EDA技术发展历史EDA技术涵义EDA技术主要内容PLD设计方法学;PLD设计概论PLD设计流程SOPC设计流程HDL硬件描述语言HDL硬件描述语言概念HDL语言特点和比较HDL语言最新发展一、EDA设计导论 EDA技术随着计算机、集成电路、电子系统设计的发展,经历了三个发展阶段: 1、计算机辅助设计(CAD) 2、计算机辅助工程设计(CAE) 3、电子设计自动化(EDA)EDA技术发展历史1、计算机辅助设计(CAD)硬件设计发展

2、的初级阶段。在此阶段,大量选用中小规模标准集成电路,将产品设计过程中高度重复性的布图布线工作,采用二维图形编辑与分析的CAD工具。由于PCB布图布线工具受到计算机工作平台的制约,其支持的设计工作有限且性能比较差。2、计算机辅助工程(CAE) 采用少数几种通用的标准芯片实现电子系统的设计。 CAE阶段的EDA工具已经可以进行设计描述、综合与优化和设计结果验证。但是,大部分从原理图出发的EDA工具仍然不能适应复杂电子系统的设计要求,而具体化的元件图形制约着优化设计。3、电子系统设计自动化阶段各种规模的可编程逻辑器件和EDA工具的发展,通过一些简单标准化的设计过程,利用微电子厂家提供的设计库来完成数

3、万门ASIC和集成系统的设计与验证。在此阶段,硬件描述语言HDL的出现使得EDA设计进入到抽象描述的设计层次。现在,EDA设计进入了片上系统设计SOPC(System On Programmable Chip)阶段,可编程逻辑器件内集成了数字信号处理器的内核、微处理器的内核等,使得可编程逻辑器件不再只是完成复杂的逻辑功能,而是具有了强大的信号处理和控制功能。 EDA技术包括狭义EDA技术和广义EDA技术。狭义EDA技术指以大规模可编程逻辑器件为设计载体,以硬件描述语言为系统逻辑描述的主要表达方式,以计算机、大规模可编程逻辑器件的开发软件及实验开发系统为设计工具,通过有关的开发软件,自动完成用软

4、件方式设计的电子系统到硬件系统的逻辑编译、逻辑化简、逻辑分割、逻辑综合及优化、逻辑布局布线、逻辑仿真,直至对于特定目标芯片的适配编译、逻辑映射、编程下载等工作,最终形成集成电子系统或专用集成芯片的技术,或称为IES/ASIC自动设计技术。EDA技术含义广义EDA技术,是通过计算机及其电子系统的辅助分析和设计软件,完成电子系统某一部分的设计过程。因此,广义EDA技术除了包含狭义的EDA技术外,还包括计算机辅助分析CAA技术(如PSPICE,EWB,MATLAB等),印刷电路板计算机辅助设计PCB-CAD技术(如PROTEL,ORCAD等)和其它高频和射频设计和分析的工具等。EDA技术的共同特点:

5、1、通过使用相应的电路分析和设计软件,完成电子系统各部分的设计;2、在电子系统设计中所使用的EDA软件基本都符合自顶向下的设计流程的理念;3、使用EDA软件设计电子系统,都需要分工设计,团体协作;4、使用EDA软件设计电子系统,提高了设计的效率,缩短了设计周期;5、使用EDA软件设计电子系统,采用了模块化和层次化的设计方法;6、大多数EDA软件都具有仿真和模拟功能;基于狭义EDA技术进行可编程逻辑器件的设计应掌握以下几个方面的内容:、大规模可编程逻辑器件PLD,是利用EDA技术进行电子系统设计的载体;、硬件描述语言HDL,是利用EDA技术进行电子系统设计的主要表达手段;、EDA设计软件EDAS

6、:是利用EDA技术进行电子系统设计的自动化设计工具;、相关的硬件平台,是利用EDA技术进行电子系统设计的下载工具及硬件验证工具;EDA技术的主要内容、大规模可编程逻辑器件PLDPLD器件一般包含现场可编程门阵列(FPGA)和复杂可编程逻辑器件(CPLD)。由于EDA开发工具的通用性、设计语言的标准化以及设计过程几乎与所用器件的硬件结构无关,因而设计开发成功的各类逻辑功能块软件有很好的兼容性和可移植性。与ASIC设计相比,PLD显著的优势是开发周期短、投资风险小、产品上市速度快、市场适应能力强和硬件升级回旋余地大,而且当产品定型和产量扩大后,可将在生产中达到充分检验的VHDL设计迅速实现ASIC

7、投产。2、硬件描述语言常用硬件描述语言有VHDL、Verilog和ABEL语言。下面从使用方面对这三种语言进行简要的对比:(1)逻辑描述层次:一般的硬件描述语言可以在三个层次上进行电路描述,其层次由高到低依次可分为行为级、寄存器传输级RTL和门电路级。VHDL语言是一种高级描述语言,适用于行为级和RTL级的描述,最适于描述电路的行为;Verilog语言和ABEL语言是一种较低级的描述语言,适用于RTL级和门电路级的描述,最适于描述门级电路。(2)设计要求:VHDL进行电子系统设计时可以不了解电路的结构细节,Verilog和ABEL语言进行电子系统设计时需了解电路的结构细节。(3)综合过程:任何

8、一种语言源程序,最终都要转换成门电路级才能被布线器或适配器所接受。因此,VHDL语言源程序的综合要经过行为级RTL级门电路级的转化,VHDL几乎不能直接控制门电路的生成。而Verilog语言和ABEL语言源程序的综合过程只经过RTL级门电路级的转化,易于控制电路资源。(4)对综合器的要求:VHDL描述语言层次较高,不易控制底层电路,因而对综合器的性能要求较高,Verilog和ABEL对综合器的性能要求较低。(5)支持的EDA工具:支持VHDL和Verilog的EDA工具很多,但支持ABEL的综合器仅仅Dataio一家。(6)国际化程度:VHDL和Verilog已成为IEEE标准,而ABEL正朝

9、国际化标准努力。现在,VHDL与Verilog语言将承担几乎全部的数字系统设计任务。3、软件开发工具基于高复杂度PLD器件的开发,在很大程度上依靠EDA软件完成。PLD的EDA工具以计算机软件为主,将典型的单元电路封装起来形成固定模块并形成标准的硬件开发语言(如HDL语言)供设计人员使用。PLD开发软件需要自动地完成逻辑编译、化简、分割、综合及优化、布局布线、仿真以及对于特定目标芯片的适配编译和编程下载等工作。典型的EDA工具中必须包含两个特殊的软件包,即综合器和适配器。综合器的功能就是将设计者在EDA平台上完成的针对某个系统项目的HDL、原理图或状态图形描述,针对给定的硬件系统组件,进行编译

10、、优化、转换和综合。、硬件开发平台硬件开发平台提供芯片下载电路及EDA实验/开发的外围资源,以供硬件验证。硬件开发平台一般包括:)实验或开发所需的各类基本信号发生模块,包括时钟、脉冲、高低电平等;)PLD输出信息显示模块,包括数码显示、发光管显示、声响指示等;)监控程序模块,提供“电路重构软配置”;)目标芯片适配座以及上面的FPGA/CPLD目标芯片和编程下载电路。 传统上的设计方法是自下而上的设计方法,是以固定功能元件为基础,基于电路板的设计方法。这种设计方法有下面的缺点:设计依赖于设计人员的经验。设计依赖于通用元器件。设计后期的仿真不易实现,并且调试复杂。设计实现周期长,灵活性差,耗时耗力

11、,效率低下。 系统调试、测试与性能分析完整系统构成电路板设计固定功能元件系统功能需求传统设计方法PLD设计方法学设计目标设计目标设计输入设计输入功能级仿真功能级仿真网表转换、映射、布局布线(网表转换、映射、布局布线(CPLDCPLD为适配)为适配)时序仿真时序仿真系统验证系统验证系统产品系统产品原理图输入,文本输入(包括器件选择、元件库的建立、原理图或状态机设计、VHDL语言设计)网表转换、映射、布局布线、产生时序数据、产生配置文件配置文件加载后,用示波器、逻辑分析仪、软件程序观察FPGA开发的一般流程开发的一般流程综合优化综合优化行为仿真行为仿真生成网表文件PLD设计流程1、设计目标在系统设

12、计之前,首先要进行的是方案论证、系统设计和FPGA芯片选择等准备工作。根据任务要求,如系统的指标和复杂度,对工作速度和芯片本身的各种资源、成本等方面进行权衡,选择合理的设计方案和合适的器件类型。一般都采用自顶向下的设计方法,把系统分成若干个基本单元,然后再把每个基本单元划分为下一层次的基本单元,直到可以直接使用EDA元件库为止。 PLD设计流程2、设计输入 设计输入是将所设计的系统或电路以开发软件要求的某种形式表示出来,并输入EDA工具的过程。常用的方法有硬件描述语言(HDL)和原理图输入方法等。原理图输入方式是一种最直接的描述方式,在可编程芯片发展的早期应用较广,它将所需的器件从元件库中调出

13、来,画出原理图。这种方法虽然直观并易于仿真,但效率低,且不易维护。更主要的缺点是可移植性差。HDL语言输入法利用文本描述设计,主要使用行为级HDL,其主流语言是Verilog HDL和VHDL。3、功能仿真 功能仿真也称为前仿真,是在编译之前对用户所设计的电路进行逻辑功能验证,此时的仿真没有延迟信息,仅对初步的功能进行检测。仿真前,要先利用波形编辑器和HDL等建立波形文件和测试向量(即将所关心的输入信号组合成序列),仿真结果将会生成报告文件和输出信号波形,从中便可以观察各个节点信号的变化。如果发现错误,则返回设计修改逻辑设计。常用的工具有Model Tech公司的ModelSim、Sysnop

14、sys公司的VCS和Cadence公司的NC-Verilog, 以及NC-VHDL等软件。 4、综合优化 所谓综合就是将较高级抽象层次的描述转化成较低层次的描述。综合优化根据目标与要求优化所生成的逻辑连接,使层次设计平面化,供FPGA布局布线软件进行实现。综合优化是指将设计输入编译成由与门、或门、非门、RAM、触发器等基本逻辑单元组成的逻辑连接网表,而并非真实的门级电路。真实具体的门级电路需要利用FPGA制造商的布局布线功能,根据综合后生成的标准门级结构网表来产生。由于门级结构、RTL级的HDL程序的综合是很成熟的技术,所有的综合器都可以支持到这一级别的综合。 常用的综合工具有Synplici

15、ty公司Synplify/ Synplify Pro软件以及各个FPGA厂家自己推出的综合开发工具。 5、综合后仿真 综合后仿真检查综合结果是否和原设计一致。在仿真时,把综合生成的标准延时文件反标注到综合仿真模型中去,可估计门延时带来的影响。但这一步骤不能估计线延时,因此和布线后的实际情况还有一定的差距,并不十分准确。目前的综合工具较为成熟,对于一般的设计可以省略这一步,但如果在布局布线后发现电路结构和设计意图不符,则需要回溯到综合后仿真来确认问题之所在。在功能仿真中介绍的软件工具一般都支持综合后仿真。6、实现与布局布线 将综合生成的逻辑网表配置到具体的FPGA芯片上,布局布线是其中最重要的过

16、程。布局将逻辑网表中的硬件原语和底层单元合理地配置到芯片内部的固有硬件结构上,并且往往需要在速度最优和面积最优之间作出选择。布线根据布局的拓扑结构,利用芯片内部的各种连线资源,合理正确地连接各个元件。布线结束后,软件工具会自动生成报告,提供有关设计中各部分资源的使用情况。 由于只有FPGA芯片生产商对芯片结构最为了解,所以布局布线必须选择芯片开发商提供的工具。7、时序仿真也称为后仿真,是指将布局布线的延时信息反标注到设计网表中来检测有无时序违规(即不满足时序约束条件或器件固有的时序规则,如建立时间、保持时间等)现象。时序仿真包含的延迟信息最全,也最精确,能较好地反映芯片的实际工作情况。由于不同

17、芯片的内部延时不一样,不同的布局布线方案也给延时带来不同的影响。因此在布局布线后,通过对系统和各个模块进行时序仿真,分析其时序关系,估计系统性能,以及检查和消除竞争冒险是非常有必要的。在功能仿真中介绍的软件工具一般都支持综合后仿真。 8、板级仿真与验证 板级仿真主要应用于高速电路设计中,对高速系统的信号完整性、电磁干扰等特征进行分析,一般都以第三方工具进行仿真和验证。 9、芯片编程与调试 设计的最后一步就是芯片编程与调试。芯片编程是指产生使用的数据文件,然后将编程数据下载到FPGA芯片中。 其中,芯片编程需要满足一定的条件,如编程电压、编程时序和编程算法等方面。目前,主流的FPGA芯片生产商都

18、提供了内嵌的在线逻辑分析仪来解决上述矛盾,它们只需要占用芯片少量的逻辑资源,具有很高的实用价值。 硬件描述语言(Hardware Description Language)是硬件设计人员和电子设计自动化(EDA)工具之间的界面,其主要目的是用来编写设计文件,建立电子系统行为级的仿真模型。即利用计算机的巨大能力对Verilog HDL或VHDL建模的复杂数字逻辑进行仿真,然后再自动综合,生成符合要求且在电路结构上可以实现的数字逻辑网表(Netlist),根据网表和某种工艺的器件自动生成具体电路,最后生成该工艺条件下这种具体电路的时延模型。仿真验证无误后,该模型可用于制造ASIC芯片或写入CPLD

19、和FPGA器件中。HDL硬件描述语言 在HDL语言出现之前,已有了许多程序设计语言,如汇编、C、Pascal、Fortran、Prolog等。它们适合于描述过程和算法,不适合作硬件描述。在使用EDA工具进行电子系统设计时,就需要一种硬件描述语言来作为EDA工具的工作语言。因此,众多的EDA工具软件开发者相继推出了自己的HDL语言。HDL硬件描述语言概念 在HDL语言的发展过程中,美国国防部起了非常重要的作用。美国国防部电子系统项目有众多的承包公司,他们使用各自的HDL语言,造成了信息交换困难和维护困难。美国政府为了降低开发费用,避免重复设计,国防部为他们的超高速集成电路提供了一种硬件描述语言,

20、以期望VHDL功能强大、严格、可读性好。政府要求各公司的合同都用它来描述,以避免产生歧义。HDL语言的特点主要体现在以下几个方面:1、HDL语言既包含一些高层程序设计语言的结构形式,同时也兼顾描述硬件线路连接的具体构件。、HDL语言是并发的,即具有在同一时刻执行多任务的能力。一般来讲编程语言是非并行的,但在实际硬件中许多操作都是在同一时刻发生的,所以HDL语言具有并发的特征。、HDL语言有时序的概念。一般来讲,编程语言是没有时序概念的,但在硬件电路中从输入到输出总是有延迟存在的,为描述这些特征,HDL语言需要建立时序的概念。 因此,使用HDL除了可以描述硬件电路的功能外,还可以描述其时序要求。

21、HDL语言特点和比较、通过使用结构级或行为级描述可以在不同的抽象层次描述设计,HDL语言采用自顶向下的数字电路设计方法,主要包括3个领域5个抽象层次,如下表所示:行为领域结构领域物理领域系统级性能描述部件及它们之间的逻辑连接方式芯片、模块、电路板和物理划分的子系统算法级I/O应答算法级硬件模块数据结构部件之间的物理连接、电路板、底盘等寄存器传输级并行操作寄存器传输、状态表算术运算部件、多路选择器、寄存器总线、微定序器、微存储器之间的物理连接方式芯片、宏单元逻辑级用布尔方程叙述门电路、触发器、锁存器标准单元布图电路级微分方程表达晶体管、电阻、电容、电感元件晶体管布图总的来说,它们有以下几点不同:

22、、VHDL偏重于标准化的考虑,Verilog HDL则和EDA工具结合得更为紧密。VHDL是为了实现美国国防部VHSIC计划所推出的各个电子部件供应商具有统一数据交换格式标准的要求。Verilog HDL是在全球最大的EDA/ESDA供应商Cadence公司的支持下针对EDA工具专门开发的硬件描述语言。、Verilog HDL拥有广泛的设计群体,成熟的资源远比VHDL丰富。同时Verilog HDL是从高级设计语言C语言发展而来的,比VHDL而言更容易上手,其编码风格也更为简洁明了,是一种非常容易掌握的硬件描述语言。Verilog和VHDL比较、Verilog HDL和VHDL在行为级抽象建模

23、的覆盖范围方面也有所不同。一般认为Verilog HDL在系统抽象方面比VHDL要强一些,Verilog HDL比较适合算法级(Algorithm)、寄存器传输级(RTL)、逻辑级(Logic)以及门级(Gate)的设计,而VHDL更适合特大型系统级(System)的设计。目前对于一个系统芯片设计项目,可以采用的方案包括以下几种: 1、在系统级采用VHDL,在软件级采用C语言,在实现级采用Verilog。目前,软件与硬件的协调设计还是一个很具挑战性的工作,因为软件越来越成为SoC设计的关键。该方案的特点是:风险小,集成难度大,与原有方法完全兼容,有现成的开发工具,但工具集成由开发者自行负责完成

24、。、系统级及软件级采用Superlog,硬件级和实现级均采用Verilog HDL描述,这样和原有的硬件设计可以兼容。该方案特点是风险较小,易于集成,与原硬件设计兼容性好,有集成开发环境。HDL语言最新发展3、系统级和软件级采用SystemC,硬件级采用Verilog HDL,SystemC与常规的Verilog HDL互相转换,与原来的软件编译环境完全兼容。开发者只需要一组描述类库和一个包含仿真核的库,就可以在通常ANSI C+编译环境下开发,但硬件描述与原有方法完全不兼容。该方法特点是风险较大,与原软件开发兼容性好,硬件开发有风险。 IC(Integrated Circuit)设计方法一般

25、分为6类: 1、全定制法:如ROM,RAM或PLA等; 2、定制法:通常包括标准单元和通用单元; 3、半定制法:通常包括数字电路门阵列和线性阵列; 4、模块编译法:对设计模块进行描述,然后通过编译直接得到电路掩膜版图; 5、可编程逻辑器件法:通常是指PAL、PLA、GAL器件和CPLD器件; 6、逻辑单元阵列法:通常是指现场可编程门阵列FPGA器件。二、可编程逻辑器件设计方法 可编程逻辑器件(Programmable Logic Device,PLD)起源于20世纪70年代,是在专用集成电路(ASIC)的基础上发展起来的一种数字系统设计的主要硬件平台。 其主要特点: 1、由用户通过软件进行配置

26、和编程,从而完成某种特定的功能,且可以反复擦写; 2、在修改和升级PLD时,不需额外地改变PCB电路板,只是在计算机上修改和更新程序,使硬件设工作成为软件开发工作,缩短了系统设计的周期,提高了实现的灵活性并降低了成本。可编程逻辑器件概述PLD器件包括4种基本类型:编程只读存储器(Programmable Read Only Memory,PROM);现场可编程逻辑阵列(Field Programmable Logic Array,FPLA);可编程阵列逻辑(Programmable Array Logic,PAL);通用阵列逻辑(Generic Array Logic,GAL);按照颗粒度可以

27、分为3类:小颗粒度(“门海(sea of gates)”架构)中等颗粒度(如:FPGA)大颗粒度(如:CPLD)PLD产品分类按编程工艺可以分为四类:熔丝(Fuse)和反熔丝(Antifuse)编程器件可擦除的可编程只读存储器(UEPROM)编程器件电信号可擦除的可编程只读存储器(EEPROM)编程器件SRAM编程器件。 前3类为非易失性器件,编程后,配置数据保留在器件上;第4类为易失性器件,掉电后配置数据会丢失,因此在每次上电后需要重新进行数据配置。可编程逻辑器件的发展可以划分为4个阶段:第1阶段的可编程器件只有简单的可编程只读存储器(PROM)、紫外线可擦除只读存储器(EPROM)和电可擦

28、只读存储器(EEPROM)3种,由于结构的限制,只能完成简单的数字逻辑功能。第2阶段出现了结构上稍微复杂的可编程阵列逻辑(PAL)和通用阵列逻辑(GAL)器件,正式被称为PLD,能够完成各种逻辑运算功能。典型的PLD由“与”、“非”阵列组成,用“与或”表达式来实现任意组合逻辑,所以PLD能以乘积和形式完成大量的逻辑组合。可编程逻辑器件的发展历史第3阶段Xilinx和Altera分别推出了与标准门阵列类似的FPGA和类似于PAL结构的扩展性CPLD,提高了逻辑运算的速度,具有体系结构和逻辑单元灵活、集成度高以及适用范围宽等特点,兼容了PLD和通用门阵列的优点,能够实现超大规模的电路,编程方式也很

29、灵活,成为产品原型设计和中小规模(一般小于10000)产品生产的首选。第4阶段出现了SOPC和SOC技术,是PLD和ASIC技术融合的结果,涵盖了实时化数字信号处理技术、高速数据收发器、复杂计算以及嵌入式系统设计技术的全部内容。超越了ASIC器件的性能和规模,也超越了传统意义上FPGA的概念,使PLD的应用范围从单片扩展到系统级。CPLD更适合完成各种算法和组合逻辑,FPGA更适合于完成时序逻辑。换句话说, FPGA更适合于触发器丰富的结构,而CPLD更适合于触发器有限而乘积项丰富的结构。CPLD的连续式布线结构决定了它的时序延迟是均匀的和可预测的,而FPGA的分段式布线结构决定了其延迟的不可

30、预测性。在编程上FPGA比CPLD具有更大的灵活性。CPLD通过修改具有固定内连电路的逻辑功能来编程,FPGA主要通过改变内部连线的布线来编程;FPGA可在逻辑门下编程,而CPLD是在逻辑块下编程。CPLD和FPGA的比较FPGA的集成度比CPLD高,具有更复杂的布线结构和逻辑实现。CPLD比FPGA使用起来更方便。CPLD的编程采用E2PROM或FASTFLAS技术,无需外部存储器芯片,使用简单。而FPGA的编程信息需存放在外部存储器上,使用方法复杂。CPLD的速度比FPGA快,并且具有较大的时间可预测性。这是由于FPGA是门级编程,并且CLB(可配置逻辑模块 Configurable Lo

31、gic Block)之间采用分布式互联,而CPLD是逻辑块级编程,并且其逻辑块之间的互联是集总式的。在编程方式上,CPLD主要是基于E2PROM或FLASH存储器编程,编程次数可达1万次,优点是系统断电时编程信息也不丢失。CPLD又可分为在编程器上编程和在系统编程两类。FPGA大部分是基于SRAM编程,编程信息在系统断电时丢失,每次上电时,需从器件外部将编程。数据重新写入SRAM中。其优点是可以编程任意次,可在工作中快速编程,从而实现板级和系统级的动态配置。 CPLD保密性好,FPGA保密性差。 一般情况下,CPLD的功耗要比FPGA大,且集成度越高越明显。Verilog HDL语言基础 Ve

32、rilog语言概述Verilog HDL(以下简称Verilog)是一种硬件描述语言,用于从算法级、门级到开关级的多种抽象设计层次的数字系统建模。Verilog HDL语言具有下述描述能力:设计的行为特性:使用过程化结构建模设计的数据流特性:使用连续赋值语句方式建模设计的结构组成:使用门和模块实例语句建模包含响应监控和设计验证方面的时延和波形产生机制。Verilog HDL语言提供了编程语言接口,通过该接口可以在模拟、验证期间从设计外部访问设计,包括模拟的具体控制和运行。Verilog 语言从C编程语言中继承了多种操作符和结构。并提供了扩展的建模能力。Verilog语言是IEEE标准,为IEE

33、E Std13642019。Verilog硬件描述语言的主要功能包括:基本逻辑门,如and、or和nand等内置在语言中。用户定义原语(UDP)创建的灵活性。用户定义的原语既可以是组合逻辑原语,也可以是时序逻辑原语。开关级基本结构模型,例如pmos和nmos等也内置在语言中。提供显式语言结构指定设计中的端口到端口的时延及路径时延和设计的时序检查。可采用三种不同方式或混合方式对设计建模:行为描述方式使用过程化结构建模;数据流方式使用连续赋值语句方式建模;结构化方式使用门和模块实例语句描述建模。Verilog HDL硬件描述语言功能Verilog HDL中有两类数据类型:网络类型表示构件间的物理连

34、线寄存器类型表示抽象的数据存储元件能够描述层次设计,可使用模块实例结构描述任何层次。设计的规模可以是任意的,语言不对设计的规模(大小)施加任何限制。Verilog HDL语言的描述能力能够通过使用编程语言接口(PLI)机制进一步扩展。PLI是允许外部函数访问Verilog模块内信息、允许设计者与模拟器交互的例程集合。人和机器都可阅读Verilog 语言,因此可作为EDA工具和设计者之间的交互语言。设计能够在多个层次上加以描述,从开关级、门级、寄存器传送级(RTL)到算法级,包括进程和队列级。能够使用内置开关级原语在开关级对设计完整建模。同一语言可用于生成模拟激励和指定测试的验证约束条件,例如输

35、入值的指定。Verilog HDL能够监控模拟验证的执行,即模拟验证执行过程中设计的值能够被监控和显示。这些值也能够用于与期望值比较,在不匹配的情况下,打印报告消息。一个复杂电路系统的完整Verilog HDL模型是由若干个Verilog HDL模块构成的,每一个模块又可以由若干个子模块构成。Verilog使用大约100个预定义的关键词定义该语言的结构。用Verilog 描述的电路设计就是该电路的 Verilog 模型,也称为模块,是Verilog的基本描述单位。一般来说一个模块可以是一个元件或者是一个更低层设计模块的集合。模块是并行运行的,通常需要一个高层模块通过调用其他模块的实例来定义一个

36、封闭的系统,包括测试数据和硬件描述。Verilog程序结构Verilog模块结构module 模块名(端口列表); endmodule 端口定义 input 输入端口 output 输出端口 inout 输入/输出端口 数据类型说明 wire reg parameter 逻辑功能定义 assign always function task .Verilog结构位于module和endmodule声明语句之间,每个Verilog程序包括端口定义、数据类型说明和逻辑功能定义部分。是模块唯一的标识符;是由模块各个输入、输出和双向端口组成,这些端口用来与其他模块进行通信;数据类型说明部分用来指定模块内

37、用到的数据对象为寄存器型、存储器型还是连线型;逻辑功能定义部分通过使用逻辑功能语句来实现具体的逻辑功能。每个Verilog 程序源文件都以.v作为文件扩展名;Verilog HDL区分大小写,每条语句以分号结束,endmodule语句后不加分号。白空(新行、制表符和空格)没有特殊意义。模块声明包括模块名字,模块的输入,输出端口类表。模块的定义格式如下:module (port_name1,port_namen);. endmodule; 其中: module_name为模块名,是该模块的唯一标识。port_name为端口名,这些端口名使用“,”分割。端口是模块与外部其它模块进行信号传递的通道(

38、信号线),模块端口分为输入、输出或双向端口。端口的定义格式为: input , .;input为关键字,用于声明后面的端口为输入口;input_port_name为输入端口名字;other_inputs为用逗号分割的其它输入端口的名字; output ,.;output为关键字,用于声明后面的端口为输出端口;output_port_name为输出端口名字;other_outputs为逗号分割的其它输出端口的名字; inout ,.;inout为关键字,用于声明后面端口为输入/输出类型;other_inouts为输入/输出端口的名字;other_inouts为逗号分割的其它输入/输出端口的名字;

39、在声明输入/输出时,还要声明其数据类型;默认的端口类型为wire类型。输入和双向端口不能声明为寄存器型。【例例3.1】端口说明实例module addr(cout,sum,ina,inb,cin)input cin;input7:0 ina,inb;output7:0 sum;output cout;endmodule注意,在verilog中,也可以使用ANSI C风格进行端口声明。可避免端口名在端口列表和端口声明语句中的重复。如果声明中未指明端口的数据类型,那么默认端口具有wire数据类型。【例例3.2】 ANSI C风格的端口说明实例 module fulladd4(output reg3

40、:0 sum, output reg c_out, input3:0 a,b, input c_in); endmodule 对模块中所用到的所有信号(包括端口信号)都必须进行数据类型的定义。Verilog HDL语言提供了各种信号类型,分别模拟实际电路中的各种物理连接和物理实体。【例例3.3】信号类型声明 reg cout; /定义信号cout的数据类型为reg reg7:0 out; /定义信号out的数据类型为8位reg wire A,B,C,D,F /定义信号A,B,C,D,F为wire(连线)型 信号类型声明 逻辑功能定义用于实现模块中的具体的功能。主要的方法有:赋值语句实现逻辑定义

41、:用assign赋值语句【例例3.4】assign F=(A&B)|(C&D);模块调用:指从模块模板生成实际的电路结构对象的操作,这样的电路结构对象被称为模块实例,模块调用也被称为实例化。一个Verilog模块可以被任意多个其他模块调用。在Verilog 语言中,模块不能被嵌套定义,但是却可以包含其他模块的拷贝,即调用其他模块的实例。模块的定义和模块的实例是两个不同的概念,在一个设计中,只有通过模块调用(实例化)才能使用一个模块。逻辑功能定义always过程赋值:always块经常用来描述逻辑功能,实现时序逻辑电路。【例例3.5】always过程实现计数器的过程。 always (posed

42、ge clk) /正沿触发 begin if(reset) out=0; else out=out+1; end函数和任务调用:模块调用和函数调用非常相似,但是在本质上又有很大差别:一个模块代表拥有特定功能的一个电路块,每当一个模块在其他模块内被调用一次,被调用模块所表示的电路结构就会在调用模块代表的电路内部被复制一次(即生成被调用模块的一个实例);但是模块调用不能像函数调用一样具有“退出调用”的操作,因为硬件电路结构不会随着时间而发生变化,被复制的电路块将一直存在。Verilog语言要素 注释,在Verilog HDL中有两种格式的注释:/*第一种形式:可以扩展至多行* / /第二种形式:在

43、本行结束。间隔符:包括空格字符(b)、制表符(t)、换行符(n)以及换页符。标识符:Verilog HDL中的标识符(identifier)可以是任意一组字母、数字、$符号和_(下划线)符号的组合。标识符的第一个字符必须是字母或者下划线。另外,标识符是区分大小写的。关键字:所有的关键字都使用小写字母。运算符:Verilog提供了丰富的运算符。 Verilog常量Verilog HDL中有三类常量:整型;实数型;字符串型。整数型常量可以按如下两种方式描述:简单的十进制格式 +32 十进制数32 -15 十进制数-15基数表示法:;:定义以位计的常量的位长;:单引号是指定位宽格式表示法的固有字符,

44、不能省略。:是基于base的值的数字序列,由相应基数格式的数字串组成。值x和z以及十六进制中的a到f不区分大小写。【例例3.6】下面给出基数表示的具体实例。 5O37 5位八进制数 4D2 4位十进制数 4B1x_01 4位二进制数 7Hx 7位x(扩展的x),即xxxxxxx 4hZ 4位z(扩展的z),即zzzz 4d-4 非法,数值不能为负 8 h 2A 8位十六进制数 3 b001 非法,和基数b之间不允许出现空格 (2+3)b10 非法,位长不能够为表达式整数型常量【例例3.7】采用不同基数表示的例子 o721 9位八进制数 hAF 8位十六进制数【例例3.8】补零填充的例子 10b

45、10,左边添0占位,0000000010 10bx0x1,左边添x占位, xxxxxxx0x1【例例3.9】数据被截断的例子 3b1001_0011与3b011相等 5H0FFF与5H1F相等实数可以用下列两种形式描述:十进制计数法【例例3.10】十进制计数法表示实数常量的例子 2.0,5.678,11572.12,0.1 2.为非法,因为小数点两侧必须要有1位数字科学计数法【例例3.11】科学计数法表示实数常量的例子 23_5.1e2其值为23510.0;忽略下划线 3.6E2其值为360.0e(与E相同) 5E-4其值为0.0005 Verilog语言定义了实数如何隐式地转换为整数:实数通

46、过四舍五入被转换为最相近的整数。实数型常量【例例3.12】对实数四舍五入后的表示 42.446,42.45转换为整数42 92.5,92.699转换为整数93 -15.62转换为整数-16 -26.22转换为整数-26字符串是双引号内的字符序列,用一串8位二进制ASC码的形式表示,每一个8位二进制ASC码代表一个字符。例如:字符串“ab”等价于16h 5758。如果字符串被用作Verilog表达式或复制语句的操作数,则字符串被看做无符号整数序列。字符串变量声明:字符串变量是寄存器型变量,它具有与字符串的字符数乘以8相等的位宽。字符串常量【例例3.13】字符串变量的声明。 存储12个字符的字符串

47、“Hello China!”需要8*12(即96位)宽的寄存器。 reg 8*12:1 str; initial begin str =“Hello China!”; end字符串操作 可以使用Verilog HDL的操作符对字符串进行处理,被操作符处理的数据是8位ASC码的序列。在操作过程中,如果声明的字符串变量位数大于字符串实际长度,则在赋值操作后,字符串变量的左端(即高位)补0。【例例3.14】字符串操作的例子module string_test; reg8*14:1 stringvar;initialbegin stringvar=“Hello China”; $display(“%s

48、 is stored as %h”,stringvar,stringvar); stringvar=stringvar.“!”; $display(“%s is stored as %h”,stringvar,stringvar);endendmoduleVerilogVerilog常量常量常量常量- -字符串常量字符串常量输出结果为:Hello China is stored as 00000048656c6c6f20776f726c64Hello China! is stored as 48656c6c6f20776f726c64212121特殊字符:在某些字符之前加上一个引导性的字符(转

49、移字符),这些的字符只能用于字符串中。 下表列出了这些特殊字符的表示和意义。字符意义 n换行符tTab键符号”符号”ddd3位八进制数表示的ASCII值(0d7)Verilog HDL有下列四种基本的值:1)0:逻辑0或“假”状态;2)1:逻辑1或“真”状态;3)x(X):未知状态,对大小写不敏感;4)z(Z):高阻状态,对大小写不敏感。Verilog数据类型 在Verilog HDL中,根据赋值和对值保持方式不同,可将数据类型主要分为两大类:网络(net)型和变(Variable)型。这两类数据也代表了不同的硬件结构。网络和变量net表示器件之间的物理连接,需要门和模块的驱动。网络数据类型是

50、指输出始终根据输入的变化而更新其值的变量,它一般指的是硬件电路中的各种物理连接。 没有声明的net的默认类型为1位(标量)wire类型。Verilog HDL禁止对已经声明过的网络、变量或参数再次声明。 netnet(网络)型(网络)型下面给出net声明的语法格式: range delay ,net_name; net_type:表示网络型数据数据的类型。range:指定数据为标量或矢量。默认为1位的标量;反之,由该项指定数据的矢量形式。delay:指定仿真延迟时间。net_name:net名称,一次可定义多个net,用逗号分开。【例例3.15】网络的声明wand w; / 一个标量wand类

51、型net tri 15: 0 bus; / 16位三态总线 wire 0: 31 w1, w2; / 两个32位wire,MSB为bit0 类型功能可综合性wire,tri标准内部连接线supply1,supply0电源和地wor,trior多驱动源线或wand,triand多驱动源线与trireg能保存电荷的nettri1,tri0无驱动时上拉/下拉 常用的net型变量 网络和变量网络和变量 -net-net(网络)型(网络)型网络数据类型包含多种不同种类的网络子类型: wire型,tri型,wor型,trior型,wand型,triand型,trireg型,tri1型,tri0型,supp

52、ly0型,supply1型。简单的网络类型说明语法为: net_kindmsb:lsbnet1,net2, . . . , netN; 网络型数据的默认初始化值为Z。带有驱动的网络型数据应当为它们的驱动输出指定默认值。trireg网络型数据时一个例外。它的默认初始值为x,而且在声明语句中应当为其指定电荷量强度。 在一个网络型数据类型声明中,可以指定两类强度:电荷量强度(charge strength)驱动强度(drive strength)。 1)电荷量强度(charge strength)一个trireg网络型数据用于模拟电荷存储。电荷量强度可由下面的关键字来制定电容量的相对大小:small

53、、medium、large。默认的电荷强度为medium。一个trireg网络型数据能够模拟一个电荷存储节点,该节点的电荷量将随时间而逐渐衰减。对于一个trireg网络型数据在仿真时,其电荷衰减时间应当制定为延迟时间。2)驱动强度(drive strength)在一个网络型数据的声明语句中如果对数据对象进行了连续赋值,就可以为声明的数据对象指定驱动强度。1wire和tri网络类型用于连接单元的连线wire是最常见的网络类型。连线与三态线(tri)网语法和语义一致;三态线可以用于描述多个驱动源驱动同一根线的网络类型;并没有其他特殊的意义。多个驱动源驱动一个连线(或三态网络),其有效值由下表确定。

54、wire或tri01xz00xx01x1x1XxxxxZ01xzwire型变量的定义格式如下:wire n-1:0 ,;其中name1,namen表示wire型名字。【例例3.16】wire型变量的说明 wire L; /将电路的输出信号L声明为网络型变量 wire 7:0 data bus; /声明一个8bit宽的网络型总线变量2wor和trior网络类型wor和trior用于连线型逻辑结构建模。当有多个驱动源驱动wor和trior型数据时,将产生线或结构。如果驱动源中任一个为1,那么网络型数据的值也为1。线或和三态线或(trior)在语法和功能上是一致的。如果多个驱动源驱动这类网,网的有效

55、值由下表决定。wor或trior01xz001x011111xx1xxz01xz3wand和triand网络类型当有多个驱动源驱动线与网wand和triand时,网络的值为0。线与和三态线与(triand)网在语法和功能上是一致的。如果这类网络存在多个驱动源,网络的有效值由下表决定。Wand或triand01xz00000101x1X0xxxZ01xz4Trireg网络类型一个trireg网络型数据可以处于以下两种状态之一:1)驱动状态:当至少被一个驱动源驱动时,trireg网型数据有一个值(1、0、x)。判决值被导入trireg型数据,也就是trireg型网络的驱动值。2)电容性状态:如果所

56、有驱动源都处于高阻状态(z),trireg网络型数据则保持它最后的驱动值。高阻值不会从驱动源导入trireg网络型数据。5tri0和tri1网络类型若无驱动源驱动,tri0的值为0,tri1的值为1。网络值的驱动强度都为pull。tri0相当于这样一个wire型网络:有一个强度为pull的0值连续驱动该wire。同样,tri1相当于这样一个wire型网络:有一个强度为pull的1值连续驱动该wire。下表给出在多个驱动源情况下tri0或tri1网的有效值。tri0或tri101xZ00xx01x1x1XxxxXZ01x0或16supply0和supply1网络类型supply0用于对“地”建模

57、,即低电平0;supply1网用于对电源建模,即高电平1。 【例例3.17】supply0和supply1网络类型描述 supply0 Gnd,ClkGnd; supply1 2:0 Vcc;7未说明的网络在Verilog HDL中,可不必声明某种网络类型,默认为1位wire网络。可以使用default_nettype编译器指令改变这一隐式网络说明方式。使用方法如下: default_nettypenet_kind 例如,带有下列编译器指令 default_nettype wand 任何未被说明的网默认为1位线与网。1整型变量声明整型变量常用于对循环控制变量的说明,在算术运算中被视为二进制补码

58、形式的有符号数。整型数据与32位的寄存器型数据在实际意义上相同,只是寄存器型数据被当做无符号数来处理。 【例例3.183.18】整数变量的声明 integer i,j; integer31:0 D;需要注意的是虽然interger有位宽度的声明,但是integer型变量不能作为位向量访问。D6和D16:0的声明都是非法的。在综合时,integer型变量的初始值是x。变量数据类型2实数型变量声明 实数型数据在机器码表示法中是浮点型数值,可用于对延迟时间的计算。实数型变量是不可综合的。3时间型变量声明 时间型变量与整型变量类似,只是它是64位的无符号数。时间型变量主要用于对仿真时间的存储与计算处理

59、,常与系统函数$time一起使用。4寄存器型变量声明 寄存器型变量对应的是具有状态保持作用的硬件电路,如触发器、锁存器等。寄存器型变量与网络络数据的区别主要在于:寄存器型变量保持最后一次的赋值,而wire型数据需要有连续的驱动。寄存器型变量只能在initial或always内部被赋值。寄存器型变量声明的格式如下: range , reg_name; reg_type为寄存器类型;range为矢量范围,MSB:LSB格式,只对reg类型有效;reg_name为reg型变量的名字,一次可定义多个reg型变量,使用逗号分开。 【例例3.19】寄存器型变量的声明及使用module mult(clk,

60、rst, A_IN, B_OUT);input clk,rst,A_IN;output B_OUT;reg arb_onebit = 1b0;always (posedge clk or posedge rst)begin if (rst) arb_onebit = 1b1; else arb_onebit = A_IN; endend B_OUT = arb_onebit;endmoduleVerilog HDL中的参数(parameter)既不属于变量类型也不属于网络类型范畴。参数不是变量,而是常量。用参数声明一个可变常量,常用于定义延时及宽度等参数。参数定义的格式:parameter p

61、ar_name1=expression1, , par_namen=expression;par_name1,.par_namen为参数的名字;expression1,.,expression为表达式。参数【例例3.203.20】参数的声明及使用parameter BUS_WIDTH=8;reg BUS_WIDTH-1:0 my_reg;可一次定义多个参数,用逗号隔开。参数的定义是局部的,只在当前模块中有效。参数定义可使用以前定义的整数和实数参数。 参数值也可以在编译时被改变。改变参数值可以使用参数定义语句或通过在模块初始化语句中定义参数值。【例例3.21】参数的声明及使用module lpm

62、_reg (out, in, en, reset, clk);parameter SIZE=8;input in, en, reset, clk;output out;wire SIZE-1:0 in;reg SIZE-1:0 out;always (posedge clk or negedge reset)begin if (!reset) out=1b0; else if(en) out=in; else out = out; endendmodule1向量说明 向量范围由常量表达式来说明(也就是通常所说的数组)。msb_constant_expression(最高位常量 表 达 式 )代

63、 表 范 围 的 左 侧 值 ,lsb_constant_expression(最低位常量表达式)代表范围的右侧值。右侧表达式的值可以大于、等于、小于左侧表达式的值。 net和reg型向量遵循以2为模(2n)的乘幂算术运算法则,此处的n值是向量的位宽。net和reg型向量如果没有被声明为有符号量或者链接到一个已声明为有符号的数据端口,那么该向量被隐含当做无符号的量。 向量 向量可以将已声明过类型的元素组合成多维的数据对象。向量声明时,应当在声明的数据标识符后面指定元素的地址范围。每一个维度代表一个地址范围。数组可以是一维向量(一个地址范围),也可以是多维向量(多重地址范围)。向量的索引表达式应

64、当是常量表达式,该常量表达式的值应当是整数。一个数组元素可以通过一条单独的赋值语句被赋值,但是整个向量或向量的一部分不能为一个表达式赋值。要给一个向量元素赋值,需要为该向量元素指定索引。向量索引可以是一个表达式,这就为向量元素的选择提供了一种机制,即依靠对该向量索引表达式中其他的网络数据或变量值的运算结果来定位向量元素。【例例3.223.22】多维向量的声明实例1 wire 7:0 array2 0:2550:15该声明表示一个256 16的wire型数据,其中的每个数据是8位的宽度。只能在结构化描述的Verilog HDL中分配。【例例3.233.23】多维向量的声明实例2 reg 63:0

65、 regarray2 255:07:0该声明表示一个256 8的reg型数据,其中的每个数据是64位宽度。只能在行为化描述的Verilog HDL中分配。【例例3.243.24】多维向量的声明实例3wire 7:0 array3 0:150:2550:15该声明表示一个三维的向量,表示16个256x16的wire型数据,每个数据8位宽度。只能在结构化描述的Verilog HDL中分配。 2向量网络型数据的可访问性vectored和scalared是矢量网络型或矢量寄存器型数据声明中的可选择关键字。如果使用关键字vectored,那么矢量的位选择或部分位选择以及强度指定就被禁止,而PLI(编程语

66、言接口)就会认为数据对象未被展开。如果使用关键字scalared,那么矢量的位或部分位选择就被允许,PLI认为数据对象将被展开。下例是使用关键字vectored和scalared的例子。【例例3.25】关键字vectored和scalaredtri scalared63:0 bus64; /一个将被展开的数据总线tri vectored31:0 data; /一个未被展开的数据总线 3.存储器如果一个向量的元素类型为reg型,那么这样的一维向量也称为存储器。存储器只用于ROM(只读存储器)、RAM(随机存取存储器)和寄存器组建模。向量中的每一个寄存器也叫做元素或字,并且是通过单一的索引来寻址的

67、。一个n位的寄存器可以通过一条单独的赋值语句被赋值,但是整个存储器组不能通过这样的一条语句被赋值。为了对存储器的某个字赋值,需要为该字指定数组索引。该索引可以是一个表达式,该表达式中含有其他的变量或网络数据,通过对该表达式的运算,得到一个结果值,从而定位存储器的字。【例例3.26】存储器型的声明reg7:0 mymemory1023:0;上述声明定义了一个1024个存储单元的存储器变量mymemory,每个存储单元的字长为8位。在表达式中可以用下面的语句来使用存储器。 mymemory7=75; /存储器mymemory的第7个字被赋值75表达式是将操作数和操作符联合起来使用的一种Verilo

68、g HDL语言结构,通过运算得到一个结果。表达式可以在出现数值的任何地方使用。Verilog 语言表达式Verilog HDL中的操作符按功能可以分为下述类型:算术操作符、关系操作符、相等操作符、逻辑操作符、按位操作符、归约操作符、移位操作符、条件操作符、连接和复制操作符;按运算符所带操作数的个数可分为三类:单目操作符、双目操作符和三目操作符。下表给出了所有操作符的优先级和名称。操作符操作符+ 一元加- 一元减! 一元逻辑非 一元按位求反& 归约与& 归约与非 归约异或或 归约异或非| 归约或 | 归约或非* 乘/ 除% 取模+ 二元加_ 二元减 右移 小于 大于 = 大于等于= = 逻辑相等

69、! = 逻辑不等= = = 全等! = = 非全等& 按位与 按位异或 or 按位异或非| 按位或& & 逻辑与| | 逻辑或? : 条件操作符Verilog HDL中,延迟表达式的格式为用圆括号括起来的三个表达式,这三个表达式之间用冒号分隔开。三个表达式一次代表最小、典型、最大延迟时间值。下面举例说明延迟表达式的用法。【例例3.393.39】延迟表达式的使用。(a:b:c)+(d:e:f) 表示最小延迟值为a+d的和,典型延迟值为b+e的和,最大延迟值为c+f的和延迟表达式延迟表达式表达式位宽是由包含在表达式内的操作数和表达式所处的环境决定的。自主表达式的位宽由它自身单独决定,比如延迟表达式

70、。环境决定型表达式的位宽由该表达式自己的位宽和它所处的环境来决定,比如一个赋值操作中右侧表达式的位宽由它自己的位宽和赋值符左侧的位宽来决定。表达式位宽规则如下表所示:表达式的位宽表达式的位宽表达式结果值位宽说明不定长常数与整数相同定长常数与给定的位宽相同iopj,op为:+-*/%&|ormax(L(i),L(j))op为操作符opi,op为:+-L(i)iopj,op为:=!=!=&|=L(i)j是自主表达式i?j:kmax(L(j),L(k)i是自主表达式i,jL(i)+.+L(j)所有操作数都是自主表达式ij,ki*(L(i)+.+L(j)所有操作数都是自主表达式下面是表达式符号类型规则

71、:表达式的符号类型仅仅依靠操作数,与LHS(左侧)值无关。简单十进制格式数值是有符号数。基数格式数值是无符号数。无论操作数是何类型,其位选择结果为无符号型。无论操作数是何类型,其部分位选择结果为无符号型,即使部分位选择指定了一个完整的矢量。有符号表达式有符号表达式无论操作数是何类型,连接(或复制)操作的结果为无符号型。无论操作数是何类型,比较操作的结果(1或0)为无符号型。通过类型强制转换为整型的实数为有符号型。任何自主操作数的符号和位宽由操作数自己决定,而独立于表达式的其余部分。对于非自主操作数遵循下面的规则:如果有任何操作数为实型,则结果为实型;如果有任何操作数为无符号型,则结果为无符号型

72、,而不论是什么操作符;如果所有操作数为有符号型,则结果为有符号型,而不论是什么操作符。 模块的几种描述方式(或者叫做建模方式),包括行为级建模(RTL级建模也属于行为级建模)、结构级建模(包括门级建模和开关级建模)以及行为级和结构级的混合建模。当模块内部只包括过程块和连续赋值语句(assign),而不包含模块实例(模块调用)语句和基本元件实例语句时,就称该模块采用的是行为级建模;当模块内部只包含模块实例和基本元件实例语句,而不包含过程块语句和连续赋值语句时,就称该模块采用的是结构级建模;当然在模块内部也可以采用这两种建模方式的结合,即混合建模方式。Verilog行为描述语句过程语句过程语句Ve

73、rilog HDL中的多数过程模块都属于以下两种过程语句:initial 语句always语句一个模块中可以包含任意多个initial或always语句。这些语句相互并行执行,即这些语句的执行顺序与其在模块中的顺序无关。一个initial语句或always语句的执行产生一个单独的控制流,所有的initial和always语句在0时刻开始并行执行。 initial语句只执行一次。initial 语句在模拟开始时执行,即在0时刻开始执行。initial语句的语法如下:initial begin statement1; /描述语句1 statement2; /描述语句2 .end顺序过程(begin

74、.end)最常使用在进程语句中。initial initial 语句语句时序控制可以是时延控制,即等待一个确定的时间;或事件控制,即等待确定的事件发生或某一特定的条件为真。initial语句的各个进程语句仅执行一次。注意initial语句在模拟的0时刻开始执行。initial语句根据进程语句中出现的时间控制在以后的某个时间完成执行。Initial语句通常用于仿真模块对激励向量的描述,或用于给寄存器变量赋初值,它是面向模拟仿真过程的语句,不能被综合。 【例例3.40】initial语句的描述reg a;.initiala=2;上述initial语句中包含无时延控制的过程赋值语句。initial语

75、句在0时刻执行,促使a在0时刻被赋值为2。 【例例3.41】带有时延控制的initial语句的描述reg Curt;.initial#2 a=1;寄存器变量a在时刻2被赋值为1。initial语句在0时刻开始执行,在时刻2完成执行。 【例例3.42】带有顺序过程的initial语句例子parameter SIZE = 1024;reg 7:0 RAM0:SIZE-1 ;reg RibReg;initialbegin: SEQ_BLK_A integer Index; RibReg = 0; for (Index = 0; Index SIZE; Index = Index + 1) RAM I

76、ndex = 0;end顺序过程由关键词begin.end定界,它包含顺序执行的进程语句,与C语言等高级编程语言相似。SEQ_BLK_A是顺序过程的标记;如果过程中没有局部说明部分,不要求这一标记。例如,如果对Index的说明部分在initial语句之外,可不需要标记。整数型变量Index已在过程中声明。并且,顺序过程包含1个带循环语句的过程性赋值。这一initial语句在执行时将所有的内存初始化为0。always语句重复执行,always语句语法如下: always (敏感信号表达式) begin /过程赋值 /if-else,case语句 /while,repeat,for循环语句 /ta

77、sk,function调用 endalwaysalways语句语句always语句有一个过程性赋值。因为always语句重复执行,因此,always语句的执行必须带有某种时序控制。 1、敏感信号为组合逻辑的always语句描述【例例3.43】always语句用于4选1开关的Verilog HDL描述module mux4 (sel, a, b, c, d, outmux); input 1:0 sel; input 1:0 a, b, c, d; output 1:0 outmux; reg 1:0 outmux;always (sel or a or b or c or d)begin ca

78、se (sel) 2b00: outmux = a; 2b01: outmux = b; 2b10: outmux = c; default: outmux = d; endcaseendendmodule2、敏感信号为时钟沿的always语句描述【例例3.44】 module EXAMPLE (DI, CLK, RST, DO); input 7:0 DI; input CLK, RST; output reg 7:0 DO;always (posedge CLK or posedge RST) if (RST=1b1) DO=8b00000000; else DO=DI;endmodule

79、 语句块提供将两条或更多条语句组合成语法结构上相当于一条语句的机制。在Verilog HDL中有两类语句块,即:顺序语句块(begin.end):语句块中的语句按给定次序顺序执行。并行语句块(fork.join):语句块中的语句并行执行。语句块顺序语句块中的语句按顺序方式执行。每条语句中的时延值与其前面的语句执行的模拟时间相关。一旦顺序语句块执行结束,跟随顺序语句块过程的下一条语句继续执行。顺序语句块的语法如下: begin: /declaration /behavior statement1 /behavior statementnend顺序语句块顺序语句块(begin-end)(begin

80、-end) 其中,block_name为模块的标识符,该标识符是可选的;declaration为块内局部变量的声明,这些声明可以是reg型变量声明、integer型变量声明及real型变量声明;behavior statement为行为描述语句。【例例3.45】并行语句块的Verilog HDL描述begin#2 St ream=1;#5 Stream=0;#3 Stream = 1;#4 Stream = 0;#2 Stream = 1;#5 Stream = 0;end假定顺序语句块在第10个时间单位开始执行。两个时间单位后第1条语句执行,即第12个时间单位。此执行完成后,下1条语句在第1

81、7个时间单位执行(延迟5个时间单位)。然后下1条语句在第20个时间单位执行,以此类推。顺序语句产生波形【例例3.46】顺序语句块的Verilog HDL描述begin Pat=Mask|Mat; (negedge Clk) FF=&Pat;end在该例中,第1条语句首先执行,然后执行第2条语句。当然,第2条语句中的赋值只有在Clk上出现负沿时才执行。并行语句块带有定界符fork和join,并行语句块中的各语句并行执行。并行语句块内的各条语句指定的时延值都与语句块开始执行的时间相关。当并行语句块中最后的动作执行完成时(最后的动作并不一定是最后的语句),顺序语句块的语句继续执行。换一种说法就是并行

82、语句块内的所有语句必须在控制转出语句块前完成执行。并行语句块并行语句块(fork-join)(fork-join)并行语句块语法如下:fork:/declaration/behavior statement1 /behavior statementnjoin其中,block_name为模块标识符,declaration为块内局部变量声明,声明可以是reg型变量声明、integer型变量声明、real型变量声明、time型变量声明和事件(event)声明语句。【例例3.47】顺序语句块Verilog HDL描述fork#2 Stream = 1; #7 Stream = 0;#10 Stream

83、 = 1;#14 Stream = 0;#16 Stream = 1;#21 Stream = 0;join如果并行语句块在第10个时间单位开始执行,所有的语句并行执行并且所有的时延都是相对于时刻10的。行为描述模块中过程块内的语句块是由过程性赋值语句和高级程序语句构成的:门基元赋值语句;连续赋值语句;过程赋值语句;阻塞赋值语句和非阻塞赋值语句。 赋值语句门基元赋值语句格式: gate_keywords(gate_out, gate_input1, gate_input2, gate_inputn);其中:gate_keywords为基本逻辑门的关键字,是Verilog 预定义的逻辑门,包括a

84、nd、or、not、xor、nand、nor等;gate_out为逻辑门的输出;gate_input为逻辑门的输入。【例例3.48】门单元赋值的Verilog HDL描述nand(y,a,b,c,d);该赋值语句表示,具有a、b、c、d四个输入和y为输出与非门的实现。门基元赋值语句门基元赋值语句Verilog中的连续赋值语句与过程块一样也是一种行为描述语句。连续赋值语句主要用来对组合逻辑电路的行为进行描述,二者需要制定组合逻辑电路元件之间具体的硬件连接关系。连续赋值语句格式: assignvariable=expression;variable为wire型变量;expression为赋值的表达

85、式。【例例3.49】连续赋值的Verilog HDL描述assign y=(a & b & c & d);该连续赋值语句表示,输出y的变化跟随输入a、b、c、d的变化而变化,反映了信号变化的连续性。连续赋值语句连续赋值语句过程赋值语句的硬件实现是:从赋值语句右边提取出的逻辑,用于驱动赋值语句左边的变量(必须是reg型)。有两种类型的过程赋值语句: 阻塞赋值语句(Blocking Assignmet Statement) 非阻塞赋值语句(Non-blocking Assignmet Statement)阻塞赋值语句 以赋值操作符“=” 标识的赋值操作称为阻塞型过程赋值语句:在一个always块中

86、,语句是按从上到下顺序执行的。它具有如下特点:1)顺序块内的各条阻塞语句以它们在顺序块中的排列先后次序依次得到执行;而并行块中的各条阻塞赋值语句则是同时得到执行。2)阻塞赋值语句的执行过程是:首先计算右端赋值表达式的取值,然后立即将计算结果赋值给“=”左端的被赋值变量。这种语句更多的用在行为仿真和时序仿真的过程中。非阻塞赋值语句:以赋值操作符“=”标识的赋值操作,也是出现在initial和always块语句中。在非阻塞赋值语句中,赋值号“=”左边的赋值变量也必须是reg型变量,其值不象在过程赋值语句那样,语句结束时即刻得到,而在该块语句结束才可得到。 在begin-end顺序语句块中,一条非阻

87、塞赋值语句块的执行不会阻塞下一条语句的执行。 【例例3.50】非阻塞赋值的Verilog HDL描述module block(a3,a2,a1,clk);input clk,a1; output reg a3,a2;always (posedge clk)begin a2=a1; a3=a2;end endmodule非阻塞赋值综合后的结构【例例3.51】阻塞赋值的Verilog HDL描述module block(a3,a2,a1,clk);input clk,a1; output reg a3,a2;always (posedge clk)begin a2=a1; a3=a2;end en

88、dmodule阻塞赋值综合后的结构从上述两个例子中,可以清楚地看到两种赋值语句的明显不同。对于非阻塞赋值语句,是并发执行的;对于阻塞赋值语句,是按照指定顺序执行的,语句的书写顺序对执行的结果有着直接的影响。 Verilog HDL中的语言可以分为分支语句和循环控制语句两类。Verilog HDL中存在着两种分支语句: if-else分支控制语句 case分支控制语句分支语句 if-else语句可以有下面的三种表示方法: 1) if(condition_1) procedural_statement1; 2) if(condition_1) procedural_statement1; else

89、 procedural_statement2; 3) if(condition_1) procedural_statement_1; else if(condition_2) procedural_statement_2; else if(condition_n) procedural_statement_n; else procedural_statement_n+1;if-else语句其中:conditon_1,.,condition_n为条件表达式;procedural_statement_1,.,procedural_ statement_n+1为描述语句。如果对condition_1

90、求值的结果为一个非零值,那么procedural_statement_1被执行,如果condition_1的值为0、x或z,那么procedural_statement_1不执行。语句可以是一个描述语句,也可以是多个描述语句,当为多个描述语句时用“begin-end”语句将其包含进去。【例例3.54】使用if-else语句实现D触发器的Verilog HDL描述module v_registers_2 (C,D,CLR,Q); input C, D, CLR; output Q; reg Q;always (negedge C or posedge CLR)begin if (CLR) Q=1

91、b0; else Q=D;endendmodule【例例3.55】使用if-else语句实现不变模式的单端口RAMmodule v_rams_03 (clk, we, en, addr, di, do); input clk,we,en; input 5:0 addr; input 15:0 di; output reg 15:0 do; reg 15:0 RAM 63:0;always (posedge clk)begin if (en)begin if (we) RAMaddr=di; else do=RAMaddr;end endendmodulecase语句是一个多路条件分支形式,其语

92、法如下:case(case_expr)case_item_expr_1: procedural_statement_1; case_item_expr_2: procedural_statement_2;. case_item_expr_n: procedural_statement_n;default: procedural_statement_n+1;endcase其中:case_expr为条件表达式;case_item_expr_1, ., case_item_expr_n为条件值。procedual_statement_1,., procedual_statement_n+1为描述语句

93、。case语句 case语句首先对条件表达式case_expr求值,然后依次对各分支项求值并进行比较,第一个与条件表达式值相匹配的分支中的语句被执行。可以在1个分支中定义多个分支项;这些值不需要互斥。默认分支覆盖所有没有被分支表达式覆盖的其他分支。分支表达式和各分支项表达式不必都是常量表达式。在case语句中,x和z值作为文字值进行比较。【例例3.56】case语句实现多路选择器的Verilog HDL语句module mux4 (sel, a, b, c, d, outmux);input 1:0 sel,a,b.c,d;output reg 1:0 outmux;always (sel o

94、r a or b or c or d)begin case (sel) 2b00: outmux=a; 2b01: outmux=b; 2b10: outmux=c; default: outmux=d; endcaseendendmodule【例例3.57】case语句实现3-8解码器的Verilog HDL描述module v_decoders_1 (sel, res);input 2:0 sel;output reg 7:0 res;always (sel)begin case (sel) 3b000 : res=8b00000001; 3b001 : res=8b00000010;3b

95、010 : res=8b00000100;3b011 : res=8b00001000;3b100 : res=8b00010000;3b101 : res=8b00100000;3b110 : res=8b01000000;default : res=8b10000000; endcase end endmodulecase语句还有其它两种形式:casex和casez,语法与case语句完全一致。在casez语句中,出现在case表达式和任意分支项表达式中的值z被认为是无关值,即那个位被忽略(不比较)。在casex语句中,值x和z都被认为是无关位。【例例3.58】casez语句的Verilo

96、g HDL描述casez(Mask ) 4b1? : Dbus4 = 0; 4b01? : Dbus3 = 0; 4b001? : Dbus2 = 0; 4b0001 : Dbus1 = 0;endcase字符 ? 用来代替字符z,表示无关位。casez语句表示如果Mask的第1位是1(忽略其它位),那么将Dbus4赋值为0;如果Mask的第1位是0,并且第2位是1(忽略其它位),那么Dbus 3被赋值为0,依此类推。Verilog HDL中有四类循环语句,用于控制语句的执行次数,这四种语句分别为: forever循环 repeat循环 while循环 for 循环循环控制语句这一形式的循环语

97、句语法格式如下:forever procedural_statement;其中:procedural_statement为描述语句。此循环语句连续执行过程语句。因此为跳出这样的循环,中止语句可以与过程语句共同使用。同时,在过程语句中必须使用某种形式的时序控制,否则,forever循环将在0时延后永远循环下去。foreverforever循环语句循环语句【例例3.59】forever循环语句的Verilog HDL描述initial begin Clock=0; # 5 forever #10 Clock = Clock;end这一实例产生时钟波形:时钟首先初始化为0,并保持到第5个时间单位。此

98、后每隔10个时间单位,Clock反相一次。repeat循环语句语法格式如下:repeat (loop_count) procedural_statement;其中:loop_count为循环次数,procedural_statement为描述语句。这种循环语句执行指定循环次数的过程语句。如果循环计数表达式的值不确定,即为x或z时,那么循环次数按0处理。repeatrepeat循环语句循环语句【例例3.60】repeat循环语句repeat (Count) Sum= Sum+10; repeat (Shift_By) P_Reg=P_Reg 1;while 循环语句语法如下:while(cond

99、ition) procedural_statement;其中:condition为循环的条件表达式procedural_statement为描述语句。此循环语句循环执行过程赋值语句直到指定的条件为假。如果表达式在开始时为假,那么过程语句便永远不会执行。如果条件表达式为x或z,它也同样按0(假)处理。whilewhile循环语句循环语句【例例3.61】while循环语句parameter P = 4;always (ID_complete)begin : UNIDENTIFIEDinteger i;reg found;unidentified=0;i=0;found = 0;while (!fo

100、und & (i P) begin found=!ID_completei; unidentifiedi=!ID_completei; i=i+1; endendfor 循环语句的形式如下: for(initial_assignment;condition;step_assignment)procedural_statement;其中:initial_addignment为初始值,给出循环变量的初始值;condition为循环条件表达式,条件表达式指定循环在什么情况下必须结束;step_assigment给出要修改的赋值,通常为增加或减少循环变量计数; procedural_statement

101、为描述语句。一个for循环语句按照指定的次数重复执行过程赋值语句若干次。只要条件为真,循环中的语句就执行。 for for 循环语句循环语句【例例3.62】for循环语句module countzeros (a, Count); input 7:0 a; output reg2:0 Count;reg 2:0 Count_Aux;integer i;always (a)beginCount_Aux = 3b0;for (i = 0; i 8; i = i+1)begin if (!ai) Count_Aux = Count_Aux+1; end Count = Count_Aux;endend

102、module Verilog门级描述语句 内置基本门级元件 Verilog HDL中提供下列内置基本门:1)多输入门:and,nand,or,nor,xor,xnor2)多输出门:buf,not3)三态门:bufif0,bufif1,notif0,notif14)上拉、下拉电阻:pullup,pulldown 门级逻辑设计描述中可使用具体的门实例语句。下面是简单的门实例语句的格式: gate_typeinstance_name(term1, term2, . . . ,termN) ; 其中:gate_ type为门类型的关键字;instance_name是可选的;term1,.,termN用

103、于表示与门的输入/输出端口相连的网络或寄存器。 同一门类型的多个实例能够在一个结构形式中定义: gate_type instance_name1 (term11,term12,.,term1N) instance_name2 (term21,term22,.,term2N) . instance_nameM (termM1,termM2,.,termMN);1、多输入门内置的多输入门包括:and,nand,nor,or,xor,xnor。这些逻辑门只有单个输出,有1个或多个输入。多输入门实例语句的语法如下:multiple_input_gate_type instance_name (Outp

104、utA,Input1,Input2,.,InputN);【例例3.63】and A1(Out1,In1,In2); 该门实例语句是单元名为A1、输出为Out1、并带有两个输入In1和In2的两输入与门。【例例3.64】and RBX (Sty,Rib,Bro,Qit,Fi);该门实例语句是四输入与门,单元名为RBX,输出为Sty,4个输入为Rib、Bro、Qit和Fix。【例3.65】xor (Bar,Bud0,Bud1,Bud2);该门实例语句是异或门的具体实例,没有单元名。它的输出是Bar,三个输入分别为Bud0、Bud1和Bud2。2、多输出门多输出门包括:buf,not这些门都只有单个

105、输入,一个或多个输出。这些门的实例语句的基本语法如下:multiple_output_gate_typeinstance_name (Out1,Out2,.,OutN,InputA);最后的端口是输入端口,其余的所有端口为输出端口。【例例3.66】buf B1 (Fan0,Fan1,Fan2,Fan3,Clk);该门实例语句中,Clk是缓冲门的输入,门B1有4个输出:Fan0到Fan3。【例例3.67】not N1 (PhA,PhB,Ready);该门实例语句中,Ready是非门的唯一输入端口。门N1有两个输出:PhA和PhB。3、三态门 三态门有:bufif0,bufif1,notif0,n

106、otif1 这些门用于对三态驱动器建模。这些门有一个输出、一个数据输入和一个控制输入。 三态门实例语句的基本语法如下:tristate_gateinstance_name (OutputA,InputB,ControlC); 第一个端口Output A是输出端口,第二个端口Input B是数据输入,Control C是控制输入。根据控制输入,输出可被驱动到高阻状态,即值z。对于bufif0,若通过控制输入为1,则输出为z;否则数据被传输至输出端。对于bufif1,若控制输入为0,则输出为z。对于notif0,如果控制输出为1,那么输出为z;否则输入数据值的非传输到输出端。对于notif1,若控

107、制输入为0;则输出为z。【例例3.68】bufif1 BF1 (Dbus,MemData,Strobe);在该门实例语句中,当Strobe为0时,bufif1门BF1驱动输出Dbus为高阻;否则MemData被传输至Dbus。【例例3.69】notif0 NT2 (Addr, Abus, Probe) ;在该门实例语句中,当Probe为1时,Addr为高阻;否则Abus的非传输到Addr。4、上拉、下拉电阻 上拉、下拉电阻有:pullup,pulldown 这类门没有输入只有输出。上拉电阻将输出置为1。下拉电阻将输出置为0。门实例的端口表只包含1个输出。 门实例语句形式如下: pull_gat

108、einstance_name (Output A);【例例3.70】 pullup PUP (Pwr) ;在该例中,此上拉电阻实例名为PUP,输出Pwr置为高电平1。5、门时延 门时延定义门从任何输入到其输出的信号传输时延。门时延可以在门自身实例语句中定义。 带有时延定义的门实例语句的语法如下:gate_type delay instance_name (terminal_list) ; 时延规定了从门的任意输入到输出的传输时延。当没有强调门时延时,默认的时延值为0。 门时延由三类时延值组成:上升时延;下降时延;截止时延 门时延定义可以包含0个、1个、2个或3个时延值。下表为不同个数时延值条件

109、下,各种具体的时延取值情形。无时延 1个时延(d)2个时延(d1,d2)3个时延(dA,dB,dC)上升0dd1dA下降0dd2dBto_x0dmin(d1,d2)min(dA,dB,dC)截止0dmin(d1,d2)dC【例例3.71】无门延迟的Verilog HDL描述not N1 (Qbar,Q); 因为没有定义时延,门时延为0。【例例3.72】有门延迟的Verilog HDL描述nand #6 (Out, In1, In2); 所有时延均为6,即上升时延和下降时延都是6。因为输出决不会是高阻态,截止时延不适用于与非门。转换到x的时延也是6。【例例3.73】有门延迟的Verilog HD

110、L描述and #(3,5) (Out, In1, In2, In3 ); 在这个实例中,上升时延被定义为3,下降时延为5,转换到x的时延是3和5中间的最小值,即3。【例例3.74】有门延迟的Verilog HDL描述notif1 #(2,8,6) ( Dout, Din1, Din2);上升时延为2,下降时延为8,截止时延为6,转换到x的时延是2、8和6中的最小值,即2。对多输入门(例如与门和非门)和多输出门(缓冲门和非门)总共只能够定义2个时延(因为输出决不会是z)。三态门共有3个时延,并且上拉、下拉电阻实例门不能有任何时延。 门延迟也可采用min:typ:max形式定义。形式如下:mini

111、mum: typical: maximum 最小值、典型值和最大值必须是常数表达式。【例例3.75】有门延迟的Verilog HDL描述nand #(2:3:4, 5:6:7) (Pout,Pin1,Pin2); 选择使用哪种时延通常作为模拟运行中的一个选项。例如,如果执行最大时延模拟,与非门单元使用上升时延4和下降时延7。程序块也能够定义门时延。 6实例数组 当需要重复性的实例时,在实例描述语句中能够有选择地定义范围说明(范围说明也能够在模块实例语句中使用)。这种情况的门描述语句的语法如下:gate_typedelayinstance_name left_bound : right_boun

112、d (list_of_terminal_names) ; left_bound和right_bound值是任意的两个常量表达式。左界不必大于右界,并且左、右界两者都不必限定为0。【例例3.76】实例数组的Verilog HDL描述wire 3:0 Out, InA, InB;.nand Gang 3:0 (Out, InA, InB) ; 带有范围说明的实例语句与下述语句等价:nandGang3 (Out3,InA3,InB3),Gang2 (Out2,InA2,InB2),Gang1 (Out1,InA1,InB1),Gang0 (Out0,InA0,InB0); 注意定义实例数组时,实例名

113、称是不可选的。UDP可以描述组合电路;时序电路。其语法格式如下:primitive UDP_name (OutputName,List_of_inputs)output_declarationinput_declarationsreg_declarationinitial_statementtableList_of_table_entriesendtableendprimitive用户自定义基本元件UDP 其中:OutputName为输出端口名;List_of_inputs为用“,”分割的输入端口的名字;output_delarations为输出端口的类型声明;input_declaratio

114、ns为输入端口的类型声明;reg_declaration为输出寄存器类型数据的声明;initial_statement为元件的初始状态声明;tableendtable为关键字;List_of_table_entries为表项1到n的声明。 UDP的定义不依赖于模块定义,因此出现在模块定义以外。也可以在单独的文本文件中定义UDP。 UDP只能有一个输出和一个或多个输入。第一个端口必须是输出端口。此外,输出可以取值0、1或x(不允许取z值)。输入中出现值z以x处理。UDP的行为以table的形式描述。 1、组合电路、组合电路UDP在组合电路UDP中,表规定了不同的输入组合和相对应的输出值。没有指定

115、的任意组合输出为x。【例例3.77】2-1多路选择器UDPprimitive MUX2x1 (Z,Hab,Bay,Sel); output Z; input Hab,Bay,Sel; table 0 ? 1 : 0 ; 1 ? 1 : 1 ; ? 0 0 : 0 ; ? 1 0 : 1 ; 0 0 x : 0 ; 1 1 x : 1 ; endtableendprimitive字符?代表不必关心相应变量的具体值,即它可以是0、1或x。输入端口的次序必须与表中各项的次序匹配,即表中的第一列对应于原语端口队列的第一个输入(例子中为Hab ),第二列是Bay,第三列是Sel。在多路选择器的表中没有输

116、入组合01x项(还有其它一些项);在这种情况下,输出的默认值为x(对其它未定义的项也是如此)。【例例3.78】使用UDP的2-1多路选择器构成4-1多路选择器的Verilog HDL的描述。module MUX4x1 (Z,A,B,C,D,Sel); input A,B,C,D; input 2:1 Sel ; output Z; parameter tRISE=2,tFALL=3; MUX2x1 #(tRISE,tFALL) (TL,A,B,Sel1), (TP,C,D,Sel1), (Z,TL,TP,Sel2);endmodule2、时序电路UDP 在时序电路UDP中,使用1位寄存器描述内

117、部状态。该寄存器的值是时序电路UDP的输出值。有两种不同类型的时序电路UDP:一种模拟电平触发行为;另一种模拟边沿触发行为。时序电路UDP使用寄存器当前值和输入值决定寄存器的下一状态(和后继的输出)。1)初始化状态寄存器时序电路UDP的状态初始化可以使用带有一条过程赋值语句的初始化语句实现。形式如下:initial reg_name = 0,1,or x;初始化语句在UDP定义中出现。2)电平触发的时序电路UDP下面是D锁存器建模的电平触发的时序电路UDP示例。只要时钟为低电平0,数据就从输入传递到输出;否则输出值被锁存。【例例3.79】D锁存器建模的电平触发的时序电路UDPprimitive

118、 Latch (Q,Clk,D);output reg Q;input Clk,D;table/Clk D : Q(current_state) : Q(next_state) 0 1 : ? : 1; 0 0 : ? : 0; 1 ? : ? : -;endtableendprimitive“-”字符表示值“无变化”。UDP的状态存储在寄存器D中。3)边沿触发的时序电路UDP【例例3.80】边沿触发的时序电路UDP,初始化语句用于初始化触发器的状态。primitive D_Edge_FF (Q, Clk, Data) ;output reg Q ;input Data, Clk;initia

119、l Q = 0;table / Clk Data Q (current_State) Q(next_state)(01) 0 : ? : 0 ;(01) 1 : ? : 1 ;(0x) 1 : 1 : 1 ;(0x) 0 : 0 : 0 ; (?0) ? : ? : - ; / 忽略时钟负边沿 ? ? : ? : - ; / 忽略在稳定时钟上的数据变化endtableendprimitive表项(01)表示从0转换到1,表项(0x )表示从0转换到x,表项(?0)表示从任意值(0, 1或x)转换到0,表项(?)表示任意转换。对任意未定义的转换,输出默认为x。 假定D_Edge_FF为UDP定义

120、,它现在就能够象基本门一样在模块中使用,如下面的4位寄存器所示。【例例3.81】4位寄存器module Reg 4 (Clk, Din, Dout) ;input Clk ;input 0:3 Din;out put 0:3 Dout;D_Edge_FFDLAB0 (Dout0,Clk, Din0),DLAB1 (Dout1,Clk, Din1),DLAB2 (Dout2,Clk, Din2),DLAB3 (Dout3,Clk, Din3),endmodule4)边沿触发和电平触发的混合行为在同一个表中能够混合电平触发和边沿触发项。在这种情况下,边沿变化在电平触发之前处理,即电平触发项覆盖边沿

121、触发项。【例例3.82】带异步清空的D触发器的UDPprimitive D_Async_FF (Q, Clk, Clr, Data) ; output Q; reg Q; input Clr, Data, Clk; table / Clk Clr Data Q(State) Q(next ) (01) 0 0 : ? : 0 ; (01) 0 1 : ? : 1 ; (0x) 0 1 : 1 : 1 ; (0x) 0 0 : 0 : 0 ; / 忽略时钟负边沿: (?0) 0 ? : ? : - ; (?) 1 ? : ? : 0 ; ? 1 ? : ? : 0; endtableend pr

122、imitive4、表项汇总下表列出了所有能够用于UDP原语中表项的可能值。符号意义符号意义0逻辑0(AB)由A变到B1逻辑1*与(?)相同x未知的值r上跳变沿,与(01)相同?0、1或x中的任一个f下跳变沿,与(10)相同b0或1中任一个p(01)、(0x)和(x1)的任一种输出保持n(10)、(1x)和(x0)的任一种同C语言中的编译预处理指令一样,Verilog HDL也提供了大量编译指令。通过这些编译指令,EDA工具厂商使用他们的工具解释Verilog HDL模型变得相当容易。以(反引号)开始的某些标识符是编译器指令。在Verilog HDL语言编译时,特定的编译器指令在整个编译过程中有

123、效(编译过程可跨越多个文件),直到遇到其它的不同编译程序指令。 Verilog编译指示语句完整的标准编译器指令主要包含:1)define,undef:宏编译指令2)ifdef,elsififndef,else,endif:条件编译指令3)default_nettype:默认网络类型声明指令4)include:文件包含指令5)resetall:复位编译指令6)timescale:时间标度指令7)unconnected_drive, nounconnected_drive:驱动编译指令8)celldefine, endcelldefine:单元模块定义指令9)line:行号编译指令1、宏编译指令一

124、个文本宏替换可以非常方便地代替经常使用的一个文本块。例如:在整篇源程序描述的多个地方如果频繁使用某一数字常量,而要对该数字常量进行修改时比较繁琐的,但是如果使用文本宏代替该常量,那么只需要在一个地方对文本宏进行修改就可以了,非常方便。一个文本宏不会受指令resetall影响。1)define指令(宏定义指令) define指令用于文本替换,它很像C语言中的#define指令。它生成一个文本宏(macro)。该指令既可以放在模块定义内部,也可以放在模块定义之外。如果已 经 定 义 了 一 个 文 本 宏 , 那 么 在 它 的 宏 名(macro_name)之前加上重音符号(),就可以在源程序中

125、引用该文本宏。编译器编译时将会自动用相应文本块代替字符串macro_name。Verilog HDL中的所有编译指令都被看做预定义的宏名,要将一个编译指令重新定义为一个宏名是非法的。一个文本宏定义可以带有一个参数,这样就允许为每一个单独的应用定制文本宏。 文本宏定义的语法格式如下:define其中:为宏名,其语法格式为: text_macro_identifier其中:text_macro_identifier为宏标识符,要求是简单标识符。为形参列表,一旦一个宏名被定义,它就可以在源程序的任何地方被使用,没有范围限制;:宏文本,可以是与宏名同行的任意指定文本。【例例3.84】宏指令define

126、define wordsize 8 reg 1:wordsize data; /用可变延迟定义与非门define var_nand(dly) nand #dly var_nand(2) g121(q21,n10,n11); var_nand(5) g122(q22,n10,n11);2)undef指令(取消宏定义指令) undef指令取消前面定义的宏。如果先前并没有使用指令define进行宏定义,那么现在使用undef指令将会导致一个警告。undef指令的语法格式如下:undef text_macro_identifier一个取消了的宏没有值,就如同没有被定义一样。2、条件编译指令指令ifde

127、f,else,endif用于条件编译,条件编译指令的语法格式如下:1) ifdef macro_name statement_block endif2) ifdef macro_name statement_block_1 else statement_block_2 endif其中:macro_name为宏的名字;statement_block为宏模块的模块。【例【例3.86】条件编译指令ifdef WINDOWS parameter WORD_SIZE=16else parameter WORD_SIZE=32endif在编译过程中,如果已定义了名字为WINDOWS的文本宏,就选择第一种参

128、数声明,否则选择第二种参数说明。3、default_nettype指令该指令用于为隐式网络指定网络类型。也就是将那些没有被说明的连线定义网络类型。其指令格式为(例):default_nettype wand该实例定义的默认的为线与类型。因此,如果在此指令后面的任何模块中没有说明的连线,那么该网络被假定为线与类型。4、文件包含指令include编译器指令用于嵌入内嵌文件的内容。文件既可以用相对路径名定义,也可以用全路径名定义。【例例3.87】include “././primitives.v编译时,这一行由文件“././primitives.v”的内容替代。5、重新设置指令resetall编译器

129、指令将所有的编译指令重新设置为默认值。6、时间标记指令在Verilog HDL模型中,所有时延都用单位时间表述。使用timescale编译器指令将时间单位与实际时间相关联。该指令用于定义时延的单位和时延精度。timescale编译器指令格式为:timescale time_unit/time_precisiontime_unit和time_precision由值1、10、和100以及单位s、ms、us、ns、ps和fs组成。 【例3.88】timescale 1ns/100ps表示时延单位为1ns,时延精度为100ps。timescale编译器指令在模块说明外部出现,并且影响后面所有的时延值。

130、【例例3.89】带有timescale语句的Verilog HDL描述timescale 1ns/100psmodule AndFunc (Z,A,B) ;output Z;input A,B;and # (5.22, 6.17 ) Al (Z,A,B);Endmodule在编译过程中,timescale指令影响这一编译器指令后面所有模块中的时延值,直至遇到另一个timescale指令或resetall指令。当一个设计中的多个模块带有自身的timescale编译指令时,模拟器总是定位在所有模块的最小时延精度上,并且所有时延都相应地换算为最小时延精度。7、unconnected_drive和no

131、unconnected_drive指令在模块实例化中,出现在这两个编译器指令间的任何未连接的输入端口为正偏电路状态或反偏电路状态。unconnected_drive pull1 / *在这两个程序指令间的所有未连接的输入端口为正偏电路状态(连接到高电平)* /nounconnected_driveunconnected_drive pull0 / *在这两个程序指令间的所有未连接的输入端口为反偏电路状态(连接到低电平)* /nounconnected_drive8、celldefine 和endcelldefine指令这两个程序指令用于将模块标记为单元模块。它们表示包含模块定义,如下例所示。【

132、例例3.90】celldefine和endcelldefine指令celldefine module FD 1S 3AX (D, CK, Z) ; . endmoduleendcelldefine某些PLI例程使用单元模块为了便于设计者对仿真过程进行控制,以及对仿真结果进行分析,Verilog HDL提供了大量的系统功能调用,大致可以分为两类:一种是任务型的功能调用,称为系统任务;另一种是函数型的功能调用,称为系统函数。Verilog HDL中以$字符开始的标识符表示系统任务或系统函数。他们的区别主要有两点:系统任务可以返回0个或多个值,而系统函数只有一个返回值;此外,系统函数在0时刻执行,即

133、不允许延迟,而系统任务可以带有延迟。 Verilog系统任务和函数Verilog HDL提供了内置的系统任务和系统函数,即在语言中预定义的任务和函数,用户可以随意调用。而且用户可以根据自己的需要,基于Verilog仿真系统提供的PLI(Programming Language Interface)编程接口编制特殊的系统任务和系统函数。根据系统任务和系统函数实现的功能不同,可分为: 显示任务(display task) 文件输入/输出任务(File I/O task) 时间标度任务(timescale task) 模拟控制任务(simulation control task) 时序验证任务(ti

134、ming check task) PLA建模任务(PLA modeling task) 随机建模任务(stochastic modeling task) 实数变换函数(conversion functions for real) 概率分布函数(probabilistic distribution function)显示系统任务用于信息显示和输出。这些系统任务进一步分为:显示和写入任务、探测监控任务和连续监控任务。1)显示和写入任务语法如下:task_name (format_specification 1, argument_list 1 ,format_specification 2 , a

135、rgument_list 2 ,format_specification N , argument_list N) ;其中:task_name是如下编译指令的一种:$display,$displayb,$displayh,$displayo,$write,$writeb,$writeh,$writeo。显示任务%e 或 %E 指数格式输出实数%f 或 %F 浮点格式输出实数%g 或 %G 以上两种格式中较短的输出实数n换行t制表符字符字符”ddd3位八进制数表示的ASCII值%字符 %输出格式符格式说明%h 或 %H十六进制%d 或 %D十进制%o 或 %O八进制%b 或 %B二进制%c 或

136、%CASCII字符%v 或 %V 网络信号长度%m 或 %M模块分级名%s 或 %S字符串%t 或 %T当前时间格式如果没有特定的参数格式说明,默认值如下:$display与$write :十进制数;$display b与$write b :二进制数;$display o与$write o :八进制数;$display h与$write h :十六进制数;【例例3.91】$display与$write任务 $display(Simulation time is %t,$time) ; $display($time,:R=%b,S=%b,Q=%b,QB=%b,R,S,Q,QB); $write(

137、Simulation time is:); $write(%tn,$time) ; 执行结果如下: Simulation time is 10 10:R=1, S=0, Q=0, QB=1 Simulation time is 102)探测任务探测任务有:$strobe,$strobeb,$strobeh,$strobeo。在指定时间显示模拟数据,是在该特定时间步结束时显示模拟数据。“时间步结束”意味着对于指定时间步内的所有事件都已经处理了。【例3.92】$strobe任务always(posedge Rst )$strobe(the flip-flop value is %b at time

138、 %t, Q, $time) ;当Rst有一个上升沿时,$strobe任务输出Q的值和当前模拟时间。 下面是Q和$time的一些值的输出。这些值在每次Rst的上升沿时被输出。The flip-flop value is 1 at time 17The flip-flop value is 0 at time 24The flip-flop value is 1 at time 26其格式定义与显示和写入任务相同。探测任务与显示任务的不同之处在于:显示任务在遇到语句时执行,而探测任务的执行要推迟到时间步结束时进行。 【例例3.93】探测任务与显示任务 integer Cool; initial

139、begin Cool = 1; $display(“After first assignment, Cool has value %d”, Cool) ; $strobe(When strobe is executed, Cool has value %d, Cool) ; Cool = 2; $display(After second assignment, Cool has value %d, Cool) ; end输出为:After first assignment, Cool has value 1 When strobe is executed, Cool has value 2 A

140、fter second assignment, Cool has value 2第一个$display任务输出Cool的值1(Cool的第一个赋值)。第二个$display任务输出Cool的值2(Cool的第二个赋值)。$strobe任务输出Cool的值2,这个值保持到时间步结束。3)监控任务监控任务有:$monitor,$monitorb,$monitorh,$monitoro。这些任务连续监控指定的参数。只要参数表中的参数值发生变化,整个参数表就在时间步结束时显示。【例例3.94】$monitor任务initial$monitor (At %t, D = %d, Clk = %d, $ti

141、me, D , Clk,and Q is %b, Q); 当监控任务被执行时,对信号D、Clk和Q的值进行监控。若这些值发生任何变化,则显示整个参数表的值。可以用如下两个系统任务打开和关闭监控。$monitor off; /禁止所有监控任务。$monitor on; /使能所有监控任务。 1)打开/关闭文件 系统函数$fopen用于打开一个文件:=$fopen(“”); 其中:指定被打开的文件名及其路径,如果路径与文件名正确,则返回一个32位的句柄描述符,且其中只有一位为高电平,否则返回出错信息。因为标准输出具有自己的最低位设置,所以当第一次使用$fopen时,返回的32位句柄描述符中将次低位

142、设置为高电平。每一次调用$fopen都会返回一个新的句柄,且高电平依次左移。文件管理任务【例例3.95】打开文件integer handleA, handleB; /定义两个32位整数initialbegin handleA=$fopen(“myfile.out”);/handleA=0000_0000_0000_0000_0000_0000_0000_0010 handleB=$fopen(“anotherfile.out”);/handleB=0000_0000_0000_0000_0000_0000_0000_0100end系统任务$fclose关闭一个文件:$fclose();当使用多

143、个文件时,为了提高速度,可以将一些不再使用的文件关闭。一旦某个文件关闭,则不能再向它写入信息,打开其他文件可以使用该文件的句柄。2)输出到文件Verilog 中将信息输出到文件的系统任务有$fdisplay、$fwrite、$fstrobe、$fmonitor。它们具有如下相同的语法格式:(,);其中是上述四种系统任务中的一种。是文件句柄描述符,与打开文件不同,可以对句柄进行多位设置。用来指定输出格式。 3)从文件中读取数据 Verilog 中有两个系统任务$readmemb和$readmemh能够用于从文本文件中读取数据,并将数据加载到存储器。前者要求以二进制数据格式存放数据文件,而后者要求

144、以十六进制数据格式存放数据文件。它们具有相同的语法格式:(, ,);其中指定任一上述任务。读出数据的文件名。为要读入数据的存储器。和分别为存储器的起始地址和结束地址。【例例3.97】从文件中读出数据到存储器module testmemory reg7:0memory9:0 integer index;initialbegin $readmemb(“mem.dat”,memory); for(index=0;index10;index=index+1) $display(“memory%d=%b”,index,memoryindex);endendmoduleVerilog HDL提供了下列数字

145、类型转换的功能函数: $rtoi(real_value):通过截断小数值将实数转换为整数。 $itor(integer_value):将整数转换为实数。 $realtobits(real_value):将实数转换为64位模式 $bitstoreal(bit_value):将位模式转换为实数转换函数$random(seed):根据种子变量(seed)的值返回一个32位的有符号整形随机数。种子变量(必须是寄存器、整数或时间寄存器类型)控制函数的返回值,即不同的种子将产生不同的随机数。如果没有指定种子,每次$random函数被调用时根据默认种子产生随机数。概率分布函数 【例例3.102】概率分布函数

146、的Verilog HDL描述integer Seed, Rnum;wire Clk ;initial Seed = 12;always (Clk) Rnum= $random (Seed) ; 在Clk的每个边沿,$random被调用并返回一个32位有符号整型随机数。如果数字在取值范围内,下述模运算符可产生10+10之间的数字。Rnum = $random(Seed)%11;下面是没有显式指定种子的例子。Rnum = $random /2; /种子变量是可选的。注意数字产生的顺序是伪随机排序的,即对于一个初始种子值产生相同的数字序列。表达式:random%11产生10之间的一个随机数。并置操作

147、符 将$random函数返回的有符号整数变换为无符号数。下列函数根据在函数名中指定的概率函数产生伪随机数。 $dist_uniform (seed,start,end) $dist_normal(seed,mean,standard_deviation,upper) $dist_exponential(seed,mean) $dist_poisson(seed,mean) $dist_chi_square(seed,degree_of_freedom) $dist_t(seed,degree_of_freedom) $dist_erland(seed,k_stage, mean)这些函数的所有

148、参数都必须是整数。 一个任务就像一个过程,它可以从不同位置通过任务调用执行共同的代码段。任务可以包含时序控制,即时延控制,并且任务也能调用其它任务和函数。1)任务的定义: task ; input ; output ; begin ; end endtask任务(task) 【例例3.103】任务的Verilog HDL描述module Has_Task;parameter MAXBITS = 8;task Reverse_Bits;inputMAXBITS1:0 Din;outputMAXBITS1:0 Dout;integer K; beginfor (K=0;KMAXBITS;K=K+1

149、)DoutMAXBITS-K=DinK; end endtask . . .endmodule2)任务的调用一个任务由任务调用语句调用。任务调用语句给出传入任务的参数值和接收结果的变量值。任务调用语句是过程性语句,可以在always语句或initial语句中使用。形式如下:(, );其中:task_name为任务的名称;comma_separated_inputs为“,”分割的输入端口的名字;comma_separated_outputs为“,”分割的输出端口的名字。任务调用语句中参数列表必须与任务定义中的输入、输出和输入输出参数说明的顺序匹配。此外,参数要按值传递,不能按地址传递。【例例3.

150、105】任务调用的Verilog HDL描述regMAXBITS-1:0 Reg_X, New_Reg; /寄存器说明部分Reverse_Bits(Reg_X, New_Reg); /任务调用。Reg_X的值作为输入值传递,即传递给Din。任务的输出Dout返回到New_Reg。注意,因为任务能够包含定时控制,任务可在被调用后再经过一定时延才返回值。因为任务调用语句是过程性语句,所以任务调用中的输出和输入输出参数必须是寄存器类型的。下面的例子不通过参数传入变量。尽管引用全局变量被认为是不良的编程风格,它有时却非常有用。【例例3.106】任务调用的Verilog HDL描述module Glob

151、al_Var;reg 0:7 RamQ0:63 ;integer Index;reg CheckBit;task GetParity;input Address;output ParityBit;ParityBit= RamQAddress ;endtaskinitial for(Index = 0; Index = 63; Index = Index+1) beginGetParity(Index, CheckBit) ;$display(Parity bit of memory word %d is %b., Index, CheckBit) ; end endmodule存储器RamQ的

152、地址被作为参数传递,而存储器本身在任务内直接引用。 任务可以带有时序控制,或等待特定事件的发生。 输出参数的值直到任务退出时才传递给调用参数。【例例3.107】任务调用的Verilog HDL描述module TaskWait;reg NoClock;task GenerateWaveform;output ClockQ;beginClockQ = 1;#2 Clock Q = 0;#2 Clock Q = 1;#2 Clock Q = 0;endendtaskinitialGenarateWaveform(NoClock) ;endmodule 任务GenerateWaveform对Cloc

153、kQ的赋值不出现在NoClock上,即没有波形出现在NoClock上;只有对ClockQ的最终赋值0在任务返回后出现在NoClock上。为避免这一情形出现,最好将ClockQ声明为全局寄存器类型,即在任务之外声明它。函数,如同任务一样,也可以在模块不同位置执行共同代码。函数与任务的不同之处是函数只能返回一个值,它不能包含任何时延或时序控制,并且不能调用其它任务。此外,函数必须带有至少一个输入,在函数中允许没有输出或输入输出说明。函数可以调用其它的函数。1、函数声明function : ; input ; begin end endfunction函数(Function)其中:lower:upp

154、er声明了输出的数据宽度;output_name为函数输出(即返回值)的名字;name为输入数据的名字;statements为描述语句。如果函数说明部分中没有指定函数取值范围,则其默认的函数值为1位二进制数。【例例3.108】函数声明module Function_Example parameter MAXBITS=8; function MAXBITS-1:0 Reverse_Bits; input MAXBITS-1:0 din; integer k; begin for (k=0;kMAXBITS;k=k+1) Reverse_BitsMAXBITS-k=dink ;end endfun

155、ction .endmodule函数名为Reverse_Bits。函数返回一个长度为MAXBITS的向量。函数有一个输入dink是局部整型变量。函数定义在函数内部隐式地声明一个寄存器变量,该寄存器变量与函数同名并且取值范围相同。函数通过在函数定义中显式地对该寄存器赋值来返回函数值。对这一寄存器的赋值必须出现在函数定义中。2、函数调用函数调用语句的语法格式如下: = ();其中:signal为与调用函数返回参数宽度一样的信号名字;function_name为函数名字;comma_separated_inputs为“,”分割的输入信号名。Verilog语言模块描述方式模块的描述方式又称为建模方式。

156、Verilog既是一门行为化又是一门结构化的HDL语言。根据设计的需要,每个模块的内部可以分为四种抽象级别来进行描述。模块在外部环境中的表现都是同等的,而与其内部具体描述的抽象级别无关。因此模块的内部具体描述相对于外部环境来说是隐藏的。改变一个模块内部描述的抽象级别,可以不用对其外部环境做任何的改动。模块大致可以按以下四类抽象级别来进行描述。1) 行为级或算法级的描述方式(行为级建模);2) 数据流描述方式(数据流级建模);3) 门级描述方式(门级建模);4) 开关级描述方式(开关级建模)。层次化设计方法层次化设计方法 层次化设计对于原理图和HDL输入都很重要,因为:可以将设计概念化;将设计结

157、构化;使调试设计更容易;使设计的不同部分的不同输入设计方法(原理图,HDL,本地编辑)能更容易结合;使更容易更新设计,其中包括设计,实现,以及在设计过程中验证个别元件;减少优化时间;便于并行设计; 在层次化设计中,一个特定的等级名字区分了每个库元件,特定的模块,以及实例创建。在层次化的设计方法中,各个模块的描述可以采用行为级描述、数据流描述和结构级描述的方法来实现各个模块的功能。模块的行为级描述模块的行为级描述 Verilog HDL的行为级描述是最能体现EDA风格的硬件描述方式,它既可以描述简单的逻辑门,也可以描述复杂的数字系统乃至微处理器;既可以描述组合逻辑电路,也可以描述时序逻辑电路。它

158、是Verilog 最高抽象级别的描述方式。一个模块可以按照要求的设计算法来实现,而不用关心具体硬件实现的细节。在这种抽象级别描述方式上的设计非常类似C编程。 行为描述是通过行为语句来实现的,行为功能可使用下述过程语句结构描述。initial语句:此语句只执行一次。always语句:此语句循环执行。 只有寄存器类型数据能够在这两种语句中被赋值。寄存器型数据在被赋新值前保持原有值不变。所有的initial语句和always语句在零时刻并行执行。【例例3.111】8位计数器的Verilog HDL行为级描述module counter8(clk,clr,out);input clk,clr; out

159、put reg7:0 out;always (posedge clk or posedge clr)begin if(clr) out=0; else out=out+1; endendmodule模块的数据流描述模块的数据流描述 数据流描述方式,也称为RTL(寄存器传输级)描述方式。在这种描述方式下,设计者需要知道数据是如何在寄存器之间传输的以及将被如何处理。数据流描述方式类似于布尔方程,它能够比较直观地表达低层逻辑行为。用数据流描述方式对一个设计建模的最基本的机制就是使用连续赋值语句。在连续赋值语句中,某个值被指派给网络变量。 连续赋值语句的语法为:assign delay LHS_net

160、=RHS_expression; 右边表达式使用的操作数无论何时发生变化,左边表达式都重新计算,并且在指定的时延后变化值被赋予左边表达式的网络变量。时延定义了右边表达式操作数变化与赋值给左边表达式之间的持续时间。如果没有定义时延值, 默认时延为0。下图显示了使用数据流描述方式对2-4解码器电路的建模的实例模型。 模块的数据流描述模块的数据流描述 2-4解码器电路结构模块数的数据流描述模块数的数据流描述 【例例3.112】2-4解码器的Verilog HDL数据流描述timescale 1ns/1nsmodule Decoder2x4(A,B,EN,Z);input A,B,EN;output

161、0:3 Z;wire Abar,Bbar;assign #1 Abar =A;assign #1 Bbar =B;assign #2 Z0=(Abar & Bbar & EN);assign #2 Z1=(Abar & B & EN);assign #2 Z2=(A & Bbar & EN);assign #2 Z3=(A & B & EN);endmodule模块的数据流描述模块的数据流描述 模块的结构描述模块的结构描述 结构描述就是在设计中,通过调用库中的元件或者是已经设计好的模块来完成设计实体功能的描述。在结构体中,描述只表示元件(模块)之间的互联。 模块调用语句的基本格式如下:();其

162、中:1)module_name是模块定义时指定的模块名。 2)list_of_variable是可选项,是由一些参数值组成的一张有序表,这些参数值将被传递给被调用模块实例内的各个参数。 3)module_instance_name是模块调用后所生成的模块实例所取的一个名字,它是模块实例的唯一标识。在某一主模块内可以对同一子模块多次调用,但是每次调用生成的模块实例名不能重复,实例名和模块名的区别是:模块名表示不同的模块,即用来区分电路单元的不同种类;而实例名则表示不同的模块实例,用来区分电路系统中的不同硬件电路单元。4)list_of_port是由外部信号端子组成的一张有序表,这些外部信号端子代

163、表着与模块实例各端口相连的外部信号。所以指明了模块实例端口与外部电路的连接情况。【例例3.113】4位全加器的Verilog HDL结构级描述 include “full_add_1.v” module add4_1(sum,cout,a,b,cin); input cin; input3:0 a, b; output3:0 sum; output cout; full_add_1 f0(a0,b0,cin,sim0,cin1); full_add_1 f1(a1,b1,cin1,sum1,cin2); full_add_1 f2(a2,b2,cin2,sum2,cin3); full_add_1 f3(a3,b3,cin3,sum3,cout); endmodule模块的结构描述模块的结构描述 【例例3.114】1位半加器的Verilog HDL结构级描述module halfadd (X, Y, C, S);input X, Y;output C, S;wire S1, S2, S3;nand NANDA(S3,X,Y);nand NANDB(S1,X,S3);nand NANDC(S2,S3,Y);nand NANDD(S,S1,S2);assign C=S3;endmodule模块的结构描述模块的结构描述

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号