EDA技术及应用-基于FPGA的电子系统设计:Verilog HDL语法与要素_第1页
EDA技术及应用-基于FPGA的电子系统设计:Verilog HDL语法与要素_第2页
EDA技术及应用-基于FPGA的电子系统设计:Verilog HDL语法与要素_第3页
EDA技术及应用-基于FPGA的电子系统设计:Verilog HDL语法与要素_第4页
EDA技术及应用-基于FPGA的电子系统设计:Verilog HDL语法与要素_第5页
已阅读5页,还剩226页未读 继续免费阅读

下载本文档

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

文档简介

VerilogHDL语法与要素

主要内容5.1VerilogHDL简介5.2VerilogHDL语言要素5.3常量5.4数据类型5.5运算符5.6VerilogHDL语言的基本结构5.7VerilogHDL仿真与测试5.1概述

硬件描述语言(HardwareDescriptionLanguage)是具有特殊结构能够对硬件逻辑电路的功能进行描述的一种高级编程语言,是硬件设计人员和电子设计自动化(EDA)工具之间的界面。VHDL:起源于ADA语言,格式严谨,不易初学,VHDL出现较晚,但标准化早,1987年被标准化(IEEE1706-1987)。ABEL-HDL:ABEL语言从早期可编程逻辑器件(PLD)的设计中发展而来。ABEL-HDL被广泛用于各种可编程逻辑器件的逻辑功能设计,由于其语言描述的独立性,因而适用于各种不同规模的可编程器的设计。AHDL:(AlteraHDL)是ALTERA公司发明的HDL,特点是非常易学易用,学过高级语言的人可以在很短的时间(如几周)内掌握AHDL。它的缺点是移植性不好,通常只用于ALTERA自己的开发系统。5.1概述Superlog:Superlog集合了Verilog的简洁、C语言的强大、功能验证和系统级结构设计等特征,是一种高速的硬件描述语言。SystemC:所有的SystemC都是基于C++的,实际使用中,SystemC由一组描述类库和一个包含仿真核的库组成。在用户的描述程序中,必须包括相应的类库,可以通过通常的ANSIC++编译器编译该程序。目前VerilogHDL和VHDL语言是使用用户最多的两类语言,因为在IC设计领域,90%以上的公司都是采用VerilogHDL或VHDL进行设计。5.1概述一、什么是VerilogHDLVerilogHDL是一种用于数字逻辑电路设计的硬件描述语言(HradwareDescriptionLanguage),可以用来进行数字电路的仿真验证、时序分析、逻辑综合。用VerilogHDL描述的电路设计就是该电路的VerilogHDL模型。VerilogHDL既是一种行为描述语言也是一种结构描述语言。既可以用电路的功能描述,也可以用元器件及其之间的连接来建立VerilogHDL模型。5.1引言二、VerilogHDL的发展历史1983年,由GDA(GateWayDesignAutomation)公司的PhilMoorby首创;1989年,Cadence公司收购了GDA公司;1990年,Cadence公司公开发表VerilogHDL;1995年,IEEE制定并公开发表VerilogHDL1364-1995标准;1999年,模拟和数字电路都适用的Verilog标准公开发表5.1引言三、不同层次的VerilogHDL抽象VerilogHDL模型可以是实际电路的不同级别的抽象。抽象级别可分为五级:系统级(systemlevel):用高级语言结构(如case语句)实现的设计模块外部性能的模型;算法级(algorithmiclevel):用高级语言结构实现的设计算法模型(写出逻辑表达式);RTL级(registertransferlevel):描述数据在寄存器之间流动和如何处理这些数据的模型;门级(gatelevel):描述逻辑门(如与门、非门、或门、与非门、三态门等)以及逻辑门之间连接的模型;开关级(switchlevel):描述器件中三极管和储存节点及其之间连接的模型。5.1引言四、VerilogHDL的特点语法结构上的主要特点:形式化地表示电路的行为和结构;借用C语言的结构和语句;可在多个层次上对所设计的系统加以描述,语言对设计规模不加任何限制;具有混合建模能力:一个设计中的各子模块可用不同级别的抽象模型来描述;基本逻辑门、开关级结构模型均内置于语言中,可直接调用;易创建用户定义原语(UDP,UserDesignedPrimitive)。易学易用,功能强与C语言非常相似!5.2VerilogHDL语言要素Verilog程序由符号流构成,符号包括空白符(Whitespace)注释(Comments)操作符(Operators)数字(Numbers)字符串(Strings)标识符(Identifiers)关键字(Keywords)等5.2.1空白符空白符(Whitespace)空白符包括:空格、tab、换行和换页。空白符使代码错落有致,阅读起来更方便。在综合时空白符被忽略。VerilogHDL程序可以不分行,也可以加入空白符采用多行书写。例如:

initalbegina=3’b001;b=3’b110;end

这段程序等同于下面的书写格式:

initalbegin//加入空格,换行符等,使代码错落有致,提高可读性a=3’b001;b=3’b110;end注释(Comment)◆单行注释:以“//”开始到本行结束◆多行注释:多行注释以“/*”开始,到“*/”结束5.2.2注释

关键字关键字——事先定义好的确认符,用来组织语言结构;或者用于定义VerilogHDL提供的门元件(如and,not,or,buf)。用小写字母定义!

