集成电路EDA设计技术:第三章 硬件描述语言verilog_hdl基础

上传人:pu****.1 文档编号:568824544 上传时间:2024-07-27 格式:PPT 页数:265 大小:5.27MB
返回 下载 相关 举报
集成电路EDA设计技术:第三章 硬件描述语言verilog_hdl基础_第1页
第1页 / 共265页
集成电路EDA设计技术:第三章 硬件描述语言verilog_hdl基础_第2页
第2页 / 共265页
集成电路EDA设计技术:第三章 硬件描述语言verilog_hdl基础_第3页
第3页 / 共265页
集成电路EDA设计技术:第三章 硬件描述语言verilog_hdl基础_第4页
第4页 / 共265页
集成电路EDA设计技术:第三章 硬件描述语言verilog_hdl基础_第5页
第5页 / 共265页
点击查看更多>>
资源描述

《集成电路EDA设计技术:第三章 硬件描述语言verilog_hdl基础》由会员分享,可在线阅读,更多相关《集成电路EDA设计技术:第三章 硬件描述语言verilog_hdl基础(265页珍藏版)》请在金锄头文库上搜索。

1、Verilog HDL 基础基础 第一部分第一部分 初级篇初级篇 第一讲第一讲 Verilog 的基本概念的基本概念2024/7/272n硬件描述语言HDL(Hardware Description Language)是硬件设计人员和电子设计自动化(EDA)工具之间的接口,其主要目的是用来编写设计硬件电路的程序,自动综合以生成符合要求且在电路结构,或建立电子系统行为级的仿真模型。n强调:这门课程中“硬件”指的是“芯片”,是微观的电路(微电子)和PCB电路板宏观电路不同。1.1 1.1 硬件描述语言硬件描述语言HDLHDL2024/7/2731.1 1.1 硬件描述语言硬件描述语言HDLHDLn

2、硬件描述语言利用计算机的巨大能力对用HDL建模的复杂数字逻辑进行仿真,然后再自动综合以生成符合要求且在电路结构上可以实现的数字逻辑网表(Netlist),根据网表和某种工艺的器件自动生成具体电路然后生成该工艺条件下这种具体电路的延时模型。仿真验证无误后用于制造ASIC芯片或写入CPLD和FPGA器件中。2024/7/274什么是硬件描述语言(HDL)n具有特殊结构能够对硬件逻辑电路的功能进行描述的一种高级编程语言,可以设计硬件电路(芯片)或仿真硬件电路行为nHDL主要功能:q描述电路的连接描述电路的连接q描述电路的功能描述电路的功能q在不同抽象级上描述电路在不同抽象级上描述电路q描述电路的时序

3、描述电路的时序q表达具有并行性表达具有并行性q仿真硬件电路仿真硬件电路nHDL主要有两种:Verilog和VHDLqVerilog起源于起源于C语言,因此非常类似于语言,因此非常类似于C语言,容易掌握语言,容易掌握qVHDL格式严谨格式严谨qVHDL出现较晚,但标准化早。出现较晚,但标准化早。IEEE 1706-1985标准。标准。2024/7/275为什么要使用硬件描述语言n n电路的逻辑功能容易理解;电路的逻辑功能容易理解;n n便于计算机对逻辑进行分析处理;便于计算机对逻辑进行分析处理;n n把逻辑设计与具体电路的实现分成两个独立的阶把逻辑设计与具体电路的实现分成两个独立的阶段来操作;段

4、来操作;n n逻辑设计与实现的工艺无关;逻辑设计与实现的工艺无关;n n逻辑设计的资源积累可以重复利用;逻辑设计的资源积累可以重复利用;n n可以由多人共同更好更快地设计非常复杂的逻辑可以由多人共同更好更快地设计非常复杂的逻辑电路(几十万门以上的逻辑系统)。电路(几十万门以上的逻辑系统)。2024/7/2761.2 1.2 VerilogVerilog HDL HDL 的历史的历史1.2.1 什么是什么是Verilog HDL Verilog HDL是硬件描述语言的一种,用于数字电子系统设计(芯片设计)。设计者可用它进行各种级别的逻辑设计,可用它进行数字逻辑系统的仿真验证、时序分析、逻辑综合。

5、它是目前应用最广泛的一种硬件描述语言。 2024/7/2771.2 1.2 VerilogVerilog HDL HDL 的历史的历史1.2.2 Verilog HDL的产生及发展的产生及发展lVerilog HDL是在是在1983年由年由GDA(GateWay Design Automation)公司的公司的Phil Moorby所创。所创。Phi Moorby后来成为后来成为Verilog-XL的主的主要设计者和要设计者和Cadence公司的第一个合伙人公司的第一个合伙人。l在在19841985年间,年间,Moorby设计出了第一个设计出了第一个Verilog-XL的仿真器。的仿真器。l1

6、986年,年,Moorby提出了用于快速门级仿真的提出了用于快速门级仿真的XL算法。算法。l1990年,年,Cadence公司收购了公司收购了GDA公司公司l1991年,年,Cadence公司公开发表公司公开发表Verilog语言,成立了语言,成立了OVI(Open Verilog International)组织来负责组织来负责Verilog HDL语言的发展。语言的发展。l1995年制定了年制定了Verilog HDL的的IEEE标准,即标准,即IEEE1364。2024/7/2781.2 1.2 VerilogVerilog HDL HDL 的历史的历史2024/7/279n nVHDL

7、 - 比比VerilogHDL早几年成为早几年成为I EEE标准;标准; - 语法语法/结构比较严格,因而编写出的结构比较严格,因而编写出的 模块风格模块风格比较清晰;比较清晰; - 比较适合由较多的设计人员合作完成比较适合由较多的设计人员合作完成 的特大型项目(一百万门以上)。的特大型项目(一百万门以上)。1.3 Verilog HDL 和和 VHDL的比较的比较2024/7/2710n nVerilog HDL - 较多的第三方工具的支持较多的第三方工具的支持 - 语法结构比语法结构比VHDL简单简单 - 学习起来比学习起来比VHDL容易容易 - 仿真工具比较好使仿真工具比较好使 - 测试

8、激励模块容易编写测试激励模块容易编写1.3 Verilog HDL 和和 VHDL的比较的比较2024/7/27111.3 Verilog HDL 和和 VHDL的比较的比较2024/7/27121.4 Verilog 目前的应用情况和适用的设计目前的应用情况和适用的设计nVerilog的主要应用包括:的主要应用包括:qASICASIC和和FPGAFPGA工程师编写可综合的工程师编写可综合的RTLRTL代码代码q高抽象级系统仿真进行系统结构开发高抽象级系统仿真进行系统结构开发q测试工程师用于编写各种层次的测试程序测试工程师用于编写各种层次的测试程序q用于用于ASICASIC和和FPGAFPGA

9、单元或更高层次的模块的模型开单元或更高层次的模块的模型开发发q其实很多时候其实很多时候FPGAFPGA只是电路系统中的一部分,也只是电路系统中的一部分,也就是说我们学习就是说我们学习verilogverilog不一定只是做芯片设计。不一定只是做芯片设计。2024/7/27131.4 Verilog 目前的应用情况和适用的设计目前的应用情况和适用的设计 Verilog 较为适合系统级(System)、算法级(Alogrithem)、寄存器传输级(RTL)、逻辑(Logic)、门级(Gate)和电路开关级(Switch)的设计,而对于特大型(千万门级以上)的系统级(System)设计,则VHDL更

10、为合适。在数字电路设计中,寄存器传输级(英语:register-transfer level, RTL)是一种对同步数字电路的抽象模型,这种模型是根据数字信号在硬件寄存器之间的流动,以及其逻辑代数运作方式来确定的。一个同步电路由两个主要元素构成:寄存器和组合逻辑电路。寄存器通常由D触发器组成,按照给定时间脉冲来进行同步时序操作,这个部分使得时序逻辑电路具有记忆的功能。组合逻辑电路则由逻辑门组成,提供电路的所有逻辑功能。2024/7/27151.5 采用采用 Verilog HDL 设计复杂数字电路的优点设计复杂数字电路的优点1.5.1 传统设计方法传统设计方法电路原理图输入法电路原理图输入法

11、采用电路原理图输入法进行设计,周期长、需要专门的设计工具、需手工布线等。这种低水平的设计方法大大延长了设计周期。2024/7/2716 采用Verilog输入法,可以很容易地把完成的设计移植到不同厂家的不同芯片中去,并在不同规模应用时可以较容易地作修改。 采用Verilog输入法最大的优点是其与工艺无关与工艺无关与工艺无关与工艺无关性性性性。实际上这是利用了计算机的巨大能力并在EDA工具帮助下,把逻辑验证与具体工艺库匹配、布线即时延计算分成不同的阶段来实现,从而减轻了人们的繁琐劳动。1.5.2 1.5.2 VerilogVerilog HDL HDL 设计法与传统的电路原设计法与传统的电路原理

12、图输入法的比较理图输入法的比较2024/7/27171.5 采用采用 Verilog HDL 设计设计复杂数字电路的优点复杂数字电路的优点1.5.3 Verilog 的标准化与软核的重用的标准化与软核的重用 Verilog 是在1983年由GDA公司首先开发成功的,经过诸多改进,于1995年11月正式被批准为Verilog IEEE13631995标准,又于2001年3月在原标准的基础上经过改进和补充推出Verilog IEEE13642001新标准。 由于Verilog HDL设计方法与工艺无关性,因而大大提高了Verilog 模型的可重用性。我们把功能经过验证的、可综合的、实现后电路结构总

13、门数在5000门以上的Verilog HDL模型称之为“软核”(Softcore),而把由软核构成的器件成为虚拟器件。利用软核和虚拟器件的可重复利用的特性就可利用软核和虚拟器件的可重复利用的特性就可大大缩短设计周期,加快了复杂电路的设计。大大缩短设计周期,加快了复杂电路的设计。2024/7/27181.6.3 1.6.3 具体模块的设计编译和仿真的过程具体模块的设计编译和仿真的过程1.6 1.6 VerilogVerilog HDL HDL 的设计流程简介的设计流程简介 从左图可以看出,模块设计流程主要由两大主要功能部分组成:1)1)1)1)设计开发:设计开发:设计开发:设计开发:即从编写设计

14、文件综合到布局布线投片生成这样一系列步骤。2)2)2)2)设计验证:设计验证:设计验证:设计验证:也就是进行各种仿真的一系列步骤,如果在仿真过程中发现问题就返回设计输入进行修改。2024/7/27191.6 1.6 VerilogVerilog HDL HDL 的设计流程简介的设计流程简介 1.6.4 1.6.4 对应具体工艺器件的优化、映象和布局布线对应具体工艺器件的优化、映象和布局布线 由于各种ASIC和FPFA器件的工艺各不相同,因而当用不同厂家的不同器件来实现已验证的逻辑网表(EDIF文件)时,就需要不同的基本单元库与布线延迟模型与之对应才能进行准确的优化、映象、和布局布线。基本单元库

15、与布线延迟模型由熟悉本厂工艺的工程师提供,再由EDA厂商的工程师编入相应的处理程序,而逻辑电路设计师只需用一文件说明所用的工艺器件和约束条件,EDA工具就会自动地根据这一文件选择相应的库和模型进行准确的处理从而大大提高设计效率。2024/7/27201.7 小结n掌握掌握HDLHDL设计方法应从学习设计方法应从学习VerilogVerilog HDL HDL设计方法开始。设计方法开始。n由于由于Top-DownTop-Down的设计方法是首先从系统设计入手的,因而从顶层的设计方法是首先从系统设计入手的,因而从顶层进行功能划分和结构设计。系统的总体仿真是顶层进行功能化分进行功能划分和结构设计。系

16、统的总体仿真是顶层进行功能化分的重要环节,这时的设计与工艺无关。的重要环节,这时的设计与工艺无关。n从底向上的设计在某种意义上讲是从底向上的设计在某种意义上讲是Top-DownTop-Down设计的逆过程。设计的逆过程。第二讲第二讲 初识初识VerilogVerilog 程序程序Verilog程序是用多个模块module组成的,有点类似C语言程序是由多个函数组成的。C语言程序基本结构:2024/7/27242.1 Verilog 程序举例程序举例 下面先介绍几个简单的下面先介绍几个简单的VerilogVerilog HDL HDL 程序,从中了解程序,从中了解VerilogVerilog程序的

17、特性程序的特性 【例例 2.1】 module muxtwo (out, a, b, sl); input a,b,sl; output out; reg out; always (sl or a or b) if (! sl) out = a; else out = b; endmoduleabslout2024/7/27252.1 Verilog 程序举例程序举例nMUX(多路选择器)的行为可以描述为:只要信号a或b或sl发生变化,如果sl为0则选择a输出;否则选择b输出。n这个行为的描述并没有说明如果输入 a 或 b是三态的(高阻时)输出应该是什么,但有具体结构的真实电路是有一定的输出的

18、。n没有考虑延时问题2024/7/27262.1 Verilog 程序举例程序举例【例例2.2】module module twomuxtwomux (out, a, b, (out, a, b, slsl);); input a, b, input a, b, slsl; ; output out; output out; not u1 ( not u1 (nslnsl, , slsl ); ); and #1 u2 ( and #1 u2 (selasela, a, , a, nselnsel);); and #1 u3 ( and #1 u3 (selbselb, b, , b, sls

19、l);); or #2 u4 (out, or #2 u4 (out, selasela, , selbselb););endmoduleendmoduleabslselbselansel MUXMUX的结构级描述,采用的结构级描述,采用VerilogVerilog基本单元基本单元( (门门) )描述。描描述。描述中含有传输延时。述中含有传输延时。Verilog程序是用多个模块程序是用多个模块modulemodule组成的,组成的,not 、and、or都可以看做一个都可以看做一个module。2024/7/27272.1 Verilog 程序举例程序举例【例例 2.3】 module add

20、er ( module adder ( count,sum,a,b,cincount,sum,a,b,cin ); ); input 2:0 input 2:0 a,ba,b; ; input input cincin; ; output count; output count; output 2:0 sum; output 2:0 sum; assign assign count,sumcount,sum=a+b+cina+b+cin; ; endmoduleendmodule 这个例子描述了一个三位的加法器。从例子中可以看这个例子描述了一个三位的加法器。从例子中可以看出,整个出,整个Ver

21、ilogVerilog HDL HDL程序是位于程序是位于modulemodule和和endmoduleendmodule声明声明语句之间的语句之间的2024/7/27282.1 Verilog 程序举例程序举例【例例 2.4】 module compare ( equal,a,b ); output equal; /声明输出信号声明输出信号equal input 1:0 a,b; /声明输入信号声明输入信号a,b assign equal=(a=b)?)?1:0; /*如果两个输入信号相等则输出为如果两个输入信号相等则输出为1。否则输出为。否则输出为0*/ endmodule 这个程序描述了

22、一个比较器这个程序描述了一个比较器. .在这个程中在这个程中,/*.*/,/*.*/和和/./.表示注释部分表示注释部分, ,注释只是为了注释只是为了方便程序员理解程序方便程序员理解程序, ,对编译是不起作用的。对编译是不起作用的。2024/7/2729n【例例2.52.5】nmodule trist2(out,in,enable);module trist2(out,in,enable);n output out; output out;n input in ,enable; input in ,enable;n bufil1 bufil1 mybuf(out,in,enablemybuf(

23、out,in,enable););nendmoduleendmodule2.1 Verilog 程序举例程序举例程序通过调用一个在Verilog语言提供的原语库中现存的三态驱动器元件bufil1来实现其逻辑功能。这个调用过程也称为库元件bufif1的实例化,在本模块中它被具体化为mybuf.30【例例2.62.6】module trist1(sout,sin,ena);module trist1(sout,sin,ena); output output soutsout; ; input input sin,enasin,ena; ; mytrimytri tri_inst(.out(sout

24、),.in(sin),.enable(enatri_inst(.out(sout),.in(sin),.enable(ena););/调用由调用由mytrimytri模块定义的实例元件模块定义的实例元件tri_insttri_inst,即把已定义的模块,即把已定义的模块myfrimyfri在本模块中具体化为在本模块中具体化为tri_insttri_instendmoduleendmodulemodule module mytri(out,in,enablemytri(out,in,enable);); output out; output out; input input in,enablei

25、n,enable; ; assign out= assign out=enable?in:enable?in:bzbz; ;endmoduleendmodule2.1 Verilog 模块的基本概念模块的基本概念312.2 小结小结通过上面的例子可以看到通过上面的例子可以看到: :(1 1)VerilogVerilog HDL HDL程序是由模块构成的。每个模块的内容都是位于程序是由模块构成的。每个模块的内容都是位于modulemodule和和endmoduleendmodule两个语句之间。每个模块实现特定的功能。两个语句之间。每个模块实现特定的功能。(2 2)模块是可以进行层次嵌套的。)模

26、块是可以进行层次嵌套的。(3 3)每个模块要进行端口定义)每个模块要进行端口定义, ,并说明输入输出口并说明输入输出口, ,然后对模块的功能进行然后对模块的功能进行描述。描述。(4 4)VerilogVerilog HDL HDL程序的书写格式自由程序的书写格式自由, ,一行可以写几个语句一行可以写几个语句, ,一个语句也可一个语句也可以分写多行。以分写多行。(5 5)除了)除了endmoduleendmodule语句外语句外, ,每个语句和数据定义的最后必须有分号。每个语句和数据定义的最后必须有分号。(6 6)可以用)可以用/*.*/*.*/和和/./.对对VerilogVerilog HD

27、L HDL程序的任何部分作注释。一个程序的任何部分作注释。一个好的好的, ,有使用价值的源程序都应当加上必要的注释有使用价值的源程序都应当加上必要的注释, ,以增强程序的可读以增强程序的可读性和可维护性。性和可维护性。第三讲第三讲 Verilog 语言语言Verilog语言学习n学会并记住10%20%语法,完成80%90%的程序设计(千万不要反过来!)n多看网络上的例程,尤其是有讲解的,如真oo无双博客。n边进行程序设计,边学习语法n优酷深入浅出玩转FPGA淘宝上开发板二百多一块,并且有书。3.1 Verilog模块3.2 数据类型 赋值语句、块语句条件语句、循环语句结构说明语句:initia

28、l、always、任务和函数系统任务和函数语句Verilog语言上述内容就是verilog语言的基本内容,其实每一种语言基本都是这些内容,只是有些细微差别,有点类似我们学习的语文,先学字母,拼音,字,词,句,章。C语言,是不是基本也是上述内容?3.3 运算符3.4 语句3.5 3.5 编译预处理编译预处理编译预处理编译预处理 生成语句(元件例化语句)3.1 模块的结构模块的结构 VerilogVerilog的基本设计单元是的基本设计单元是“模块模块”( (modulemodule ) ) 。一个模一个模块块是由两部分组成的,一部分描述接口,另一部分描述是由两部分组成的,一部分描述接口,另一部分

29、描述逻辑功能,即定义输入是如何影响输出的。逻辑功能,即定义输入是如何影响输出的。 module block1(a, b, c, d); module block1(a, b, c, d); input a, b; input a, b; output c, d; output c, d; assign c = a | b; assign c = a | b; assign d = a & b; assign d = a & b; endmoduleendmoduleabcd VerilogVerilog 模块的结构由在模块的结构由在modulemodule和和endmoduleendmodul

30、e 关键词之间的四个主要部分组成:关键词之间的四个主要部分组成: - - 端口定义:端口定义:端口定义:端口定义: module block1(a, b, c, d ); - I/O- I/O说明说明说明说明 : input a, b, c ; output d ; - - 内部信号声明:内部信号声明:内部信号声明:内部信号声明: wire x; - - 功能定义:功能定义:功能定义:功能定义: assign d = a | x ; assign x = ( b & c ); endmodule 3.1 模块的结构模块的结构3.1 模块的结构模块的结构3.1.1 3.1.1 模块的端口定义模块

31、的端口定义 模块的端口声明了模块的输入输出口。其格式如下:模块的端口声明了模块的输入输出口。其格式如下: module module 模块名模块名( (口口1 1,口,口2 2,口,口3 3,口,口4, 4, ););3.1.2 3.1.2 模块内容模块内容 模块的内容包括模块的内容包括I/OI/O说明、内部信号声明、功能定义。说明、内部信号声明、功能定义。n nI/OI/OI/OI/O说明的格式说明的格式说明的格式说明的格式 输入口: input信号位宽1:0 端口名1; input信号位宽1:0 端口名2; input信号位宽1:0 端口名i; /(共有i个输入口)3.1 模块的结构模块的

32、结构输出口输出口 outputoutput信号位宽信号位宽1 1:0 0 端口名端口名1 1; outputoutput信号位宽信号位宽1 1:0 0 端口名端口名2 2; output output信号位宽信号位宽1 1:0 0 端口名端口名j j; /(/(共有共有j j个个输出口输出口) )输入输入/ /输出口:输出口: inoutinout 信号位宽信号位宽1 1:0 0 端口名端口名1 1; inoutinout 信号位宽信号位宽1 1:0 0 端口名端口名2 2; inoutinout 信号位宽信号位宽1 1:0 0 端口名端口名k k; /(/(共有共有k k个个双向总线端口双向

33、总线端口) ) I/O I/O说明也可以写在端口声明语句里。其格式如下:说明也可以写在端口声明语句里。其格式如下: module module module_name(inputmodule_name(input port1,input port2, port1,input port2, output port1,output port2 output port1,output port2 ); );3.1 模块的结构模块的结构n n内部信号说明内部信号说明内部信号说明内部信号说明 在模块内用到的和与端口有关的在模块内用到的和与端口有关的wire wire 和和 regreg 变量的声明。变量

34、的声明。 如:如: regreg width-1 : 0 R width-1 : 0 R变量变量1 1,R R变量变量2 2 ; wire width-1 : 0 W wire width-1 : 0 W变量变量1 1,W W变量变量2 2 ; 3.1 模块的结构模块的结构n n功能定义功能定义 模块中最重要的部分是逻辑功能定义部分。有三种方法可在模块中最重要的部分是逻辑功能定义部分。有三种方法可在模块中产生逻辑。模块中产生逻辑。 - - - - 用用用用 assign assign assign assign 语句(数据流描述语句(数据流描述语句(数据流描述语句(数据流描述):):):):

