《电子技术综合设计与实践教程》课件第5章_第1页
《电子技术综合设计与实践教程》课件第5章_第2页
《电子技术综合设计与实践教程》课件第5章_第3页
《电子技术综合设计与实践教程》课件第5章_第4页
《电子技术综合设计与实践教程》课件第5章_第5页
已阅读5页,还剩64页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第5章VerilogHDL语言简介5.1VerilogHDL程序的基本构成 5.2VerilogHDL语言的数据类型 5.3词汇规定 5.4模块和端口 5.5行为描述 5.6VerilogHDL语言编程练习

VerilogHDL是一种硬件描述语言,用于从算法级、门级到开关级的多种抽象设计层次的数字系统建模。被建模的数字系统对象的复杂性可以介于简单的门和完整的电子数字系统之间。数字系统能够按层次描述,并可在相同描述中显式地进行时序建模。VerilogHDL语言具有下述描述能力:设计的行为特性、设计的数据流特性、设计的结构组成以及包含响应监控与设计验证方面的时延和波形产生机制。

VerilogHDL语言是于1983年由GatewayDesignAutomation公司为其模拟器产品开发的硬件建模语言。最初它只是一种专用语言,后来由于模拟、仿真器产品的广泛使用,VerilogHDL作为一种方便且实用的语言逐渐为众多设计者所接受。VerilogHDL语言于1990年被推向公众领域。OpenVerilogInternational(OVI)是促进Verilog发展的国际性组织。1992年,OVI决定致力将VerilogOVI标准推广成为IEEE标准。这一努力最后获得成功,Verilog语言于1995年成为IEEE标准,称为IEEEStd1364-1995。Verilog硬件描述语言参考手册中详细描述了该标准。本章主要对VerilogHDL语言作一简介,详细的编程使用请参考夏宇闻编写的《Verilog数字系统设计教程》一书。

VerilogHDL程序设计的基本单元是模块(module)。一个模块由两部分组成,一部分描述接口,另一部分描述逻辑功能,即定义输入是如何影响输出的。Verilog模块设计描述了一个模块的对外特性和内部功能,包括模块端口定义、I/O说明、内部信号声明和功能定义等四部分,如图5-1所示。5.1VerilogHDL程序的基本构成

图5-1VerilogHDL程序模块结构图模块是Verilog的基本描述单位,用于描述某个设计的功能或结构及与其它模块通信的外部端口。一个设计的结构可使用开关级原语、门级原语和用户定义的原语方式描述;设计的数据流行为使用连续赋值语句进行描述;时序行为使用过程结构进行描述。一个模块可以在另一个模块中使用,进行层次嵌套。正因为如此,才可以将大型的数字电路设计分割成不同的子模块来实现特定的功能,最后通过顶层模块调用子模块来实现整体功能。

1.模块端口的定义

模块端口定义声明了输入/输出口,其格式如下:

Module模块名(口1,口2,口3,…)

端口定义的圆括弧中的内容,是设计电路模块与外界联系的全部输入/输出端口信号或引脚,它是设计实体对外的一个通信界面,是外界可以看到的部分(不包含电源和接地端),多个端口名之间用“,”分隔。例如:

moduleadder(sum,cont,ina,inb,cin);

2.I/O说明

模块的I/O说明用来声明模块端口定义中各端口数据的流动方向,包括输入(input)、输出(output)和双向(inout)。其格式如下:

输入:input[信号位宽-1:0]端口名

输出:out[信号位宽-1:0]端口名

输入输出:inout[信号位宽-1:0]端口名

3.内部信号声明

内部信号声明用来说明设计电路的功能描述中所用信号的数据类型以及函数声明。其格式如下:

reg[width-1:0]变量1,变量2

wire[width-1:0]变量1,变量2

4.功能定义

功能定义是VerilogHDL程序设计中最主要的部分,用来描述设计模块的内部结构和模块端口间的逻辑关系,在电路上相当于器件的内部电路结构。功能定义采用三种方法产生逻辑,其格式如下:

(1)使用assign声明语句。

如:assigna=b&c;

(2)用实例元件(instantiate)。

如:and#2u1(q,a,b);

(3)使用always块。

如:always@(posedgeclkorposedgeclr)

begin……

end

在每个模块中,可用四种方式描述一个设计:数据流方式、行为方式、结构方式、上述描述方式的混合。

1)数据流方式

用数据流方式描述一个设计建模的最基本的机制就是使用连续赋值语句。在连续赋值语句中,某个值被指派给线网变量。连续赋值语句的语法如下:

assign[delay]LHS_net=RHS_expression;

其中,右边表达式使用的操作数无论何时发生变化,表达式值都会重新计算,并且在指定时延后被赋予左边的线网变量。时延定义了右边表达式操作数变化与赋值给左边表达式之间的持续时间。如果没有定义时延值delay,则缺省时延为0。连续赋值语句对电路的数据流行为采用的建模方式是隐式而非显式的。此外,连续赋值语句是并发执行的,也就是说各语句的执行顺序与其在描述中出现的顺序无关。

2)行为方式

设计的行为功能采用下述过程语句结构描述:

(1)

initial语句:此语句只执行一次。

(2)

always语句:此语句总是循环执行,或者说此语句重复执行。

只有寄存器类型的数据能够在这两种语句中被赋值。寄存器类型的数据在被赋新值前保持原有值不变。所有的初始化语句和always语句在0时刻并发执行。

3)结构方式

在VerilogHDL语言中可使用四种方式描述结构:内置门原语(在门级);开关级原语(在晶体管级);用户定义的原语(在门级);模块实例(创建层次结构)。

(1)内置门原语(在门级)。VerilogHDL语言中提供下列内置基本门:

●多输入门:and,nand,or,nor,xor,xnor。

●多输出门:buf,not。

●三态门:bufif0,bufif1,notif0,notif1。

●上拉、下拉电阻:pullup,pulldown。

(2)开关级原语(在晶体管级)。

MOS开关:cmos,nmos,pmos,rcmos,rnmos,rpmos。

●双向开关:tran,tranif0,tranif1,rtran,rtranif0,rtranif1。

门级逻辑设计描述中可使用具体的门实例语句。下面是简单的门实例语句格式:

gate_type[instance_name](term1,term2,…,term);N

注意,instance_name是可选的;gate_type为前面列出的某种门类型。各term用于表示与门的输入/输出端口相连的线网或寄存器。同一门类型的多个实例能够在一个结构形式中定义。语法如下:

gate_type

[instance_name1](term11,term12,…,term)1,N

[instance_name2](term21,term22,…,term)2,N

[instance_nameM](termM1,termM2,…,term)M;N

(3)用户定义的原语(UDP,在门级)。

以下语法的UDP说明可用来定义UDP:

PrimitiveUDP_name(OutputName,List_of_inpu)ts

Output_declaration

List_of_input_declarations

[Reg_declaration]

[Initial_statement]

table

List_of_tabel_entries

endtable

endprimitive

UDP的定义不依赖于模块定义,因此出现在模块定义以外,也可以在单独的文本文件中定义UDP。

UDP只能有一个输出和一个或多个输入。第一个端口必须是输出端口。此外,输出

可以取值0、1或x(不允许取z值)。输入中出现z值时以x处理。UDP的行为以表的形式描述。在UDP中可以描述下面两类行为:

●组合电路。在组合电路UDP中,规定了不同的输入组合和相对应的输出值。没有指定的任意组合输出为x。

●时序电路(边沿触发和电平触发)。在时序电路UDP中,使用1位寄存器描述内部状态。该寄存器的值是时序电路UDP的输出值。共有两种不同类型的时序电路UDP:一种模拟电平触发行为;另一种模拟边沿触发行为。时序电路UDP使用寄存器的当前值和输入值来决定寄存器的下一状态(和后继的输出)。

(4)模块实例(创建层次结构)。

首先构建基本模块,再逐层实例化,构成高级模块。