——如always,assign,begin,case,casex,else,end,for,function,if,input,output,repeat,table,time,while,wire用户程序中的变量、节点等名称不能与关键字同名!5.2.3关键字13VerilogHDL关键字edgeelseendendcaseendfunctionendprimitiveendmoduleendspecifyendtableendtaskeventforforceforeverforkfunctionhighz0highz1ififnoneinitialinoutinputintegerjoinlargemacromodulemediummodulenandnegedgenornotnotif0notif1nmosoroutputparameterpmosposedgeprimitivepulldownpulluppull0pull1andalwaysassignbeginbufbufif0bufif1casecasexcasezcmosdeassigndefaultdefparamdisable14VerilogHDL关键字(续)tri0tri1vectoredwaitwandweak0weak1whilewireworxnorxorrcmosrealrealtimeregreleaserepeatrnmosrpmosrtranrtranif0rtranif1scalaredsmallspecifyspecparamstrengthstrong0strong1supply0supply1tabletasktrantranif0tranif1timetritriandtriortrireg标识符

任何用VerilogHDL语言描述的“东西”都通过其名字来识别,这个名字被称为标识符。如源文件名、模块名、端口名、变量名、常量名、实例名等。标识符可由字母、数字、下划线和$符号构成;但第一个字符必须是字母或下划线,不能是数字或$符号!标识符最长可以包括1023个字符。此外,标识符是区分大小写的。合法的名字:A_99_ZReset_54MHz_Clock$Module

不合法的名字:123a$datamodule7seg.v标识符不能与关键字同名!5.2.4标识符

还有一类标识符称为转义标识符,转义标识符以符号“\”开头,以空白符结尾,可以包含任何字符。例如:\7400\n

反斜线和结束空白符并不是转义标识符的一部分,因此,标识符“\out”和标识符“out”恒等。

Verilog有下面四种基本的逻辑状态。◆

0:低电平、逻辑0或逻辑非◆

1:高电平、逻辑1或“真”◆

x或X:不确定或未知的逻辑状态◆

z或Z:高阻态Verilog中的所有数据都在上述4类逻辑状态中取值,其中x和z都不区分大小写,也就是说,值0x1z与值0X1Z是等同的。5.3常量◆

整数◆

实数◆

字符串parameter常量(或称符号常量)。5.3常量

程序运行中,值不能被改变的量称为常量(constants),Verilog中的常量主要有如下4种类型:

整常数的3种表达方式:表达方式说明举例<位宽>’<进制><数字>完整的表达方式8’b11000101或8’hc5<进制><数字>缺省位宽,则位宽由机器系统决定,至少32位hc5<数字>缺省进制为十进制,位宽默认为32位197(1)整数型常量(即整常数)的4种进制表示形式:二进制整数(b或B);十进制整数(d或D);十六进制整数(h或H);八进制整数(o或O)。注:这里位宽指对应二进制数的宽度。5.3.1整数20(2)x和z值x表示不定值,z表示高阻值;8’b1001xxxx或8’h9x8’b1010zzzz或8’haz每个字符代表的二进制数的宽度取决于所用的进制;当用二进制表示时,已标明位宽的数若用x或z表示某些位,则只有在最左边的x或z具有扩展性!为清晰可见,最好直接写出每一位的值![例]8’bzx=8’bzzzz_zzzx[例]8’b1x=8’b0000_001x“?”是z的另一种表示符号,建议在case语句中使用?表示高阻态z[例]casez(select)4’b???1:out=a;4’b??1?:out=b;4’b?1??:out=c;4’b1???:out=d;endcase(3)负数在位宽前加一个减号,即表示负数如:-8’d5//5的补数,=8‘b11111011减号不能放在位宽与进制之间,也不能放在进制与数字之间!8’d-5//非法格式为提高可读性,在较长的数字之间可用下划线_隔开!但不可以用在<进制>和<数字>之间。如:16‘b1010_1011_1100_1111//合法

8‘b_0011_1010//非法当常量未指明位宽时,默认为32位。10=32‘d10=32’b1010-1=-32’d1=32’b1111……1111=32’hFFFFFFFF例如:10缺省位宽,所以位宽是32位二进制‘h4ac缺省位宽,所以位宽为32位二进制9’o671位宽9,八进制数3’b10x位宽3,二进制数6’hf3位宽5,十六进制数6’hx位宽6,十六进制数一些规定:(1)问号“?”是高阻态的一种,与z相同,如2’B1?=2’b1z,表示两位2进制数,其低位为高阻状态。(2)数值中,左边是数值最高位(MSBMostSignificantBit),右边是最低有效位(LSBLeastSignificantBit)。(3)在二进制中,x、z只代表相应位的逻辑状态。x表示不定,z表示高阻(4)当位宽缺省时,位宽为32位。(5)位宽<数值位数时,高位舍去。如:6’hf3=6’b11_0011(6)位宽>数值位数时,高位补0(z,x则补相应的z,x)

如:6’hf=6’b00_1111,6’hx=6’bxx_xxxx(7)数值与数值之间可以有空格(8)位宽不允许为表达式注意:“_”增加可读性,没有实际意义。实数(Real)有下面两种表示法。◆

十进制表示法。例如:2.00.1 //以上2例是合法的实数表示形式2. //非法:小数点两侧都必须有数字◆

科学计数法。例如:43_5.1e2 //其值为43510.09.6E2 //960.0(e与E相同)5E-4 //0.00055.3.2实数(Real)5.3.3字符串(Strings)字符串是双引号内的字符序列。字符串不能分成多行书写。例如:

"INTERNALERROR"字符串的作用主要是用于仿真时,显示一些相关的信息,或者指定显示的格式。\n\t\\\”