35、assign assign a a = = b b & & c c ; ; - - - - 用实例元件(结构化描述用实例元件(结构化描述用实例元件(结构化描述用实例元件(结构化描述):):):): and2 and2 and_instand_inst ( q, a, b); ( q, a, b); - - - - 用用用用 “ “alwaysalwaysalwaysalways” ” 块(行为描述块(行为描述块(行为描述块(行为描述):):):): always ( always (posedgeposedge clkclk or or posedgeposedge clrclr) ) beg

36、in begin if ( if (clrclr) q= 0; else if (en) q= d;) q= 0; else if (en) q= d; end end3.1 模块的结构模块的结构3.1.3 理解要点理解要点如在模块中逻辑功能由下面三个语句块组成如在模块中逻辑功能由下面三个语句块组成 : assign cs = ( a0 & a1 & a2 ) ; / -1 and2 and_inst ( qout, a, b); / -2 always (posedge clk or posedge clr) /-3 begin if (clr) q= 0; else if (en) q=

37、d; end三条语句是并行的,它们产生独立的逻辑电路;三条语句是并行的,它们产生独立的逻辑电路;而在而在 always 块中块中: begin 与与 end 之间是顺序执行的。之间是顺序执行的。3.2 数据类型及其常量及变量数据类型及其常量及变量3.2.1.3.2.1.常量常量常量常量 在程序运行过程中在程序运行过程中在程序运行过程中在程序运行过程中, ,其值不能被改变的量称为常量。其值不能被改变的量称为常量。其值不能被改变的量称为常量。其值不能被改变的量称为常量。一数字一数字一数字一数字l l整数。整数。整数。整数。在在VerilogVerilog HDL HDL中中, ,整型常量即整常数有

38、以下四种进制表示整型常量即整常数有以下四种进制表示形式形式: :1) 1) 二进制整数二进制整数(b(b或或B)B)2) 2) 十进制整数十进制整数(d(d或或D)D)3) 3) 十六进制整数十六进制整数(h(h或或H)H)4) 4) 八进制整数八进制整数(o(o或或O)O) 数字表达方式有以下三种数字表达方式有以下三种: :1) 1) 这是一种全面的描述方式。这是一种全面的描述方式。2) 2) 在这种描述方式中在这种描述方式中, ,数字的位宽采用缺省位宽数字的位宽采用缺省位宽( (这由具体的机器系统决定这由具体的机器系统决定, ,但至少但至少3232位位) )。3) 3) 在这种描述方式中在

39、这种描述方式中, ,采用缺省进制十进制。采用缺省进制十进制。数值1. Verilog HDL中的数值可取下面的四类值:0逻辑零、逻辑非、低电平1逻辑1、逻辑真、高电平x或X不确定的逻辑状态z或Z高阻态Verilog HDL中有两类数值常量 整型数和实型数 下划线符号“_”除了不能放于数值的首位以外,可以随意用在整型数与实型数中,他们对数值的大小没有任何改变,只是为了提高可读性。 1)整型数及其表示 Verilog HDL的整数可以使二进制(b或B)、十进制(d或D)、十六进制(h或H)与八进制(o或O),有下面三种书写形式(1)简单的十进制格式;(2)缺省位宽的基数格式;(3)指定位宽的基数格

40、式。Verilog HDL中有两类数值常量 整型数和实型数()简单的十进制格式:()简单的十进制格式:用的数字串组成的十进制数,可以用符号用的数字串组成的十进制数,可以用符号“”或或“”来表示数的来表示数的正负正负()缺省位宽的基数格式;()缺省位宽的基数格式; 表示形式为:表示形式为:符号符号“”为基数格式表示的固有字符,该字符不能省略,否则为非法表示为基数格式表示的固有字符,该字符不能省略,否则为非法表示形式;参数形式;参数用于说明数值采用的进制格式;参数用于说明数值采用的进制格式;参数为相应进制格式下的一串数字这种格式未指定位宽,其缺省值至少为位为相应进制格式下的一串数字这种格式未指定位

41、宽,其缺省值至少为位()指定位宽的基数格式:()指定位宽的基数格式: 表示形式为:表示形式为:sizebase_formatnumber参数参数size用来指定所表示数字的位宽当位宽小于数值的实际大小时,用来指定所表示数字的位宽当位宽小于数值的实际大小时,相应的高位部分被忽略;当位宽大于数值的实际位数,且数值的最高位是或相应的高位部分被忽略;当位宽大于数值的实际位数,且数值的最高位是或时,相应的高位部分补;而当位宽大于数值的实际位数,但数值的最高位是时,相应的高位部分补;而当位宽大于数值的实际位数,但数值的最高位是x或或z时,相应的高位部分补或时,相应的高位部分补或数制基数符号合法的表示值二进

42、制b or B0,1,x,X,z,Z,?,_八进制o or O07,x,X,z,Z,?,_十进制d or D09,_十六进制h or H09,af,AF,x,X,z,Z,?,_Verilog HDL中有两类数值常量 整型数和实型数基数符号及其合法的表示值数值表示位宽数制等效二进制值及其解书释10缺省十进制00_1010(32位或以上)4ac缺省十进制非法,十进制表示不允许出现ac字样h4ac缺省十六进制0_0100_1010_1100(32位或以上)9o6719位八进制0110_0111_00019o-6719位八进制非法,符号位只能出现在表示的最左端6hf36位十六进制11_0011,高位部

43、分被舍去6hf6位十六进制00_1111,高位部分由0补足3b10x3位二进制10x12h2x612位十六进制0010_xxxx_10106hx6位十六进制xx_xxxx,高位部分由x补足Verilog HDL中有两类数值常量 整型数和实型数例;三种格式的整数表示法15(十进制15)简单的十进制h15(十进制21,十六进制15)缺省位宽的十六进制5b10011(十进制19,二进制10011)位的二进制12h01F(十进制31,十六进制01F)位的十六进制Verilog HDL中有两类数值常量 整型数和实型数Verilog HDL中的实数可以用十进制与科学计数法两种格式来表示,如果采用十进制格式

44、,小数点两边必须都有数字,否则为非法的表示形式实数表示法的实例1.8 /十进制计数法3.8e10 /科学计数法2.1E-9 /科学计数法可用e或E表示,其结果相同3_2387.3398_3047 /使用下划线提高可读性3. /非法表示,小数点两遍都必须有数.2e6 /非法表示,小数点两遍都必须有数.12 /非法表示,小数点两遍都必须有数实型数及其表示Verilog HDL中有两类数值常量 整型数和实型数3.2 数据类型及其常量及变量数据类型及其常量及变量l lx x和和z z值。值。l在数字电路中在数字电路中,x,x代表不定值代表不定值,z,z代表高阻值。一代表高阻值。一个个x x可以用来定义

45、十六进制数的可以用来定义十六进制数的4 4位二进制数的位二进制数的状态状态, ,八进制数的八进制数的3 3位位, ,二进制数的二进制数的1 1位。位。z z的表的表示方式同示方式同x x类似。类似。z z还有一种表达方式是可以写还有一种表达方式是可以写作作“? ?”。3.2 数据类型及其常量及变量数据类型及其常量及变量l l 负数。负数。负数。负数。一个数字可以被定义为负数一个数字可以被定义为负数, ,只需在位宽表达式前加一个减号只需在位宽表达式前加一个减号, ,减号减号必须写在数字定义表达式的最前面。注意减号不可以放在位宽和进制之间必须写在数字定义表达式的最前面。注意减号不可以放在位宽和进制

46、之间也不也不可以放在进制和具体的数之间。可以放在进制和具体的数之间。 -8d5 / -8d5 /这个表达式代表这个表达式代表5 5的补数(用八位二进制数表示的补数(用八位二进制数表示) ) 8 8d-5 /d-5 /非法格式非法格式l l下画线下画线下画线下画线(underscore_)(underscore_)(underscore_)(underscore_)。下划线可以用来分隔开数的表达以提高程序可。下划线可以用来分隔开数的表达以提高程序可读性。但不可以用在位宽和进制处读性。但不可以用在位宽和进制处, ,只能用在具体的数字之间。只能用在具体的数字之间。 16b1010_1011_1111

47、_1010 / 16b1010_1011_1111_1010 /合法格式合法格式 8b_0011_1010 / 8b_0011_1010 /非法格式非法格式 当常量不说明位数时,默认值是当常量不说明位数时,默认值是3232位,每个字母用位,每个字母用8 8位的位的ASCIIASCII值表值表示。示。3.2 数据类型及其常量及变量数据类型及其常量及变量二参数二参数(parameter)型型用参数声明一个可变常量,常用于定义延时及宽度变量。用参数声明一个可变常量,常用于定义延时及宽度变量。参数定义的语法:参数定义的语法:parameter ;可一次定义多个参数,用逗号隔开。可一次定义多个参数,用逗

48、号隔开。在使用文字在使用文字(literal)的地方都可以使用参数。的地方都可以使用参数。参数的定义是局部的,只在当前模块中有效。参数的定义是局部的,只在当前模块中有效。参数定义可使用以前定义的整数和实数参数。参数定义可使用以前定义的整数和实数参数。module mod1( out, in1, in2);module mod1( out, in1, in2); . . . . . .parameter cycle = 20, prop_ del = 3,parameter cycle = 20, prop_ del = 3, setup = cycle/2 - setup = cycle/2

49、- prop_delprop_del, , p1 = 8, p1 = 8, x_ word = 16bx, x_ word = 16bx, file = / usr1/ file = / usr1/ jdoughjdough/ design/ / design/ memmem_ file. _ file. datdat; ; . . . . . . wire p1: 0 w1; / A wire declaration using parameter wire p1: 0 w1; / A wire declaration using parameter . . . . . .endmodule

50、endmodule注意注意:参数:参数file不是不是string,而是一个整数,而是一个整数,其值是所有字母的扩展其值是所有字母的扩展ASCII值。若值。若file=“AB”,则,则file值为值为8h4142。用法:用法:$fopen(file);$display(“%s”, file);3.2 数据类型及其常量及变量数据类型及其常量及变量3.2.2 变量变量 变量即在程序运行过程中其值可以改变的量。常用的网络数据类型包括wirewire型和型和tritri型型。wire型变量通常是用来表示单个门驱动或连续赋值语句驱动的网络型数据,tri型变量则用来表示多驱动器驱动的网络型数据。 表 1.

51、3.1 Wire/tri 变量的真值3.2 数据类型及其常量及变量数据类型及其常量及变量一一一一 wirewire型型型型 wire型数据常用来表示用于以assign关键字指定的组合逻辑信号。Verilog程序模块中输入输出信号类型缺省时自动定义为wire型。其格式如下: wire n-1:0 数据名1,数据名2,数据名i; /共有i条总线,每条总线内有n条线路,或 wire n:1 数据名1,数据名2,数据名i;3.2 数据类型及其常量及变量数据类型及其常量及变量二二二二 regreg型型型型 寄存器是数据储存单元的抽象。寄存器数据类型的关键寄存器是数据储存单元的抽象。寄存器数据类型的关键字

52、是字是 regreg。 regreg类型数据的默认初始值为不定值类型数据的默认初始值为不定值x x。 regreg型数据常用来表示用于型数据常用来表示用于“alwaysalways”模块内的指定信号,模块内的指定信号,常代常代表触发器。表触发器。在在“alwaysalways”块内被赋值的每一个信号都必须定块内被赋值的每一个信号都必须定义成义成regreg型。型。 regreg型数据的格式如下:型数据的格式如下: regreg n-1:0 n-1:0 数据名数据名1,1,数据名数据名2,2, 数据名数据名i;i;或或 regreg n:1 n:1 数据名数据名1,1,数据名数据名2,2, 数据

53、名数据名i;i;module top;module top;wire y;wire y; regreg a, b; a, b; DUT u1(y,a,b); DUT u1(y,a,b); initial initial begin begin a = 0; b = 0; a = 0; b = 0; #10 a =1; #10 a =1; . . end endendmoduleendmodule module DUT(Y, A, B_);output Y;input A,B: wire Y, A, B; and (Y, A, B);endmodule模块DUT的边界输入口输出口输出/入口net

54、netnet/registernetnet/registernetinout举例说明数据类型的选择举例说明数据类型的选择n输入口(输入口(inputinput)可以由寄存器或网络连接驱)可以由寄存器或网络连接驱动,但它本身只能驱动网络连接。动,但它本身只能驱动网络连接。n输出口输出口 (output)(output)可以由寄存器或网络连接驱可以由寄存器或网络连接驱动,但它本身只能驱动网络连接。动,但它本身只能驱动网络连接。n输入输入/ /输出口输出口( (inoutinout) )只可以由网络连接驱动,只可以由网络连接驱动,它本身也只能驱动网络连接。它本身也只能驱动网络连接。n如果信号变量是在

55、过程块如果信号变量是在过程块 (initial(initial块块 或或 alwaysalways块块) )中被赋值的,必须把它声明为寄存中被赋值的,必须把它声明为寄存器类型变量器类型变量 如何选择正确的数据类型?如何选择正确的数据类型?如何选择正确的数据类型如何选择正确的数据类型module top;module top;wire y; wire y; regreg a, b; a, b;DUT u1 (y, a, b) ;DUT u1 (y, a, b) ;initial begininitial begina = 0; b = 0;a = 0; b = 0; #5 a = 1; #5 a

56、 = 1; end endendmoduleendmodulemodule DUT (Y, A, B);module DUT (Y, A, B);output Y;output Y;input A, B;input A, B;wire Y, A, B;wire Y, A, B;and (Y, A, B) ;and (Y, A, B) ;endmoduleendmodule输入端口可以由输入端口可以由net/register驱动,但驱动,但输入端口只能是输入端口只能是net输出端口可以是输出端口可以是net/register类型,输类型,输出端口只能驱动出端口只能驱动net在过程块中只能给在过程

57、块中只能给register类型赋值类型赋值若若Y,A,B说明为说明为reg则会产生错误。则会产生错误。in1in2OABY双向端口输入双向端口输入/输出输出只能是只能是net类型类型选择数据类型时常犯的错误举例选择数据类型时常犯的错误举例修改前:修改前:module example(o1, o2, a, b, c, d); input a, b, c, d; output o1, o2; reg c, d; reg o2 and u1(o2, c, d); always (a or b) if (a) o1 = b; else o1 = 0;endmodule修改后:修改后:module ex

58、ample(o1, o2, a, b, c, d); input a, b, c, d; output o1, o2;/ reg c, d;/ reg o2 reg o1; and u1(o2, c, d); always (a or b) if (a) o1 = b; else o1 = 0;endmoduleexample.v选择数据类型时常犯的错误举例Compiling source file example.vError! Illegal left-hand-side assignment Verilog-ILHSA example.v, 11: o1 = b;Error! Illeg

59、al left-hand-side assignment Verilog-ILHSA example.v, 12: o1 = 0;2 errors第一次编译信息第一次编译信息verilog c example.v第二次编译信息第二次编译信息Compiling source file example.vError! Incompatible declaration, (c) defined as input at line 2 Verilog-IDDIL example.v, 5: Error! Incompatible declaration, (d) defined as input at

60、line 2 Verilog-IDDIL example.v, 5: Error! Gate (u1) has illegal output specification Verilog-GHIOS example.v, 8: 3 errors3.2 数据类型及其常量及变量数据类型及其常量及变量三三三三 memorymemory型型型型 VerilogVerilog HDL HDL通过对通过对regreg型变量建立数组来对存储器建模,型变量建立数组来对存储器建模,可以描述可以描述RAMRAM型存储器,型存储器,ROMROM存储器和存储器和regreg文件。数组中的每一个单元文件。数组中的每一个单

61、元通过一个通过一个数组索引进行寻址。在数组索引进行寻址。在VerilogVerilog语言中没有多维数组存在。语言中没有多维数组存在。 memorymemory型数型数据是通过扩展据是通过扩展regreg型数据的地址范围来生成的。其格式如下:型数据的地址范围来生成的。其格式如下: regreg n-1:0 n-1:0 存储器名存储器名m-1:0m-1:0;或或 regreg n-1:0 n-1:0 存储器名存储器名m:1m:1;3.3 运算符及表达式运算符及表达式 VerilogVerilog HDL HDL语言的运算符范围很广,其运算符按其功能可分语言的运算符范围很广,其运算符按其功能可分为

62、以下几类为以下几类: :运算符分类所含运算符算术运算符+,-,*,/,%逻辑运算符!,&,|关系运算符,=相等运算符=,!=,=,!=位运算符,&,|,or归约运算符&,&,|,|,or移位运算符条件运算符?:连接运算符3.3 运算符及表达式运算符及表达式 在在Verilog HDL语言中运算符所带的操作数是不同的,按其所带语言中运算符所带的操作数是不同的,按其所带操作数的个数运算符可分为三种操作数的个数运算符可分为三种:1) 单目运算符单目运算符(unary operator):可以带一个操作数可以带一个操作数,操作数放在运算符的右边。操作数放在运算符的右边。2) 二目运算符二目运算符(bi

63、nary operator):可以带二个操作数可以带二个操作数,操作数放在运算符的两边。操作数放在运算符的两边。3) 三目运算符三目运算符(ternary operator):可以带三个操作可以带三个操作,这三个操作数用三目运算符这三个操作数用三目运算符分隔开。分隔开。 见下例见下例: clock = clock; / 是一个单目取反运算符是一个单目取反运算符, clock是操作数。是操作数。 c = a | b; / 是一个二目按位或运算符是一个二目按位或运算符, a 和和 b是操作数。是操作数。 r = s ? t : u; / ?: 是一个三目条件运算符是一个三目条件运算符, s,t,u

64、是操作数。是操作数。3.3 运算符及表达式运算符及表达式3.3.1.基本的算术运算符基本的算术运算符 + 加加 - 减减 * 乘乘 / 除除 % 模模 将负数赋值给将负数赋值给reg或其它无符号变或其它无符号变量使用量使用2的补码算术。的补码算术。 如果操作数的某一位是如果操作数的某一位是x或或z,则,则结果为结果为x 在整数除法中,余数舍弃在整数除法中,余数舍弃 模运算中使用第一个操作数的符模运算中使用第一个操作数的符号号module module arithopsarithops (); (); parameter five = 5; parameter five = 5; integer

65、 integer ansans, , intint; ; regreg 3: 0 3: 0 regarega, , regbregb; ; regreg 3: 0 num; 3: 0 num; initial begin initial begin regarega = 3; = 3; regbregb = 4b1010; = 4b1010; intint = -3; / = -3; /intint = 11111111_1101 = 11111111_1101 end end initial fork initial fork #10 #10 ansans = five * = five *

66、 intint; / ; / ansans = -15 = -15 #20 #20 ansans = ( = (intint + 5)/ 2; / + 5)/ 2; / ansans = 1 = 1 #30 #30 ansans = five/ = five/ intint; / ; / ansans = -1 = -1 #40 num = #40 num = regarega + + regbregb; / num = 1101; / num = 1101 #50 num = #50 num = regarega + 1; / num = 0100 + 1; / num = 0100 #60

67、 num = #60 num = intint; / num = 1101; / num = 1101 #70 num = #70 num = regbregb % % regarega; / num = 1; / num = 1 #80 $finish; #80 $finish;joinjoinendmoduleendmodule注意integer和reg类型在算术运算时的差别。integer是有符号数,而reg是无符号数。3.3 运算符及表达式运算符及表达式3.3.2.位运算符位运算符 not & and | or xor xnor xnor 按位操作符对矢量中相对应位运算。按位操作符对矢

68、量中相对应位运算。regbregb = 4b1 0 1 0 = 4b1 0 1 0regcregc = 4b1 x 1 0 = 4b1 x 1 0num = num = regbregb & & regcregc = 1 0 1 0 ; = 1 0 1 0 ; 位值为位值为x x时不一定产生时不一定产生x x结果。如结果。如#50#50时的时的oror计算。计算。module bitwise ();module bitwise (); regreg 3: 0 3: 0 regarega, , regbregb, , regcregc; ; regreg 3: 0 num; 3: 0 num;

69、initial begin initial begin regarega = 4b1001; = 4b1001; regbregb = 4b1010; = 4b1010; regcregc = 4b11x0; = 4b11x0; end end initial fork initial fork #10 num = #10 num = regarega & 0; / num = 0000 & 0; / num = 0000 #20 num = #20 num = regarega & & regbregb; / num = 1000; / num = 1000 #30 num = #30 nu

70、m = regarega | | regbregb; / num = 1011; / num = 1011 #40 num = #40 num = regbregb & & regcregc; / num = 10x0; / num = 10x0 #50 num = #50 num = regbregb | | regcregc; / num = 1110; / num = 1110 #60 $finish; #60 $finish; join joinendmoduleendmodule01xz结果结果10xx&01xz00000101xxx0xxxz0xxx五类按位操作符的运算规则五类按位

71、操作符的运算规则|01xz001xx11111xx1xxzx1xx01xz001xx110xxxxxxxz0xx1or01xz010x0101xxxxxxxzxxxx五类按位操作符的运算规则五类按位操作符的运算规则module bitTest; reg3: 0a,b,c; initial begin a=4b1100;b=4b0011;c=4,b0101; $displayb(a); /按位非运算符,结果为4b0011 $displayb(a&c); /按位与运算符,结果为4b0100 $displayb(a|b); /按位或运算符,结果为4b1111 $displayb(bc); /按位异或

72、运算符,结果为4b0110 $displayb(ac); /按位异或非运算符,结果为4b0110 end endmodule按位运算的例子3.3 运算符及表达式运算符及表达式3.3.2.位运算符位运算符当两个操作数位数不同时,当两个操作数位数不同时,位数位数少的操作数零扩展到相同位少的操作数零扩展到相同位数数。a = 4b1011;a = 4b1011;b = 8b01010011;b = 8b01010011;c = a | b; / ac = a | b; / a零扩展为零扩展为 8b000010118b00001011 位运算符中除了位运算符中除了是单目运算符以外是单目运算符以外,均为二