moduleDFF(d,clk,clr,q,qb);

....//定义各种逻辑

endmodule//构建基本模块DEF

moduleREG4(d,clk,clr,q,qb);

output[3:0]q,qb;

input[3:0]d;

inputclk,clr;

DFFd0(d[0],clk,clr,q[0],qb[0]);

DFFd1(d[1],clk,clr,q[1],qb[1]);

DFFd2(d[2],clk,clr,q[2],qb[2]);

DFFd3(d[3],clk,clr,q[3],qb[3]);

endmodule//在REG4模块内,通过实例化基本模块DEF构建高层模块

4)上述描述方式的混合

在模块中,结构方式和行为方式的描述可以自由混合。也就是说,模块描述中可以包含实例化的门、模块实例化语句、连续赋值语句以及always语句和initial语句的混合。它们之间也可以相互包含。来自always语句和initial语句(切记只有寄存器类型的数据才可以在这两种语句中被赋值)的值能够驱动门或开关,而来自于门或连续赋值语句(只能驱动线网)的值能够反过来用于触发always语句和initial语句。

VerilogHDL语言有两种数据类型。

(1)线网类型(nettype):表示Verilog结构化元件间的物理连线。它的值由驱动元件的值决定,例如连续赋值或门的输出。如果没有驱动元件连接到线网,则线网的缺省值为z。

5.2VerilogHDL语言的数据类型

(2)寄存器类型(registertype):表示一个抽象的数据存储单元,它只能在always语句和initial语句中被赋值,并且它的值从一个赋值到另一个赋值被保存下来。寄存器类型的变量具有x的缺省值。5.2.1线网类型

线网数据包含以下不同的线网子类型:wire、tri、wor、trior、wand、triand、trireg、tri1、tri0、supply0、supply1。

通用的线网类型说明语法如下:

net_kind[msb:lsb]net1,net2,...,netN;

线网子类型描述如表5-1所示。

表5-1线网子类型描述

1.wire和tri线网

用于连接单元的连线(wire)是最常见的线网类型。三态线(tri)与连线的语法和语义一致。三态线可以用于描述多个驱动源驱动同一根线的线网类型,并且没有其它特殊的意义。

2.wor和trior线网

线或(wor)指如果某个驱动源为1,那么线网的值也为1。三态线或(trior)与线或在语法和功能上是一致的。

3.wand和triand线网

线与(wand)指如果某个驱动源为0,那么线网的值为0。三态线与(triand)和线与在语法和功能上是一致的。

4.trireg线网

三态寄存器(trieg)线网用于存储数值(类似于寄存器)及电容节点的建模。当三态寄存器线网的所有驱动源都处于高阻态时,也就是说,当值为z时,三态寄存器线网保存作用在线网上的最后一个值。此外,三态寄存器线网的缺省初始值为x。例如:

trireg[1:8]Dbus,Abus;

5.tri0和tri1线网

这类线网可用于线逻辑的建模,即线网有多于一个的驱动源。tri0(tri1)线网的特征是,若无驱动源驱动,则它的值为0(tri1的值为1)。

6.supply0和supply1线网

supply0用于对“地”建模,即低电平0;supply1用于对电源建模,即高电平1。例如:

supply0Gnd,ClkGnd;

supply1[2:0]Vcc;5.2.2寄存器类型

VerilogHDL语言中有五种不同的寄存器类型:reg、integer、time、real、realtime。

1.reg寄存器类型

reg寄存器类型是最常见的数据类型。简单的寄存器类型说明如下:

reg[msb:lsb]reg1,reg2,…,regN;其中,msb和lsb定义了范围,并且均为常数值表达式。范围定义是可选的,如果没有定义范围,则缺省值为1位寄存器。该寄存器可以取任意长度。寄存器中的值通常被解释为无符号数。例如:

reg[3:0]Sat; //Sat为4位寄存器

regCnt; //1位寄存器

reg[1:32]Kisp,Pisp,Lisp; //32位寄存器

2.存储器类型