换行符Tab键

字符\本身

字符”字符串宽度为字符串中字符的个数乘以8。例如:

“ERROR\n”//6个字符,宽度为6*8(48b)字符串中有一类特殊字符,特殊字符必须用字符“\”来说明,如表所示。265.3.4parameter常量(符号常量)用parameter来定义一个标识符,代表一个常量——称为符号常量。参数型数据的确认符parameter

参数名1=表达式,参数名2=表达式,……;每个赋值语句的右边必须为常数表达式,即只能包含数字或先前定义过的符号常量!

parameteraddrwidth=16;//合法格式

parameteraddrwidth=datawidth*2;//非法格式常用参数来定义延迟时间和变量宽度。可用字符串表示的任何地方,都可以用定义的参数来代替。参数是本地的,其定义只在本模块内有效。在模块或实例引用时,可通过参数传递改变在被引用模块或实例中已定义的参数!赋值语句表格式27变量在程序运行过程中,其值可以改变的量,称为变量。其数据类型有19种,常用的有3种:网络型(netstype)寄存器型(registertype)数组(memorytype)1.nets型变量定义——输出始终随输入的变化而变化的变量。表示结构实体(如门)之间的物理连接。常用nets型变量:wire,tri:连线类型(两者功能一致)wor,trior:具有线或特性的连线(两者功能一致)wand,triand:具有线与特性的连线(两者功能一致)tri1,tri0:上拉电阻和下拉电阻supply1,supply0:电源(逻辑1)和地(逻辑0)

nets型变量不能储存值!5.4数据类型

28wire型变量最常用的nets型变量,常用来表示以assign语句赋值的组合逻辑信号。模块中的输入/输出信号类型缺省为wire型。可用做任何方程式的输入,或“assign”语句和实例元件的输出。wire

数据名1,数据名2,……,数据名n;wire[n-1:0]

数据名1,数据名2,……,数据名m;或wire[n:1]

数据名1,数据名2,……,数据名m;每条总线位宽为n共有m条总线wire型向量(总线)格式29定义——对应具有状态保持作用的电路元件(如触发器、寄存器等),常用来表示过程块语句(如initial,always,task,function)内的指定信号。常用register型变量:reg:常代表触发器integer:32位带符号整数型变量real:64位带符号实数型变量time:无符号时间变量纯数学的抽象描述2.variable型变量30variable型变量与nets型变量的根本区别是:variable型变量需要被明确地赋值,并且在被重新赋值前一直保持原值。variable型变量必须通过过程赋值语句赋值!不能通过assign语句赋值!在过程块内被赋值的每个信号必须定义成variable型!31reg型变量定义——在过程块中被赋值的信号,往往代表触发器,但不一定就是触发器(也可以是组合逻辑信号)!reg

数据名1,数据名2,……,数据名n;reg[n-1:0]

数据名1,数据名2,……,数据名m;或reg[n:1]

数据名1,数据名2,……,数据名m;每个向量位宽为n共有m个reg型向量[例]reg[4:1]regc,regd;//regc,regd为4位宽的reg型向量reg型向量(总线)格式32用reg型变量生成组合逻辑举例:

modulerw1(a,b,out1,out2);

inputa,b;

outputout1,out2;

regout1;

wireout2;

assignout2=a;

always@(b)

out1<=~b;

endmoduleaout2BUFFbINVout1过程赋值语句连续赋值语句电平触发Verilog中reg与wire的区别reg型变量既可生成触发器,也可生成组合逻辑;wire型变量只能生成组合逻辑。33用reg型变量生成触发器举例:

modulerw2(clk,d,out1,out2);

inputclk,d;

outputout1,out2;

regout1;

wireout2;

assignout2=d&~out1;

always@(posedgeclk)

begin

out1<=d;

end

endmodule

过程赋值语句连续赋值语句dout2AND2i1clkout1DQDFF沿触发34定义——由若干个相同宽度的reg型向量构成的数组。VerilogHDL通过reg型变量建立数组来对存储器建模。memory型变量可描述RAM、ROM和reg文件。memory型变量通过扩展reg型变量的地址范围来生成:reg[n-1:0]

存储器名[m-1:0];或reg[n-1:0]存储器名[m:1];每个存储单元位宽为n共有m个存储单元3.memory型变量——数组QuartusII不支持!VerilogHDL中的变量名、参数名等标记符是对大小写字母敏感的!35含义不同

[例]reg[n-1:0]

rega;//一个n位的寄存器

regmema[n-1:0];//由n个1位寄存器组成的存储器

必须指明存储单元的地址!0n-10n-1n-2···地址赋值方式不同

一个n位的寄存器可用一条赋值语句赋值;一个完整的存储器则不行!若要对某存储器中的存储单元进行读写操作,必须指明该单元在存储器中的地址!

[例]rega=0;

//合法赋值语句

mema=0;

//非法赋值语句

mema[8]=1;

//合法赋值语句

mema[1023:0]=0;//合法赋值语句memory型变量与reg型变量的区别

需要指出的是,这里讨论的VerilogHDL存储器设计不管是RAM还是ROM,在综合时,综合器通常会用触发器来实现。平时在实际设计中如果需要用到存储器,更多的是采用设计软件所提供的存储器宏功能模块去实现,这样,设计软件(如QuartusII)综合时,在没有人工指定的情况下,会自动采用FPGA器件中的嵌入式存储器块去物理实现。1.标量与向量宽度为1位的变量称为标量,如果在变量声明中没有指定位宽,则默认为标量(1位)。举例如下:

wirea; //a为标量

regclk; //clk为标量reg型变量线宽大于1位的变量(包括net型和variable型)称为向量(vector)。向量的宽度用下面的形式定义:

[msb:lsb]比如:

wire[3:0]bus;//4位的总线注意:2.位选择和域选择在表达式中可任意选中向量中的一位或相邻几位,分别称为位选择和域选择,例如:A=mybyte[6];//位选择B=mybyte[5:2];//域选择再比如:reg[7:0]a,b;reg[3:0]c;regd;d=a[7]&b[7]; //位选择c=a[7:4]+b[3:0]; //域选择395.5运算符一、算术运算符二、逻辑运算符三、位运算符四、关系运算符五、等式运算符

内容概要六、缩减运算符七、移位运算符八、条件运算符九、位拼接运算符十、运算符的优先级405.5运算符及表达式运算符按功能分为9类:算术运算符逻辑运算符关系运算符等式运算符缩减运算符条件运算符位运算符移位运算符位拼接运算符运算符按操作数的个数分为3类:单目运算符——带一个操作数逻辑非!,按位取反~,缩减运算符,移位运算符双目运算符——带两个操作数算术、关系、等式运算符,逻辑、位运算符的大部分三目运算符——带三个操作数条件运算符

415.5运算符及表达式一、算术运算符算术运算符说明

+-*/%加减乘除求模双目运算符进行整数除法运算时,结果值略去小数部分,只取整数部分!%称为求模(或求余)运算符,要求%两侧均为整型数据;求模运算结果值的符号位取第一个操作数的符号位!

[例]-11%3结果为-2进行算术运算时,若某操作数为不定值x,则整个结果也为x。 MAX+PLUSII不支持“/”

和“%”运算!QuartusII都支持!425.5运算符及表达式[例]除法和求模运算的区别注意/和%的区别!435.5运算符及表达式9/4=29%4=1arithmetic.vwf445.5运算符及表达式二、逻辑运算符逻辑运算符把它的操作数当作布尔变量:非零的操作数被认为是真(1‘b1);零被认为是假(1‘b0);不确定的操作数如4’bxx00,被认为是不确定的(可能为零,也可能为非零)(记为1’bx);但4’bxx11被认为是真(记为1’b1,因为它肯定是非零的)。逻辑运算符说明

&&(双目)||(双目)!(单目)逻辑与逻辑或逻辑非进行逻辑运算后的结果为布尔值(为1或0或x)!455.5运算符及表达式“&&”和“||”的优先级除高于条件运算符外,低于关系运算符、等式运算符等几乎所有运算符;逻辑非“!”优先级最高。[例](a>b)&&(b>c) 可简写为:a>b&&b>c

(a==b)||(x==y) 可简写为:a==b||x==y

(!a)||(a>b) 可简写为:!a||a>b为提高程序的可读性,明确表达各运算符之间的优先关系,建议使用括号!465.5运算符及表达式三、位运算符位运算符说明~&|^^~,~^按位取反按位与按位或按位异或按位同或双目运算符单目运算符位运算其结果与操作数位数相同。位运算符中的双目运算符要求对两个操作数的相应位逐位进行运算。两个不同长度的操作数进行位运算时,将自动按右端对齐,位数少的操作数会在高位用0补齐。

[例]若A=5’b11001,B=3’b101,则A&B=(5’b11001)&(5’b00101)=5’b00001

475.5运算符及表达式[例]&&运算符和&(按位与)的区别&&运算的结果为1位的逻辑值注意&&和&的区别!被认为是

1‘b1被认为是

1‘bx逻辑与结果为

1‘bx485.5运算符及表达式四、关系运算符关系运算符说明<<=>>=小于小于或等于大于大于或等于双目运算符括号内先运算!算术运算先运算!运算结果为1位的逻辑值1或0或x。关系运算时,若关系为真,则返回值为1;若声明的关系为假,则返回值为0;若某操作数为不定值x,则返回值为x。所有的关系运算符优先级别相同。关系运算符的优先级低于算术运算符。[例]a<size-1 等同于:a<(size-1)size-(1<a) 不等同于:size-1<a495.5运算符及表达式五、等式运算符等式运算符说明==!====!==等于不等于全等不全等双目运算符运算结果为1位的逻辑值1或0或x。等于运算符(==)和全等运算符(===)的区别:使用等于运算符时,两个操作数必须逐位相等,结果才为1;若某些位为x或z,则结果为x。使用全等运算符时,若两个操作数的相应位完全一致(如同是1,或同是0,或同是x,或同是z),则结果为1;否则为0。所有的等式运算符优先级别相同。===和!==运算符常用于case表达式的判别,又称为“case等式运算符”。MAX+PLUSII和QuartusII都不支持!505.5运算符及表达式[例]if(A

==

1’bx)$display(“AisX”);//当A为不定值时,式(A==1’bx)的运算结果为x,则该语句不执行