73、目运算符均为二目运算符,即要求运算符两侧各有一个操作数即要求运算符两侧各有一个操作数. 位运算符中的二目运算符要求对两个操作数的相应位位运算符中的二目运算符要求对两个操作数的相应位进行运算操作。进行运算操作。3.3.3 逻辑运算符逻辑运算符!not&and|or 逻辑操作符的结果为一位逻辑操作符的结果为一位1,0或或x。逻辑操作符只对逻辑值运算。逻辑操作符只对逻辑值运算。如操作数为全如操作数为全0,则其逻辑值为,则其逻辑值为false如操作数有一位为如操作数有一位为1,则其逻辑值为,则其逻辑值为true若操作数若操作数只只包含包含0、x、z,则逻辑值,则逻辑值为为x逻辑反操作符将操作数的逻辑值

74、逻辑反操作符将操作数的逻辑值取反。例如,若操作数为全取反。例如,若操作数为全0,则,则其逻辑值为其逻辑值为0,逻辑反操作值为,逻辑反操作值为1。module logical ();module logical (); parameter five = 5; parameter five = 5; regreg ansans; ; regreg 3: 0 3: 0 regarega, , regbregb, , regcregc; ; initial initial begin begin regarega = 4b0011; = 4b0011; / /逻辑值为逻辑值为“1 1” regbreg

75、b = 4b10xz; / = 4b10xz; /逻辑值为逻辑值为“1 1” regcregc = 4b0z0x; / = 4b0z0x; /逻辑值为逻辑值为“x x” end end initial fork initial fork #10 #10 ansans = = regarega & 0; / & 0; / ansans = 0 = 0 #20 #20 ansans = = regarega | 0; / | 0; / ansans = 1 = 1 #30 #30 ansans = = regarega & five; / & five; / ansans = 1 = 1 #40

76、#40 ansans = = regbregb & & regarega; / ; / ansans = 1 = 1 #50 #50 ansans = = regcregc | 0; / | 0; / ansans = x = x #60 $finish; #60 $finish; join joinendmoduleendmodule3.3 运算符及表达式运算符及表达式Verilog HDL提供了三种逻辑运算符:1.逻辑与运算符:&2.逻辑或运算符: |3.逻辑非运算符:!其中逻辑与和逻辑或是双目运算符,逻辑非是单目运算符mn!m!nM&nM|n00110001100110010111001

77、1逻辑运算的真值表逻辑运算符逻辑运算符module logicalTest; reg3:0a,b,c; initial begin a=2;b=0;c=4hx; $display(a&b); /逻辑与,结果为0 $display(a|b); /逻辑或,结果为1 $display(!a); /逻辑非,结果为0 $display(a|c); /结果为1,未知数|1(=1) $display(!c); /结果为未知数 endendmodule逻辑运算符逻辑运算符3.3.4 关系运算符关系运算符大于大于=大于等于大于等于 regarega ; / ; / valval = x = x #20 #20

78、valval = = regbregb = = regarega ; / ; / valval = 1 = 1 #40 #40 valval = = regbregb regcregc ; / ; / valval = 1 = 1 #50 $finish; #50 $finish; join joinendmoduleendmodulerega和和regc的关系取决的关系取决于于x无论无论x为何值,为何值,regbregc 其结果是其结果是1b1、1b0或或1bx。3.3 运算符及表达式运算符及表达式3.3.5 等式运算符等式运算符= =01xz010xx101xxxxxxxzxxxx 赋值操

79、作符,将等式右边表达式的值拷贝到左赋值操作符,将等式右边表达式的值拷贝到左边。边。 逻辑等逻辑等 case等等= 01xz0100010100x0010z0001a = 2b1x;a = 2b1x;b = 2b1x;b = 2b1x;if (a = b)if (a = b) $display( a is equal to b); $display( a is equal to b);elseelse $display( a is not equal to b); $display( a is not equal to b);a = 2b1x;a = 2b1x;b = 2b1x;b = 2b1x

80、;if (a = b)if (a = b) $display( a is identical to b); $display( a is identical to b);elseelse $display( a is not identical to b); $display( a is not identical to b);注意逻辑等与注意逻辑等与注意逻辑等与注意逻辑等与casecase等的差别等的差别等的差别等的差别2b1x=2b0x 值为值为0,因为不相,因为不相等等2b1x=2b1x 值为值为x,因为可能,因为可能不相等,也可能相等不相等,也可能相等2b1x=2b0x 值为值为0,因

81、为不相,因为不相同同2b1x=2b1x 值为值为1,因为相同,因为相同3.3 运算符及表达式运算符及表达式= 逻辑等逻辑等! = 逻辑不等逻辑不等 其结果是其结果是1b1、1b0或或1bx。 如果左边及右边为确定值并如果左边及右边为确定值并且相等,则结果为且相等,则结果为1。 如果左边及右边为确定值并如果左边及右边为确定值并且不相等,则结果为且不相等,则结果为0。 如果左边及右边有值不能确如果左边及右边有值不能确定的位,但值确定的位相等,定的位,但值确定的位相等,则结果为则结果为x。!=的结果与的结果与= =相反相反值确定是指所有的位为值确定是指所有的位为0或或1。不确定值是有值为。不确定值是

82、有值为x或或z的位。的位。module equalities1();module equalities1(); regreg 3: 0 3: 0 regarega, , regbregb, , regcregc; ; regreg valval; ; initial begin initial begin regarega = 4b0011; = 4b0011; regbregb = 4b1010; = 4b1010; regcregc = 4b1x10; = 4b1x10; end end initial fork initial fork #10 #10 valval = = regare

83、ga = = regbregb ; / ; / valval = 0 = 0 #20 #20 valval = = regarega != != regcregc; / ; / valval = 1 = 1 #30 #30 valval = = regbregb != != regcregc; / ; / valval = x = x #40 #40 valval = = regcregc = = regcregc; / ; / valval = x = x #50 $finish; #50 $finish; join joinendmoduleendmodule3.3.5 等式运算符等式运算

84、符3.3 运算符及表达式运算符及表达式 module module equTestequTest; ; reg3: 0a,b,c,d,e,f; reg3: 0a,b,c,d,e,f; initial begin initial begin a=4;b=7; / a=4;b=7; /缺省值为十进制数缺省值为十进制数 c=4c=4b010;b010; d=4 d=4bx10;bx10; e=4 e=4bx101;bx101; f=4 f=4bxx01;bxx01; $ $displayb(cdisplayb(c); /); /输出输出00100010 $ $displayb(ddisplayb(d

85、); /); /输出输出xx10xx10 $ $displayb(adisplayb(a=b); /=b); /相等运算符,结果为相等运算符,结果为0 0 $ $displayb(cdisplayb(c !=d); / !=d); /不相等运算符,结果为不相等运算符,结果为x x $ $displayb(cdisplayb(c !=f); / !=f); /不相等运算符,结果为不相等运算符,结果为1 1 $ $displayb(ddisplayb(d=e); /=e); /全等运算符,结果为全等运算符,结果为0 0 $ $displayb(cdisplayb(c !=d); / !=d); /

86、非全等运算符,结果为非全等运算符,结果为1 1 end endendmoduleendmodule相等关系运算符的例子= 相同相同(case等等)! = 不相同不相同(case不等不等) 其结果是其结果是1b1、1b0或或1bx。 如果左边及右边的值如果左边及右边的值相同(包括相同(包括x、z),则,则结果为结果为1。如果左边及右边的值不如果左边及右边的值不相同,则结果为相同,则结果为0。!=的结果与的结果与 = 相反相反综合工具不支持综合工具不支持module equalities2();module equalities2(); regreg 3: 0 3: 0 regarega, , r

87、egbregb, , regcregc; ; regreg valval; ; initial begin initial begin regarega = 4b0011; = 4b0011; regbregb = 4b1010; = 4b1010; regcregc = 4b1x10; = 4b1x10; end end initial fork initial fork #10 #10 valval = = regarega = = regbregb ; / ; / valval = 0 = 0 #20 #20 valval = = regarega != != regcregc; / ;

88、 / valval = 1 = 1 #30 #30 valval = = regbregb = = regcregc; / ; / valval = 0 = 0 #40 #40 valval = = regcregc = = regcregc; / ; / valval = 1 = 1 #50 $finish; #50 $finish; join joinendmoduleendmodule3.3.6 移位运算符移位运算符逻辑右移逻辑右移逻辑左移逻辑左移 移位操作符对其左边的操作数进移位操作符对其左边的操作数进行向左或向右的位移位操作。行向左或向右的位移位操作。第二个操作数(移位位数)是无第二

89、个操作数(移位位数)是无符号数符号数若第二个操作数是若第二个操作数是x x或或z z则结果为则结果为x x 将左边的操作数右移右将左边的操作数右移右边操作数指定的位数边操作数指定的位数在赋值语句中,如果右边在赋值语句中,如果右边(RHS)(RHS)的结果的结果: :位宽大于左边,则把最高位截去位宽大于左边,则把最高位截去位宽小于左边,则零扩展位宽小于左边,则零扩展module shift ();module shift (); regreg 9: 0 num, num1; 9: 0 num, num1; regreg 7: 0 7: 0 regarega, , regbregb; ; init

90、ial initial regarega = 8b00001100; = 8b00001100; initial fork initial fork #10 num = #10 num = regarega 5 ; / num = 01_1000_0000 5 ; / num = 01_1000_0000 #10 #10 regbregb = = regarega 5 ; / 5 ; / regbregb = 1000_0000 = 1000_0000 #20 num = #20 num 3; / num = 00_0000_0001 3; / num = 00_0000_0001 #20 #

91、20 regbregb = 3 ; / 3 ; / regbregb = 0000_0001 = 0000_0001 #30 num = 10b11_1111_0000; #30 num = 10b11_1111_0000; #40 #40 regarega = num 2; / = num 2; /regarega = 1100_0000 = 1100_0000 #40 num1 = num 2;/num1=11_1100_0000 #40 num1 = num 2;/num1=11_1100_0000 #50 #50 regarega 2; / 2; /regarega = 1111_11

92、00 = 1111_1100 #50 num1 2;/num1=00_1111_1100 #50 num1 2;/num1=00_1111_1100 #60 $finish; #60 $finish; join joinendmoduleendmodule建议:表达式左右位数一建议:表达式左右位数一致致3.3 运算符及表达式运算符及表达式3.3.7 位拼接运算符位拼接运算符 位拼接还可以用嵌套的方式来表达。位拼接还可以用嵌套的方式来表达。位拼接还可以用嵌套的方式来表达。位拼接还可以用嵌套的方式来表达。 b,3a,b / b,3a,b / b,3a,b / b,3a,b /这等同于这等同于这等同

93、于这等同于 b,a,b,a,b,a,bb,a,b,a,b,a,bb,a,b,a,b,a,bb,a,b,a,b,a,b 用于表示重复的表达式如上例中的用于表示重复的表达式如上例中的用于表示重复的表达式如上例中的用于表示重复的表达式如上例中的4 4 4 4和和和和3 3 3 3,必须是常数表达式。,必须是常数表达式。,必须是常数表达式。,必须是常数表达式。 位拼接运算符位拼接运算符其使用方法如下:其使用方法如下:信号信号1的某几位,信号的某几位,信号2的某几位,的某几位,.,.,信号信号n的某的某几位几位例:例: a,b3:0,w,3b101位拼接还可以用重复法来简化表达式。位拼接还可以用重复法来

94、简化表达式。 4w / 4w /这等同于这等同于 w,w,w,ww,w,w,w 3.3 运算符及表达式运算符及表达式 module module concatTestconcatTest; ; regreg a; a; regreg 1: 0b; 1: 0b; regreg 5: 0c; 5: 0c; initial begin initial begin a=1 a=1b1;b1; b=2 b=2b00;b00; c=6 c=6b101001;b101001;$ $displayb(adisplayb(a, b);/, b);/产生一个产生一个3 3位数位数3 3b100b100$displ

95、ayb(c5: 3, a); $displayb(c5: 3, a); /产生一个产生一个4 4位数位数4 4b1011b1011 end endendmoduleendmodule module module replicTestreplicTest; ; regreg a; a; regreg 1: 0b; 1: 0b; regreg 5: 0c; 5: 0c; initial begin initial begin a=1 a=1b1;b1; b=2 b=2b00;b00; $displayb(4a); / $displayb(4a); /结果为结果为11111111 c=4a; c=4

96、a; $ $displayb(cdisplayb(c); /); /结果为结果为001111001111 end end endmoduleendmodule连接运算的例子连接运算的例子复制运算的例子复制运算的例子3.3.8 缩减运算符缩减运算符 缩减运算的具体运算过程是这样的缩减运算的具体运算过程是这样的:第一步先将操作数第一步先将操作数的第一位与第二位进行或与非运算的第一位与第二位进行或与非运算,第二步将运算结果与第第二步将运算结果与第三位进行或与非运算三位进行或与非运算,依次类推依次类推,直至最后一位。直至最后一位。 reg 3:0 B; reg C; C = &B; 相当于:相当于:

97、C =( (B0&B1) & B2 ) & B3; 由于缩减运算的与、或、非运算规则类似于位运算符与、或、由于缩减运算的与、或、非运算规则类似于位运算符与、或、非运算规则非运算规则,这里不再详细讲述这里不再详细讲述,请参照位运算符的运算规则介绍请参照位运算符的运算规则介绍3.3 运算符及表达式运算符及表达式3.3.9 优先级别优先级别下面对各种运算符的优先级别关系作一总结。见下下面对各种运算符的优先级别关系作一总结。见下表表: :操作符类型操作符类型操作符类型操作符类型符号符号符号符号连接及复制操作符连接及复制操作符一元操作符一元操作符算术操作符算术操作符逻辑移位操作符逻辑移位操作符关系操作符

98、关系操作符相等操作符相等操作符按位操作符按位操作符逻辑操作符逻辑操作符条件操作符条件操作符 ! * / %+ - = = = = = = != != =& | &|?:最高最高优先级优先级最低最低3.3 运算符及表达式运算符及表达式3.4 语句语句n赋值语句赋值语句 在在在在VerilogVerilog HDL HDL语言中,信号有两种赋值方式:语言中,信号有两种赋值方式:语言中,信号有两种赋值方式:语言中,信号有两种赋值方式:(1) 非阻塞非阻塞(Non_Blocking)赋值方式赋值方式( 如如 b = a; )块结束后才完成赋值操作。块结束后才完成赋值操作。b的值并不是立刻就改变的。的值

99、并不是立刻就改变的。这是一种比较常用的赋值方法。(特别在编写可综合模块时)这是一种比较常用的赋值方法。(特别在编写可综合模块时)(2) 阻塞阻塞(Blocking)赋值方式赋值方式( 如如 b = a; )赋值语句执行完后赋值语句执行完后,块才结束。块才结束。b的值在赋值语句执行完后立刻就改变的。的值在赋值语句执行完后立刻就改变的。在沿触发的在沿触发的always块中使用时,综合后可能会产生意想不到的结果。块中使用时,综合后可能会产生意想不到的结果。3.4.1 赋值语句和块语句赋值语句和块语句3.4.1 赋值语句和块语句赋值语句和块语句n赋值语句赋值语句module module swap_v

100、alsswap_vals; ; regreg a, b, a, b, clkclk; ; initial begin initial begin a = 0; b = 1; a = 0; b = 1; clkclk = 0; = 0; end end always #5 always #5 clkclk = = clkclk; ; always ( always ( posedgeposedge clkclk) ) begin begin a a = b; / b; / 非阻塞过程赋非阻塞过程赋值值 b b = a; / a; / 交换交换a a和和b b值值 endendendmodulee

101、ndmodule过程赋值有两过程赋值有两类类阻塞过程赋值阻塞过程赋值非阻塞过程赋非阻塞过程赋值值 阻塞过程赋值执行完成后再执行在顺序块内下一条语句。非阻塞赋值不阻塞过阻塞过程赋值执行完成后再执行在顺序块内下一条语句。非阻塞赋值不阻塞过程流,仿真器读入一条赋值语句并对它进行调度之后,就可以处理下一条赋值语程流,仿真器读入一条赋值语句并对它进行调度之后,就可以处理下一条赋值语句。若过程块中的所有赋值都是非阻塞的,赋值按两步进行:句。若过程块中的所有赋值都是非阻塞的,赋值按两步进行:1.仿仿真真器器计计算算所所有有RHS表表达达式式的的值值,保保存存结结果果,并并进进行行调调度度在在时时序序控控制制

102、指指定定时时间间的的赋赋值。值。2.在经过相应的延迟后,仿真器通过将保存的值赋给在经过相应的延迟后,仿真器通过将保存的值赋给LHS表达式完成赋值。表达式完成赋值。3.4.1 赋值语句和块语句赋值语句和块语句n赋值语句赋值语句阻塞与非阻塞赋值语句行为差别举例阻塞与非阻塞赋值语句行为差别举例阻塞与非阻塞赋值语句行为差别举例阻塞与非阻塞赋值语句行为差别举例1 1module non_block1;module non_block1; regreg a, b, c, d, e, f; a, b, c, d, e, f; initial begin / blocking assignments init

103、ial begin / blocking assignments a = #10 1; / time 10 a = #10 1; / time 10 b = #2 0; / time 12 b = #2 0; / time 12 c = #4 1; / time 16 c = #4 1; / time 16 end end initial begin / non- blocking assignments initial begin / non- blocking assignments d = #10 1; / time 10 d = #10 1; / time 10 e = #2 0; /

104、 time 2e = #2 0; / time 2 f = #4 1; / time 4 f end_wave; /触发事件end_wave. join 块语句块语句并行块并行块 在这个例子中用并行块来替代了前面例子中的顺序块在这个例子中用并行块来替代了前面例子中的顺序块在这个例子中用并行块来替代了前面例子中的顺序块在这个例子中用并行块来替代了前面例子中的顺序块来产生波形,用这两种方法生成的波形是一样的。来产生波形,用这两种方法生成的波形是一样的。来产生波形,用这两种方法生成的波形是一样的。来产生波形,用这两种方法生成的波形是一样的。3.4.1 赋值语句和块语句赋值语句和块语句 在在Veril

105、gHDL语言中,可以给每个块取一个名字,只需将语言中,可以给每个块取一个名字,只需将名名字加在关键词字加在关键词begin或或fork后面即可。这样做的原因有以下几后面即可。这样做的原因有以下几点。点。1) 这样可以在块内定义局部变量,即只在块内使用的变量。这样可以在块内定义局部变量,即只在块内使用的变量。2) 这样可以允许块被其它语句调用,如被这样可以允许块被其它语句调用,如被disable语句。语句。3) 在在Verilog语言里,所有的变量都是静态的,即所有的变量语言里,所有的变量都是静态的,即所有的变量都只有一个唯一的存储地址,因此进入或跳出块并不影响都只有一个唯一的存储地址,因此进入

106、或跳出块并不影响存储在变量内的值。存储在变量内的值。块语句块语句块名块名3.4.1 赋值语句和块语句赋值语句和块语句 当一个块嵌入另一个块时,块的起始时间和结束时当一个块嵌入另一个块时,块的起始时间和结束时间间是很重要的。至于跟在块后面的语句只有在该块的结束是很重要的。至于跟在块后面的语句只有在该块的结束时时间到了才能开始执行,也就是说,只有该块完全执行完间到了才能开始执行,也就是说,只有该块完全执行完后,后面的语句才可以执行。后,后面的语句才可以执行。块语句块语句起始时间和结束时间起始时间和结束时间 对于顺序块,起始时间就是第一条语句开始被执行对于顺序块,起始时间就是第一条语句开始被执行的时

107、间,结束时间就是最后一条语句执行完的时间。的时间,结束时间就是最后一条语句执行完的时间。 对于并行块,起始时间对于块内所有的语句是相同对于并行块,起始时间对于块内所有的语句是相同的,即程序流程控制进入该块的时间,其结束时间是按的,即程序流程控制进入该块的时间,其结束时间是按时间排序在最后的语句执行完的时间。时间排序在最后的语句执行完的时间。3.4.2 条件语句条件语句uif_else语句语句 always #20always #20 if if (index 0) / (index 0) / 开始外层开始外层 if if if if ( (regarega regbregb) / ) / 开始

108、内层第一层开始内层第一层 if if result = result = regarega; ; elseelse result = 0; / result = 0; / 结束内层第一层结束内层第一层 if if elseelse if if (index = 0)(index = 0) begin begin $display( Note : Index is zero); $display( Note : Index is zero); result = result = regbregb; ; end end elseelse $display( Note : Index is nega

109、tive); $display( Note : Index is negative);描述方式:描述方式:if (表达式) begin end else begin end3.4.2 条件语句条件语句n n五点说明:五点说明:(1)三种形式的三种形式的if语句中在语句中在if后面都有后面都有“表达式表达式”,一般为,一般为逻辑表达式或关系表达式。逻辑表达式或关系表达式。(2) 第二、第三种形式的第二、第三种形式的if语句中,在每个语句中,在每个else前面有一分前面有一分号,整个语句结束处有一分号。号,整个语句结束处有一分号。(3) 在在if和和else后面可以包含一个内嵌的操作语句后面可以包

110、含一个内嵌的操作语句(如上例如上例),也可以有多个操作语句,此时用,也可以有多个操作语句,此时用 begin和和end这两个这两个关键词将几个语句包含起来成为一个复合块语句。关键词将几个语句包含起来成为一个复合块语句。(4) 允许一定形式的表达式简写方式。允许一定形式的表达式简写方式。(5) if语句的嵌套在语句的嵌套在if语句中又包含一个或多个语句中又包含一个或多个if语句称为语句称为if语句的嵌套。语句的嵌套。uif_else语句语句3.4.2 条件语句条件语句uucasecase语句语句语句语句module compute (result, module compute (result,

111、 regarega, , regbregb, , opcodeopcode); );input 7: 0 input 7: 0 regarega, , regbregb; ;input 2: 0 input 2: 0 opcodeopcode; ;output 7: 0 result;output 7: 0 result;regreg 7: 0 result; 7: 0 result;always ( always ( regarega or or regbregb or or opcodeopcode) ) case ( case (opcodeopcode) ) 3b000 : resul