存储器是一个寄存器数组。在赋值语句中需要注意如下区别:存储器赋值不能在一条赋值语句中完成,但是寄存器可以。因此在存储器被赋值时,需要定义一个索引。

存储器使用如下说明方式:

reg[msb:lsb]memory1[upper1:lower1], //msb、lsb分别表示寄存器的最高位、

memory2[upper2:lower2],...; //最低位,upper1、lower1分别表示

//存储器包含的最高寄存器编号、最低

//寄存器编号

例如:

reg[0:3]MyMem[0:63] //MyMem为64个4位寄存器的数组

regBog[1:5] //Bog为5个1位寄存器的数组

3.integer寄存器类型

integer(整数)寄存器的值为整数值。整数寄存器可以作为普通寄存器使用,其典型应用为高层次行为建模。

使用整数型的说明如下:

integerinteger1,integer2,...,intergerN[msb:lsb];

其中,msb和lsb是定义整数数组界限的常量表达式,数组界限的定义是可选的。

4.time寄存器类型

time(时间)类型的寄存器用于存储和处理时间。

5.real和realtime寄存器类型

real(实数)寄存器类型和realtime(实数时间)寄存器类型中的参数是常量。该参数经常用于定义时延和变量的宽度。

real类型说明的变量的缺省值为0。

real类型寄存器说明如下:

realreal_reg1,real_reg2,…,real_regN;

realtime类型寄存器说明如下:

realtimerealtime_reg1,realtime_reg2,...,realtime_regN;

realtime与real类型完全相同。例如:

realSwing,Top;

realtimeCurrTime;5.2.3常量

常量是一个恒定不变的值数,一般在程序前部定义。常量定义格式如下:

parameter常量名1=表达式,常量名2=表达式,…,常量名n=表达式;

parameter是常量定义关键字,常量名是用户定义的标识符,表达式是为常量赋的值。例如:

parameterVcc=5,fbus=8'b11010001;

使用参数说明的参数只被赋值一次。参数说明如下:

parameterparam1=const_expr1,param2=const_expr2,...,paramN=const_exprN;

1.空白符和注释

VerilogHDL语言中的空白符包括空格、tab符号、换行和换页。空白符如果不是出现在字符串中,则在编译源程序时将被忽略。

注释分为行注释和块注释两种方式。行注释用符号//(两个斜杠)开始,注释到本行结束。块注释用/*开始,用*/结束。块注释可以跨越多行,但它们不能被嵌套。5.3词汇规定

2.常数

VerilogHDL语言中的常数包括数字、未知x和高阻z三种。数字可以用二进制、十进制、八进制和十六进制等4种不同数制来表示,完整的数字格式如下:

<位宽>'<进制符号><数字>

其中,位宽表示数字对应的二进制数的位数宽度;进制符号包括b或B(表示二进制数),d或D(表示十进制数),h或H(表示十六进制数),o或O(表示八进制数)。例如:

8'b10110001 //表示位宽为8位的二进制数

8'hf5 //表示位宽为8位的十六进制数

十进制数的位宽和进制符号可以缺省,例如:

125 //表示十进制数125

8'b1111xxxx //等价于8'hfx

8'b1101zzzz //等价于8'hdz

3.字符串

字符串是用双引号括起来的可打印字符序列,它必须包含在同一行中。例如,"ABC"、"ABOY."、"A"、"1234"都是字符串。

4.标识符

标识符是用户编程时为常量、变量、模块、寄存器、端口、连线、示例和begin-end块等元素定义的名称。标识符可以是字母、数字和下划线“_”等符号组成的任意序列。定义标识符时应遵循如下规则:

(1)首字符不能是数字。

(2)字符数不能多于1024个。

(3)大小写字母是不同的。

(4)不要与关键字同名。

5.关键字

关键字是VerilogHDL预先定义的单词,它们在程序中有不同的使用目的。例如,用module和endmodule来指出源程序模块的开始和结束;用assign来描述一个逻辑表达式等。VerilogHDL的关键字有97个。