if(A

===

1’bx)$display(“AisX”);//当A为不定值时,式(A===1’bx)的运算结果为1,该语句执行==01xz01xz10xx01xxxxxxxxxx===01xz01xz1000010000100001表5-1“==”的真值表表5-2“===”的真值表等于运算的结果可能为1或0或x全等于运算的结果只有1或0515.5运算符及表达式六、缩减运算符缩减运算符说明&~&|~|^^~,~^与与非或或非异或同或单目运算符运算法则与位运算符类似,但运算过程不同!对单个操作数进行递推运算,即先将操作数的最低位与第二位进行与、或、非运算,再将运算结果与第三位进行相同的运算,依次类推,直至最高位。运算结果缩减为1位二进制数。[例]reg[3:0]a;b=|a;//等效于b=((a[0]|a[1])|a(2))|a[3]注意缩减运算符和位运算符的区别!525.5运算符及表达式七、移位运算符移位运算符说明>><<右移左移单目运算符只有当右操作数为常数时MAX+PLUSII支持!左移会扩充位数!用法:A>>n或A<<n

将操作数右移或左移n位,同时用n个0填补移出的空位。[例]4’b1001>>3=4’b0001;4’b1001>>4=4’b00004’b1001<<1=5’b10010;4’b1001<<2=6’b100100;

1<<6=32’b1000000将操作数右移或左移n位,相当于将操作数除以或乘以2n。右移位数不变,但右移的数据会丢失!53(1)逻辑左移:<<(2)逻辑右移:>>设a是操作对象,n是移位位数,则a<<n表示将a左移n位。进行移位操作时,用0填补移出的空位。(3)算术左移:<<<(4)算术右移:>>>算术左移,用0填补移出的空位。算术右移,看最高位,如果是1就补1,如果是0就补0。545.5运算符及表达式八、条件运算符三目运算符in1outMUXin0sel信号=条件?表达式1:表达式2条件运算符为?:用法:[例]数据选择器assignout=sel?in1:in0;当条件为真,信号取表达式1的值;为假,则取表达式2的值。sel=1时out=in1;sel=0时out=in0555.5运算符及表达式九、位拼接运算符位拼接运算符为{}用于将两个或多个信号的某些位拼接起来,表示一个整体信号。用法:{信号1的某几位,信号2的某几位,……,信号n的某几位}例如在进行加法运算时,可将进位输出与和拼接在一起使用。[例1]output[3:0]sum;//和

outputcout;//进位输出input[3:0]ina,inb;inputcin;assign{cout,sum}=ina+inb+cin;//进位与和拼接在一起[例2]{a,b[3:0],w,3’b101}={a,b[3],b[2],b[1],b[0],w,1’b1,1’b0,1’b1}565.5运算符及表达式可用重复法简化表达式,如:{4{w}}//等同于{w,w,w,w}还可用嵌套方式简化书写,如:

{b,{3{a,b}}}//等同于{b,{a,b},{a,b},{a,b}},也等同于{b,a,b,a,b,a,b}用于表示重复的表达式必须为常数表达式!在位拼接表达式中,不允许存在没有指明位数的信号,必须指明信号的位数;若未指明,则默认为32位的二进制数!如{1,0}=64’h00000001_00000000,注意{1,0}不等于2‘b10575.5运算符及表达式十、运算符的优先级类别运算符优先级逻辑、位运算符!~高低算术运算符*/%+-移位运算符<<>>关系运算符<<=>>=等式运算符==!====!==缩减、位运算符&~&^^~|~|逻辑运算符&&||条件运算符?:表5-8运算符的优先级为提高程序的可读性,建议使用括号来控制运算的优先级![例](a>b)&&(b>c)

(a==b)||(x==y)

(!a)||(a>b)5.6VerilogHDL基本结构一、简单的VerilogHDL例子二、VerilogHDL模块的结构三、逻辑功能定义四、关键字五、标识符六、编写VerilogHDL源代码的标准内容概要5.6VerilogHDL基本结构moduleaoi(a,b,c,d,f);/*模块名为aoi,端口列表a,b,c,d,f*/inputa,b,c,d; //模块的输入端口为a,b,c,doutputf;//模块的输出端口为fwirea,b,c,d,f;//定义信号的数据类型assignf=~((a&b)|(~(c&d))); //逻辑功能描述endmodule“与-或-非”电路

605.6VerilogHDL基本结构VerilogHDL程序是由模块构成的。每个模块嵌套在module和endmodule声明语句中。模块是可以进行层次嵌套的。每个VerilogHDL源文件中只准有一个顶层模块,其他为子模块。每个模块要进行端口定义,并说明输入输出端口,然后对模块的功能进行行为逻辑描述。程序书写格式自由,一行可以写几个语句,一个语句也可以分多行写。除了endmodule语句、begin_end语句和fork_join语句外,每个语句和数据定义的最后必须有分号。可用/*.....*/和//...对程序的任何部分作注释。加上必要的注释,以增强程序的可读性和可维护性。总结615.6VerilogHDL基本结构二、VerilogHDL模块的结构Verilog的基本设计单元是“模块

(block)”

。Verilog模块的结构由在module和endmodule关键词之间的4个主要部分组成:moduleblock1(a,b,c,d);

inputa,b,c;

outputd;

wirex;

assignd=a|x;assignx=(b&~c);endmoduleI/O说明端口定义功能描述信号类型声明12341.模块定义行:该行以module开头,紧接着是模块名和括号内的端口名列表,最后以分号结束。2.端口类型定义:VerilogHDL中的端口类型只有输入(input)、输出(output)和双向(inout)三种。凡是在端口列表的端口,都必须经过定义。3.数据类型定义:VerilogHDL支持的数据类型有连线类和寄存器类。每个类又可以细分,除了连线类可以使用缺省定义外,其它凡在后面的描述中出现的变量都应该给出数据类型定义。4.描述部分:本部分对模块进行描述,本部分包含如下语句:(1)initial叙述——行为描述(2)always叙述——行为描述(3)模块调用——结构化描述(4)门调用——结构化描述(5)UDP调用——结构化描述(6)assign叙述——数据流描述5.结束行关键字endmodule用于结束行,注意其后没有分号。635.6VerilogHDL基本结构VerilogHDL模块的模板(仅考虑用于逻辑综合的部分)module<顶层模块名>(<输入输出端口列表>);