112、t = 3b000 : result = regarega + + regbregb; ; 3b001 : result = 3b001 : result = regarega - - regbregb; ; 3b010 , / specify multiple cases 3b010 , / specify multiple cases withtwitht he same result he same result 3b100 : result = 3b100 : result = regarega / / regbregb; ; default : begin default : beg

113、in result = result = bx bx; ; $display ( no match); $display ( no match); end end endcaseendcaseendmoduleendmodule在Verilog中重复说明case项是合法的,因为Verilog的case语句只执行第一个符合项。 3.4.2 条件语句条件语句casecase语语语语句句句句是是是是测测测测试试试试表表表表达达达达式式式式与与与与另另另另外外外外一一一一系系系系列列列列表表表表达达达达式式式式分分分分支支支支是是是是否否否否匹匹匹匹配配配配的的的的一一一一个个个个多多多多路路路路条条

114、条条件件件件语语语语句。句。句。句。nCase语句进行逐位比较以求完全匹配(包括语句进行逐位比较以求完全匹配(包括x和和z)。)。nDefault语句可选,在没有任何条件成立时执行。此时如语句可选,在没有任何条件成立时执行。此时如果未说明果未说明default,Verilog不执行任何动作。不执行任何动作。n多个多个default语句是非法的。语句是非法的。重要内容:重要内容:重要内容:重要内容:使用使用default语句是一个很好的编程习惯,特别是用于检测语句是一个很好的编程习惯,特别是用于检测x和和z。Casez和和casex为为case语句的变体,允许比较无关语句的变体,允许比较无关(d

115、ont-care)值。)值。case表表达达式式或或case项项中中的的任任何何位位为为无无关关值值时时,在在比比较较过过程程中中该该位位不不予予考虑。考虑。在在casez语句中,语句中,? 和和 z 被当作无关值。被当作无关值。在在casex语句中,语句中,?,z 和和 x 被当作无关值。被当作无关值。case语法:语法:case , :赋值语句或空语句;:赋值语句或空语句; , :赋值语句或空语句;:赋值语句或空语句; default:赋值语句或空语句;:赋值语句或空语句;uucasecase语句语句语句语句3.4.2 条件语句条件语句case语句与语句与if_else_if语句的区别主要

116、有两点语句的区别主要有两点:1) 与与case语句中的控制表达式和多分支表达式这种比较结构语句中的控制表达式和多分支表达式这种比较结构相比,相比,if_else_if结结 构中的条件表达式更为直观一些。构中的条件表达式更为直观一些。2) 对于那些分支表达式中存在不定值对于那些分支表达式中存在不定值x和高阻值和高阻值z位时位时,case语句提供了处理这种情况的手段。语句提供了处理这种情况的手段。【例例5.2】 case(sig) 1 bz: $display(signal is floating); 1 bx: $display(signal is unknown); default: $dis

117、play(signal is %b, sig); endcaseuu case case语句语句语句语句3.4.2 条件语句条件语句【例例5.3】 reg7:0 ir; casez(ir) 8 b1?: instruction1(ir); 8 b01?: instruction2(ir); 8 b00010?: instruction3(ir); 8 b000001?: instruction4(ir); endcase 【例例5.4】 reg7:0 r, mask; mask = 8bx0x0x0x0; casex(rmask) 8 b001100xx: stat1; 8 b1100xx00

118、: stat2; 8 b00xx0011: stat3; 8 bxx001100: stat4; endcaseuucasecase语句语句语句语句3.4.2 条件语句条件语句n n使用条件语句不当在设计中生成了原本没想到有的锁存器使用条件语句不当在设计中生成了原本没想到有的锁存器使用条件语句不当在设计中生成了原本没想到有的锁存器使用条件语句不当在设计中生成了原本没想到有的锁存器 Verilog HDL设计中容易犯的一个通病是由于不正确使用设计中容易犯的一个通病是由于不正确使用语言,生成了并不想要的锁存器。语言,生成了并不想要的锁存器。 如果用到如果用到如果用到如果用到if if语句,最好写上

119、语句,最好写上语句,最好写上语句,最好写上elseelse项。如果用项。如果用项。如果用项。如果用casecase语句,最语句,最语句,最语句,最好写上好写上好写上好写上defaultdefault项。遵循上面两条原则,就可以避免发生这项。遵循上面两条原则,就可以避免发生这项。遵循上面两条原则,就可以避免发生这项。遵循上面两条原则,就可以避免发生这种错误,使设计者更加明确设计目标,同时也增强了种错误,使设计者更加明确设计目标,同时也增强了种错误,使设计者更加明确设计目标,同时也增强了种错误,使设计者更加明确设计目标,同时也增强了VerilogVerilog程序的可读性。程序的可读性。程序的可读

120、性。程序的可读性。不正确使用if语句造成的错误always(a1 or d) begin if(a1) q=d end 有锁存器always(a1 or d) begin if(a1) q=d else q=0 end 无锁存器缺少default项生成锁存器always(sel1:0 or a or b) case(sel1:0) 2b00: q=a; 2b11: q=b; endcasealways(sel1:0 or a or b) case(sel1:0) 2b00: q=a; 2b11: q=b; default: q=b0 endcase有锁存器无锁存器3.4.3 循环语句循环语句有

121、四种循环语句有四种循环语句:repeat:将一块语句循环执行确定次数:将一块语句循环执行确定次数 repeat (repeat (次数表达式)次数表达式) whilewhile:在条件表达式为真时一直循环执行:在条件表达式为真时一直循环执行 while (while (条件表达式)条件表达式) foreverforever:重复执行直到仿真结束:重复执行直到仿真结束 forever forever forfor:在在执执行行过过程程中中对对变变量量进进行行计计算算和和判判断断,在在条条件件满满足足时时执执行行 for(for(赋初值;条件表达式;计算)赋初值;条件表达式;计算) 综合工具综合工

122、具还不支持还不支持3.4.3 循环语句循环语句forever forever 语句的格式如下:语句的格式如下:语句的格式如下:语句的格式如下: forever 语句语句; 或或 forever begin 多条语句多条语句 end u forever 语句语句 forever循环语句常用于产生周期性的波形,用来作为仿真测试信号。它与always语句不同处在于不能独立写在程序中,而必须写在initial块中。其具体使用方法将在“事件控制”这一小节里详细地加以说明。 3.4.3 循环语句循环语句repeat语句的格式如下语句的格式如下: repeat(表达式表达式) 语语句;句; 或或 repea

123、t(表达式表达式) begin 多条语句多条语句 end urepeat 语句语句/ / ParameterizableParameterizable shift and add multiplier shift and add multipliermodule multiplier( result, module multiplier( result, op_aop_a, , op_bop_b); ); parameter size = 8; parameter size = 8; input size:1 input size:1 op_aop_a, , op_bop_b; ; outpu

124、t 2* size:1 result; output 2* size:1 result; regreg 2* size:1 2* size:1 shift_opashift_opa, result;, result; regreg size:1 size:1 shift_opbshift_opb; ; always ( always ( op_aop_a or or op_bop_b) begin) begin result = 0; result = 0; shift_opashift_opa = = op_aop_a; / ; / 零扩展至零扩展至16 16位位 shift_opbshif

125、t_opb = = op_bop_b; ; repeat (size) begin repeat (size) begin #10 if (shift_opb1) result = #10 if (shift_opb1) result = resultresult + + shift_opashift_opa; ; shift_opashift_opa = = shift_opashift_opa 1; / Shift left 1; / Shift right 1; / Shift right end end end endendmoduleendmodule为什么要说明一为什么要说明一个个

126、shift_opb变量变量?3.4.3 循环语句循环语句while语句的格式如下:语句的格式如下: while(表达式表达式) 语句语句或或 while(表达式表达式) begin 多条语句多条语句 enduwhile 语句语句. . . . .regreg 7: 0 7: 0 tempregtempreg; ;regreg 3: 0 count; 3: 0 count;. . . . . count = 0; count = 0; while ( while (tempregtempreg) / ) / 统计统计tempregtempreg中中 1 1 的个数的个数 beginbegin i

127、f ( if (tempregtempreg 0) count = 0) count = countcount + 1; + 1; tempregtempreg = = tempregtempreg 1; / Shift right 1; / Shift right end endendend. . . . .3.4.3 循环语句循环语句for语句的一般形式为:语句的一般形式为: for(表达式(表达式1;表达式;表达式2;表达式;表达式3) 语句语句 ufor 语句语句它的执行过程为:它的执行过程为:1) 1) 先求解表达式先求解表达式1 1;2) 2) 求解表达式求解表达式2 2,若其值为

128、真(非,若其值为真(非0)0),则执行,则执行forfor语句中语句中指定的内嵌语句,然后执行下面的第指定的内嵌语句,然后执行下面的第3 3步。若为假步。若为假(0)(0),则,则结束循环,转到第结束循环,转到第5 5步。步。3) 3) 若表达式为真,在执行指定的语句后,求解表达式若表达式为真,在执行指定的语句后,求解表达式3 3。4) 4) 转回上面的第转回上面的第2 2步继续执行。步继续执行。5) 5) 执行执行forfor语句下面的语句。语句下面的语句。For语句最简单的应用形式beginbegin 循环变量赋初值循环变量赋初值 while(while(循环结束条件循环结束条件) ) b

129、egin begin 执行语句执行语句 循环变量增值;循环变量增值; endendendendForFor语句最简单的应用形式是很容易理解的,其形式如下:语句最简单的应用形式是很容易理解的,其形式如下:ForFor(循环变量赋初值;循环结束条件;循环变量增值)(循环变量赋初值;循环结束条件;循环变量增值)3.4.3 循环语句循环语句【例例5.5】 begin: init_mem reg7:0 tempi; for(tempi=0;tempimemsize;tempi=tempi+1) memorytempi=0; end ufor 语句语句例例例例5.55.5用用用用forfor语句来初始化语

130、句来初始化语句来初始化语句来初始化memorymemory。3.4.4 结构说明语句结构说明语句 VerilogVerilogVerilogVerilog 语言中的任何过程模块都从属于以下四种结语言中的任何过程模块都从属于以下四种结语言中的任何过程模块都从属于以下四种结语言中的任何过程模块都从属于以下四种结构的说明构的说明构的说明构的说明语句语句语句语句。1) initial 1) initial 1) initial 1) initial 说明语句说明语句说明语句说明语句2) always 2) always 2) always 2) always 说明语句说明语句说明语句说明语句3) ta

131、sk 3) task 3) task 3) task 说明语句说明语句说明语句说明语句4) function 4) function 4) function 4) function 说明语句说明语句说明语句说明语句 initialinitial和和alwaysalways说明语句在仿真的一开始即开始执行。说明语句在仿真的一开始即开始执行。initialinitial语句只执行一次。相反,语句只执行一次。相反,alwaysalways语句则是不断地重语句则是不断地重复执行,直到仿真过程结束。在一个模块中,使用复执行,直到仿真过程结束。在一个模块中,使用initialinitial和和always

132、always语句的次数是不受限制的。语句的次数是不受限制的。tasktask和和functionfunction语句语句可以在程序模块中的一处或多处调用可以在程序模块中的一处或多处调用3.4.4 结构说明语句结构说明语句initial语句的格式如下:语句的格式如下: initial begin 语句语句1; 语句语句2; . 语句语句n; enduuinitial 语句语句【例例6.1】 initial begin areg=0; /初始化寄存器areg for(index=0;indexsize;index=index+1) memoryindex=0; /初始化一个memory end 在

133、这个例子中用在这个例子中用initial语句在仿真开语句在仿真开始时对各变量进行初始化。始时对各变量进行初始化。3.4.4 结构说明语句结构说明语句nalways语句在仿真过程中是不断重复执行的。语句在仿真过程中是不断重复执行的。 其声明格式如下:其声明格式如下: always always always语句由于其不断重复执行的特性,只有和一语句由于其不断重复执行的特性,只有和一定的时序定的时序控制结合在一起才有用。如果一个控制结合在一起才有用。如果一个always语句没有时序语句没有时序控制,则控制,则这个这个always语句将会生成一个仿真死锁。语句将会生成一个仿真死锁。 uualways

134、 always 语句语句【例例6.3】 always always aregareg = = aregareg; ; 这个这个always语句将会生成一个语句将会生成一个0延迟的无限循环跳变过延迟的无限循环跳变过程,程,这时会发生仿真死锁。这时会发生仿真死锁。3.4.4 结构说明语句结构说明语句 如果加上时序控制,则这个如果加上时序控制,则这个always语句将变为语句将变为一条一条非常有用的描述语句。非常有用的描述语句。 【例例6.4】 always # half_period areg = areg; 这个例子生成了一个周期为这个例子生成了一个周期为:period(=2*half_peri

135、od) 的无限延续的信号波形,常用这种方法来描述时钟的无限延续的信号波形,常用这种方法来描述时钟信信号,作为激励信号来测试所设计的电路。号,作为激励信号来测试所设计的电路。uualways 语句语句例例6.5 6.5 reg7:0counter;reg7:0counter;regreg tick; tick; always(posedgealways(posedge aregareg) ) begin begin tick=tick;tick=tick; counter+1; counter+1;endenduualways 语句语句always(posedgealways(posedge c

136、lock or clock or posedgeposedge reset) reset) begin begin . . . . . .endendalways(aalways(a or b or c) or b or c) begin begin . . . . . .endendutask 和和 function tasktask和和functionfunction分别用来定义任务和函数。利用任务和分别用来定义任务和函数。利用任务和函数可以把一个很大的程序模块分解成许多较小的任务和函函数可以把一个很大的程序模块分解成许多较小的任务和函数便于理解和调试。输入、输出和总线信号的值可以传入、数

137、便于理解和调试。输入、输出和总线信号的值可以传入、传出任务和函数。任务和函数往往还是大的程序模块中在不传出任务和函数。任务和函数往往还是大的程序模块中在不同地点多次用到的相同的程序段。学会使用同地点多次用到的相同的程序段。学会使用tasktask和和functionfunction可以简化程序的结构,使程序明白易懂,这是编写较大型模可以简化程序的结构,使程序明白易懂,这是编写较大型模块的基本功。块的基本功。3.4.4 结构说明语句结构说明语句utask 和和 function1) 1) 函数只能与主模块共用同一个仿真时间单位,而任务可以定义自己函数只能与主模块共用同一个仿真时间单位,而任务可以

138、定义自己的仿真时间单位。的仿真时间单位。2) 2) 函数不能启动任务,而任务能启动其它任务和函数。函数不能启动任务,而任务能启动其它任务和函数。3) 3) 函数至少要有一个输入变量,而任务可以没有或有多个任何类型的函数至少要有一个输入变量,而任务可以没有或有多个任何类型的变量。变量。4) 4) 函数返回一个值,而任务则不返回值。函数返回一个值,而任务则不返回值。 函数的目的是通过返回一个值来响应输入信号的值。任务却能支函数的目的是通过返回一个值来响应输入信号的值。任务却能支持多种目的,能计算多个结果值,这些结果值只能通过被调用的任持多种目的,能计算多个结果值,这些结果值只能通过被调用的任务的输

139、出或总线端口送出务的输出或总线端口送出. .task和和function的不同点的不同点task 和和 function1)任务的定义。)任务的定义。 task ; . endtasktask2) 任务的调用及变量的传递。任务的调用及变量的传递。 (端口端口1,端口,端口2,.,端口,端口n);task 和和 function任务定义:任务定义: task task my_taskmy_task; ; input a, b; input a, b; inoutinout c; c; output d, e; output d, e; / /执行任务执行任务工作相应的语句工作相应的语句 c =

140、foo1; / c = foo1; /赋初始赋初始值值 d = foo2; / d = foo2; /对任务对任务的输出变量赋值的输出变量赋值 e = foo3; e = foo3; endtaskendtasktask任务调用:任务调用: my_task(v,w,x,y,zmy_task(v,w,x,y,z);); 任务调用变量任务调用变量( (v,w,x,y,zv,w,x,y,z) )和任务定义的和任务定义的I/OI/O变量变量( (a,b,c,d,ea,b,c,d,e) )之间是之间是一一对应的。当任务启动时,一一对应的。当任务启动时,由由v,wv,w, ,和和x x。传入的变量赋给。传

141、入的变量赋给了了a,ba,b, ,和和c c,而当任务完成后,而当任务完成后的输出又通过的输出又通过c,dc,d和和e e赋给了赋给了x,yx,y和和z z。task 和和 functionfunctionfunction函数的目的是返回一个用于表达式的值。函数的目的是返回一个用于表达式的值。函数的目的是返回一个用于表达式的值。函数的目的是返回一个用于表达式的值。(1)(1)定义函数的语法定义函数的语法: : function function ( (函数函数名名);); begin begin . . end end endfunctionendfunction task 和和 functi

142、on(3)函数的调用函数的调用: ( (,*)*) 通过对两次调用函数通过对两次调用函数getbyte的结果值进行位拼接运算的结果值进行位拼接运算来生来生成一个字。成一个字。 word = control? getbyte(msbyte),getbyte(lsbyte) : 0;function函数名作为确认符。函数名作为确认符。函数名作为确认符。函数名作为确认符。(2)(2)从函数返回的值从函数返回的值从函数返回的值从函数返回的值: : 函数的定义蕴含声明了与函数同名的、函数内部的寄存函数的定义蕴含声明了与函数同名的、函数内部的寄存器。如在函数的声明语句中器。如在函数的声明语句中为缺省为缺省

143、,则这个寄存器是一位的,否则是与函数定义中则这个寄存器是一位的,否则是与函数定义中一致的寄存器。函数的定义把函数返回值所赋值一致的寄存器。函数的定义把函数返回值所赋值寄存器的名称初始化为与函数同名的内部变量。寄存器的名称初始化为与函数同名的内部变量。task 和和 function(4)(4)函数的使用规则函数的使用规则: :l函数的定义不能包含有任何的时间控制语句,即任何函数的定义不能包含有任何的时间控制语句,即任何用、用、 、或、或waitwait来标识的语句。来标识的语句。l函数不能启动任务。函数不能启动任务。l定义函数时至少要有一个输入参量。定义函数时至少要有一个输入参量。l在函数的定

144、义中必须有一条赋值语句给函数中的一个在函数的定义中必须有一条赋值语句给函数中的一个内部变量赋以函数的结果值,该内部变量具有和函数内部变量赋以函数的结果值,该内部变量具有和函数名相同的名字。名相同的名字。functionu系统函数和任务系统函数和任务 这两个函数和系统任务的作用是用来输出信息,即将参这两个函数和系统任务的作用是用来输出信息,即将参数数p2p2到到pnpn按参数按参数p1p1给定的格式输出。参数给定的格式输出。参数p1p1通常称为通常称为“格式控制格式控制”,参,参数数p2p2至至pnpn通常称为通常称为“输出表列输出表列”。这两个任务的作用基本相。这两个任务的作用基本相同同。$d

145、isplay和和$write任务任务 $display(p1,p2,.pn); $write(p1,p2,.pn);系统函数和任务系统函数和任务 (1 1)格式说明,由)格式说明,由“% %”和格式字符组成。它的和格式字符组成。它的作用是将输出的数据转作用是将输出的数据转换成指定的格式输出。换成指定的格式输出。右表给出了常用的几种右表给出了常用的几种输出格式。输出格式。$display和和$write任务任务系统函数和任务系统函数和任务 (2)(2)普通字符,即需要原样输出的字符。下面表中普通字符,即需要原样输出的字符。下面表中的字符形式用于格式字符串参数中,用来显示的字符形式用于格式字符串参

146、数中,用来显示特殊的字符。特殊的字符。$display和和$write任务任务换码序列换码序列功能功能n换行换行t横向跳格(即跳到下一个输出区)横向跳格(即跳到下一个输出区)反斜杠字符反斜杠字符”双引号字符双引号字符”013位八进制数代表的字符位八进制数代表的字符%百分符号百分符号系统函数和任务系统函数和任务【例例6.6】 module disp; initial begin $display(t%n123); end endmodule 输出结果为输出结果为 % S$display和和$write任务任务 在在$display$display和和$write$write的参数列的参数列表中,

147、其表中,其“输出表列输出表列”是需要输出是需要输出的一些数据,可以是表达式。的一些数据,可以是表达式。 从上面的这个例子中可以从上面的这个例子中可以看到一些特殊字符的输出形式看到一些特殊字符的输出形式( (八进制数八进制数123123就是字符就是字符S)S)。系统任务系统任务 $monitorn n格式:格式:格式:格式:$monitor(p1,p2,.,pn);$monitor;$monitoron;$monitoroff; 任务任务$monitor$monitor提供了监控和输出参数列表中的表达式或变量值的功提供了监控和输出参数列表中的表达式或变量值的功能。能。 每当参数列表中变量或表达式

148、的值发生变化时,整个参数列表中变每当参数列表中变量或表达式的值发生变化时,整个参数列表中变量或表达式的值都将输出显示量或表达式的值都将输出显示时间度量系统函数时间度量系统函数 $timen$ $realtimerealtime系统函数。系统函数。$ $realtimerealtime和和$time$time的作用是的作用是一样的,只是一样的,只是$ $realtimerealtime返回的时间数字是一个实返回的时间数字是一个实型数,该数字也是以时间尺度为基准的。型数,该数字也是以时间尺度为基准的。p系统函数系统函数$time$time。$time$time可以返回一个可以返回一个6464比特的

149、整数来表比特的整数来表示的当前仿真时刻值。该时刻是以模块的仿真时间尺度为示的当前仿真时刻值。该时刻是以模块的仿真时间尺度为基准的。基准的。系统任务系统任务 $finish对于不同的参数值,系统输出的特征信息:对于不同的参数值,系统输出的特征信息:0 0 不输出任何信息不输出任何信息1 1 输出当前仿真时刻和位置输出当前仿真时刻和位置2 2 输出当前仿真时刻,位置和在仿真过程中所用输出当前仿真时刻,位置和在仿真过程中所用memorymemory及及CPUCPU时间的统计时间的统计 格式:格式: $finish; $finish(n); 系统任务系统任务$finish$finish的作用是退出仿真

