vhdl基本语法.docx
《vhdl基本语法.docx》由会员分享,可在线阅读,更多相关《vhdl基本语法.docx(36页珍藏版)》请在冰豆网上搜索。
![vhdl基本语法.docx](https://file1.bdocx.com/fileroot1/2023-2/22/d189896f-b683-420b-8465-638ad1d4a5d0/d189896f-b683-420b-8465-638ad1d4a5d01.gif)
vhdl基本语法
vhdl基本语法
VHDL基础语法篇――VHDLVHDL硬件描述语言1.1VHDL概述1.1.1VHDL的特点
VHDL语言作为一种标准的硬件描述语言,具有结构严谨、描述能力强的特点,由于
VHDL语言E1=14*161=224;(3)位(BIT)数据类型
位数据类型的位值用字符.0.和.1.表示,将值放在单引号中,表示二值逻辑的0和1。
这里
的0和1与整数型的0和1不同,可以进行算术运算和逻辑运算,而整数类型只能进行算术运算。
位数据类型的定义格式为:
TYPEBITis('0','1');例如:
RESULT:
OUTBIT;RESULT=.1.;
将RESULT引脚设置为高电平。
(4)位向量(BIT_VECTOR)数据类型
位向量是基于BIT数据类型的数组。
VHDL位向量的定义格式为:
TYPEBIT_VECTORisarray(*****range)ofBIT;
使用位向量必须注明位宽,即数组的个数和排列顺序,位向量的数据要用双引号括起来。
例如“1010”,X“A8”。
其中1010是四位二进制数,用X表示双引号里的数是十六进制数。
例如:
SIGNALA:
BIT_VECTOR(3DOWNTO0);A=“1110”;
表示A是四个BIT型元素组成的一维数组,数组元素的排列顺序是A3=1,A2=1,A1=1,A0=0。
(5)布尔(*****)数据类型
一个布尔量具有真(TRUE)和假(FALSE)两种状态。
布尔量没有数值的含义,不能
用于数值运算,它的数值只能通过关系运算产生。
例如,在IF语句中,AB是关系运算,如果A=3,B=2,则AB关系成立,结果是布尔量TRUE,否则结果为FALSE。
VHDL中,布尔数据类型的定义格式为:
TYPE*****IS(FALSE,TRUE);(6)字符(*****ER)数据类型
在*****D程序包中预定义了128个ASCII码字符类型,字符类型用单引号括起来,如.A.,.b.,.1.等,与VHDL标识符不区分大小写不同,字符类型中的字符大小写是不同的,如.B.和.b.不同。
(7)字符串(STRING)
在*****D程序包中,字符串的定义是:
TYPESTRINGisarray(*****Erange)of*****ER;
字符串数据类型是由字符型数据组成的数组,字符串必须用双引号括起来。
例如:
*****TSTR1:
STRING:
=“Hellowworld”;定义常数ST1是字符串,初值是“Hellowworld”。
小提示:
与C语言类似,字符类型用单引号括起来,而字符串必须用双引号括起来,别弄混了。
(8)时间(TIME)数据类型
表示时间的数据类型,一个完整的时间类型包括整数表示的数值部分和时间单位两个部分,数值和单位之间至少留一个空格,如1ms,20ns等。
*****D程序包中定义时间格式为:
TYPETIMEisrange-***-********-*****808to***-********-*****807UNITSfs;--飞秒
ps=1000fs;--皮秒ns=1000ps;--纳秒us=1000ns;--微秒ms=1000us;--毫秒sec=1000ms;--秒min=60sec;--分hr=60min;--小时ENDUNITS;小提示:
实数,时间类型仅用于VHDL仿真,一般综合器不支持。
2.IEEE预定义的标准逻辑位和标准逻辑位向量
(1)标准逻辑位(STD_LOGIC)数据类型
STD_LOGIC是位(BIT)数据类型的扩展,是STD_ULOGIC数据类型的子类型。
它是一
个逻辑型的数据类型,其取值取代BIT数据类型的取值0和1两种数值,扩展定义了九种值,在IEEE*****程序包中,STD_ULOGIC和STD_LOGIC数据类型定义格式为:
TYPEstd_ulogicIS(U',--Uninitialized
'X',--ForcingUnknown'0',--Forcing0'1',--Forcing1
'Z',--HighImpedance'W',--WeakUnknown'L',--Weak0'H',--Weak1'-'--Don'tcare);
*****Nresolved(s:
std_ulogic_vector)RETURNstd_ulogic;*****std_logicISresolvedstd_ulogic;小提示:
STD_LOGIC中的数据类型必须要大写,不能使用小写字母代替,在实际的IC集成时,一般只使用.0.,.1.,.Z.,._.四种数据类型,其余的.W.,.L.,.H.是不可综合的。
STD_LOGIC和STD_ULOGIC数据类型的区别在于STD_LOGIC数据类型是经过重新定义的,可以用来描述多路驱动的三态总线,而STD_ULOGIC数据类型只能用于描述单路驱动的三态总线。
(2)标准逻辑位向量(STD_LOGIC_VECTOR)数据类型
STD_LOGIC_VECTOR是基于STD_LOGIC数据类型的标准逻辑一维数组,和
BIT_VECTOR数组一样,使用标准逻辑位向量必须注明位宽和排列顺序,数据要用双引号括起来。
例如:
SIGNALSA1:
STD_LOGIC_VECTOR(3DOWNTO0);SA1=“0110”;
在IEEE_STD_1164程序包中,STD_LOGIC_VECTOR数据类型定义格式为:
TYPEstd_logic_vectorISARRAY(*****RANGE)OFstd_logic;3.其它预定义的数据类型
在STD_LOGIC_ARITH程序包中定义了无符号(*****D)和带符号(SIGNED)数据类型,这两种数据类型主要用来进行算术运算。
定义格式为:
TYPE*****Disarray(*****range)ofSTD_LOGIC;TYPESIGNEDisarray(*****range)ofSTD_LOGIC;
(1)无符号(*****D)数据类型
无符号数据类型是由STD_LOGIC数据类型构成的一维数组,它表示一个自然数。
在一个结构体中,当一个数据除了执行算术运算之外,还要执行逻辑运算,就必须定义成*****D,而不能是SIGNED或*****类型。
例如:
SIGNALDAT1:
*****D(3DOWNTO0);DAT1=“1001”;定义信号DAT1是四位二进制码表示的无符号数据,数值是9。
(2)带符号(SIGNED)数据类型
带符号(SIGNED)数据类型表示一个带符号的整数,其最高位用来表示符号位,用补
码表示数值的大小。
当一个数据的最高位是0时,这个数表示正整数,当一个数据的最高位是1时,这个数表示负整数。
例如:
*****EDB1,DB2:
SIGNED(3DOWNTO0);DB1=“0110”;DB2=“1001”;
定义变量DB1是6,变量DB2是-7。
4.用户自定义的数据类型
在VHDL中,用户可以根据设计需要,自己定义数据的类型,称为用户自定义的数据类型。
利用用户自己定义数据类型可以使设计程序便于阅读。
用户自定义的数据类型可以通过两种途径来实现,一种方法是通过对预定义的数据类型作一些范围限定而形成的一种新的数据类型。
这种定义数据类型的方法有如下几种格式:
TYPE数据类型名称IS数据类型名RANGE数据范围;例如:
TYPEDATAIS*****RANGER0TO9;定义DATA是*****数据类型的子集,数据范围是0~9。
*****数据类型名称IS数据类型名RANGE数据范围;例如:
*****DBISSTD_LOGIC_VECTOR(7DOWNTO0);
定义DB是STD_LOGIC_VECTOR数据类型的子集,位宽8位。
另一种方法是在数据类型定义中直接列出新的数据类型的所有取值,称为枚举数据类型。
定义该种数据类型的格式为:
TYPE数据类型名称IS(取值1,取值2,?
);例如:
TYPEBITIS(.0.,.1.);TYPESTATE_MIS(STAT0,STAT1,STAT2,STAT3);定义BIT数据类型,取值0和1。
定义STATE_M是数据类型,表示状态变量STAT0,STAT1,STAT2,STAT3。
在VHDL中,为了便于阅读程序,可以用符号名来代替具体的数值,前例中STATE_M是状态变量,用符号STAT0,STAT1,STAT2,STAT3表示四种不同的状态取值是00,01,10,11。
例如定义一个“WEEK”的数据类型用来表示一个星期的七天,定义格式为:
TYPEWEEKIS(SUN,MON,TUE,WED,THU,FRI,SAT);小提示:
使用枚举数据类型定义后,综合器会自动将字符类型从0开始进行二进制编码,编码的位数由枚举元素个数决定。
5.数组(ARRAY)的定义
数组是将相同类型的单个数据元素集合在一起所形成的一个新的数据类型。
它可以是一维数组(一个下标)和多维数组(多个下标),下标的数据类型必须是整数。
前面介绍的位向量(BIT_VECTOR)和标准逻辑位向量(STD_LOGIC_VECTOR)数据类型都属于一维数组类型。
数组定义的格式为:
TYPE数据类型名称ISARRAY数组下标的范围OF数组元素的数小提示:
VHDL多维数组定义,多维数组声明即将第一维的数组作为第二维数组的元素定义即可。
TYPE1维数据类型名称ISARRAY数组下标的范围OF数组元素的数据类型;
TYPE2维数据类型名称ISARRAY数组下标的范围OF上面所定义的1维数据类型;根据数组元素下标的范围是否指定,把数组分为非限定性数组和限定性数组两种类型。
非限定性数组不具体指定数组元素下标的范围,而是用*****RANGER表示,当用到该数组时,再定义具体的下标范围。
如前面介绍的位向量(BIT_VECTOR)和标准逻辑位向量(STD_LOGIC_VECTOR)数据类型等在程序包中预定义的数组属于非限定性数组。
例如,在IEEE程序包中定义STD_LOGIC_VECTOR数据类型的语句是TYPEstd_logic_vectorISARRAY(*****RANGE)OFstd_logic;没有具体指出数组元素的下标范围,在程序中用信号说明语句指定。
例如:
SIGNALDAT:
STD_LOGIC_VECTOR(3DOWNTO0);
限定性数组的下标的范围用整数指定,数组元素的下标可以是由低到高,如0TO3,也可以是由高到低,如7DOWNTO0,表示数组元素的个数和在数组中的排列方式。
例如:
TYPEDISARRAY(0TO3)OFSTD_LOGIC;TYPEAISARRAY(4DOWNTO1)OFBIT;
定义数组D是一维数组,由四个STD_LOGIC型元素组成,数组元素的排列顺序是D(0),D
(1),D
(2),D(3)。
A数组是由四个元素组成的BIT数据类型,数组元素的排列顺序是A(4),A(3),A
(2),A
(1)。
小提示:
对于数组数据类型,可以给一组数据多个值一起赋值:
如上例:
SIGNALARRAY1:
D;BEGIN
ARRAY1=(.1.,.0.,.0.,.1.);6.数据类型的转换
在VHDL语言中,数据类型的定义是相当严格的,不同类型的数据是不能进行运算和赋
值的。
为了实现不同类型的数据赋值,就要进行数据类型的变换。
变换函数在VHDL语言程序包中定义。
在程序包STD_LOGIC_1164、STD_LOGITH_ARITH和STD_LOGIC_*****D中提供的数据类型变换函数如表1-2-3所列。
例如把*****数据类型的信号转换为STD_LOGIC_VECTOR数据类型的方法是:
定义A,B为:
*****:
*****RANGER0TO15;
*****:
STD_LOGIC_VECTOR(3DOWNTO0);
需要调用STD_LOGIC_ARITH程序包中的函数CONV_STD_LOGIC_VECTOR
调用的格式是:
B=CONV_STD_LOGIC_VECTOR(A);
表1-2-3数据类型变换函数
程序包名称
STD_LOGIC_1164
函数名称TO_BIT
TO_*****ORTO_*****IC
TO_**********R
功能由STD_LOGIC转换为BIT
由STD_LOGIC_VECTOR转换为BIT_VECTOR
由BIT转换为STD_LOGIC由BIT_VECTOR转换为STD_LOGIC_VECTOR
由*****D,SIGNED转换为*****
由SIGNED,*****转换为*****D
由*****,*****D,SIGNED
转换为STD_LOGIC_VECTOR由STD_LOGIC_VECTOT转换为*****
STD_LOGIC_ARITH
CONV_*****CONV_*****D
CONV_STD_LOGIC_VECTOR
STD_LOGIC_*****DCONV_*****
1.2.3VHDL的运算符
与高级语言一样,VHDL语言的表达式也是由运算符和操作数组成的。
VHDL标准预
定义了四种运算符,即逻辑运算符、算术运算符、关系运算符、移位运算符和连接运算符,并且定义了与运算符相应的操作数的数据类型。
各种运算符之间是有优先级的,例如在所有运算符中,逻辑运算符NOT的优先级别最高。
表1-2-4列出了所有运算符的优先级顺序。
表1-2-4VHDL运算符列表运
算符类型逻辑运算符ORNANDNORXORNXOR
关系运算符/===
移位运算符SLASRLSRAROLROR
符号运算符-
连接运算符
运算符
功能
优先级
AND
=
SLL
++
逻辑与逻辑或逻辑与非逻辑或非逻辑异或逻辑异或非
等于
不等于小于大于
小于等于大于等于
逻辑左移
算术左移逻辑右移算术右移
逻辑循环左移逻辑循环右移
正
负
位合并
加
减乘除求模求余乘方
求绝对值逻辑非
最低
算术运算符-*/
MODREM**ABS
逻辑非运算符
NOT最高
1.逻辑运算符
在VHDL语言中定义了七种基本的逻辑运算符,它们分别是:
AND(与)、OR(或)、NOT(非)、NAND(与非)、NOR(或非)、XOR(异或)和NXOR(异或非)等。
由逻辑运算符和操作数组成了逻辑表达式。
在VHDL语言中,逻辑表达式中的操作数的数据类型可以是BIT和STD_LOGIC数据类型,也可以是一维数组类型BIT_VECTOR和STD_LOGIC_VECTOR,要求运算符两边的操作数的数据类型相同、位宽相同。
逻辑运算是按位进行的,运算的结果的数据类型与操作数的数据类型相同。
例如用VHDL描述逻辑表达式是Y=AB,Z=A+B+C的程序如下:
ENTITYlogaIS
PORT(
A,B,C:
INSTD_LOGIC;Y,Z:
OUTSTD_LOGIC);
ENDloga;
*****CTUREstraOFlogaISBEGIN
Y=AANDB;Z=AORBORC;
ENDstra;
例如用VHDL描述两个位向量的逻辑运算的程序如下:
ENTITYlogbISPORT(
A,B:
INBIT_VECTOR(0TO3);Y:
OUTBIT_VECTOR(0TO3));ENDlogb;
*****CTUREstrbOFlogbISBEGIN
Y=AANDB;
ENDstrb;
如果A=1011,B=1101,则程序仿真的结果是Y=1001。
在一个逻辑表达式中有两个以上的运算符时,需要用括号对这些运算进行分组。
例如语句
X1=(AANDB)OR(CANDB);X2=(AORB)ANDC;是正确的。
如果一个逻辑表达式中只有AND、OR和XOR三种运算符中的一种运算符,那么改变运算顺序不会影响电路的逻辑关系,表达式中的括号是可以省略的。
例如下列语句是正确的。
Y1=AANDBANDC;Y2=AORBORD;2.算术运算符
VHDL语言定义了五种常用的算术运算符,分别是+加或正,A+B,+A-减或负,A-B,-B
*乘,A*B
/除,A/B
**指数,N**2以及MOD(求模)、REM(取余)、ABS(求绝对值)等算术运算符。
在算术运算表达式中,两个操作数必须具有相同的数据类型,加法和减法的操作数的数据类型可以是整数、实数或物理量,乘除法的操作数可以是整数或实数。
为了节约硬件资源,除法和乘法的操作数应该选用*****、STD_LOGIC_VECTOR或BIT_VECTOR等数据类型。
例如X=A+B;
Y=C*D;Z=A-C**2小提示:
对于/,MOD,REM运算,要求操作符的右操作数必须为2的正整数次幂,可以用实际电路移位实现,才可以综合。
3.关系运算符
关系运算符是将两个相同类型的操作数进行数值比较或关系比较,关系运算的结果的
数据类型是TRUE或FALSE,即*****类型。
VHDL语言中定义了六种关系运算符,分别是:
=等于/=不等于大于小于
=大于或等于=小于或等于
在VHDL中,关系运算符的数据类型根据不同的运算符有不同的要求。
其中“=”(等于)和“/=”(不等于)操作数的数据类型可以是所有类型的数据,其他关系运算符可以使用整数类型、实数类型、枚举类型和数组。
整数和实数的大小排序方法与数学中的比较大小方法相同。
枚举型数据的大小排序方法与它们的定义顺序一致,例如BIT型数据10,*****型数据*****SE。
在利用关系运算符对位向量数据进行比较时,比较过程是从左到右的顺序按位进行比较的,操作数的位宽可以不同,但有时会产生错误的结果。
如果A、B是STD_LOGIC_VECTOR数据类型,A=“1110”,B=“*****”,关系表达式AB的比较结果是TRUE,也就是说AB。
对于以上出现的错误可以利用STD_LOGIC_ARITH
程序包中定义的数据类型*****D来解决,把要比较的操作数定义成*****D数据类型。
4.移位运算符
VHDL93标准中增加了六个移位运算符,分别是SLL逻辑左移,SRL逻辑右移,SLA算术左移,SRA算术右移,ROL逻辑循环左移,ROR逻辑循环右移。
移位运算符的格式是:
操作数名称移位运算符移位位数;
操作数的数据类型可以是BIT_VECTOR、STD_LOGIC_VECTOR等一维数组,也可以是*****型,移位位数必须是*****型常数。
六条移位运算符所执行的操作如图1-2-1所示。
其中SLL是将位向量左移,右边移空位补零。
SLA是将位向量左移,右边第一位的数值保持原值不变。
SRL是将位向量右移,左边移空位补零。
SRA是将位向量右移,左边第一位的数值保持原值不变。
ROR和ROL是自循环移位方式。
例如
A=“0101”;B=ASLL1;
仿真的结果是B=1010。
5.连接运算符()
用连接运算符可以将多个数据对象合并成一个新的一维数组,也可以将两个一维数组中的元素分解合并成新的一维数组。
连接两个操作符产生新的一维数组的位宽等于两个操作数的位宽之和,新的数组元素的顺序是由操作数的位置决定的,连接符“”左边的操作数的元素在左,连接符“”右边的操作数的元素在右。
操作数可以是BIT或STD_LOGIC如果
1011,0010A:
BIT_VECTOR(0TO7)0001,0110B:
BIT_VECTOR(0TO7)C=B(0TO3)A(5TO7).1.;则C=1011,1101
1.2.4VHDL的数据对象
在算法语言中,定义了多种数据对象,如常数、变量和数组等,用来存放不同类型的数据,如整数、实数、复数、逻辑常数和逻辑变量等。
在VHDL程序中,常用的数据对象分为三种类型,即常数(*****T)、变量(*****E)和信号(SIGNAL),在使用过程中,这三种数据对象除了具有一定的数据功能外,还赋予了不同的物理意义,在应用时要特别注意。
1.常数(*****T)
常数被赋值后就保持某一固定的值不变。
在VHDL中,常数通常用来表示计数器的模的大小、数组数据的位宽和循环计数次数等,也可以表示电源电压值的大小。
常数的使用范围与其在设计程序中的位置有关,如果常数在结构体中赋值,则这个常数可供整个设计单元使用,属于全局量,如果常数在*****语句或子程序中赋值,只能供进程或子程序使用,属于局部量。
程序设计中使用常数有利于提高程序的可读性和方便对程序进行修改。
通常常数的赋值在程序开始前进行,其数据类型在常数说明语句中指明,赋值符号为“:
=”。
常数定义语句的格式为:
*****T常数名称:
数据类型:
=表达式例如:
*****TVcc:
REAL:
=5.0;
*****TDALY:
TIME:
=20ns;
*****TKN:
*****:
=60;
在上面的例子中,Vcc的数据类型是实数,被赋值为5.0,DALY被赋值为时间常数20ns,KN被赋值为60的整数。
注意:
常数所赋的值的数据类型必须与定义的数据类型一致,在程序中常数被赋值后不能再改变。
2.变量(*****E)
在VHDL程序中,变量只能在进程和子程序中定义和使用,不能在进程外部定义使用,变量属于局部量,在进程内部主要用来暂存数据。
对变量操作有变量定义语句和变量赋值语句,变量在赋值前必须通过定义,可以在变量定义语句中赋初值,变量初值不是必需的,变量初值的赋值的符号是“:
=”。
小提示:
变量与信号赋初值语句仅可用于仿真,在综合时被忽略,不起作用。
变量定义语句的格式为:
*****变量名称:
数据类型:
=初值;例如:
*****S1:
*****:
=0;*****S2,S3:
*****
*****CON1:
*****RANGER0TO20;
*****D1,D2:
STD_LOGIC