output

输出端口列表;

input

输入端口列表;

//(1)使用assign语句定义逻辑功能

wire结果信号名;

assign<结果信号名>=表达式;

//(2)使用always块定义逻辑功能

always@(<敏感信号表达式>)begin //过程赋值语句

//if语句

//case语句

//while,repeat,for循环语句

//task,function调用

end645.6VerilogHDL基本结构//(3)元件例化

<module_name

><instance_name

>(<port_list>);//模块元件例化

<gate_type_keyword><instance_name

>(<port_list>);//门元件例化endmodule例化元件名也可以省略!1.模块声明模块声明包括模块名字,模块输入、输出端口列表。模块定义格式如下:module模块名(端口1,端口2,端口3,……);2.端口定义对模块的输入输出端口要明确说明,其格式为:input端口名1,端口名2,……端口名n;//输入端口output端口名1,端口名2,……端口名n;//输出端口inout端口名1,端口名2,……端口名n;//输入输出端口

端口是模块与外界连接和通信的信号线,有三种端口类型分别是输入端口(input),输出端口(output)和输入/输出双向端口(inout)。5.6VerilogHDL基本结构模块定义和端口定义:input

EN;//定义1位宽(标量)输入信号ENinput

[7:0]DIN;//定义8位宽(失量)输入信号DINoutput[7:0]DOUT;//定义8位宽(失量)输出信号DOUTmoduleSINGLEBUS(EN,DIN,DOUT);3.信号类型定义

对模块中所用到的所有信号(包括端口信号、节点信号等)都必须进行数据类型的定义。Verilog语言提供了各种信号类型,分别模拟实际电路中的各种物理连接和物理实体。

如果信号的数据类型没有定义,则综合器将其默认为是wire型。

在Verilog-2001标准中,规定可将端口定义和信号类型定义放在一条语句中完成,例如:outputregf;//f为输出端口,其数据类型为reg型outputreg[3:0]out;//out为输出端口,其数据类型为4位宽reg型

还可以将端口定义和信号类型定义放在模块列表中,而不是放在模块内部。[例]将端口类型和信号类型定义放在模块列表中moduleNAND(inputwirea,inputwireb,outputwiref);

assignf=~(a&b);//逻辑功能描述endmodule端口与内部信号数据类型说明:(1)信号可以分为端口信号和内部信号。出现在端口列表中的信号是端口信号,其它的信号为内部信号。(2)对于端口信号,输入端口只能是连线类型。输出端口可以是连线(net)类型,也可以是寄存器(register)类型。若输出端口在过程块中赋值则为register类型;若在过程块外赋值,则为net类型。(3)内部信号类型与输出端口相同,可以是连线(net)或寄存器(register)类型。若在过程块中赋值,则为register类型;若在过程块外赋值,则为net类型。netPORT连接的规则*input:符号内部总是net,外部可连net和reg数据类型*output:其内部可为net或reg,而外部必须连各种net数据类型*inouts:它的内外都用net且只能连各种net数据类型moduletop;

moduledev(a,b,c);

xbinputsregornet

outputsayinoutsregornetnet

cnet

znet定义端口时应注意如下几点:

(1)每个端口除了要声明是输入、输出还是双向端口外,还要声明其数据类型,是wire型,还是reg等其他类型。

(2)输入和双向端口不能声明为reg型。

(3)在测试模块中不需要定义端口。4.逻辑功能定义◆结构(Structural)描述◆行为(Behavioural)描述◆数据流(DataFlow)描述一个复杂电路的完整VerilogHDL模型由若干个VerilogHDL模块构成,每个模块由若干的子模块构成——可分别用不同抽象级别的VerilogHDL描述。在同一个VerilogHDL模块中可有多种级别的描述。系统级(systemlevel):用高级语言结构(如case语句)实现的设计模块外部性能的模型;算法级(algorithmiclevel):用高级语言结构实现的设计算法模型(写出逻辑表达式);RTL级(registertransferlevel):描述数据在寄存器之间流动和如何处理这些数据的模型;门级(gatelevel):描述逻辑门(如与门、非门、或门、与非门、三态门等)以及逻辑门之间连接的模型;开关级(switchlevel):描述器件中三极管和储存节点及其之间连接的模型。73

所谓结构描述方式,是指在设计中通过调用库中的元件或已设计好的模块来完成设计实体功能的描述。在结构体中,描述只表示元件(或模块)和元件(或模块)之间的互连,就像网表一样。当调用库中不存在的元件时,必须首先进行元件的创建,然后将其放在工作库中,这样才可以通过调用工作库来调用元件。在Verilog程序中可通过如下方式描述电路的结构◆调用Verilog内置门元件(门级结构描述)◆调用开关级元件(晶体管级结构描述)◆用户自定义元件UDP(也在门级)多层次结构电路的设计中,不同模块间的调用也属于结构描述。一、

门级结构描述

VerilogHDL的门级描述75门类型关键字