150、器,返回主操作系统,的作用是退出仿真器,返回主操作系统,也就也就是结束仿真过程。任务是结束仿真过程。任务$finish$finish可以带参数,根据参数的值输可以带参数,根据参数的值输出不出不同的特征信息。如果不带参数,默认同的特征信息。如果不带参数,默认$finish$finish的参数值为的参数值为1 1。系统任务系统任务 $stop $stop$stop任务的作用是把任务的作用是把EDAEDA工具工具( (例如仿真器例如仿真器) )置成暂停模式,置成暂停模式,在仿真环境下给出一个交互式的命令提示符,将控制权交在仿真环境下给出一个交互式的命令提示符,将控制权交给用户。这个任务可以带有参数表

151、达式。根据参数值给用户。这个任务可以带有参数表达式。根据参数值(0(0,1 1或或2 2的不同,输出不同的信息。参数值越大,输出的信息的不同,输出不同的信息。参数值越大,输出的信息越多。越多。 格式:格式: $stop; $stop(n);系统任务系统任务 $readmemb 和和$readmemh 系统任务系统任务$ $readmembreadmemb和和$ $readmemhreadmemh用来从文件中读取数用来从文件中读取数据到存贮器中。这两个系统任务可以在仿真的任何时据到存贮器中。这两个系统任务可以在仿真的任何时刻被执行使用。刻被执行使用。1) $1) $readmembreadmem

152、b(,););2) $2) $readmembreadmemb(,););3) $3) $readmembreadmemb(,););4) $4) $readmemhreadmemh(,););5) $5) $readmemhreadmemh(,););6) $6) $readmemhreadmemh(,););系统任务系统任务 $readmemb 和和$readmemh 先定义一个有先定义一个有256个地址的字节存贮器个地址的字节存贮器 mem: reg7:0 mem1:256; 下面给出的系统任务以各自不同的方式装载数据到存贮器下面给出的系统任务以各自不同的方式装载数据到存贮器mem中。中

153、。 initial $readmemh(mem.data,mem); 第一条语句在仿真时刻为第一条语句在仿真时刻为0时,将装载数据到以地址是时,将装载数据到以地址是1的存贮器单元为起的存贮器单元为起始存放单元的存贮器中去。始存放单元的存贮器中去。 initial $readmemh(mem.data,mem,16); 第二条语句将装载数据到以单元地址是第二条语句将装载数据到以单元地址是16的存贮器单元为起始存放单元的的存贮器单元为起始存放单元的存贮器中去,一直到地址是存贮器中去,一直到地址是256的单元为止。的单元为止。 initial $readmemh(mem.data,mem,128,1

154、); 第三条语句将从地址是第三条语句将从地址是128的单元开始装载数据,一直到地址为的单元开始装载数据,一直到地址为1的单元。的单元。在第三种情况中,当装载完毕,系统要检查在数据文件里是否有在第三种情况中,当装载完毕,系统要检查在数据文件里是否有128个数据,个数据,如果没有,系统将提示错误信息。如果没有,系统将提示错误信息。系统任务系统任务 $random 这个系统函数提供了一个产生随机数的手段。当函数被这个系统函数提供了一个产生随机数的手段。当函数被调用时返回一个调用时返回一个32bit的随机数。它是一个带符号的整形数。的随机数。它是一个带符号的整形数。 $ramdom % b ,其中其中

155、 b0. 它给出了一个范围在它给出了一个范围在(-b+1):(b-1)中的随机数。中的随机数。reg23:0 rand;rand = $random % 60;reg23:0 rand;rand = $random % 60;给出了一个范围在给出了一个范围在59到到59之间的随机数之间的随机数通过位并接操作产生一个值通过位并接操作产生一个值在在0到到59之间的数之间的数3.4.5 生成语句(元件例化) 显而易见,通过显而易见,通过Verilog HDL模块的调用,可以构成任模块的调用,可以构成任何复杂结构的电路。何复杂结构的电路。这种以结构方式所建立的硬件模型不仅这种以结构方式所建立的硬件模型

156、不仅是可以仿真的,也是可综合的。是可以仿真的,也是可综合的。由已经设计成的模块构成更高一层的模块由已经设计成的模块构成更高一层的模块由已经设计成的模块构成更高一层的模块由已经设计成的模块构成更高一层的模块 如果已经编制了一个模块,如触发器flop, 可以在另外的模块中引用这个模块。只需在前面写上已编的模块名,紧跟着写上引用的实例名,按顺序写上实例的端口名即可,也可以用已编模块的端口名按对应的原则逐一填入1) flop f1op_d( d1, clk, clrb, q, qn);2) flop flop_d (.clock(clk),.q(q),.clear(clrb),.qb(qn),.dat

157、a(d1);层次化设计的思想重中之重!是层次化设计的思想重中之重!是VerilogVerilog设计芯片的主要方法。设计芯片的主要方法。D D 型主从触发器的电路结构图型主从触发器的电路结构图示例示例示例示例1 1 1 1:生成语句(元件例化语句):生成语句(元件例化语句):生成语句(元件例化语句):生成语句(元件例化语句)D D D D触发器触发器触发器触发器module flop(data,clock,clear,q,qb); input data,clock,clear; output q,qb; nand #10 nd1(a,data,clock,clear), nd2(b,ndata

158、,clock), nd4(d,c,b,clear), nd5(e,c,nclock), nd6(f,d,nclock), nd8(qb,q,f,clear); nand #9 nd3(c,a,d), nd7(q,e,qb); not #10 iv1(ndata,data), iv2(nclock,clock);endmodule 在这个Verilog HDL 结构描述的模块中,flop定义了模块名,设计上层模块时可以用这个名(flop)调用这个模块;module, input, output,endmodule等都是关键字; nand和not分别表示与非门和反相器;#10表示10个单位时间的延

159、时;nd1,nd2,.,nd8,iv1,iv2分别为图中的各个基本部件clrdqclkclrdqclkclrdqclkq0d0clrdqclkd3d2q2q3q1d1clrbclkf4f3f2f1四位寄存器电路结构图 由已设计的模块来构成高一级的模块由已设计的模块来构成高一级的模块由已设计的模块来构成高一级的模块由已设计的模块来构成高一级的模块示例二:生成语句(元件例化语句)移位寄存器示例二:生成语句(元件例化语句)移位寄存器示例二:生成语句(元件例化语句)移位寄存器示例二:生成语句(元件例化语句)移位寄存器include “ include “ flop.vflop.v ” ”modulem

160、odulehardreg(d,clk,clrb,qhardreg(d,clk,clrb,q); );inputinputclk,clrbclk,clrb; ;input3:0input3:0 d; d;output3:0output3:0 q; q;flopflopf1(d0,clk,clrb,q0,),f1(d0,clk,clrb,q0,), f2(d1,clk,clrb,q1,), f2(d1,clk,clrb,q1,), f3(d2,clk,clrb,q2,), f3(d2,clk,clrb,q2,), f4(d3,clk,clrb,q3,); f4(d3,clk,clrb,q3,);e

161、ndmoduleendmodule用触发器组成带清零端的用触发器组成带清零端的4 4位寄存器位寄存器/注意结束时用逗号,注意结束时用逗号,最后才用分号最后才用分号3.5 编译预处理编译预处理 用一个指定的标识符用一个指定的标识符(即名字即名字)来代表一个字来代表一个字符串符串u宏定义宏定义 definedefine 标识符标识符(宏名宏名) 字符串字符串(宏内容宏内容)define signal string 它的作用是指定用标识符它的作用是指定用标识符signal来代替来代替string这个字符串,这个字符串,在在编译预处理时,把程序中在该命令以后所有的编译预处理时,把程序中在该命令以后所有

162、的signal都替换都替换成成string。【例例7.4】 define WORDSIZE 8 module reg1:WORDSIZE data; /相当于定义 reg1:8 data;3.5 编译预处理编译预处理n关于宏定义的八点说明关于宏定义的八点说明:1)宏名可以用大写字母表示,也可以用小写字母表示。建议使用大写字母,以与变量名相区别。2)define命令可以出现在模块定义里面,也可以出现在模块定义外面。宏名的有效范围为定义命令之后到原文件结束.3)在引用已定义的宏名时,必须在宏名的前面加上符号“”,表示该名字是一个经过宏定义的名字。4)使用宏名代替一个字符串,可以减少程序中重复书写某

163、些字符串的工作量。5)宏定义是用宏名代替一个字符串,也就是作简单的置换,不作语法检查。6)宏定义不是Verilog HDL语句,不必在行末加分号。如果加了分号会连分号一起进行置换。7)在进行宏定义时,可以引用已定义的宏名,可以层层置换。8)宏名和宏内容必须在同一行中进行声明。如果在宏内容中包含有注释行,注释行不会作为被置换的内容u宏定义宏定义 define3.5 编译预处理编译预处理include “文件名文件名”u“文件包含文件包含“处理处理 include图图 1.7.1 “文件包含文件包含” 操作操作 所谓所谓“文件包含文件包含”处理是一个源文件可以将另外一个处理是一个源文件可以将另外一

164、个源文件的全部内容包含进来,即将另外的文件包含到本文源文件的全部内容包含进来,即将另外的文件包含到本文件之中。件之中。3.5 编译预处理编译预处理关于关于“文件包含文件包含”处理的五点说明:处理的五点说明:1) 一个include命令只能指定一个被包含的文件,如果要包含n个文件,要用n个include命令。注意下面的写法是非法的includeaaa.vbbb.v2) include命令可以出现在Verilog HDL源程序的任何地方,被包含文件名可以是相对路径名,也可以是绝对路径名。例如:includeparts/count.v3) 可以将多个include命令写在一行,在include命令行

165、,只可以出现空格和注释行。4) 如果文件1包含文件2,而文件2要用到文件3的内容,则可以在文件1用两个include命令分别包含文件2和文件3,而且文件3应出现在文件2之前。5) 在一个被包含文件中又可以包含另一个被包含文件,即文件包含是可以嵌套的。u“文件包含文件包含“处理处理 include3.5 编译预处理编译预处理 在这条命令中,时间单位参量是用来定义模块中仿真时间和在这条命令中,时间单位参量是用来定义模块中仿真时间和延迟时间的基准单位的。时间精度参量是用来声明该模块的仿真延迟时间的基准单位的。时间精度参量是用来声明该模块的仿真时间的精确程度的,该参量被用来对延迟时间值进行取整操作时间

166、的精确程度的,该参量被用来对延迟时间值进行取整操作( (仿仿真前真前) ),因此该参量又可以被称为取整精度。如果在同一个程序设,因此该参量又可以被称为取整精度。如果在同一个程序设计里,存在多个计里,存在多个timescaltimescal命令,则用最小的时间精度值来决定仿命令,则用最小的时间精度值来决定仿真的时间单位。另外时间精度至少要和时间单位一样精度,时间真的时间单位。另外时间精度至少要和时间单位一样精度,时间精度值不能大于时间单位值。精度值不能大于时间单位值。u时间尺度时间尺度 timescale timescale命令用来说明跟在该命令后的模块的时间单命令用来说明跟在该命令后的模块的时

167、间单位和时间精度。位和时间精度。timescale/3.5 编译预处理编译预处理【例例7.9】 timescale 1ns/1ps 在这个命令之后,模块中所有的时间值都表在这个命令之后,模块中所有的时间值都表示是示是1ns的整数倍。这是因为在的整数倍。这是因为在timescale命命令中,定义了时间单位是令中,定义了时间单位是1ns。模块中的延迟。模块中的延迟时间可表达为带三位小数的实型数,因为时间可表达为带三位小数的实型数,因为 timescale命令定义时间精度为命令定义时间精度为1ps.u时间尺度时间尺度 timescale3.5 编译预处理编译预处理 条件编译命令有以下几种形式:条件编

168、译命令有以下几种形式:1) ifdef 宏名宏名 (标识符标识符) 程序段程序段1 else 程序段程序段2 endif 它的作用是当宏名已经被定义过它的作用是当宏名已经被定义过(用用define命令定义命令定义),则对,则对程序段程序段1进行编译,程序段进行编译,程序段2将被忽略将被忽略;否则编译程序段否则编译程序段2,程序,程序段段1被忽略。被忽略。2) ifdef 宏名(标识符):宏名(标识符): 程序段程序段 1 endifu条件编译命令条件编译命令ifdef、else、endifVerilogVerilog 数字系统设计教程数字系统设计教程第二部分第二部分 中级篇中级篇概述概述 由初

169、级篇可知由初级篇可知,VerilogVerilog 模型可以是实际电路不同模型可以是实际电路不同级别的抽象。这些抽象的级别和它们对应的模型类型级别的抽象。这些抽象的级别和它们对应的模型类型共有以下五种共有以下五种: 1) 1) 系统级系统级(system(system) ) 2) 2) 算法级算法级(algorithmic(algorithmic) ) 3) 3) RTLRTL级级(RegisterTransferLevel(RegisterTransferLevel):): 4) 4) 门级门级(gate(gate-level):-level): 5) 5) 开关级开关级(switch(sw

170、itch-level)-level) 一个逻辑网络是由许多逻辑门和开关所组成,因此用逻辑门的模型来描述逻辑网络是最直观的。Verilog HDL提供了一些门类型的关键字,可以用于门级结构建模。1.1.1 1.1.1 1.1.1 1.1.1 与非门、或门和反向器等及其说明语法与非门、或门和反向器等及其说明语法与非门、或门和反向器等及其说明语法与非门、或门和反向器等及其说明语法 Verilog HDL中有关门类型的关键字共有26个之多,在本教材中我们只介绍最基本的八个。下面列出了八个基本的门类(GATETYPE)关键字和它们所表示的门的类型: and 与门与门 nand 与非门与非门 nor 或非

171、门或非门 or 或门或门 1.1 1.1 门级结构描述门级结构描述 xor 异或门异或门 xnor 异或非门异或非门 buf 缓冲器缓冲器 not 非门非门1.1.2 1.1.2 用门级结构描述用门级结构描述D D触发器触发器【例例1.1】 module flop(data,clock,clear,q,qb); input data,clock,clear; output q,qb; nand #10 nd1(a,data,clock,clear), nd2(b,ndata,clock), nd4(d,c,b,clear), nd5(e,c,nclock), nd6(f,d,nclock),

172、nd8(qb,q,f,clear); nand #9 nd3(c,a,d), nd7(q,e,qb); not #10 iv1(ndata,data), iv2(nclock,clock); endmodule 在这个在这个VerilogVerilog HDL HDL 结构描述的模块中,结构描述的模块中,flopflop定义了模块名,定义了模块名,设计上层模块时可以用这个名设计上层模块时可以用这个名(flop)(flop)调用这个模块;调用这个模块;module, input, module, input, output,endmoduleoutput,endmodule等都是关键字;等都是关

173、键字; nandnand和和notnot分别表示与非门和分别表示与非门和反相器;反相器;#10#10表示表示1010个单位时间的延时;个单位时间的延时;nd1,nd2,.,nd8,iv1nd1,nd2,.,nd8,iv1,iv2iv2分别为图分别为图2.1.12.1.1中的各个基本部件中的各个基本部件1.1 1.1 门级结构描述门级结构描述图图2 .1.2 .1. 1 D 1 D 型主从触发器的电路结构图型主从触发器的电路结构图 显而易见,通过显而易见,通过Verilog HDL模块的调用,可以构成任模块的调用,可以构成任何复杂结构的电路。何复杂结构的电路。这种以结构方式所建立的硬件模型不仅这

174、种以结构方式所建立的硬件模型不仅是可以仿真的,也是可综合的,这就是以门级为基础的结构是可以仿真的,也是可综合的,这就是以门级为基础的结构描述建模的基本思路。描述建模的基本思路。1.1.3 1.1.3 1.1.3 1.1.3 由已经设计成的模块构成更高一层的模块由已经设计成的模块构成更高一层的模块由已经设计成的模块构成更高一层的模块由已经设计成的模块构成更高一层的模块 如果已经编制了一个模块,如1.1.2节中的flop, 可以在另外的模块中引用这个模块,引用的方法与门类型的实例引用非常类似。只需在前面写上已编的模块名,紧跟着写上引用的实例名,按顺序写上实例的端口名即可,也可以用已编模块的端口名按

