1、第4讲 VHDL的语法要素4.1 VHDL的的词法元素词法元素4.2 VHDL的数据对象的数据对象4.3 VHDL的数据类型的数据类型4.4 VHDL的操作符的操作符 4.1 VHDL的的词词法元素法元素词法元素指不可以拆分为其他更小元素的字符串,它是VHDL中的最小单位。VHDL设计文件可认为是由词法元素的序列和分隔符组成的。VHDL中的词法元素的类型有分界符、标识符、注释和字符文字。词法元素必须完全处于同一行中。下面分别进行介绍。4.1.1 分界符分界符相邻的词法元素通过任意数量的分界符分开,在某些情况下,当两个词法元素连写会被当作一个词法元素时,两个词法元素之间必须加分隔符。常用空格来区
2、分同一个语句中的两个词法元素,例如“ENTITY adder IS”。在一个完整的语句末尾,必须用“;”表示语句的结束。4.1.2 标识符标识符 标识符规则是VHDL中符号书写的一般规则,用以表示VHDL语句中的变量、块、进程等对象和关键词。VHDL有两个标识符标准,分别是VHDL87标准和VHDL93标准。VHDL93标准规定的标识符也称为扩展标识符,VHDL87标准规定的标识符称为短标识符。1短标识符短标识符VHDL中的短标识符是遵守以下规则的字符序列:(1)短标识符由有效字符构成。有效字符为大、小写英文字母(AZ,az)、数字(09)和下划线(_)。(2)短标识符必须以英文字母打头。(3
3、)短标识符中的下划线前后必须都有英文字母或数字。(4)短标识符不区分大、小写。规定所有关键词不能由用户声明为对象名。VHDL87标准规定的关键词如下:举例说明:如下所示是合法的标识符:COUNT cout C_OUT BB2_5CVHSIC WT FFT DecoderA_B_C xyZ h333 STORE_NEXTITEM如表4.1所示是不合法的标识符及其错误原因。表表4.1 非法的标识符及其错误原因非法的标识符及其错误原因非法标识符错 误 原 因My-name含有非法符号“-”H¥B含有非法符号“¥”LOOP为VHDL关键词_ABC第一个字符不是英文字母Decoder_下划线后没有字母或
4、数字A_C含有连续两个下划线,每个下划线前后方都不完全是字母或数字alDha 2含有非法的空格AB AC含有非法的空格2扩展标识符扩展标识符扩展标识符具有以下特性:(1)扩展标识符两端由反斜杠确定。例如,“valid”、“_ABC”等都是合法的扩展标识符。(2)扩展标识符中间允许包含图形符号和空格符。例如,“&My Name”、“$l0ms”、“*L 50ms”等都是合法的扩展标识符。(3)反斜杠之间的字符可以用保留字。例如,“1abel”、“PORT”和“enitiy”等都是合法的扩展标识符。(4)每两个反斜杠之间可以用数字打头。例如,“12mspulse”、“20_puls”和“50”都是
5、合法的扩展标识符。(5)扩展标识符允许多个下划线相连。例如,“A_B”、“my_projects”等都是合法的扩展标识符。(6)扩展标识符区分大小写。例如,“CLK”与“clk”分别表示两个不同的标识符。(7)扩展标识符与短标识符不同。例如,“CLK”与“CLK”分别表示两个不同的标识符。(8)实体名一般不使用扩展标识符。4.1.3 注释注释注释是用分界符“-”开头,必须放在一行语句末的词法元素。它可以跟在一行之中的合法词法元素之后,也可以是该行唯一的词法元素。注释的内容不影响编译器和仿真程序,其目的是为了增加程序的可读性。注释中可包括所有特殊字符。表4.2所示的是注释的一些例子。表表4.2
6、注释语句示例注释语句示例注释格式解 释-注释语句该行只有一句注释C=A;-注释语句注释词法元素在VHDL赋值语句之后 -较长的注释语句第一行 -较长的注释语句第二行 -较长的注释语句最后一行对于较长的注释,可以采用分行注释的方法,为便于阅读,每行的分界符要对齐 4.1.4 字符文字字符文字字符文字用来指定用于标量对象初始化的常量值,包括单个字符文字、字符串文字、位串文字和数字。1单个字符文字单个字符文字单个字符文字是仅包括一个字符的词法元素,其格式为在两个撇号之间插入一个字符。该字符可以是任何字符,包括空格和特殊符号。以下是单个字符文字的例子:A,B、!、1、0、字符可用来定义一个新的数据类型
7、。2字符串文字字符串文字字符串文字是在两个引号之间插入一串可显示字符而得到的词法元素。一个字符串文字的长度指的是串中字符的个数(将双引号记为一个字符)。字符串主要用来作注释或信息提示。举例说明:VHDL study 长度为10的字符串,包括一个空格 长度为0的字符串,不包括任何内容 A 长度为1的字符串,与A不同 长度为1,包括一个引号$,#,|长度为5的字符串,包含特殊字符$、#和|字符串文字词法元素必须写在一行中,长度超过一行的串在前一行的末尾必须使用连接符“&”将两行连接起来。以下是一个连接示例:“This is a long string literal that will not f
8、it on one”&line which requires using the concatenation operator.3位串文字位串文字位串文字用来表示数码矢量,它是由进制标志符和数字字符串组成的词法元素。进制标志符及其对应的数字串如表4.3所示。表4.3 位 串 文 字进制标志符表示的意义对应的数字串示 例D二进制0,1D0100101O八进制07O45X十六进制09,AFX1F 位串文字用于指定二进制寄存器的内容的初始状态。位串文字也可被直接指定为位串,而不使用任何进位标志符。位串文字中可添加下划线字符,以提高文字的可读性,下划线字符不会影响位串的值。位串文字的长度即位串中位的个
9、数,与进位标志符无关。下划线不影响位串文字的长度。然而,在未指定字符文字的进制标志符时,不允许使用下划线。4数字数字数字表示的是一个数,是标量,而位串文字所表示的是一串0、1位信号,是矢量。数字可分为实型和整型数字。实型数字含有一个小数点;整型数字不包含小数点。根据进制的不同,数字还可分为十进制数字和基数字两类。十进制数字必须以数字作为第一个字符。对于用科学计数法描述的十进制数,可以使用指数符号“E”或者“e”,只有实型十进制数才允许指数为负。基数字用于表示其他进制的数字。基数字包括一个基标志、数字位和可选的指数位,在数字位前后各有一个“#”分界符,为增加可读性,可以在数字位中增加下划线,下划
10、线不会对数值有任何影响。在基数字中不允许出现其他的非法字符。表4.7所示即为基数字的例子。表表4.7 基数字及其意义基数字及其意义基数字所表示的数值2#1_0110#十进制的4610#46#十进制的468#56#十进制的4616#2E#十进制的4616#8F#E1十进制的2288,即十进制的143164#3#e2十进制的48,即十进制的3422#1.1111_01#e8二进制的111110100,即十进制的500举例说明举例说明:十进制整数表示的数量121225_45025 4505E25005e2500000151551e051表表4.4 十进制整数及其意义十进制整数及其意义表表4.5 十进
11、制实数及其意义十进制实数及其意义十进制实数表示的数量1.21.25.0e05.05.25E25255.0e-20.050.000_12540.000 125 401.51.55.1e02510表4.6所示为非法十进制数字及其错误原因。表表4.6 非法十进制数字及其错误原因非法十进制数字及其错误原因非法十进制数错误原因1e-2实数中未确定小数点.25未用数字开头5.25 E2字符E前面有空格5.0e-2字符e后面有空格45,458出现非法字符“,”4.2 VHDL的数据对象的数据对象1常常量量 固定值,不能在程序中被改变 增强程序的可读性、可维护性和可移植性 在综合后,连接到电源和地 可在Lib
12、rary、Entity、Architecture、Process中进行定义,其有效范围也相应限定常量说明的一般格式如下:CONSTANT 常量名:数据类型:=表达式;如:CONSTANT data:INTEGER:=50;该语句定义了一个名为“data”的整数常数,并且赋予初值50。2变量变量只能在Process、Function和Procedure中定义,并只在其内部有效。它是一个局部量,在仿真过程中执行到变量赋值语句后,变量被即时赋值。临时数据,没有物理意义。变量说明语句的一般格式如下:VARIABLE变量名:数据类型:=初值表达式;如:“VARIABLE t,m:INTEGER;”语句表
13、示定义了两个名为t和m的整型变量。“VARIABLE a:INTEGER:=50;”语句表示定义了一个名为a的整型变量,并且赋初值50。变量赋值使用数字符号“:=”,如:variable result:std_logic:=0;result:=result+1;3信号信号信号可认为是电路中的连线,它除了没有数据流动方向说明以外,其他性质几乎和前面所述的“端口”概念一致。信号的使用范围是结构体、包集合和实体说明。信号定义语句的一般格式如下:SIGNAL信号名:数据类型约束条件:=表达式;在VHDL中对信号赋值采用“=”作为赋值符号,如 signal count:bit_vector(3 down
14、to 0):=“0011”;Count=count+1;信号赋值的时刻是按仿真时间,即信号值的改变需要按照仿真时间的计划表行事,某一个正在进行的进程中对信号赋值的操作需要等到该进程结束后才会生效。信号与变量的区别(1)architecture rtl of start is signal count:integer range 0 to 7;begin process(clk)begin if(clkevent and clk=1)then count=count+1;if(count=0)then carryout=1;else carryout=0;end if;end if;end pr
15、ocess;end rtl;architecture rtl of start is begin process(clk)variable count:integer range 0 to 7;begin if(clkevent and clk=1)then count:=count+1;if(count=0)then carryout=1;else carryout=0;end if;end if;end process;end rtl;信号与变量的区别(2)architecture rtl of sig is signal a,b:std_logic;begin process(a,b)b
16、egin a=b;b=a;end process;End architecture rt1;architecture rt1 of var is begin processvariable a,b:std_logic;begin a:=b;b:=a;end process;end architecture rtl;4.3 VHDL的数据类型的数据类型VHDL要求设计实体中的每一个常数、信号、变量、函数以及设定的各种参量都必须具有确定的数据类型。不同类型的数据间无法直接进行操作,数据类型相同而位长不同时,也不能直接代入。1布尔布尔(BOOLEAN)类型类型布尔类型在程序包STANDARD中定义的
17、源代码如下:TYPE BOOLEAN IS (FALSE,TRUE);布尔类型实际上是一个二值枚举数据类型。根据其定义,该数据类型的取值范围为TRUE(真)和FALSE(伪)两种。综合器用一个二进制位表示BOOLEAN型变量或信号。布尔量不属于数值,因此不能应用于计算操作,它只能通过关系运算符获得。4.3.1 VHDL标准程序包标准程序包 STANDARD中定义的数据类型中定义的数据类型VHDL标准程序包STANDARD中定义了10种标准数据类型。例如,当a=b时,在IF语句中的关系运算表达式(a=b)的结果是布尔量TRUE。综合器将TRUE转变为信号量“1”,将FALSE转变为信号量“0”。
18、布尔量常用来表示信号的状态或者总线上的情况。如果某个信号或者变量被定义为布尔量,那么用EDA工具对设计进行仿真时,系统自动对其赋值进行核查。一般布尔类型的数据对象的初始值为FALSE。2位位(BIT)类型类型位类型属于二值枚举数据类型,程序包STANDARD中定义的源代码如下:TYPE BIT IS (0,1);根据定义,其取值也只能是“0”或者“1”,位通常用来表示一个信号值。位值的表示方法是,用字符“0”或者“1”表示。位“1”和“0”与整数中的1和0不同,“1”和“0”仅表示一个位的两种取值,没有数值意义。位类型只能进行逻辑运算,运算结果仍然是位。3位矢量位矢量(BIT_VECTOR)类
19、型类型位矢量只是基于位数据类型的数组,在程序包STANDARD中对位矢量定义的源代码如下:TYPE BIT_VECTOR IS ARRAY(Natural Range)OF BIT;依照位矢量的定义,在声明位矢量时必须注明位宽,即数组中的元素个数和排列。例如:SIGNAL data:BIT_VECTOR(7 DOWNTO 0);该语句表示声明一个名为data的位矢量信号,共有8位,各位的排列分别是data7,data6,data0。元素的排列必须为自然数。位矢量数字的格式为用双引号括起来的一组位数据。例如,“01000010”表示一个8位的位矢量;x“FF”表示一个十六进制的位矢量,VHDL编
20、译器将其等价为“11111111”。4整数整数(INTEGER)类型类型整数类型的数包括正整数、负整数和零。可以使用预定义的运算操作符,如加“+”、减“-”、乘“*”、除“”等进行算术运算。在VHDL中,整数的取值范围是2 147 483 647+2 147 483 647,即可用32位有符号的二进制数表示。VHDL综合器无法综合未限定范围的整数类型的信号或变量。如下是一个定义整数类型变量的语句:VARIABLE a:INTEGER RANGE 127 TO 127;该语句中定义了一个名为a的整数类型变量,并且限制其范围在(127,127)区间内。5自然数自然数(NATURAL)和正整数和正整
21、数(POSITIVE)类型类型自然数和正整数都是整数的子集。自然数包括零和正整数;而正整数是大于零的整数,是自然数的子集。4.实数实数(REAL)类型类型VHDL的实数类型也称浮点类型,类似于数学上的实数。其取值范围为1.0E38+1.0E38。在书写时需要加上小数点,否则会与整数混淆。通常情况下,由于直接通过硬件实现浮点类型的表达是相当复杂的,在电路规模上难以承受,应用极少,因此VHDL综合器不支持实数,实数类型仅能在VHDL仿真器中使用。7字符字符(CHARACTER)类型类型字符类型通常用单引号引起来,如 A。字符类型已在STANDARD程序包中作了定义,与标识符不同,字符类型是区分大小
22、写的,如 B不同于 b。当要明确指出1的字符数据时,可写为CHARACTER(1)。8字符串字符串(STRING)类型类型字符串(或称为字符串数组)类型是字符类型的一个非约束型数组,它必须用双引号标明。VHDL综合器支持字符串类型。9时间时间(TIME)类型类型时间类型数据是VHDL中定义的一个物理量数据。时间类型数据一般用于仿真,而不用于逻辑综合。完整的时间类型数据包含整数和物理量单位两部分,而且整数和物理量单位之间至少应留一个空格的位置,如55 ms,2 min。10错误等级错误等级(SEVERITY_LEVEL)类型类型错误等级类型数据用来表示系统的状态。它分为4种:NOTE(注意)、W
23、ARNING(警告)、ERROR(出错)和FAILURE(失败)。在仿真过程中可以用这4种状态来提示系统当前的工作情况。4.3.2 用户定义的数据类型用户定义的数据类型VHDL允许用户自己定义数据类型。可由用户自己定义的数据类型有枚举(ENUMERATED)类型、整数(INTEGER)类型和实数(REAL)类型、数组(ARRAY)类型、存取(ACCESS)类型、文件(FILE)类型、记录(RECORD)类型和时间(TIME)类型(物理类型)。下面对常用的几种用户定义的数据类型作简要说明。1枚举枚举(ENUMERATED)类型类型枚举类型是把类型中的各个可能的取值都列举出来,这种定义数据的方式方
24、便、直观。使用枚举类型的数据可提高程序的可阅读性。在使用状态机时常采用枚举类型来定义状态参数。枚举类型的一般书写格式如下:TYPE 数据类型名 IS(元素,元素,);例如:TYPE Door IS (open,close);VARIABLE door1:Door:=open;2整数整数(INTEGER)类型和实数类型和实数(REAL)类型类型在标准程序包中已经定义了整数类型和实数类型,这里所说的是用户根据特殊用途需要再定义的整数和实数的数据类型。用户自定义整数或实数类型的一般格式如下:TYPE数据类型名 IS 数据类型 定义的约束范围;例如:TYPE int IS INTEGER RANGE
25、0 TO 255;VARIABLE num:int;3数组数组(ARRAY)类型类型数组类型是将相同类型的数据集合在一起形成的一个新的数据类型,是一种复合型的数据类型。数组可以是一维的,其中的每个元素只需要由一个下标确定其在数组中的位置,例如a1、a2、a3、a10就是一个一维的数组。数组也可以是二维或多维的,例如,a11、a12、a13a21、a22、a23a31、a32、a33就是一个二维数组,每个元素由两个下标确定其在数组中的位置,VHDL仿真器支持多维数组,但是综合器只支持一维数组。数组的元素可以是任何一种数据类型,用以定义数组元素的下标范围子句决定了数组中元素的个数,以及元素的排序方
26、向,即下标数是由低到高,或是由高到低。如子句“0 TO 7”是由低到高排序的8个元素;“15 DOWNTO 0”是由高到低排序的16个元素。VHDL允许用户自定义两种不同类型的数组,即限定性数组和非限定性数组。它们的区别是,限定性数组下标的取值范围在数组定义时就被确定了,而非限定性数组下标的取值范围需留待随后确定。限定性数组定义语句格式如下:TYPE 数组名 IS ARRAY (数组范围)OF 数据类型;其中:数组名是新定义的限定性数组类型的名称,可以是任何标识符;数据类型即指数组各元素的数据类型;数组范围明确指出数组元素的定义数量和排序方式,以整数来表示其数组的下标。限定性数组定义示例如下:
27、TYPE busA IS ARRAY (7 DOWNTO 0)OF BIT;限定性数组还可以采用以下格式定义:TYPE data IS (low,high);TYPE data_bus IS ARRAY (0 TO 7,data)OF BIT;非限制性数组类型就是不说明所定义的数组下标的取值范围,而是定义某一数据对象为此数组类型时,再确定该数组下标的取值范围。这样就可以通过不同的定义取值,使相同的数据对象具有不同下标取值的数组类型。非限制性数组的定义语句格式如下:TYPE 数组名 IS ARRAY (数组下标名RANGE )OF 数据类型;其中:数组名是定义的非限制性数组类型的取名;数组下标名
28、是以整数类型设定的一个数组下标名称,符号“”是下标范围待定符号,用到该数组类型时,再填入具体的数值范围;数据类型是数组中每一元素的数据类型。4存取存取(ACCESS)类型类型存取类型用来给新对象分配或释放存储空间。在VHDL标准IEEE内的STD_1076的程序包TEXTIO中,有一个预定义的存取类型Line:TYPE Line IS ACCESS stlin9;这表示类型为Line的变量是指向字符串值的指针。只有变量才可以定义为存取类型,如:VARIABLE line_buffer line;5文件文件(FILE)类型类型文件类型用于在主系统环境中定义代表文件的对象。文件对象的值是主系统文件
29、中值的序列。在IEEE STD_1076的程序包TEXTIO中,有一个预定义的文件类型Text,用户也可以定义自己的文件类型。如:TYPE Text IS FILE OF String;-TEXTIO程序包中预定义的文件类型TYPE Input_type IS FILE OF Character;-用户自定义的文件类型在程序包TEXTIO中,有2个预定义的标准文本文件:FILE INPUT:Text OPEN read_mode IS“STD_INPUT”;FILE OUTPUT:Text OPEN write_mode IS STD_OUTPUT;4.记录记录(RECORD)类型类型记录类型
30、是将不同类型的数据和数据名组织在一起而形成的数据类型。记录类型与数组类型的区别在于,数组是由多个同一类型的数据集合起来,记录可由不同类型数据组合,定义记录类型的数据时需要一一定义。用记录描述总线结构和通信协议是比较方便的,记录数据类型适用于系统仿真。在生成逻辑电路时,要将记录数据类型拆分开来。记录类型的一般书写格式如下:TYPE 数据类型名 IS RECORD元素名:数据类型名:元素名:数据类型名;END RECORD;在从记录数据类型中提取元素数据类型时应使用“.”。例4.8所示就是一个声明记录数据类型并引用数据类型的例子。例4.8TYPE CUSTOM_BUS IS RECORDADDR:
31、BIT_VECTOR(7 DOWNTO 0);DATA:BIT_VECTOR(15 DOWNTO 0);END RECORD;-定义一个RECORD数据类型SIGNAL address:BIT_VECTOR(7 DOWNTO 0);SIGNAL data:BIT_VECTOR(15 DOWNTO 0);SIGNAL bus1:CUSTOM_BUS:=(“00000000”,0000000000000000);address=bus1.ADDR;data=bus1.DATA;7时间时间(TIME)类型类型(物理类型物理类型)时间类型是表示时间的物理数据类型,在仿真时是必不可少的。其一般书写格式如
32、下:TYPE 数据类型名 IS 范围;UNITS 基本单位;单位END UNITS;例4.9所示就是一个定义时间类型的例子。例4.9TYPE time IS RANGE 0 TO 65535;UNITS s;min=60s;hour=60min;END UNITS;例4.9中定义了一个名为“time”的时间类型,其基本单位是“s”。4.3.3 IEEE预定义标准逻辑位与矢量预定义标准逻辑位与矢量IEEE标准库预定义了两个非常重要的数据类型,即标准逻辑位(STD_LOGIC)和标准逻辑矢量(STD_LOGIC_VETOR)数据类型。1标准逻辑位标准逻辑位(STD_LOGIC)数据类型数据类型IE
33、EE在1993标准中对“BIT”类型进行了扩展,定义了“STD_LOGIC”数据类型,共有如下9种不同的值:U:初始值;X:不定;0:0;1:1;Z:高阻;W:弱信号不定;T:弱信号0;H:弱信号l;-:不可能情况。如下是一个使用“STD_LOGIC”数据类型的语句:SIGNAL sig:STD_LOGIC:=Z;2标准逻辑矢量标准逻辑矢量(STD_LOGIC_VECTOR)数据类型数据类型“STD_LOGIC_VECTOR”是“STD_LOGIC_1164”程序包中定义的标准逻辑矢量,其定义如下:TYPE STD_LOGIC_VECTOR IS ARRAY(NATURAL RANGE)OF
34、STD_LOGIC;“STD_LOGIC_VECTOR”是由“STD_LOGIC”类型所组成的数组。使用“STD_LOGIC”和“STD_LOGIC_VECTOR”时,在程序中必须写出如下所示的库说明语句和使用包集合的声明语句:LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;4.3.4 VHDL的类型转换的类型转换为了实现正确的运算和赋值操作,必须要对信号或者变量进行类型转换。转换函数通常由VHDL的包集合提供。例如,在“STD_LOGIC_1164”“STD_LOGIC_ARYTH”和“STD_LOGIC_UNSIGNED”程序包中都提供了数据类型转换函数。
35、数据类型转换函数的输入参数为被转换的数据类型,返回值为转换后的数据类型。常用的数据类型转换函数如下。1“TO_STD_LOGIC_VECTOR()”函数函数“TO_STD_LOGIC_VECTOR()”函数是定义在程序包“IEEE.STD_LOGIC_1164”中的转换函数,其功能是将位矢量“BIT_VECTOR”数据类型转换为逻辑矢量“STD_LOGIC_VECTOR”数据类型。例4.10所示为调用“TO_STD_LOGIC_VECTOR()”函数的语句SIGNAL a:BIT_VECTOR(7 DOWNTO 0);SIGNAL b:STD_LOGIC_VECTOR(7 DOWNTO 0);
36、b=TO_ STD_LOGIC_VECTOR(a);上面的语句中通过调用“TO_STD_LOGIC_VECTOR(a);”语句将“a”转化为“STD_LOGIC_VECTOR”数据类型,然后赋值给“b”。2“CONV_INTEGER()”函数函数“CONV_INTEGER()”是定义在“IEEE.STD_LOGIC_UNSIGNED”程序包中的数据类型转换函数,其功能是将逻辑矢量“STD_LOGIC_VECTOR”数据类型转换为整数“INTEGER”数据类型。例4.11所示为调用“CONV_INTEGER()”函数的语句。SIGNAL a:STD_LOGIC_VECTOR(7 DOWNTO 0
37、);SIGNAL b:INTEGER RANGE 0 to 255;b=CONV_INTEGER(a);上面的语句中通过调用“CONV_INTEGER(a);”语句将“a”转化为“INTEGER”数据类型,然后赋值给“b”。3“CONV_STD_LOGIC_VECTOR()”函数函数“CONV_STD_LOGIC_VECTOR()”函数是定义在“IEEE.STD_LOGIC_UNSIGNED”程序包中的数据类型转换函数,其功能是将整数“INTEGER”数据类型转换为逻辑矢量“STD_LOGIC_VECTOR”数据类型。例4.12SIGNAL a:INTEGER RANGE 0 TO 255;S
38、IGNAL b:STD_LOGIC_VECTOR(7 DOWNTO 0);b=CONV_STD_LOGIC_VECTOR(a,8);上面的语句通过调用“CONV_STD_LOGIC_VECTOR(a,8);”函数将“a”转化为8位的“STD_LOGIC_VECTOR”数据类型,然后赋值给“b”。4.4 VHDL的操作符的操作符在VHDL中共有如下4类操作符,即逻辑(LOGICAL)操作符、算术(ARITHMETIC)操作符、关系(RELATIONAL)操作符和并置(CONCATENATION)操作符。操作符操作的对象是操作数,且操作数的类型应该和操作符所要求的类型相一致。操作符的左边和右边,以
39、及代入的信号的数据类型必须是相同的。另外,操作符是有优先级的,例如,逻辑操作符“NOT”在所有操作符中优先级最高。4.4.1 逻辑逻辑(LOGICAL)操作符操作符在VHDL中,逻辑操作符有7种,如表4.9所示。表表4.9 逻逻辑辑操操作作符符操作符功 能操作数的数据类型NOT取反运算BIT、BOOLEAN或STD_LOGICAND与运算BIT、BOOLEAN或STD_LOGICOR或运算BIT、BOOLEAN或STD_LOGICNAND与非运算BIT、BOOLEAN或STD_LOGICNOR或非运算BIT、BOOLEAN或STD_LOGICXOR异或运算BIT、BOOLEAN或STD_LOG
40、ICXNOR异或非运算BIT、BOOLEAN或STD_LOGIC 当一条VHDL语句中存在两个以上的逻辑操作符时,左、右没有优先级差别。如果存在多于两个的逻辑操作符,则需要使用括号来确定先后顺序,先做括号里的运算,再做括号外的运算。例如:x=(a OR b)AND (NOT c OR d);如果一个逻辑表达式中只有“AND”、“OR”或者“XOR”三种逻辑操作符中的一种,那么改变运算顺序将不会导致逻辑值的改变,此时,括号是可以省略的。例如以下语句:a=b AND c AND d AND e;a=b OR c OR d OR e;a=b XOR c XOR d XOR e:a=(b AND c)
41、OR d;-必须要括号如果逻辑操作符左、右都是数组,则要求数组的长度必须一致。4.4.2 算术算术(ARITHMETIC)操作符操作符VHDL中定义了16种算术操作符,如表4.10所示。表表4.10 算算术术操操作作符符操作符功 能操作数的数据类型加运算INTEGER减运算INTEGER*乘运算INTEGER或者REAL/除运算INTEGER或者REALMOD求模运算INTEGERREM取余运算INTEGER操作符功 能操作数的数据类型*指数运算INTEGERABS取绝对值运算INTEGERSLL逻辑左移BIT或BOOLEAN型的一位数组SRL逻辑右移BIT或BOOLEAN型的一位数组SLA算
42、术左移BIT或BOOLEAN型的一位数组SRA算术右移BIT或BOOLEAN型的一位数组ROL逻辑循环左移BIT或BOOLEAN型的一位数组ROR逻辑循环右移BIT或BOOLEAN型的一位数组负数INTEGER+正数INTEGER说明:实际上,能够真正综合逻辑电路的算术操作符的只有“+”、“”和“*”。在数据位较长的情况下,使用算术操作符进行运算,特别是使用乘法操作符“*”时,应特别慎重。因为对于16位的乘法运算,综合时逻辑门电路会超过2000个门。对于算术操作符“/”、“MOD”和“REM”,当分母的操作数为2乘方的常数时,逻辑电路综合是可能的。4.4.3 关系关系(RELATIONAL)操
43、作符操作符VHDL中有6种关系操作符,如表4.11所示。操作符功 能操作数的数据类型=等于任何数据类型/=不等于任何数据类型小于枚举与INTEGER,及对应的一维数组大于枚举与INTEGER,及对应的一维数组=大于等于枚举与INTEGER,及对应的一维数组表表4.11 关关系系操操作作符符在进行关系运算时,左右两边的操作数的数据类型必须相同,但是位长度不要求相同。在利用关系操作符对位矢量数据进行比较时,比较过程是从最左边的位开始,自左至右按位进行比较的。在位长不同的情况下,只能按自左至右的比较结果作为关系运算的结果。例4.13所示的就是对4位和8位的位矢量进行比较的语句。例4.13SIGNAL
44、 a:BIT_VECTOR(3 DOWNTO 0);SIGNAL b:BIT_VECTOR(7 DOWNTO 0);SIGNAL c:BIT;a=1110 -“a”的值为14bb)THENc=1;ELSEc=0;END IF;4.4.4 并置并置(CONCATENATION)操作符操作符并置操作符“&”用于位的连接。例4.14所示的就是并置操作符“&”的使用示例。例4.14SIGNAL a:STD_LOGIC_VECTOR(3 DOWNTO 0);SIGNAL b:STD_LOGIC_VECTOR(3 DOWNTO 0);SIGNAL c:STD_LOGIC_VECTOR(8 DOWNTO 0
45、);a=0000;b=1111 c=b&a;“BIT”数据类型和“STD_LOGIC”位的并置还可以使用集合体的方法,即将并置符换成逗号就可以了。例4.15所示的就是使用集合体的示例。例4.15SIGNAL s:STD_LOGIC;SIGNAL t:STD_LOGIC;SIGNAL u:STD_LOGIC_VECTOR(3 DOWNTO 0);u=(s,t,s,t);但是,这种方法不适用于位矢量之间的连接。如下的描述方法是错误的:SIGNAL a:STD_LOGIC_VECTOR(3 DOWNTO 0);SIGNAL b:STD_LOGIC_VECTOR(3 DOWNTO 0);SIGNAL c:STD_LOGIC_VECTOR(8 DOWNTO 0);c=(a,b);4.4.5 操作符的优先级操作符的优先级VHDL中不同的操作符是有优先级区别的。表4.12所列为所有操作符的优先级顺序。表表4.12 操作符的优先级顺序操作符的优先级顺序