<例化的门名称>(<端口列表>);门级描述即直接调用门原语进行逻辑的结构描述。以门级为基础的结构描述所建立的硬件模型不仅是可仿真的,也是可综合的;一个逻辑网络由许多逻辑门和开关组成,用逻辑门的模型来描述逻辑网络最直观!门类型的关键字有26个,常用的有9个:

not,and,nand,or,nor,xor,xnor,buf,

bufif1,bufif0,notif1,notif0(各种三态门)调用门原语的句法:注1:在

端口列表中输出信号列在最前面;注2:门级描述不适于描述复杂的系统!结构描述,最直观!可省略!

Verilog的内置门元件门元件的调用调用门元件的格式为:门元件名字<例化的门名字>(<端口列表>)其中普通门的端口列表按下面的顺序列出:(输出,输入1,输入2,输入3……);比如:anda1(out,in1,in2,in3); //三输入与门对于三态门,则按如下顺序列出输入输出端口:(输出,输入,使能控制端);比如:bufif1mytri1(out,in,enable); //高电平使能的三态门门元件的调用对于buf和not两种元件的调用,需注意的是:它们允许有多个输出,但只能有一个输入。比如:

notN1(out1,out2,in); //1个输入in,2个输出out1,out2bufB1(out1,out2,out3,in); //1个输入in,3个输出out1,out2,out3[例5-3]调用门原语实现4选1数据选择器注:首先必须根据逻辑功能画出逻辑电路图!79输入输出cntrl1cntrl2out00011011in1in2in3in4真值表80注:这里省略了所有的例化门元件名称!【例5-3】根据调用门元件实现的4选1MUX,画出结构图modulemux4_1a(out,in1,in2,in3,in4,s0,s1);inputin1,in2,in3,in4,s0,s1;outputout;wires0_n,s1_n,w,x,y,z;not(sel0_n,s0),(s1_n,s1);and(w,in1,s0_n,s1_n),(x,in2,s0_n,s1), (y,in3,s0,s1_n),(z,in4,s0,s1);or(out,w,x,y,z);endmodule用基本门实现的4选1MUX原理图2.模块调用

如果数字系统比较复杂,可采用“Top-down”的方法进行设计。首先把系统分为几个模块,每个模块再分为几个子模块,以此类推,直到易于实现为止。这种“Top-down”的方法能够把复杂的设计分解为许多简单的逻辑来实现,同时也适合于多人进行分工合作,如同用C语言编写大型软件一样。VerilogHDL语言能够很好地支持这种“Top-down”的设计方法。

对于顶层模块的内部设计,我们可以利用原理图的输入方式,将各个子模块相互级联构成顶层模块,也可以利用VerilogHDL的输入方式调用各个子模块。模块调用格式如下:模块名例化名(端口名表项);

其中,模块名为定义该模块时所起的名字,例化名为为该模块在此次调用中起的别名,可省略。模块调用格式类似于门调用格式。只是在端口名列表里规定有所区别。位置对应方式;端口名对应方式。【例5-6】用模块例化方式设计的1位全加器顶层设计(1)半加器定义modulehalf_add(a,b,so,co);inputa,b;outputso,co;assignco=a&b;assignso=a^b;endmodule1位全加器由两个半加器和一个或门级联而成(2)1位全加器的VerilogHDL实现:位置对应方式调用半加器模块。modulefull_add(ain,bin,cin,sum,cout);inputain,bin,cin;outputwiresum,cout;wired,e,f;half_adda1(ain,bin,e,d);

half_adda2(e,cin,sum,f);ora3(cout,d,f);endmodule端口名对应方式调用半加器模块。modulefull_add(ain,bin,cin,sum,cout);inputain,bin,cin;outputwiresum,cout;wired,e,f;half_adda1(.a(ain),.b(bin),.so(e),.co(d));

half_adda2(.a(e),.b(cin),.so(sum),.co(f));ora3(cout,d,f);endmodule二、

数据流描述

数据流描述方式主要使用持续赋值语句,多用于描述组合逻辑电路。(1)连续赋值的信号型式一定是连线wire型。(2)使用assign关键字,格式是:

assign[#delay]被赋值的连线变量=表达式;(3)只要等式右侧的值发生改变时,就会重新对左侧被赋值变量进行赋值。(4)所有output和inout引脚都是连线变量,不需要特别的连线变量声明。二、

数据流描述

用数据流描述模式设计电路与用传统的逻辑方程设计电路很相似。设计中只要有了布尔代数表达式就很容易将它用数据流方式表达出来。表达方法是用Verilog中的逻辑运算符置换布尔逻辑运算符即可。比如,如果逻辑表达式为:,则用数据流方式描述为:

assignf=(a&b)|(~(c&d))。[例5-10]利用数据流描述方式实现1位全加器。modulefull_add(ain,bin,cin,sum,cout);inputain,bin,cin;

outputwiresum,cout;

assign{cout,sum}=ain+bin+cin;endmodule三、行为描述方式用行为描述模式设计电路,可以降低设计难度。行为描述只需表示输入与输出之间的关系,不需要包含任何结构方面的信息。设计者只需写出源程序,而挑选电路方案的工作由EDA软件自动完成。在电路的规模较大或者需要描述复杂的逻辑关系时,应首先考虑用行为描述方式设计电路,如果设计的结果不能满足资源占有率的要求,则应改变描述方式。

行为描述过程块结构:VerilogHDL的行为描述以过程块为基本组成单位,一个模块的行为描述由一个或多个并行运行的过程块组成。过程块的定义:

过程语句@(事件控制敏感表)

//(斜体部分可缺省)块语句开始表示符:块名块内局部变量说明过程赋值语句高级程序语句块语句结束标识符initialalways@(敏感事件表)beginforkendjoin阻塞赋值=;非阻塞赋值<=ifelse语句case语句while,for循环task,function调用integeri;[例5-11]利用行为描述方式实现1位全加器。modulefull_add(ain,bin,cin,sum,cout); inputain,bin,cin;outputregsum,cout;

always@(*)

{cout,sum}=ain+bin+cin;endmodule描述方式中的行为语句95注:上表中,凡QuartusII不支持的语句是不可综合的,通常用在测试文件中;未注明“QuartusII不支持”的语句均是可综合的。repeat语句和task语句MAX+PLUSII不支持,但QuartusII支持;forever语句、while语句MAX+PLUSII不支持,QuartusII支持,但通常用在测试模块中;表中只有4种语句(fork_join,initial,‘include,‘timescale)是QuartusII不支持的,它们通常用在测试模块中(ModelSim软件支持)。一、

过程语句时序控制与过程语句关联。有2种时序控制形式:时延控制事件控制时延控制表示在语句执行前的“等待时延”。时延控制中的时延可以是任意表达式,即不必限定为某一常量。例如:alwaysbegin clk0=1'b0; clk0=#501'b1; #50;end971、initial语句initial

begin

语句1;语句2;

……

语句n;

endMAX+PLUSⅡ和QuartusⅡ均不支持!格式不可综合!常用在测试文件中用途在仿真的初始状态对各变量进行初始化;在测试文件中生成激励波形作为电路的仿真信号。一、

过程语句98`timescale1ns/1psmoduletest;

rega,b,c;

initialbegina=0;b=1;c=0;

#50a=1;b=0;

#50a=0;c=1;

#50b=1;

#50b=0;c=0;

#50$finish;

endendmodule[例5-12]用initial过程语句对测试变量赋值。一、过程语句2、always语句在一个模块(module)中,使用initial和always语句的次数是不受限制的。initial语句常用于仿真中的初始化,initial过程块中的语句仅执行一次;always块内的语句则是不断重复执行的。100在always块中被赋值的只能是register型变量(如reg,integer,real,time)。每个always块在仿真一开始便开始执行,当执行完块中最后一个语句,继续从always块的开头执行。always

<时序控制><语句>注1:如果always块中包含一个以上的语句,则这些语句必须放在begin_end或fork_join块中!格式规则always@(posedgeclkornegedgeclear)

begin

if(!clear)qout=0;//异步清零

elseqout=1;

end

101

[例]生成一个0延迟的无限循环跳变过程——形成仿真死锁!

alwaysareg=~areg;[例]在测试文件中,用于生成一个无限延续的信号波形——时钟信号注2:always语句必须与一定的时序控制结合在一起才有用!如果没有时序控制,则易形成仿真死锁!‘definehalf_period50modulehalf_clk_top;regreset,clk;//输入信号

wireclk_out;//输出信号

always#half_periodclk=~clk;……endmodule 102always@(<敏感信号表达式>)

begin//过程赋值语句

//if语句

//case语句

//while,repeat,for循环

//task,function调用

end一般为输入敏感信号表达式又称事件表达式或敏感表,当其值改变时,则执行一遍块内语句;在敏感信号表达式中应列出影响块内取值的所有信号!

敏感信号可以为单个信号,也可为多个信号,中间需用关键字or连接!敏感信号不要为x或z,否则会阻挡进程!always块语句模板一个变量不能在多个always块中被赋值!103always的时间控制可以为沿触发,也可为电平触发。关键字posedge表示上升沿;negedge表示下降沿。常用于描述时序逻辑常用于描述组合逻辑always@(posedgeclockorposedgereset)begin……endalways@(a,b,c)begin……end由两个沿触发的always块由多个电平触发的always块敏感信号表达式敏感信号表达式又称事件表达式或敏感信号列表,即当该表达式中变量的值改变时,就会引发块内语句的执行。因此敏感信号表达式中应列出影响块内取值的所有信号。若有两个或两个以上信号时,它们之间用“or”连接。例如:@(a) //当信号a的值发生改变@(a,b) //当信号a或信号b的值发生改变@(*)//表示包括所有输入信号变量@(posedgeclk,negedgereset) //当clk的上升沿到来或reset信号的下降沿到来105always块语句是用于综合过程的最有用的语句之一,但又常常是不可综合的。为得到最好的综合结果,always块程序应严格按以下模板来编写:模板1可综合性问题always@(Inputs)//所有输入信号必须列出,用or隔开

begin

……//组合逻辑关系

end

模板2always@(Inputs)//所有输入信号必须列出,用or隔开

if(Enable)

begin

……//锁存动作

end

106模板3always@(posedgeClock)//Clockonly

begin

……//同步动作

end

模板4always@(posedgeClockornegedgeReset)//ClockandResetonly

begin

if(!Reset)//测试异步复位电平是否有效

……//异步动作

else……//同步动作

end//可产生触发器和组合逻辑107(1)当always块有多个敏感信号时,一定要采用if-elseif语句,而不能采用并列的if语句!否则易造成一个寄存器有多个时钟驱动,将出现编译错误。注意always@posedgemin_clkornegedgereset)

beginif(reset)min<=0;

elseif(min=8’h59)//当reset无效且min=8’h59时

beginmin<=0;h_clk<=1;end

end

(2)通常采用异步清零!只有在时钟周期很

温馨提示

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

评论

0/150

提交评论