175、对应的原则逐一填入1) flop f1op_d( d1, clk, clrb, q, qn);2) flop flop_d (.clock(clk),.q(q),.clear(clrb),.qb(qn),.data(d1);clrdqclkclrdqclkclrdqclkq0d0clrdqclkd3d2q2q3q1d1clrbclkf4f3f2f1四位寄存器电路结构图 由已设计的模块来构成高一级的模块由已设计的模块来构成高一级的模块由已设计的模块来构成高一级的模块由已设计的模块来构成高一级的模块1.1.3 1.1.3 1.1.3 1.1.3 由已经设计成的模块构成更高一层的模块由已经设计成的模

176、块构成更高一层的模块由已经设计成的模块构成更高一层的模块由已经设计成的模块构成更高一层的模块include “ include “ flop.vflop.v ” ”modulemodulehardreg(d,clk,clrb,qhardreg(d,clk,clrb,q); );inputinputclk,clrbclk,clrb; ;input3:0input3:0 d; d;output3:0output3:0 q; q;flopflopf1(d0,clk,clrb,q0,),f1(d0,clk,clrb,q0,), f2(d1,clk,clrb,q1,), f2(d1,clk,clrb,q

177、1,), f3(d2,clk,clrb,q2,), f3(d2,clk,clrb,q2,), f4(d3,clk,clrb,q3,); f4(d3,clk,clrb,q3,);endmoduleendmodule用触发器组成带清零端的用触发器组成带清零端的4 4位寄存器位寄存器 设计示例二设计示例二/注意结束时用逗号,注意结束时用逗号,最后才用分号最后才用分号1.2 1.2 VerilogVerilog HDL HDL 的行为描述建模的行为描述建模 为了对已设计的模块进行检验往往需要产生一系列信号为了对已设计的模块进行检验往往需要产生一系列信号作为输出,输入到已设计的模块,并检查已设计模块的输

178、作为输出,输入到已设计的模块,并检查已设计模块的输出,看它们是否符合设计要求。这就要求我们编写测试模出,看它们是否符合设计要求。这就要求我们编写测试模块,也称作测试文件,常用带块,也称作测试文件,常用带. .tftf扩展名的文件来描述测试扩展名的文件来描述测试模块。模块。1.2.1 1.2.1 1.2.1 1.2.1 仅用于产生仿真测试信号的仅用于产生仿真测试信号的仅用于产生仿真测试信号的仅用于产生仿真测试信号的VerilogVerilogVerilogVerilog HDL HDL HDL HDL行为描述建模行为描述建模行为描述建模行为描述建模n行为级描述是对系统的高抽象级描述。在这个抽象级

179、,注重的是整行为级描述是对系统的高抽象级描述。在这个抽象级,注重的是整个系统的功能而不是实现。个系统的功能而不是实现。nVerilog有高级编程语言结构用于行为描述,包括:有高级编程语言结构用于行为描述,包括: wait, while, if then, case和和forevernVerilog的行为建模是用一系列以高级编程语言编写的并行的、动态的行为建模是用一系列以高级编程语言编写的并行的、动态的过程块来描述系统的工作。的过程块来描述系统的工作。1.2.1 1.2.1 1.2.1 1.2.1 仅用于产生仿真测试信号的仅用于产生仿真测试信号的仅用于产生仿真测试信号的仅用于产生仿真测试信号的V

180、erilogVerilogVerilogVerilog HDL HDL HDL HDL行为描述建模行为描述建模行为描述建模行为描述建模Module gen_clk (clk,reset); output clk; output reset; reg clk ,reset; initial begin reset = 1; /initial state clk=0; #3 reset = 0; #5 reset = 1; end always #5 clk = clk;endmodule 输出仿真信号初始状态时,初始状态时,clk置置为低电平,为低电平,reset为为高电平。高电平。Reset信

181、号信号输出一个复位信号输出一个复位信号后,维持在高电平。后,维持在高电平。以后每隔5个时间单位,时钟就翻转一次 include include “ “hardreg.vhardreg.v” ”module module hardreg_tophardreg_top; ;regreg clock, clock, clearbclearb; ;regreg 3:0 data 3:0 data;wire 3:0 wire 3:0 qoutqout; ;define define stimstim #100 data=4b #100 data=4b / /宏定义 stim,可使源程序简洁event e

182、vent end_first_passend_first_pass; ;/定义事件end_first_pass 编写测试模块通过仿真检查设计正确与否:编写测试模块通过仿真检查设计正确与否:编写测试模块通过仿真检查设计正确与否:编写测试模块通过仿真检查设计正确与否: hardreghardreg reg_4bit(.d(data),.clk(clock), . reg_4bit(.d(data),.clk(clock), .clrb(clearbclrb(clearb), ), . .q(qoutq(qout););/*-/*-把本模块中产生的测试信号把本模块中产生的测试信号把本模块中产生的测试

183、信号把本模块中产生的测试信号datadata、clockclock、clearbclearb输入实例输入实例输入实例输入实例reg_4bitreg_4bit以观察输出信号以观察输出信号以观察输出信号以观察输出信号qout.qout.实例实例实例实例reg_4bitreg_4bit引用了引用了引用了引用了hardreghardreg-*/-*/ initial initial begin begin clock = 0; clock = 0; clearbclearb = 1; = 1; end end always #50 clock = clock; always #50 clock = c

184、lock; 设计示例三 (续)/*-/*-宏定义宏定义宏定义宏定义stimstim引用引用引用引用, ,等同于等同于等同于等同于 #100 #100 data=4b data=4b 注意引用时要注意引用时要注意引用时要注意引用时要用用用用 符号符号符号符号。-*/-*/ stimstim 0000; 0000; stimstim 0001; 0001; . . . . . . . . . . . . stimstim 1111; 1111;endend#200 #200 end_first_passend_first_pass; ;/*-/*-延迟延迟延迟延迟200200个单位时间,触发事件个

185、单位时间,触发事件个单位时间,触发事件个单位时间,触发事件end_first_passend_first_pass-*/-*/$finish;$finish;/ /结束仿真结束仿真结束仿真结束仿真endendendmoduleendmodule 设计示例三 (续)VerilogVerilog 数字系统设计教程数字系统设计教程第二讲第二讲 如何编写和验证简单如何编写和验证简单的纯组合逻辑模块的纯组合逻辑模块 数字逻辑系统设计是一个非常细致、严密和费时的复杂过程,做这项工作的人员必须具有极其认真负责的工作态度、敏捷的头脑、顽强的毅力和细致踏实的作风2.1 2.1 加法器加法器 在数字电路课程里我们

186、已学习过一位的加法电路,即全在数字电路课程里我们已学习过一位的加法电路,即全加器。它的真值表很容易写出,电路结构也很简单仅由几个加器。它的真值表很容易写出,电路结构也很简单仅由几个与门和非门组成与门和非门组成。表表2.2.1 2.2.1 一位全加器的真值表一位全加器的真值表 表中Xi 、Yi 表示两个加数,Si 表示和,Ci -1 表示来自低位的进位、Ci 表示向高位的进位。从真值表很容易写出逻辑表达式如下: Ci = Xi Yi + Yi Ci -1 + Xi Ci - 1 Si = Xi Ci + Yi Ci + Ci - 1 Ci + Xi Yi Ci - 12.1 2.1 加法器加法器

187、 用用用用VerilogVerilog HDL HDL 来描述加法器是相当容易的,只需要把运来描述加法器是相当容易的,只需要把运来描述加法器是相当容易的,只需要把运来描述加法器是相当容易的,只需要把运算表达式写出就可以了。算表达式写出就可以了。算表达式写出就可以了。算表达式写出就可以了。 module add_4( X, Y, sum, C); input 3 : 0 X, Y; output 3: 0 sum; output C; assign C, Sum = X + Y; endmodule 在数字信号处理的快速运算电路中常常用到多位数字在数字信号处理的快速运算电路中常常用到多位数字量的

188、加法运算,这时需要用到并行加法器。并行加法器比串量的加法运算,这时需要用到并行加法器。并行加法器比串行加法器快得多,电路结构也不太复杂。行加法器快得多,电路结构也不太复杂。2.1 2.1 加法器加法器 而而而而16 16 16 16 位加法器只需要扩大位数即可位加法器只需要扩大位数即可位加法器只需要扩大位数即可位加法器只需要扩大位数即可: module add_16( X, Y, sum, C); input 15 : 0 X, Y; output 15 : 0 sum; output C; assign C, Sum = X + Y; endmodule 这样设计的加法器在行为仿真时是没有延

189、时的。借助综这样设计的加法器在行为仿真时是没有延时的。借助综合器,可以根据以上合器,可以根据以上VerilogVerilog HDL HDL源代码自动将其综合成典源代码自动将其综合成典型的加法器电路结构。型的加法器电路结构。2.2 2.2 乘法器乘法器 则则X 和和Y 的乘积的乘积Z 有有2n 位,并且式中位,并且式中YiX 称为称为部分积,记为部分积,记为P i,显然,两个一位二进制数相乘遵,显然,两个一位二进制数相乘遵循如下规则循如下规则:00=0; 01=0; 10=0; 11=1 因此因此YiXj 可用一个与门实现,记可用一个与门实现,记P Pi.ji.j = Y = Yi i X X

190、j j 设两个设两个设两个设两个n n n n 位二进制正数位二进制正数位二进制正数位二进制正数X X X X 和和和和Y Y Y Y:X : Xn-1X1 X0Y : Yn-1 Y1Y02.2 乘法器乘法器图图2.2.3 2.2.3 逐位进位并行乘法器逐位进位并行乘法器 快速乘法器常采快速乘法器常采用网格形式的迭带阵用网格形式的迭带阵列结构,图列结构,图 2.2.32.2.3 示示出两个四位二进制数出两个四位二进制数相乘的结构图。相乘的结构图。2.2 乘法器乘法器图图图图2.2.5 2.2.5 2.2.5 2.2.5 进位节省乘法器进位节省乘法器进位节省乘法器进位节省乘法器 为了提高乘法运算

191、速度可以改为图5.5 所示的进位节省乘法器(Carry-Save Multiplier)2.2 2.2 乘法器乘法器 用用用用VerilogVerilog HDL HDL 来描述乘法器是相当容易的,只需要把运算表达式来描述乘法器是相当容易的,只需要把运算表达式来描述乘法器是相当容易的,只需要把运算表达式来描述乘法器是相当容易的,只需要把运算表达式写出就可以了写出就可以了写出就可以了写出就可以了 module mult_4( X, Y, Product); input 3 : 0 X, Y; output 7 : 0 Product; assign Product = X * Y; endmod

192、ule 而而而而8 8 位乘法器只需要扩大位数即可位乘法器只需要扩大位数即可位乘法器只需要扩大位数即可位乘法器只需要扩大位数即可 module mult_8( X, Y, Product); input 7 : 0 X, Y; output 15 : 0 Product; assign Product = X * Y; endmodule 这样设计的乘法器在行为仿真时是没有延时的。借助综合这样设计的乘法器在行为仿真时是没有延时的。借助综合器,可以根据以上器,可以根据以上VerilogVerilog HDL HDL源代码自动将其综合成典型的乘源代码自动将其综合成典型的乘法器电路结构。法器电路结构

193、。2.3 2.3 比较器比较器 数值大小比较逻辑在计算逻辑中是常用的一种逻数值大小比较逻辑在计算逻辑中是常用的一种逻辑电路,一位二进制数的比较是它的基础。辑电路,一位二进制数的比较是它的基础。X Y (XY)(X=Y)(X=Y)(X=Y)(X Y) = X( Y)(X Y) = X( Y)(X Y) = ( X)Y(X Y)XGY = 1; / / 设置设置X X 大于大于Y Y 的信号为的信号为1 1else XGY = 0;if (X Y)XSY = 1; / / 设置设置X X 小于小于Y Y 的信号为的信号为1 1else XSY = 0;endendmodule 用用VerilogV

194、erilog HDL HDL来设计比较电路是来设计比较电路是很容易的。很容易的。 综合工具能自综合工具能自动把以上源代码综动把以上源代码综合成一个八位比较合成一个八位比较器器2.4 多路器多路器module Mux_8( addr,in1, in2, in3, in4, in5, in6, in7, in8, module Mux_8( addr,in1, in2, in3, in4, in5, in6, in7, in8, MoutMout, , nCSnCS); );input 2:0 input 2:0 addraddr; ;input width-1 in1, in2, in3, in

195、4, in5, in6, in7, in8;input width-1 in1, in2, in3, in4, in5, in6, in7, in8;output width-1 output width-1 MoutMout; ;parameter width = 8;parameter width = 8;always (always (addraddr or in1 or in2 or in3 or in4 or in5 or in6 or in7 or in8) or in1 or in2 or in3 or in4 or in5 or in6 or in7 or in8)beginb

196、egin if (! if (! nCSnCS) ) case(addrcase(addr) ) 3b000: 3b000: MoutMout = in1; = in1; 3b001: 3b001: MoutMout = in2; = in2; 3b010: 3b010: MoutMout = in3; = in3; 3b011: 3b011: MoutMout = in4; = in4; 3b100: 3b100: MoutMout = in5; = in5; 3b101: 3b101: MoutMout = in6; = in6; 3b110: 3b110: MoutMout = in7;

197、 = in7; 3b111: 3b111: MoutMout = in8; = in8; endcaseendcaseelseelse MoutMout = 0; = 0;endendendmoduleendmodule 多路器是一个多输入、单输出的组合逻辑电路,在数字系统中有着广泛的应用。它可以根据地址码的不同,从多个输入数据中选取一个,让其输出到公共的输出端。 综合工具能自动把以综合工具能自动把以上源代码综合成一个数据上源代码综合成一个数据位宽为位宽为8 8的八路选一数据的八路选一数据多路器多路器2.5 2.5 总线和总线操作总线和总线操作n n总线是运算部件之间数据流通的公共通道。总线是

198、运算部件之间数据流通的公共通道。总线是运算部件之间数据流通的公共通道。总线是运算部件之间数据流通的公共通道。module SampleOfBus( DataBus, link_bus,write );inout 11:0 DataBus; / 总线双向端口input link_bus; / 向总线输出数据的控制电平reg 11:0 outsigs;assign DataBus = (link_bus) ? outsigs : 12 h zzz ; /当link_bus 为高电平时通过总线把存在outsigs 的计算结果输出always (posedge write) /每当每当write wr

199、ite 信号上跳沿时信号上跳沿时begin /接收总线上数据并乘以五outsigs = DataBus * 5; /把计算结果存入outsigsendendmodule 上面是一个简单的与总线有接口的模块是如何对总线进行操作的例子通过以上例子我们可以理解使这个总线连接模块能正常工作的最重要的因素是与其他模块的配合2.6 2.6 流水线流水线n流水线(流水线(pipe-line)设计技术)设计技术: 流水线的设计方法已经在高性能的、需要经常进行大规流水线的设计方法已经在高性能的、需要经常进行大规模运算的系统中得到广泛的应用,如模运算的系统中得到广泛的应用,如CPU(中央处理器)等(中央处理器)等

200、。n 流水线设计的概念流水线设计的概念: 所谓流水线设计实际上就是把规模较大、层次较多的组合所谓流水线设计实际上就是把规模较大、层次较多的组合逻辑电路分为几个级,在每一级插入寄存器组暂存中间数据。逻辑电路分为几个级,在每一级插入寄存器组暂存中间数据。n采用流水线设计的优势在于它能提高吞吐(采用流水线设计的优势在于它能提高吞吐(throughput)n流水线设计在性能上的提高是以消耗较多的寄存器资源为代流水线设计在性能上的提高是以消耗较多的寄存器资源为代价的价的2.6 2.6 流水线流水线组合逻辑设计转化为流水线设计组合逻辑设计转化为流水线设计组合逻辑设计转化为流水线设计组合逻辑设计转化为流水线

201、设计第一级的延迟是T1 和T3 两个延迟中的最大值第二级的延迟等于T2 的延迟 为了通过这个组合逻辑得到稳定的计算结为了通过这个组合逻辑得到稳定的计算结果输出,果输出, 需要等待的传播延迟为需要等待的传播延迟为max(T1,T3)+T2个时间单位。个时间单位。寄存器的寄存器的TcoTco(触发时间)(触发时间) 采用流水线设计为取得稳定的采用流水线设计为取得稳定的输出总体计算周期为输出总体计算周期为:max(max(T1,T3)+Tco,(T2+Tco)VerilogVerilog 数字系统设计教程数字系统设计教程第三讲第三讲 复杂数字系统的构成复杂数字系统的构成3.1 3.1 运算部件和数据

202、流动的控制逻辑运算部件和数据流动的控制逻辑n组合逻辑:输出只是当前输入逻辑电平的函数(有延时),与电路的原始状态无关的逻辑电路。也就是说,当输入信号中的任何一个发生变化时,输出都有可能会根据其变化而变化,但与电路目前所处的状态没有任何关系。n时序逻辑:输出不只是当前输入的逻辑电平的函数,还与电路目前所处的状态有关的逻辑电路。3.1.1 3.1.1 数字逻辑电路的种类数字逻辑电路的种类3.1.2 3.1.2 数字逻辑电路的构成数字逻辑电路的构成组合逻辑:由与、或、非门组成的网络。常用的组合电路有:多路器、数据通路开关、加法器、乘法器.时序逻辑: 由多个触发器和多个组合逻辑块组成的网络。常用的有:

203、计数器、复杂的数据流动控制逻辑、运算控制逻辑、指令分析和操作控制逻辑。3.1 3.1 运算部件和数据流动的控制逻辑运算部件和数据流动的控制逻辑它的它的VerilogVerilog HDL HDL描述如下描述如下:define ON 1 define ON 1 b 1b 1define OFF 1 define OFF 1 b 0b 0wire wire ControlSwitchControlSwitch; ;wire 7:0 Out, In;wire 7:0 Out, In;assign Out = (assign Out = (ControlSwtichControlSwtich = =

204、ON) ? In : 8 = = ON) ? In : 8 h00h00;组合逻辑举例之一:组合逻辑举例之一:一个八位数据通路控制器一个八位数据通路控制器一个八位数据通路控制器一个八位数据通路控制器数据通道开关的逻辑图 数据通道开关的输出波形图3.1 3.1 运算部件和数据流动的控制逻辑运算部件和数据流动的控制逻辑它的Verilog HDL描述如下:define ON 1 define ON 1 b 1b 1define OFF 1 define OFF 1 b 0b 0wire wire LinkBusSwitchLinkBusSwitch; ;wire 7:0 wire 7:0 outbu

205、foutbuf; ;inoutinout 7:0 bus; 7:0 bus;assign bus = (assign bus = (LinkBusSwitchLinkBusSwitch= = ON) = = ON) ? ? outbufoutbuf : 8 : 8 hzzhzz组合逻辑举例之二:一个八位三态数据通路控制器:一个八位三态数据通路控制器三态数据通道开关的逻辑图数据流通波形图 它与组合逻辑举例之一的差别只在前者在开关断开时输出为零,而后者在开关断开时输出为高阻,即与总线脱离连接。3.1 3.1 运算部件和数据流动的控制逻辑运算部件和数据流动的控制逻辑 组合逻辑电路的输出与每个输入信号

206、的电平直接相关。组合逻辑电路的输出与每个输入信号的电平直接相关。如果能使组合逻辑电路的输入稳定一段时间,就可以得到如果能使组合逻辑电路的输入稳定一段时间,就可以得到组合逻辑电路的理想输出。而输出要被下一阶段的运算作组合逻辑电路的理想输出。而输出要被下一阶段的运算作为输入,也必须要有一段时间的稳定,因而输出的结果必为输入,也必须要有一段时间的稳定,因而输出的结果必须保存在寄存器组中。须保存在寄存器组中。3.1.3 3.1.3 数据在寄存器中的暂时保存数据在寄存器中的暂时保存3.1.4 3.1.4 数据流动的控制数据流动的控制 组合逻辑计算电路中设有许多寄存器组,它们是用来组合逻辑计算电路中设有许

207、多寄存器组,它们是用来暂存运算的中间数据。对寄存器组之间数据流动进行精确暂存运算的中间数据。对寄存器组之间数据流动进行精确的控制,在算法的实现过程中有着及其重要的作用。这种的控制,在算法的实现过程中有着及其重要的作用。这种控制是由同步状态机实现的控制是由同步状态机实现的3.2 3.2 在在VerilogVerilog HDL HDL设计中启用同步时序逻辑设计中启用同步时序逻辑 同步时序逻辑是指表示状态的寄存器组的值只可能在唯同步时序逻辑是指表示状态的寄存器组的值只可能在唯一确定的触发条件发生时刻改变。只能由时钟的正跳沿或负跳一确定的触发条件发生时刻改变。只能由时钟的正跳沿或负跳沿触发的状态机就

208、是一例。沿触发的状态机就是一例。 用用VerilogVerilog HDL HDL 设计的可综合模块设计的可综合模块, ,必须避免使用异步时必须避免使用异步时序逻辑,这不但是因为许多综合器不支持异步时序逻辑的综序逻辑,这不但是因为许多综合器不支持异步时序逻辑的综合,而且也因为用异步时序逻辑确实很难来控制由组合逻辑合,而且也因为用异步时序逻辑确实很难来控制由组合逻辑和延迟所产生的冒险和竞争。和延迟所产生的冒险和竞争。 同步时序逻辑比异步时序逻辑具有更可靠更简单的逻辑同步时序逻辑比异步时序逻辑具有更可靠更简单的逻辑关系。如果我们强行作出规定,用关系。如果我们强行作出规定,用VerilogVeril

209、og 来设计可综合的状来设计可综合的状态机必须使用同步时序逻辑态机必须使用同步时序逻辑, ,有了这个前提条件,实现自动生有了这个前提条件,实现自动生成电路结构的综合器就有了可能。成电路结构的综合器就有了可能。VerilogVerilog 数字系统设计教程数字系统设计教程第四讲第四讲 同步状态机的原理、结构和设计同步状态机的原理、结构和设计 有限状态机是由寄存器组和组合逻辑构成的有限状态机是由寄存器组和组合逻辑构成的硬件时序电路,其状态(即由寄存器组的硬件时序电路,其状态(即由寄存器组的1 1和和0 0的的组合状态所构成的有限个状态)只可能在同一时组合状态所构成的有限个状态)只可能在同一时钟跳变

210、沿的情况下才能从一个状态转向另一个状钟跳变沿的情况下才能从一个状态转向另一个状态,究竟转向哪一状态还是留在原状态不但取决态,究竟转向哪一状态还是留在原状态不但取决于各个输入值,还取决于当前所在状态。(这里于各个输入值,还取决于当前所在状态。(这里指的是米里指的是米里MealyMealy型有限状态机,而莫尔型有限状态机,而莫尔MooreMoore型有限状态机究竟转向哪一状态只决于当前状型有限状态机究竟转向哪一状态只决于当前状态。)态。)4.1 4.1 状态机的结构状态机的结构 在在Verilog HDL中可以用许多种方法来描述有限状态机,中可以用许多种方法来描述有限状态机,最常用的方法是用最常用

211、的方法是用always语句和语句和case语句。下面的状态转移语句。下面的状态转移图表示了一个有限状态机图表示了一个有限状态机4.3 4.3 如何用如何用VerilogVerilog 来描述可综合的状态来描述可综合的状态 图中所示的状态转移图中所示的状态转移图表示了一个四状态的有图表示了一个四状态的有限状态机,它的同步时钟限状态机,它的同步时钟是是Clock,输入信号是输入信号是 A 和和 Reset,输出信号是输出信号是 F 和和 G。状态的转移只能在同步时状态的转移只能在同步时钟(钟(Clock)的上升沿时)的上升沿时发生,往哪个状态的转移发生,往哪个状态的转移则取决于目前所在的状态则取决

212、于目前所在的状态和输入的信号和输入的信号Reset 和和 A) 例例4.1:4.1:module fsm (Clock, Reset, A, K2, K1); input Clock, Reset, A; output K2, K1; reg K2 , K1; reg 1:0 state ;Parameter Idle = 2b00, Start = 2b01; Stop = 2b10, Clear = 2b11;always (posedge Clock) if (! Reset) begin state = Idle; K2 =0; K1 =0; end else case (state)

213、 Idle : begin if (A) begin state = Start; K1 =0; end else state = idle; end Start : begin if (!A) state = Stop; else state = start; endStop : begin if (A) begin state = Clear; K2 = 1; end else state = Stop; endClear : begin if (! A) begin state =Idle; K2=0; K1=1; end else state = Clear; end endcasee

214、ndmodule例例4.1 4.1 采用采用GrayGray码码例例4.2:module fsm (Clock, Reset, A, K2, K1); input Clock, Reset, A; output K2,K1; reg K2,K1; reg 3:0 state ; parameter Idle = 4b1000, Start = 4b0100, Stop = 4b0010, Clear = 4b0001; always (posedge clock) if ( ! Reset) begin state = Idle; K2=0; K1=0; end else case (stat

215、e) Idle: begin if (A) begin state = Start; K1=0; end else state = Idle; endStart: begin if (!A) state = Stop; else state = Start; endStop: begin if (A) begin state = Clear; K2 = 1; end else state = Stop; endClear: begin if (!A) begin state =Idle; K2=0; K1=1; end else state = Clear; end default: stat

216、e =Idle; endcaseendmodule例4.2采用了独热编码例例4.3Module fsm( Clock, Reset, A, K2, K1); input Clock, Reset, A; output K2, K1; reg 3:0 state; assign K2=state3; assign K1=state0; parameter Zero = 4b0_0_0_0, Idle = 4b0_0_0_1, Start = 4b0_1_0_0, Stop = 4b0_0_1_0, Clear = 4b1_0_0_0; always (posedge Clock) if ( !

217、Reset) begin state=Zero; end else Case (state) Idle,Zero: begin if (A) begin state=Start; end else state=Idle; endStart: begin if (! A) state=Stop; else state=Start; endStop: begin if (A) begin state=Clear; end else state=Stop; endClear: begin if(!A) begin state=Idle; end else state=Clear; endDefaul

218、t: state=Zero;endcaseendmodule例4.3 把输出直接指定为状态码例例4.4module fsm (Clock, Reset, A, K2, K1); input Clock, Reset, A; output K2, K1; reg K2, K1; reg 1:0 state;parameter Idle = 2b00, Start = 2b01, Stop = 2b10, Clear = 2b11;always (posedge Clock) if ( ! Reset) state = Idle; else case(state) Idle: begin if (

219、A) begin state = Start; end else state = Idle; end Start: begin if ( ! A) state = Stop; else state = Start; endStop: begin if (A) state = Clear; else state = Stop; endClear: begin if ( ! A) state = Idle; else state = Clear; endDefault : state y ) begin tmp = x; x = y; y = tmp; end endtaskendmodule5.

220、5.1 5.5.1 组合逻辑电路设计实例组合逻辑电路设计实例 例例5.4. 5.4. 比较器的设计实例(利用赋值语句设比较器的设计实例(利用赋值语句设计组合逻辑)计组合逻辑) module compare(equal,a,b); parameter size=1; output equal; input size-1:0 a, b; assign equal =(a=b)? 1 : 0; endmodule5.5.1 5.5.1 组合逻辑电路设计实例组合逻辑电路设计实例 例例5.5. 3-85.5. 3-8译码器设计实例(利用赋值语句设译码器设计实例(利用赋值语句设计组合逻辑)计组合逻辑) m

221、odule decoder(out,in); output 7:0 out; input 2:0 in; assign out = 1b1in; /* /* 把最低位的把最低位的1 1左移左移 inin(根据从(根据从inin口输入的值)位,并赋予口输入的值)位,并赋予out */out */ endmodule5.5.1 5.5.1 组合逻辑电路设计实例组合逻辑电路设计实例 例例5.6. 8-35.6. 8-3编码器的设计实例编码器的设计实例 u 编码器设计方案之一:编码器设计方案之一:module encoder1(none_on,out,in); output none_on; outp

222、ut 2:0 out; input 7:0 in; reg 2:0 out; reg none_on; always (in) begin: local Integer i; out = 0; none_on = 1; /*returns the value of the highest bitnumber turned on*/ for( i=0; i8; i=i+1 ) begin if( ini ) begin out = i; none_on = 0; end end endendmodule 5.5.1 5.5.1 组合逻辑电路设计实例组合逻辑电路设计实例module encoder

223、2 ( none_on, out2, out1, out0, h, g, f, e, d, c, b, a); input h, g, f, e, d, c, b, a; output none_on, out2, out1, out0; wire 3:0 outvec; assign outvec= h? 4b0111 : g? 4b0110 : f? 4b0101: e? 4b0100 : d? 4b0011 :c? 4b0010 : b? 4b0001: a? 4b0000 : 4b1000; assign none_on = outvec3; assign out2 = outvec2

224、; assign out1 = outvec1; assign out0 = outvec0;endmoduleu 编码器设计方案之二:编码器设计方案之二:5.5.1 5.5.1 组合逻辑电路设计实例组合逻辑电路设计实例module encoder3 (none_on, out2, out1, out0, h, g, f, e, d, c, b, a); input h, g, f, e, d, c, b, a; output out2, out1, out0; output none_on; reg 3:0 outvec;assign none_on,out2,out1,out0 = out

225、vec;always ( a or b or c or d or e or f or g or h)u 编码器设计方案之三:编码器设计方案之三: begin if(h) outvec=4b0111; else if(g) outvec=4b0110; else if(f) outvec=4b0101; else if(e) outvec=4b0100; else if(d) outvec=4b0011; else if(c) outvec=4b0010; else if(b) outvec=4b0001; else if(a) outvec=4b0000; else outvec=4b1000

226、; endendmodule5.5.1 5.5.1 组合逻辑电路设计实例组合逻辑电路设计实例 例例5.7. 5.7. 多路器的设计实例。多路器的设计实例。 使用连续赋值、使用连续赋值、casecase语句或语句或if-elseif-else语句可以生成多路器语句可以生成多路器电路,如果条件语句(电路,如果条件语句(casecase或或if-elseif-else)中分支条件是互斥)中分支条件是互斥的话,综合器能自动地生成并行的多路器。的话,综合器能自动地生成并行的多路器。n 多路器设计方案之一多路器设计方案之一: :modul emux1(out, a, b, sel); output out

227、; input a, b, sel; assign out = sel? A : b;endmodule5.5.1 5.5.1 组合逻辑电路设计实例组合逻辑电路设计实例n多路器设计方案之二: module mux2( out, a, b, sel); output out; input a, b, sel; reg out; /用电平触发的用电平触发的alwaysalways块来设计多路器的组合逻辑块来设计多路器的组合逻辑 always ( a or b or sel ) begin /*检查输入信号检查输入信号sel的值,如为的值,如为1,输出,输出out为为a,如为如为0,输出,输出out

228、为为 b.*/ case( sel ) 1b1: out = a; 1b0: out = b; default: out = bx; endcase end endmodule5.5.1 5.5.1 组合逻辑电路设计实例组合逻辑电路设计实例n多路器设计方案之三多路器设计方案之三: : module mux3( out, a, b, sel); output out; input a, b, sel; reg out; always ( a or b or sel ) begin if( sel ) out = a; else out = b; end endmodule5.5.1 5.5.1

229、组合逻辑电路设计实例组合逻辑电路设计实例 例例5.8. 5.8. 奇偶校验位生成器设计实例奇偶校验位生成器设计实例module parity( even_numbits,odd_numbits,input_bus); output even_numbits, odd_numbits; input 7:0 input_bus; assign odd_numbits = input_bus; assign even_numbits = odd_numbits;endmodule5.5.1 5.5.1 组合逻辑电路设计实例组合逻辑电路设计实例 例例5.9. 5.9. 三态输出驱动器设计实例(用连续赋

230、三态输出驱动器设计实例(用连续赋值语句建立三态门模型)值语句建立三态门模型)n 三态输出驱动器设计方案之一三态输出驱动器设计方案之一: : module trist1( out, in, enable); output out; input in, enable; assign out = enable? in: bz; endmodule5.5.1 5.5.1 组合逻辑电路设计实例组合逻辑电路设计实例n三态输出驱动器设计方案之二三态输出驱动器设计方案之二: : module trist2( out, in, enable ); output out; input in, enable; /b

231、ufif1是是 一个一个 Verilog门级原语(门级原语(primitive) bufif1 mybuf1(out, in, enable); endmodule5.5.1 5.5.1 组合逻辑电路设计实例组合逻辑电路设计实例n三态输出驱动器设计方案之二三态输出驱动器设计方案之二: :module trist2( out, in, enable ); output out; input in, enable; /bufif1是是 一个一个 Verilog门级原语(门级原语(primitive) bufif1 mybuf1(out, in, enable);endmodule5.5.1 5.5

232、.1 组合逻辑电路设计实例组合逻辑电路设计实例 例例5.10. 5.10. 三态双向驱动器设计实例三态双向驱动器设计实例module bidir(tri_inout, out, in, en, b); inout tri_inout; output out; input in, en, b; assign tri_inout = en? In : bz; assign out = tri_inout b;endmodule 例例5.10. 5.10. 三态双向驱动器设计实例三态双向驱动器设计实例module bidir(tri_inout, out, in, en, b); inout tri

233、_inout; output out; input in, en, b; assign tri_inout = en? In : bz; assign out = tri_inout b;endmodule5.5.2 5.5.2 时序逻辑电路设计实例时序逻辑电路设计实例 例例5.115.11触发器设计实例触发器设计实例 module dff( q, data, clk); output q; input data, clk; reg q; always ( posedge clk ) begin q = data; end endmodule5.5.2 5.5.2 时序逻辑电路设计实例时序逻辑

234、电路设计实例 例例5.12. 5.12. 电平敏感型锁存器设计实例之一电平敏感型锁存器设计实例之一 module latch1( q, data, clk); output q; input data, clk; assign q = clk? data : q; endmodule5.5.2 5.5.2 时序逻辑电路设计实例时序逻辑电路设计实例 例例5.13. 5.13. 带置位和复位端的电平敏感型锁存器带置位和复位端的电平敏感型锁存器设计实例之二设计实例之二 module latch2( q, data, clk, set, reset); output q; input data, cl

235、k, set, reset; assign q= reset? 0 : ( set? 1:(clk? data : q ) );endmodule5.5.2 5.5.2 时序逻辑电路设计实例时序逻辑电路设计实例 例例5.14. 5.14. 电平敏感型锁存器设计实例之三电平敏感型锁存器设计实例之三 module latch3( q, data, clk); output q; input data, clk; reg q; always (clk or data) begin if(clk) q=data; end endmodule注意:有的综合器会产生一注意:有的综合器会产生一警告信息警告信

236、息 告诉你产生了一告诉你产生了一个电平敏感型锁存器。因为个电平敏感型锁存器。因为我们设计的就是一个电平敏我们设计的就是一个电平敏感型锁存器,就不用管这个感型锁存器,就不用管这个警告信息。警告信息。5.5.2 5.5.2 时序逻辑电路设计实例时序逻辑电路设计实例 例例5.15. 5.15. 移位寄存器设计实例移位寄存器设计实例 module shifter( din, clk, clr, dout); input din, clk, clr; output 7:0 dout; reg 7:0 dout; always (posedge clk) begin if(clr) /清零 dout =

237、8b0; else begin dout = dout1; /左移一位 dout0 = din; /把输入信号放入寄存器的最低位 end end endmodule5.5.2 5.5.2 时序逻辑电路设计实例时序逻辑电路设计实例 例例5.16. 5.16. 八位计数器设计实例之一八位计数器设计实例之一 module counter1( out, cout, data, load, cin, clk); output 7:0 out; output cout; input 7:0 data; input load, cin, clk; reg 7:0 out; always (posedge c

238、lk) begin if( load ) out = data; else out = out + cin; end assign cout= & out & cin; /只有当只有当out7:0的所有各位都为的所有各位都为1,并且进位并且进位cin也为也为1时才能产生进位时才能产生进位cout endmodule5.5.2 5.5.2 时序逻辑电路设计实例时序逻辑电路设计实例 例例5.17. 5.17. 八位计数器设计实例之二八位计数器设计实例之二module counter2( out, cout, data, load, cin, clk); output 7:0 out; output

239、 cout; input 7:0 data; input load, cin, clk; reg 7:0 out; reg cout; reg 7:0 preout; /创建创建8位寄存器位寄存器 always (posedge clk) begin out = preout; end/*计算计数器和进位的下一个状态,注意:为提高性能不希望加载影响进位*/always ( out or data or load or cin ) begin cout, preout = out + cin; if(load) preout = data; endendmodule5.6 5.6 状态机的置位与

240、复位状态机的置位与复位5.6.1 5.6.1 状态机的异步置位与复位状态机的异步置位与复位异步置位与复位是与时钟无关的异步置位与复位是与时钟无关的异步置位与复位是与时钟无关的异步置位与复位是与时钟无关的. . . .状态机的异步置位与复位是用状态机的异步置位与复位是用状态机的异步置位与复位是用状态机的异步置位与复位是用alwaysalways块和事件控制实现的。块和事件控制实现的。块和事件控制实现的。块和事件控制实现的。事件控制语法事件控制语法 ( ( ) ) 沿关键词包括沿关键词包括 posedge(用(用于高电平有效的于高电平有效的set、reset或上或上升沿触发的时钟)和升沿触发的时钟

241、)和 negedge(用于低电平有效的(用于低电平有效的set、reset或下降沿触发的时钟),信号可或下降沿触发的时钟),信号可以按任意顺序列出。以按任意顺序列出。事件控制实例事件控制实例1)异步、高电平有效的置位(时钟的上升沿)异步、高电平有效的置位(时钟的上升沿)(posedge clk or posedge set)2) 异步低电平有效的复位(时钟的上升沿)异步低电平有效的复位(时钟的上升沿) (posedge clk or negedge reset)3) 异步低电平有效的置位和高电平有效的复位(时钟的上升沿)异步低电平有效的置位和高电平有效的复位(时钟的上升沿) ( posedge

242、 clk or negedge set or posedge reset )5.6.1 5.6.1 状态机的异步置位与复位状态机的异步置位与复位4) 4) 带异步高电平有效的置位与复位的带异步高电平有效的置位与复位的alwaysalways块样板块样板always (posedge clk or posedge set or posedge reset) begin if(reset) begin /*置输出为置输出为0*/ end else if(set) begin /*置输出为置输出为1*/ end else begin /*与时钟同步的逻辑与时钟同步的逻辑*/ end end5.6.1

