VHDL语言是一种类型概念很强的语言。任一对象声明时必须声明其类型,并且只能携带和返回指定类型的数据。对于不同的开发系统,由于受其综合能力的限制,对数据类型的支持程度有所不同。这里介绍一些常用的数据类型。
按照VHDL 1076的标准,共定义了以下四大类数据类型。
☺ 标量(Scalar)数据类型:单个的可计量的数据类型,标准数据类型,如整数(Integer)、实数(Real)、位(Bit)等属于此类。
☺ 复合(Composite)数据类型:多个数值的集合,具体分为两类:数组(Array)和记录(Record)。
☺ 存取(Access)数据类型:提供指向对象的参考,类似于普通编程语言的指针。
☺ 文件(File)数据类型:提供指向一系列数值(典型的如磁盘文件)的参考。
这些数据类型又可以划分为预定义的数据类型和用户自定义的数据类型。预定义数据类型即已经在现成的程序包中定义,用户可通过声名库随时获得和使用的数据类型。自定义数据类型则是用户根据需要,按照VHDL语法标准声明的数据类型。预定义数据类型是VHDL最常用、最基本的数据类型,这些数据类型都已经在VHDL提供的标准程序包STANDARD和STD_LOGIC_1164及其他程序包中做出了定义,并可在设计中随时调用。
【 提示 】用户可以在QuartusⅡ中打开安装目录下的/libraries/vhdl文件夹,其中的IEEE和STD两个子文件夹内存放了相应的程序包,打开这些程序包即可看到VHDL的预定义数据类型。
存取数据类型和文件数据类型不被QuartusⅡ综合器支持,因此不做过多介绍,下面分别介绍标量数据类型和复合数据类型。
标量数据类型中,大部分是系统提供的标准数据类型,可直接使用。具体数据类型及其说明如表3-1所示。
表3-1 标量数据类型及其说明
续表
打开QuartusⅡ的程序包,能够看到各个数据类型定义的原形。例如,在STANDARD程序包中,对上述部分类型的定义语句如下:
上述数据类型中,QuartusⅡVHDL综合器只支持部分类型,包括Bit、Boolean、Integer、Charactor,而Time、Real、Severity_Level几种类型不被支持。
在VHDL程序中表述整数类型时,可采用以下书写方式:
使用整数类型来定义端口或数据对象时,其范围用range关键字来做说明,例如:
另外,在IEEE库中程序包STD_LOGIC_1164中定义了另外一类常用的数据类型STD_LOGIC(工业标准逻辑类型)和STD_LOGIC_VECTOR(工业标准逻辑矢量类型)。在程序包STD_LOGIC_ARITH中定义了SIGNED和UNSIGNED的数据类型,也是设计中经常用到的。使用这些类型时,要在程序开始时先声明其程序包,方法如下:
STD_LOGIC是类型STD_ULOGIC的子类型。STD_ULOGIC是一个9值的逻辑系统,可以表示一个信号的9种不同的逻辑状态。STD_LOGIC_VECTOR是STD_LOGIC的数组形式。STD_LOGIC数据类型在IEEE_STD_1164程序包中定义的原形如下:
使用std_logic_vector数据类型时,应在其后做数据宽度的限定,以说明声明的对象所具有的数据宽度,例如:
矢量类型的数据可以进行位操作,即可以将其中某位取出,或对其中某位进行复制。例如,针对实例3-2中的端口声明,可执行以下操作:
【 说明 】对矢量类型的端口或数据对象的声名中,其宽度的说明方式可采用升序和降序两种方式。要注意声明时的宽度说明方式决定了该矢量数据的索引值排序方式。在对该矢量进行按位赋值时,索引值将起到关键作用。
在预定义数据类型中,还包括SIGNED和UNSIGNED。SIGNED类型代表一个有符号数,即0、正数或负数;UNSIGNED类型代表一个无符号数,即0或正数。其定义如下:
使用上述数据类型时,需掌握一个原则,即其类型定义以何种格式声明的,使用时就以何种格式调用。例如,bit类型使用时,'0'、'1'的英文单引号是必需的;整数类型使用时,则直接列写数字即可。
复合数据类型是一种或多种数据类型的集合。复合数据类型包括数组和记录。表3-2对复合数据类型进行了说明。
表3-2 复合数据类型及其说明
1)数组 ( Array ) 数组是同类型数据的集合,它可以根据声明的数组范围值进行索引。表3-2中的位向量、字符串是系统预定义了的数组格式,可以直接使用。用户可以自行定义需要的数组类型。下面是一个自定义的数组声明:
该数组类型声明定义了一个由16个元素构成的数组,其索引范围值由高到低(15~0)。数组的索引值可以升序排列,也可以降序排列,且不一定从0开始。该数组声明限定了数组的索引范围,因此在声明一个该类型的变量或者信号时,必须使用同样的索引范围。这样的数组称为限定数组。相应地,把数组索引范围定义成一个类型,而不限定具体范围值,称为非限定数组。
非限定数组的类型定义语法格式如下:
例如:
2)记录 ( Record ) 记录是各种类型的数据的集合,它由各种类型的名称域组合而成。记录的域可以是已有定义的任意类型,也可以是复合类型,包括另一记录类型。记录的类型定义语法格式如下:
例如:
上述语句定义了一个具有多种类型元素的记录类型data in__type。记录类型不大适合逻辑综合,较适用于系统仿真。
在VHDL语言中,语言类型的定义是非常严格的,不同类型的数据是不能进行运算和代入的。为了实现正确的运算操作,必须将数据进行必要的数据类型转换,这时就要用到类型转换函数。数据类型转换函数通常由VHDL语言的程序包集合提供,用户也可以根据需要自行编写数据类型转换程序。例如,在“STC_LOGIC_1164”包集合中提供了如下的数据类型转换函数:
在程序包主体部分,有具体类型转换函数的实现代码。例如,上面的To_bitvector函数,将std_logic_vector数据类型转换为bit_vector,其具体程序实现如下:
另外,在程序包“STD_LOGIC_ARITH”和“STD_LOGIC_UNSIGNED”中也提供了如下类型转换函数:
不同的程序包提供了不同的数值转换函数,设计者可以通过查阅各个程序包的内容来确定函数功能,从而正确使用。在QuartusⅡ中,用户可以通过查看安装目录中Libraries\vhdl\目录下的库文件内容选择使用类型转换函数。下面举例说明在程序设计中类型转换函数的应用。
该程序中多次用到了数据类型转换,因此要在程序开始把相应的库和程序包加进来,即在程序的起始部分声明库和使用程序包。在程序开始的端口声明部分,采用了STD_LOGIC_VECTOR的数据类型,但在后续的数值转换过程中,为了便于进行数学运算将其转换为整数类型。在输出时,再将整数类型转换为STD_LOGIC_VECTOR类型。
在VHDL综合器的IEEE标准库的程序包中定义了多种数据类型转换函数,如表3-3所示。设计者可以直接调用这些函数进行类型转换。
表3-3 VHDL数据类型转换函数
【 注意 】为了能够在程序中使用这些转换函数,在程序的起始端库声明的部分,需要添加这些库和程序包的声明语句。