6.操作符

操作符也称为运算符,是VerilogHDL预先定义的函数名字,这些函数对被操作的对象(即操作数)进行规定的运算,得到一个结果。

操作符通常由1~3个字符组成,例如,“+”表示加操作,“==”(两个

=

字符)表示逻辑等操作,“=

=

=”(3个

=

字符)表示全等操作。有些操作符的操作数只有1个,称为单目操作;有些操作符的操作数有2个,称为双目操作;有些操作符的操作数有3个,称为三目操作。

1)算术操作符(Arithmeticoperators)

常用的算术操作符包括:+

(加)、-

(减)、*

(乘)、/

(除)、%(求余)。其中%是求余操作符,在两个整数相除的基础上,取出其余数。例如,5%6的值为5,13%5的值是3。

2)逻辑操作符(Logicaloperators)

逻辑操作符包括:&&(逻辑与)、||

(逻辑或)、!(逻辑非)。

3)位运算(Bitwiseoperators)

位运算是将两个操作数按对应位进行逻辑操作。位运算操作符包括:~

(按位取反)、&

(按位与)、|

(按位或)、^

(按位异或)、^~

~^

(按位同或)。

在进行位运算时,当两个操作数的位宽不同时,计算机会自动将两个操作数按右端对齐,位数少的操作数会在高位用0补齐。

4)关系操作符(Pelationaloperators)

关系操作符包括:<

(小于)、<=

(小于等于)、>

(大于)、>=

(大于等于)。其中,<=

也是赋值运算的赋值符号。

关系运算的结果是1位逻辑值。在进行关系运算时,如果关系是真,则计算结果为1;如果关系是假,则计算结果为0;如果某个操作数的值不定,则计算结果不定(未知),表示结果是模糊的。

5)等式操作符(Equalityoperators)

等值操作符包括:==

(等于)、!=

(不等于)、===

(全等)、!==

(不全等)。

等值运算的结果也是1位逻辑值,当运算结果为真时,返回值1;为假则返回值0。

相等操作符(==)与全等操作符(===)的区别是:相等运算时,两个操作数必须逐位相等,其比较结果的值才为1(真);如果某些位是不定或高阻状态,其相等比较的结果就会是不定值。

全等运算时,对不定或高阻状态位也进行比较,当两个操作数完全一致时,其结果的值才为1(真),否则结果为0(假)。

6)缩减操作符(Reductionoperators)

缩减操作符包括:&(与)、~&(与非)、|

(或)、~|

(或非)、^

(异或)、^~

或~^

(同或)。

运算结果有1位:1或0。

例如,A=8'b11010001,则&A=0(在与缩减运算中,只有A中的数字全为1时,结果才为1);|A=1(在或缩减运算中,只有A中的数字全为0时,结果才为0)。

7)转移操作符(Shiftoperators)

转移操作符包括:>>(右移)、<<(左移)。

操作数>>n;//将操作数的内容右移n位,同时从左边开始用0来填补移出的位数

操作数<<n;//将操作数的内容左移n位,同时从右边开始用0来填补移出的位数

例:设A=8'b11010001,则A>>4的结果是A=8'b00001101;而A<<4的结果是A=8'b00010000。

8)条件操作符(Conditionaloperators)

条件操作符的操作数有3个,其使用格式如下:

操作数=条件?表达式1:表达式2;

当条件为真(条件结果值为1)时,操作数=表达式1;为假(条件结果值为0)时,操作数=表达式2。

9)并接操作符(Concatenationoperators)

并接操作符为{}。

并接操作符的使用格式如下:

{操作数1,操作数2,…,操作数n}; //将操作数1、操作数2…操作数n

//并接在一起

例如,将1位全加器进位cout与和sum并接在一起使用,它们的结果由两个加数ina、inb及低位进位cin相加决定,表达式如下:

{cout,sum}=ina+inb+cin;

下面通过一个实例来说明模块的说明,图5-2(a)是逻辑功能模块,图5-2(b)是用Verilo

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论