243、 5.6.1 状态机的异步置位与复位状态机的异步置位与复位5) 带异步高电平有效的置/复位端的D触发器实例module dff1( q, qb, d, clk, set, reset ); input d, clk, set, reset; output q, qb; /声明声明q和和qb为为reg类型类型,因为它需要在因为它需要在always块块内赋值内赋值 reg q, qb; always ( posedge clk or posedge set or posedge reset ) begin if(reset) begin q = 0; qb = 1; endelse if (set

244、) begin q = 1; qb = 0; end else begin q = d; qb = d; endendendmodule5.6.2 5.6.2 状态机的同步置位与复位状态机的同步置位与复位 同步置位与复位是指只有在时钟的有效跳变沿时刻置位或复位信号才能使触发器置位或复位(即,使触发器的输出分别转变为逻辑1或0)。事件控制语法事件控制语法: : () 其中沿关键词指 posedge(正沿触发)或 negedge(负沿触发)事件控制实例事件控制实例1) 正沿触发正沿触发 (posedge clk)2) 负沿触发负沿触发 (negedge clk)3) 同步的具有高电平有效的置位与复

245、位同步的具有高电平有效的置位与复位端的端的always块样板块样板always (posedge clk) begin if(reset) begin /*置输出为置输出为0*/ end else if(set) begin /*置输出为置输出为1*/ end else begin /*与时钟同步的逻辑与时钟同步的逻辑*/ end end5.6.2 5.6.2 状态机的同步置位与复位状态机的同步置位与复位4) 4) 同步的具有高电平有效的置位同步的具有高电平有效的置位/ /复位端的复位端的D D触发器触发器module dff2( q, qb, d, clk, set, reset); inp

246、ut d, clk, set, reset; output q, qb; reg q, qb; always (posedge clk) begin if(reset) begin q=0; qb=1; endelse if(set) begin q=1; qb=0; end else begin q=d; qb=d; end endendmoduleVerilogVerilog 数字系统设计教程数字系统设计教程第六讲第六讲 深入理解阻塞和非阻塞赋值的不同深入理解阻塞和非阻塞赋值的不同6.1 6.1 深入理解阻塞和非阻塞赋值的不同深入理解阻塞和非阻塞赋值的不同n 在描述组合逻辑的在描述组合逻辑

247、的always always 块中用阻塞赋值,则综合成块中用阻塞赋值,则综合成组合逻辑的电路结构。组合逻辑的电路结构。n 在描述时序逻辑的在描述时序逻辑的always always 块中用非阻塞赋值,则综合块中用非阻塞赋值,则综合成时序逻辑的电路结构。成时序逻辑的电路结构。为什么一定要这样做呢?这是因为要使综合前仿真和综合后仿为什么一定要这样做呢?这是因为要使综合前仿真和综合后仿真一致的缘故。真一致的缘故。定义定义定义定义RHS 方程式右手方向的表达式或变量可分别缩写为:方程式右手方向的表达式或变量可分别缩写为: RHS 表达式或表达式或 RHS 变量。变量。LHS 方程式左手方向的表达式或变

248、量可分别缩写为:方程式左手方向的表达式或变量可分别缩写为: LHS 表达式或表达式或 LHS 变量。变量。6.1.1 6.1.1 阻塞赋值阻塞赋值阻塞赋值的执行可以认为是只有一个步骤的操作: 计算RHS 并更新LHS,此时不能允许有来自任何其他Verilog 语句的干扰。 所谓阻塞的概念是指在同一个always 块中,其后面的赋值语句从概念上(即使不设定延迟)是在前一句赋值语句结束后再开始赋值的。 例例6.16.1 用阻塞赋值的反馈振荡器module fbosc1 (y1, y2, clk, rst); output y1, y2; input clk, rst; reg y1, y2; al

249、ways (posedge clk or posedge rst) if (rst) y1 = 0; / reset else y1 = y2; always (posedge clk or posedge rst) if (rst) y2 = 1; / preset else y2 = y1;endmodule 如果在一个过程块中阻塞赋值如果在一个过程块中阻塞赋值的的RHS RHS 变量正好是另一个过程块中变量正好是另一个过程块中阻塞赋值的阻塞赋值的LHS LHS 变量,这两个过程变量,这两个过程块又用同一个时钟沿触发,如果阻块又用同一个时钟沿触发,如果阻塞赋值的次序安排不好,就会出现塞赋值

250、的次序安排不好,就会出现竞争。若这两个阻塞赋值操作用同竞争。若这两个阻塞赋值操作用同一个时钟沿触发,则执行的次序是一个时钟沿触发,则执行的次序是无法确定的。无法确定的。并并行行执执行行如果前一个如果前一个always块的复位信号先块的复位信号先到到0 时刻,则时刻,则y1 和和y2 都会取都会取1,而,而如果后一个如果后一个always 块的复位信号先块的复位信号先到到0 时刻,则时刻,则y1 和和y2 都会取都会取0。这。这清楚地说明这个清楚地说明这个Verilog 模块是不稳模块是不稳定的会产生冒险和竞争的情况。定的会产生冒险和竞争的情况。6.1.2 6.1.2 非阻塞赋值非阻塞赋值非阻塞

251、赋值的操作可以看作为两个步骤的过程:1) 在赋值时刻开始时,计算非阻塞赋值RHS 表达式。2) 在赋值时刻结束时,更新非阻塞赋值LHS 表达式。 例例6.26.2 用非阻塞赋值的反馈振荡器module fbosc2 (y1, y2, clk, rst); output y1, y2; input clk, rst; reg y1, y2; always (posedge clk or posedge rst) if (rst) y1 = 0; / reset else y1 = y2; always (posedge clk or posedge rst) if (rst) y2 = 1; /

252、 preset else y2 = y1;endmodule非阻塞赋值操作只能用于对寄存器类型变量进行赋值,因此只能用在initial块和always块等过程块中。非阻塞赋值不允许用于连续赋值。并并行行执执行行无论哪一个always 块的复位信号先到, 两个always 块中的非阻塞赋值都在赋值开始时刻计算RHS 表达式,而在结束时刻才更新LHS 表达式。所以这两个always 块在复位信号到来后,在always 块结束时 y1 为0 而y2为1 是确定的。从用户的角度看这两个非阻塞赋值正好是并行执行的。6.2 Verilog模块编程要点模块编程要点 掌握一下8个要点可以解决综合后仿真出现的9

253、0以上的竞争和冒险。1) 时序电路建模时,用非阻塞赋值。2) 锁存器电路建模时,用非阻塞赋值。3) 用always 块建立组合逻辑模型时,用阻塞赋值。4) 在同一个always 块中建立时序和组合逻辑电路时,用非阻塞赋值。5) 在同一个always 块中不要既用非阻塞赋值又用阻塞赋值。6) 不要在一个以上的always 块中为同一个变量赋值。7) 用$strobe 系统任务来显示用非阻塞赋值的变量值8) 在赋值时不要使用 #0 延迟6.3 Verilog的层次化事件队列的层次化事件队列 所谓层次化事件队列指的是用于调度仿真事所谓层次化事件队列指的是用于调度仿真事件的不同的件的不同的Verilo

254、g 事件队列。事件队列。 在在IEEE 1364-1995 Verilog 标准的标准的5.3 节节中定义了中定义了: 层次化事件队列在逻辑上分为用于当层次化事件队列在逻辑上分为用于当前仿真时间的前仿真时间的4 个不同的队列个不同的队列, 和用于下一段仿和用于下一段仿真时间的若干个附加队列。真时间的若干个附加队列。6.3 Verilog的层次化事件队列的层次化事件队列(1)(1)动态事件队列:动态事件队列:n 阻塞赋值;阻塞赋值;n 计算非阻塞语句右边的表达式;计算非阻塞语句右边的表达式;n 连续赋值;连续赋值;n 执行执行$display$display命令;命令;n 计算原语的输入和输出变

255、化。计算原语的输入和输出变化。(2)(2)停止运行的事件队列:停止运行的事件队列: 0 0延时阻塞赋值延时阻塞赋值6.3 Verilog的层次化事件队列的层次化事件队列(3)非阻塞事件队列:非阻塞事件队列: 更新非阻塞赋值语句更新非阻塞赋值语句LHS(左边变量左边变量)的值的值;(4)监控事件队列监控事件队列n 执行执行$monitor命令;命令;n 执行执行$strobe命令;命令;(5)其他指定的其他指定的PLI命令队列。命令队列。 大多数大多数Verilog 事件是由动态事件队列调度的,这些事件是由动态事件队列调度的,这些事件包括阻塞赋值、连续赋值、事件包括阻塞赋值、连续赋值、$disp

256、lay 命令、实例命令、实例和原语的输入变化以及他们的输出更新、非阻塞赋值语和原语的输入变化以及他们的输出更新、非阻塞赋值语句句RHS 的计算等。而非阻塞赋值语句的计算等。而非阻塞赋值语句LHS 的更新却不的更新却不由动态事件队列调度。由动态事件队列调度。6.4 6.4 自触发自触发alwaysalways块块一般而言,一般而言,VerilogVerilog 的的always always 块不能触发自己块不能触发自己 例例6.3 6.3 使用阻塞赋值的非自触发振荡器使用阻塞赋值的非自触发振荡器 module osc1 (clk); output clk; reg clk; initial #

257、10 clk = 0; always (clk) #10 clk = clk; endmodule 上例描述的时钟振荡器使用了阻塞赋值。阻塞赋值时,计上例描述的时钟振荡器使用了阻塞赋值。阻塞赋值时,计算算RHS 表达式并更新表达式并更新LHS 的值,此时不允许其他语句的干扰。的值,此时不允许其他语句的干扰。阻塞赋值必须在阻塞赋值必须在(clk)边沿触发到来时刻之前完成。当触发事边沿触发到来时刻之前完成。当触发事件到来时,阻塞赋值已经完成了,因此没有来自件到来时,阻塞赋值已经完成了,因此没有来自always 块内块内部的触发事件来触发部的触发事件来触发(clk),是一个非自触发振荡器。,是一个非

258、自触发振荡器。6.4 6.4 自触发自触发alwaysalways块块 (clkclk) )的第一次触发之后,非阻塞赋值的的第一次触发之后,非阻塞赋值的RHS RHS 表达式表达式便计算出来,把值赋给便计算出来,把值赋给LHS LHS 的事件被安排在更新事件队列的事件被安排在更新事件队列中。在非阻塞赋值更新事件队列被激活之前,又遇到了中。在非阻塞赋值更新事件队列被激活之前,又遇到了(clkclk) )触发语句,并且触发语句,并且always always 块再次对块再次对clkclk 的值变化产生反的值变化产生反应。当非阻塞应。当非阻塞LHS LHS 的值在同一时刻被更新时,的值在同一时刻被更

