VHDL中描述各种数据对象间的关系时,都需要用到操作符。VHDL的基本操作符有三种:逻辑操作符(Logical Operator)、关系操作符(Relational Operator)和算术操作符(Arithmetic Operator)。它们是完成逻辑和算术运算的基本单元,是采用VHDL语言进行功能描述的基础。
表3-5列出了VHDL操作符的符号及其功能。注意基本操作符对操作数的类型是有限定的,不符合数据类型要求的操作数不能直接进行操作。
表3-5 VHDL操作符列表
续表
当操作数的数据类型不符时,可以通过两种办法来解决,一是调用类型转化函数对操作数进行数据类型转换;二是通过加具有该操作符的重载函数的程序包,调用重载函数实现操作。
所谓重载函数,是指在VHDL中,为满足不同数据类型间进行运算的需要,允许设计者对基本操作符进行重新定义,也就是可以定义多个同名函数,这些函数分别具有不同数据类型的参数,能够对不同数据类型进行操作处理。通过引入重载函数可以拓宽操作符对操作数的数据类型要求。
事实上,在VHDL设计库中已经包含了这样的程序包。例如,在QuartusⅡ安装目录下的\libraries\vhdl\ieee\NUMERIC_BIT.VHD程序包中,就包含了对上述各操作符的重载函数定义。其中对“+”操作符重载函数定义的原形如下:
这样,设计者只要在自己的设计文件中通过“USE IEEE.NUMERIC_BIT.ALL;”语句声明使用此程序包,即可在设计描述中直接使用操作符“+”对不同数据类型的操作数进行加法操作。
各个操作符之间具有不同的优先等级,在描述相对复杂的函数关系式时,要注意其优先级关系。表达式中出现两个以上的操作符时,可通过括号“()”对其进行运算分组。表3-6列出了VHDL的操作符优先级。
表3-6 VHDL的操作符优先级
关于VHDL中的操作符的使用说明如下。
☺ 对于VHDL的7种基本逻辑操作符,使用时对数组类型的数据对象的逻辑操作是按位进行的。一般经过综合器综合后,逻辑操作符将直接生成逻辑门电路。信号或变量在这些操作符的直接作用下,可构成组合电路。
☺ 关系操作符的作用是将同类型的数据对象进行数据比较,根据关系表达式成立与否返回布尔类型的数据。对于数组类型的操作数,编译器是逐位比较对应位置的数值大小从而确立数值关系。对枚举类型数据的大小进行比较时,其排序方式与其定义的方式一致。
☺ 并置运算操作符“&”的作用是将两个操作数连接起来构成新的一维数组。例如,“hello”&“world”构成“helloworld”,或者“0”&“1”构成“01”。需要注意的是,在使用中,并置后的数组长度要与赋值目标的长度一致。
☺*、/、mod、rem等操作符的使用要注意综合器的支持程度。有时虽然综合器综合过程中并未报告错误,但综合之后的结果并非设计者的预定逻辑要求。因此,避免轻易使用乘除操作,而采用其他的变通方法来实现同样的逻辑设计。
☺ 乘方操作符“**”的左侧操作数可以是整数或浮点数,右侧操作数必须为整数,且只有在左侧操作数为浮点数时,右侧操作数才能是负整数。一般来说,VHDL综合器要求乘方操作符作用的操作数的底数必须为2。
☺ 移位操作符SLL是将数组向左移位,右边跟进的为补0;SRL则正好相反。ROL的移位方式是数组向左移位,并将左侧移出的位依次填充到右侧移空的位置;ROR移位方向相反,同样是自循环的移位方式。SLA和SRA是算术移位操作符,其移空的位用最初的首位,即符号位来填充。
在不同的EDA软件中,对操作符的支持程度不尽相同。例如,QuartusⅡ中限制“*”、“/”操作符右边的操作数必须为2的乘方,如x*8、z/2等,但使用LPM库中的子程序则无此限制。另外,QuartusⅡ也不支持MOD和REM运算操作符,有时虽然能够编译无误,但综合处的硬件系统并不能实现预定功能。因此在使用具体EDA软件时,要注意系统的编译信息提示及说明。