购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.4 VHDL程序描述

了解了VHDL语言设计的基本结构及各部分功能后,就需要进一步学习各个组成部分的语法格式。在介绍语法格式前,就本书的书写格式与VHDL语法现象做以下说明和约定。

☺ VHDL语言不区分大小写,无论是关键字还是标识符,其大小写不同组合代表的对象是相同的。

☺ 在语法格式的介绍中,用方括号“[]”表示括号内的内容是可选的,用大括号“{}”表示括号内的内容是可重复出现的。

☺ VHDL中用双横线“--”表示注释符,任何VHDL程序中,双横线后的内容都不参加编译和综合。

☺ 为了便于阅读和调试,程序书写时应注意层次缩进。同一层次的采取相同的缩进格式,低一层次的比较高层次的缩进4个英文字符。

☺ 文件命名时,尽量保证文件名与实体名称保持一致。

2.4.1 实体声明(Entity Declaration)

实体声明提供了设计实体的完整的接口信息。实体声明中要给出实体名称,并用PORT端口声明语句描述实体的外部接口情况。实体声明无须对设计实体内部结构和功能进行描述。实体声明的书写格式如下([]括号表示其内部内容为可选部分):

【实例2-1】8位2输入的比较器的实体声明

图2-2 比较器实体模型

实体声明以“ENTITY 实体名称IS”开始,以“END[ENTITY]实体名称”结束。实体名称是设计者为实体指定的名称。类属(GENERIC)参数声明是可选部分,在部分编译系统中不被支持,设计者可根据系统情况选用。参数声明的作用是为设计实体设定参数,如端口宽度、延时长度等。端口声明指定端口名称、类型和宽度等,本例中分别指定了宽度为8位和1位的I/O端口a、b、c和EQ,实体模型如图2-2所示。端口声明的语法格式要求如下:

(1)端口名称是设计者对端口的命名,其命名符合标识符的规范即可(见2.6节);同时考虑到程序的易读性,应将实体名与该设计实体的功能对应起来。

(2)端口模式可以分为以下几种,如表2-1所示。

表2-1 端口模式说明

采用输入IN方向定义的端口,在结构体内部可以将其值赋给其他信号,但不能被其他信号作为赋值目标进行赋值,即在赋值语句中,只能出现在赋值语句的右边;相应的,采用输出OUT方向定义的端口,只能被其他信号赋值,而不能赋值给其他信号,在赋值语句中,只能出现在赋值语句的左边;采用INOUT方向定义的端口可以是输入也可以是输出,成为双向端口;BUFFER是具有回读功能的输出模式,可以读或者写,但只能有一个驱动源。

(3)端口类型即端口采用的数据类型,它决定了端口可选的数值范围。常用的端口类型有以下几种,如表2-2所示。

在同一个VHDL设计文件中,在指定数据类型的时候,建议尽量使用统一的数据类型。例如,要尽量避免同时使用BIT和STD_LOGIC数据类型,因为这样做需要引入类型转换函数,从而导致了不必要的混乱和多余代码。

表2-2 常用端口数据类型

在VHDL中,不同数据类型定义可能包含在不同的程序包中,因此使用时要注意数据类型所属的程序包已经被包含进来。表2-2中所列的数据类型除了STDLOGIC_和STD_是在IEEELOGIC1164__程序报中定义的,需要做显示声名外,其他几种数LOGICVECTOR_据类型均在STD库的标准程序报中预定义,不需要进行显式声名即可使用。有关数据类型我们还会在后面的章节中详细介绍。

2.4.2 结构体声明与描述(Architecture Declaration and Description)

由于结构体是对实体功能的具体描述,所以它一定要紧跟在实体的后面。结构体的语法格式如下:

【实例2-2】比较器的结构体描述

“结构体名称”为设计者为结构体指定的标识符。一般为结构体命名时,可根据采用的结构体描述形式,将其命名为“Behavior” (行为描述)、“RTL” (寄存器传输级描述)和“Structure”(结构描述)。本例中随意指定了一个名字“compare1”。“实体名称”即该结构体所对应的实体的名称,必须与实体声明中的实体名称保持一致。“块声明语句”用来定义结构体内部所用的内部信号、数据类型、元件声明和函数定义等。本例中,在该部分定义了一个存放中间量的信号量tem_val。“并行处理语句”为结构体内部的并行描述语句,负责描述结构体的行为和连接关系,它构成结构体的主体。本例中,三个并行语句描述了该比较器的行为机制。通过该例可以看出,VHDL语言具有较好的行为描述能力。