259、新时, (clkclk) )再一再一次触发。该例是自触发式,在编写仿真测试模块时不推荐使次触发。该例是自触发式,在编写仿真测试模块时不推荐使用这种写法的时钟信号源。用这种写法的时钟信号源。 例例6.4 6.4 采用非阻塞赋值的自触发振荡器采用非阻塞赋值的自触发振荡器 module osc2 (clk); output clk; reg clk; initial #10 clk = 0; always (clk) #10 clk = clk;endmodule6.56.5移位寄存器模型移位寄存器模型n下图表示是一个简单的移位寄存器方框图下图表示是一个简单的移位寄存器方框图。图图2.6.1 2.6

260、.1 移位寄存器电路移位寄存器电路6.56.5移位寄存器模型移位寄存器模型 例例6.5 6.5 不正确地使用的阻塞赋值来描述移位寄存器。(方不正确地使用的阻塞赋值来描述移位寄存器。(方式式 #1#1) module pipeb1 (q3, d, clk); output 7:0 q3; input 7:0 d; input clk; reg 7:0 q3, q2, q1; always (posedge clk) begin q1 = d; q2 = q1; q3 = q2; end Endmodule 在上面的模块中,按顺序在上面的模块中,按顺序进行的阻塞赋值将使得在下一进行的阻塞赋值将使得

261、在下一个时钟上升沿时刻,所有的寄个时钟上升沿时刻,所有的寄存器输出值都等于输入值存器输出值都等于输入值d d。在。在每个时钟上升沿,输入值每个时钟上升沿,输入值d d 将将无延时地直接输出到无延时地直接输出到q3q3。6.56.5移位寄存器模型移位寄存器模型 例例6.6 6.6 用阻塞赋值来描述移位寄存器也是可行的,但这种用阻塞赋值来描述移位寄存器也是可行的,但这种风格并不好。(方式风格并不好。(方式 #2 #2 ) module pipeb2 (q3, d, clk); output 7:0 q3; input 7:0 d; input clk; reg 7:0 q3, q2, q1; al

262、ways (posedge clk) begin q3 = q2; q2 = q1; q1 = d; end endmodule 在上面的模块中,阻塞赋值的次序是经过仔细安排的,以使仿真的结果与移位寄存器相一致。虽然该模块可被综合成图2.6.1所示的移位寄存器,但我们不建议使用这种风格的模块来描述时序逻辑。6.5 6.5 移位寄存器模型移位寄存器模型 例例6.7 6.7 不用阻塞赋值来描述移位时序逻辑的风格不用阻塞赋值来描述移位时序逻辑的风格(方式(方式 #3#3)module pipeb3 (q3, d, clk); output 7:0 q3; input 7:0 d; input clk

263、; reg 7:0 q3, q2, q1; always (posedge clk) q1 = d; always (posedge clk) q2 = q1; always (posedge clk) q3 = q2;endmodule 本例中,阻塞赋值分别被放在不同的always 块里。仿真时,这些块的先后顺序是随机的,因此可能会出现错误的结果。这是Verilog 中的竞争冒险。按不同的顺序执行这些块将导致不同的结果。但是, 这些代码的综合结 果却是正确的流水 线寄存器。也就 是说,前仿真和 后仿真的结果可 能会不一致。6.5 6.5 移位寄存器模型移位寄存器模型 例例6.8 6.8 不用

264、阻塞赋值来描述移位时序逻辑的风格(方式不用阻塞赋值来描述移位时序逻辑的风格(方式 #4#4)module pipeb4 (q3, d, clk); output 7:0 q3; input 7:0 d; input clk; reg 7:0 q3, q2, q1; always (posedge clk) q2 = q1; always (posedge clk) q3 = q2; always (posedge clk) q1 = d;endmodule6.5 6.5 移位寄存器模型移位寄存器模型 例例6.9 6.9 正确使用非阻塞赋值来描述时序逻辑的设计风格正确使用非阻塞赋值来描述时序逻辑

265、的设计风格 (方式(方式 #1#1) module pipen1 (q3, d, clk); output 7:0 q3; input 7:0 d; input clk; reg 7:0 q3, q2, q1; always (posedge clk) begin q1 = d; q2 = q1; q3 = q2; end endmodule6.5 6.5 移位寄存器模型移位寄存器模型 例例6.10 6.10 正确使用非阻塞赋值来描述时序逻辑的设计风格正确使用非阻塞赋值来描述时序逻辑的设计风格( (方式方式 #2#2) module pipen2 (q3, d, clk); output 7:

266、0 q3; input 7:0 d; input clk; reg 7:0 q3, q2, q1; always (posedge clk) begin q3 = q2; q2 = q1; q1 = d; end endmodule6.5 6.5 移位寄存器模型移位寄存器模型 例例6.11 6.11 正确使用非阻塞赋值来描述时序逻辑的设计正确使用非阻塞赋值来描述时序逻辑的设计风格风格 (方式(方式 #3#3) module pipen3 (q3, d, clk); output 7:0 q3; input 7:0 d; input clk; reg 7:0 q3, q2, q1; always

267、 (posedge clk) q1 = d; always (posedge clk) q2 = q1; always (posedge clk) q3 = q2; endmodule6.5 6.5 移位寄存器模型移位寄存器模型 例例6.12 6.12 正确使用非阻塞赋值来描述时序逻辑的设计正确使用非阻塞赋值来描述时序逻辑的设计风格风格 (方式(方式 #4#4) module pipen4 (q3, d, clk); output 7:0 q3; input 7:0 d; input clk; reg 7:0 q3, q2, q1; always (posedge clk) q2 = q1;

268、always (posedge clk) q3 = q2; always (posedge clk) q1 = d; endmodule6.5 6.5 移位寄存器模型移位寄存器模型以上移位寄存器时序逻辑电路设计的例子表明:以上移位寄存器时序逻辑电路设计的例子表明:n4 4种阻塞赋值设计方式中有种阻塞赋值设计方式中有1 1种可以保证仿真正确种可以保证仿真正确n4 4种阻塞赋值设计方式中有种阻塞赋值设计方式中有3 3种可以保证综合正确种可以保证综合正确n4 4种非阻塞赋值设计方式全部可以保证仿真正确种非阻塞赋值设计方式全部可以保证仿真正确n4 4种非阻塞赋值设计方式全部可以保证综合正确种非阻塞赋值

269、设计方式全部可以保证综合正确6.6 6.6 阻塞赋值及一些简单的例子阻塞赋值及一些简单的例子例例6.13 module dffb (q, d, clk, rst); output q; input d, clk, rst; reg q; always (posedge clk) if (rst) q = 1b0; else q = d; endmodule 虽然可行也很简单,但我们不建议这种用阻塞赋值来描述D 触发器模型的风格。如果要把所有的模块写到一个always 块里,是可以采用阻塞赋值得到正确的建模、仿真并综合成期望的逻辑。但是,这种想法将导致使用阻塞赋值的习惯,而在较为复杂的多个alw

270、ays 块的情况下可能会导致竞争冒险.6.6 6.6 阻塞赋值及一些简单的例子阻塞赋值及一些简单的例子 例例6.14 6.14 使用非阻塞赋值来描述使用非阻塞赋值来描述D D 触发器是建议使用的风格触发器是建议使用的风格 module dffx (q, d, clk, rst); output q; input d, clk, rst; reg q; always (posedge clk) if (rst) q = 1b0; else q = d; endmodule 养成在描述时序逻辑的多个养成在描述时序逻辑的多个always always 块(甚至在单个块(甚至在单个always alw

271、ays 块)中使用非阻塞赋值的习惯比较好,此例就是这个块)中使用非阻塞赋值的习惯比较好,此例就是这个例子。例子。6.7 6.7 时序反馈移位寄存器建模时序反馈移位寄存器建模n线性反馈移位寄存器(Linear Feedback Shift-Register 简称LFSR)是带反馈回路的时序逻辑。反馈回路给习惯于用顺序阻塞赋值描述时序逻辑的设计人员带来了麻烦。n 例例6.15 6.15 用阻塞赋值实现的线性反馈移位寄存器,实际用阻塞赋值实现的线性反馈移位寄存器,实际上并不具有上并不具有LFSR LFSR 的功能的功能 module lfsrb1 (q3, clk, pre_n); output q

272、3; input clk, pre_n; reg q3, q2, q1; wire n1; assign n1 = q1 q3; always (posedge clk or negedge pre_n) if (!pre_n) begin q3 = 1b1; q2 = 1b1; q1 = 1b1; endelse begin q3 = q2; q2 = n1; q1 = q3; endendmodule6.7 6.7 时序反馈移位寄存器建模时序反馈移位寄存器建模 例例6.16 6.16 用阻塞赋值描述的线性反馈移位寄存器,其功能正用阻塞赋值描述的线性反馈移位寄存器,其功能正确,但模型的含义较

273、难理解。确,但模型的含义较难理解。 module lfsrb2 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; always (posedge clk or negedge pre_n) if (!pre_n) q3,q2,q1 = 3b111; else q3,q2,q1 = q2,(q1q3),q3; endmodule 如果将例6.15 和例6.16 中的阻塞赋值用非阻塞赋值代替,如例6.17 和例6.18 所示,仿真结果都和LFSR 的功能相一致。6.7 6.7 时序反馈移位寄存器建模时序反馈移位寄存器建模

274、例例6.17 6.17 用非阻塞语句描述的用非阻塞语句描述的LFSRLFSR,可综合其功能正确。,可综合其功能正确。module lfsrn1 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; wire n1; assign n1 = q1 q3; always (posedge clk or negedge pre_n)if (!pre_n) begin q3 = 1b1; q2 = 1b1; q1 = 1b1;endelse begin q3 = q2; q2 = n1; q1 = q3;endendmodule6

275、.7 6.7 时序反馈移位寄存器建模时序反馈移位寄存器建模 例例6.18 6.18 用非阻塞语句描述的用非阻塞语句描述的LFSRLFSR,可综合其功能正确。,可综合其功能正确。 module lfsrn2 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; always (posedge clk or negedge pre_n) if (!pre_n) q3,q2,q1 = 3b111; else q3,q2,q1 = q2,(q1q3),q3; endmodule6.7 6.7 时序反馈移位寄存器建模时序反馈移位寄存

276、器建模n从上面介绍的移位寄存器的例子以及LFSR 的例子,建议使用非阻塞赋值实现时序逻辑。而用非阻塞赋值语句实现锁存器也是最为安全的。因此,有以下原则:原则原则1 1 :时序电路建模时,用非阻塞赋值。:时序电路建模时,用非阻塞赋值。原则原则2 2 :锁存器电路建模时,用非阻塞赋值。:锁存器电路建模时,用非阻塞赋值。6.8 6.8 组合逻辑建模时应使用阻塞赋值组合逻辑建模时应使用阻塞赋值n在Verilog 中可以用多种方法来描述组合逻辑,但是当用always 块来描述组合逻辑时,应该用阻塞赋值。n有些设计人员提倡非阻塞赋值语句不仅可以用于时序逻辑,也可以用于组合逻辑的描述。对于简单的组合alwa

277、sys 块是可以这样的,但是当always 块中有多个赋值语句时,如例6.19 所示的四输入与或门逻辑,使用没有延时的非阻塞赋值可能导致仿真结果不正确。有时需要在always 块的入口附加敏感事件参数,才能使仿真正确,因而从仿真的时间效率角度看也不合算。6.8 6.8 组合逻辑建模时应使用阻塞赋值组合逻辑建模时应使用阻塞赋值 例例6.19 6.19 使用非阻塞赋值语句来描述组合逻辑使用非阻塞赋值语句来描述组合逻辑不建议不建议使用这种风格。使用这种风格。 module ao4 (y, a, b, c, d); output y; input a, b, c, d; reg y, tmp1, tm

278、p2; always (a or b or c or d) begin tmp1 = a & b; tmp2 = c & d; y = tmp1 | tmp2; end endmodule例19 中,输出y 的值由三个时序语句计算得到。由于非阻塞赋值语句在LHS 更新前,计算RHS 的值,因此tmp1 和tmp2 仍是应进入该always 块时的值,而不是在该步仿真结束时将更新的数值。输出y 反映的是刚进入always 块时的tmp1 和tmp2 的值,而不是在always 块中经计算后得到的值6.8 6.8 组合逻辑建模时应使用阻塞赋值组合逻辑建模时应使用阻塞赋值 例例6.206.20使用非

279、阻塞赋值来描述多层组合逻辑,使用非阻塞赋值来描述多层组合逻辑,虽可行,但效率不高。虽可行,但效率不高。 module ao5 (y, a, b, c, d); output y; input a, b, c, d; reg y, tmp1, tmp2;5 always (a or b or c or d or tmp1 or tmp2) begin tmp1 = a & b; tmp2 = c & d; y = tmp1 | tmp2; end endmodule例例20 和例和例19 的唯的唯一区别在于,一区别在于,tmp1 和和temp2 置置入敏感列表中。入敏感列表中。6.8 6.8 组

280、合逻辑建模时应使用阻塞赋值组合逻辑建模时应使用阻塞赋值 例例6.21 6.21 使用阻塞赋值实现组合逻辑是推荐使用的编使用阻塞赋值实现组合逻辑是推荐使用的编码风格。码风格。 module ao2 (y, a, b, c, d); output y; input a, b, c, d; reg y, tmp1, tmp2; always (a or b or c or d) begin tmp1 = a & b; tmp2 = c & d; y = tmp1 | tmp2; end endmodule原则原则3 3 :用:用always always 块块描述组合逻辑时,应描述组合逻辑时,应采用

281、阻塞赋值语句。采用阻塞赋值语句。例6.21 和例6.19 的唯一区别是,用阻塞赋值替代了非阻塞赋值。这样做可以保证仿真时经一次数据传递输出y 的值便是正确的,仿真效率高。6.9 6.9 时序和组合的混合逻辑时序和组合的混合逻辑使用非阻塞赋值使用非阻塞赋值n有时候将简单的组合逻辑和时序逻辑写在一起很方便。当把组合逻辑和时序逻辑有时候将简单的组合逻辑和时序逻辑写在一起很方便。当把组合逻辑和时序逻辑写到一个写到一个always 块中时,应遵从时序逻辑建模的原则,使用非阻塞赋值,如例块中时,应遵从时序逻辑建模的原则,使用非阻塞赋值,如例6.22 所示。所示。 例例6.22 在一个在一个always 块

282、中同时实现组合逻辑和时序逻辑块中同时实现组合逻辑和时序逻辑 module nbex2 (q, a, b, clk, rst_n); output q; input clk, rst_n; input a, b; reg q; always (posedge clk or negedge rst_n) if (!rst_n) q = 1b0; / 时序逻辑时序逻辑 else q = a b; / 异或,为组合逻辑异或,为组合逻辑 endmodule6.9 6.9 时序和组合的混合逻辑时序和组合的混合逻辑使用非阻塞赋值使用非阻塞赋值 例例6.23 6.23 将组合和时序逻辑分别写在两个将组合和时序

283、逻辑分别写在两个always always 块中块中 module nbex1 (q, a, b, clk, rst_n); output q; input clk, rst_n; input a, b; reg q, y; always (a or b) y = a b; always (posedge clk or negedge rst_n) if (!rst_n) q = 1b0; else q = y; endmodule原则原则4 4:在同一个:在同一个always always 块中描述时序和组合逻块中描述时序和组合逻辑混合电路时,用非阻辑混合电路时,用非阻塞赋值。塞赋值。6.9

284、 6.9 其他阻塞和非阻塞混合使用的原则其他阻塞和非阻塞混合使用的原则例6.24 在always 块中同时使用阻塞和非阻塞赋值的例子。(应尽量避免使用这种风格的代码,在可综合模块中应严禁使用) module ba_nba2 (q, a, b, clk, rst_n); output q; input a, b, rst_n; input clk; reg q; always (posedge clk or negedge rst_n) begin: ff reg tmp; if (!rst_n) q = 1b0; else begin tmp = a & b; q = tmp; end end

285、 endmodule例6.24 可以得到正确的仿真和综合结果,因为阻塞赋值和非阻塞赋值操作的不是同一个变量。虽然这种方法是可行的,但并不建议使用。6.10 6.10 其他阻塞和非阻塞混合使用的原则其他阻塞和非阻塞混合使用的原则 例例6.25 6.25 对同一变量既进行阻塞赋值对同一变量既进行阻塞赋值, ,又进行非阻塞赋值会又进行非阻塞赋值会产生综合错误。产生综合错误。 module ba_nba6 (q, a, b, clk, rst_n); output q; input a, b, rst_n; input clk; reg q, tmp; always (posedge clk or n

286、egedge rst_n) if (!rst_n) q = 1b0; / 对对 q 进行阻塞赋值进行阻塞赋值 else begin tmp = a & b; q = tmp; / 对对 q 进行非阻塞赋值进行非阻塞赋值 end endmodule原则原则5 5:不要在同一个:不要在同一个always always 块中同时使用阻塞和非阻塞赋块中同时使用阻塞和非阻塞赋值。值。6.11 6.11 对同一变量进行多次赋值对同一变量进行多次赋值n在一个以上在一个以上always always 块中对同一个变量进行多次赋值可能会导块中对同一个变量进行多次赋值可能会导致竞争冒险,即使使用非阻塞赋值也可能产

287、生竞争冒险。致竞争冒险,即使使用非阻塞赋值也可能产生竞争冒险。 例例6.26 使用非阻塞赋值语句,由于两个使用非阻塞赋值语句,由于两个always 块对同一变块对同一变量量q 赋值产生竞争冒险的程序:赋值产生竞争冒险的程序: module badcode1 (q, d1, d2, clk, rst_n); output q; input d1, d2, clk, rst_n; reg q; always (posedge clk or negedge rst_n) if (!rst_n) q = 1b0; else q = d1; always (posedge clk or negedge

288、rst_n) if (!rst_n) q = 1b0; else q = d2; endmodule原则原则6 6:严禁在多个:严禁在多个always always 块中对同一块中对同一个变量赋值。个变量赋值。6.12 6.12 常见的对于非阻塞赋值的误解常见的对于非阻塞赋值的误解n非阻塞赋值和$display误解误解1 1: “使用$display 命令不能用来显示非阻塞语句的赋值”事实是:事实是: 非阻塞语句的赋值在所有的$display 命令执行以后才更新数值n#0 延时赋值误解误解2 2: “0 延时把赋值强制到仿真时间步的末尾”事实是:事实是: 0 延时将赋值事件强制加入停止运行事件

289、队列中。0 0延时赋值建议遵循以下原则延时赋值建议遵循以下原则原则原则7 7:用:用$strobe $strobe 系统任务来显示用非阻塞赋值的变量值系统任务来显示用非阻塞赋值的变量值6.12 6.12 常见的对于非阻塞赋值的误解常见的对于非阻塞赋值的误解 例例6.276.27module display_cmds; reg a; initial $monitor($monitor: a = %b, a); initial begin $strobe ($strobe : a = %b, a); a = 0; a = 1; $display ($display: a = %b, a); #1

290、$finish; endendmodule6.12 6.12 常见的对于非阻塞赋值的误解常见的对于非阻塞赋值的误解n下面是上面模块的仿真结果说明$display 命令的执行是安排在活动事件队列中,但排在非阻塞赋值数据更新事件之前。 $display: a = 0 $monitor: a = 1 $strobe : a = 16.12 6.12 常见的对于非阻塞赋值的误解常见的对于非阻塞赋值的误解n例例6.28module nb_schedule1; reg a, b; initial begin a = 0; b = 1; a = b; b = a; $monitor (%0dns: $mon

291、itor: a=%b b=%b, $stime, a, b); $display (%0dns: $display: a=%b b=%b, $stime, a, b); $strobe (%0dns: $strobe : a=%b b=%bn, $stime, a, b);#0 $display (%0dns: #0 : a=%b b=%b, $stime, a, b);#1 $monitor (%0dns: $monitor: a=%b b=%b, $stime, a, b); $display (%0dns: $display: a=%b b=%b, $stime, a, b); $str

292、obe (%0dns: $strobe : a=%b b=%bn, $stime, a, b); $display (%0dns: #0 : a=%b b=%b, $stime, a, b);#1 $finish; endendmodule6.12 6.12 常见的对于非阻塞赋值的误解常见的对于非阻塞赋值的误解n下面是上面模块的仿真结果说明0 延时命令在非阻塞赋值事件发生前,在停止运行事件队列中执行。 0ns: $display : a=0 b=1 0ns: #0 : a=0 b=1 0ns: $monitor: a=1 b=0 0ns: $strobe : a=1 b=0 1ns: $dis

293、play : a=1 b=0 1ns: #0 : a=1 b=0 1ns: $monitor: a=1 b=0 1ns: $strobe : a=1 b=06.12 6.12 常见的对于非阻塞赋值的误解常见的对于非阻塞赋值的误解n对同一变量进行多次非阻塞赋值对同一变量进行多次非阻塞赋值误解误解3 3:“ 在在VerilogVerilog 语法标准中未定义可在同语法标准中未定义可在同一个一个always always 块中对某同一变量进行多次非阻塞块中对某同一变量进行多次非阻塞赋值赋值”。事实是:事实是: VerilogVerilog 标准定义了在同一个标准定义了在同一个always alway

294、s 块中可对某同一变量进行多次非阻塞赋值但多次块中可对某同一变量进行多次非阻塞赋值但多次赋值中,只有最后一次赋值对该变量起作用。赋值中,只有最后一次赋值对该变量起作用。6.13 6.13 小结小结本节中所有的原则归纳如下:n原则1:时序电路建模时,用非阻塞赋值。n原则2:锁存器电路建模时,用非阻塞赋值。n原则3:用always 块写组合逻辑时,采用阻塞赋值。n原则4:在同一个always 块中同时建立时序和组合逻辑电路时,用非阻塞赋值。n原则5:在同一个always 块中不要同时使用非阻塞赋值和阻塞赋值。n原则6:不要在多个always 块中为同一个变量赋值。n原则7:用$strobe 系统任务来显示用非阻塞赋值的变量值n原则8:在赋值时不要使用 #0 延迟n结论:遵循以上原则,有助于正确的编写可综合硬件,并且可以消除90100在仿真时可能产生的竞争冒险现象。

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

最新文档


当前位置:首页 > 高等教育 > 研究生课件

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