2.4.3 程序包(Package)

程序包就是将各类声明集中起来的一个集合,可供多个设计单元使用。我们可以把它看成一个公共的存储区域,区域内存放的数据类型、常量和子程序等,可以被整个VHDL设计实体内的各个设计单元调用。标准的程序包是非常通用的,可以在许多设计中采用。例如,“STD_LOGIC_1164”程序包中定义了我们在设计中经常用到的数据类型“STD_LOGIC”和“STD_LOGIC_VECTOR”。

程序包中包含的声明信息包括以下内容。

常量:声明系统宽度参数等,如数据总线宽度。

数据类型声明:定义整个设计实体中需要使用的数据类型。

组件声明:指明到实体的接口,使得设计中该组件能够被例化。

子程序声明:定义一些通用的算法、功能。

信号声明等。

程序包引用通过USE语句来实现,它通常是VHDL语言文件的第一条语句。其语法格式如下:

其中,“LIBRARY_NAME”是VHDL库的名称,“PACKAGE_NAME”是要使用的程序包的名称。“ALL”表示可以使用该程序包中的所有资源。

程序包定义时,其自身的结构可分成两个部分:程序包声明和程序包主体。程序包声明与主体的关系可以理解成类似于实体与结构体的关系,但程序包的声明只能最多对应一个程序包主体,有时程序包可以不包含主体部分。

1)程序包声明 Package Declaration ) 程序包声明的语法格式如下:

包名为设计者指定名称,包体声明语句可以是如下语句:

☺ USE语句;

☺ 类型声明语句;

☺ 子类型声明语句;

☺ 常量声明;

☺ 信号声明;

☺ 子程序声明;

☺ 组件声明;

☺ 别名声明等。

2)程序包体 Package Body ) 若程序包声明中包含了子程序声明或者定义了一个或多个延迟常量,就需要为程序包声明搭配一个程序包体,来具体描述子程序或完成常量赋值。程序包体必须与程序包声明在名称上保持一致。

程序包主体的语法格式如下:

包名要与对应的程序包声明一致,包体说明项可以是下列语句:

☺ USE语句;

☺ 子程序声明语句;

☺ 子程序体;

☺ 类型声明;

☺ 子类型声明;

☺ 常量声明。

下面给出一个完整的程序包实例。

【实例2-3】数据类型转换程序包

(将整数INTEGER类型的数据“num”转换成宽度为“size”的STD_LOGIC_VECTOR类型向量)

程序包声明和程序包体可以分开单独编译。在程序包声明单元中,定义数据类型和常量外,还需要对程序包体单元中的子程序做出说明。因为只有程序包声明部分说明的标识符在程序包外才是可见的。只在程序包体中声明的标识符在程序包外是不可见的。子程序不能放在程序包声明部分,只能放在程序包体中。若程序包中不包含子程序,则程序包体部分可以省略。

2.4.4 配置(Configuration)

当一个实体对应多个结构体时,由配置来进行结构体的选择工作。配置声明也可以用来指定实体的类属常数。配置的语法格式如下:

其中,配置名是设计者为该配置指定的名称;配置声明语句为USE语句;块配置部分格式如下:

由于配置在某些CPLD/FPGA开发系统中不被支持,因此应用相对较少,这里不再详述其具体细节,需要的用户可以查阅VHDL相关参考书籍。

2.4.5 库(Library)

库有不同的种类,不同的开发系统所支持的库的种类有所不同,如STD库、IEEE库、开发系统使用的工作库以及器件公司提供的支持库等。

在VHDL程序中,库的声明总是位于设计单元的最前面,标准格式如下:

例如:

库声明语句的作用范围侍从一个实体声明开始,到它所属的结构体、配置为止,或者从一个程序包的声明开始,到该程序包定义结束为止。当一个源程序中出现两个以上的实体,或者出现一个程序包定义和一个实体时,库的声明语句应该在每个实体声明语句和每个包声明语句前重复书写。

VHDL有STD和WORK两个预定义库,它们符合VHDL标准,使用时不需要显式声明,即不必在程序的开头使用USE语句,就可为设计可见,调用其中的资源。 QfmhQzHlSsKuMa4PNLQ0pXZeM1yhyCbs2U6snwru0xvUcjyV/d4Z/S7Pl8+Y66iA

点击中间区域
呼出菜单
上一章
目录
下一章
×