子程序是一个VHDL程序模块,它是利用顺序语句来定义和完成算法的,应用它能更有效地完成重复的设计工作。子程序不能从所在的结构体的其他块或进程结构中直接读取信号值或者向信号赋值,而只能通过子程序调用及与子程序的界面端口进行通用。
子程序有两种类型,即过程(PROCEDURE)和函数(FUNCTION)。过程的调用可以通过其界面获得多个返回值,而函数只能返回一个值。在函数入口中,所有参数都是输入参数,而过程有输入参数、输出参数和双向参数。过程一般被看做一种语句结构,而函数通常是表达式的一部分。过程可以单独存在,而函数通常作为语句的一部分调用。
在进程中允许对子程序进行调用。子程序包括过程和函数,可以在VHDL的结构体或程序包中的任何位置对子程序进行调用。
从硬件角度讲,一个子程序的调用类似于一个元件模块的例化,也就是说,VHDL综合器为子程序的每一次调用都生成一个电路逻辑块。所不同的是,元件的例化将产生一个新的设计层次,而子程序调用只对应于当前层次的一部分。
1.过程调用
过程调用就是执行一个给定名字和参数的过程。调用过程的语句格式如下:
其中,括号中的实参表达式称为实参,它可以是一个具体的数值,也可以是一个标识符,是当前调用程序中过程形参的接受体。在此调用格式中,形参名为当前欲调用的过程中已说明的参数名,即与实参表达式相联系的形参名。被调用中的形参名与调用语句中的实参表达式的对应关系有位置关联法和名字关联法两种,位置关联可以省去形参名。
一个过程的调用有3个步骤:首先将IN和INOUT模式的实参值赋给欲调用的过程中与它们对应的形参;然后执行这个过程;最后将过程中IN和INOUT模式的形参值赋给对应的实参。
实际上,一个过程对应的硬件结构中,其标识符形参的输入输出是与其内部逻辑相连的。在例4.32中定义了一个名为SWAP的局部过程(没有放在程序包中的过程),这个过程的功能是对一个数组中的两个元素进行比较,如果发现这两个元素的排列不符合要求,就进行交换,使得左边的元素值总是大于右边的元素值。连续调用3次SWAP后,就能将一个元素的数组元素从左至右按序排列好,最大值排在左边。
例4.32
2.函数调用
函数调用与过程调用是十分相似的,不同之处是,调用函数将返还一个指定数据类型的值,函数的参量只能是输入值。
在VHDL中有多种函数形式,函数的表达格式如下:(www.xing528.com)
一般情况下,函数定义由两部分组成,即函数首和函数体。
(1)函数首
函数首是由函数名、参数表和返回值的数据类型3部分组成的。函数首的名称即为函数的名称,须放在关键词FUNCTION之后,它可以是普通的标识符,也可以是运算符(这时必须加上双引号)。函数的参数表是用来定义输入值的,它可以是信号或常数,参数名须放在关键词CONSANT或SIGNAL之后,若没有特别的说明,则参数被默认为常数。如果要将一个已编制好的函数并入程序包,函数首必须放在程序包的说明部分,而函数体须放在程序包的包体内。如果只是在一个结构体中定义并调用函数,则仅需函数体即可。由此可见,函数首的作用只是作为程序包的有关此函数的一个接口界面。
例4.33
以上是3个不同的函数首,它们都放在某一程序包的说明部分。
(2)函数体
函数体包括对数据类型、常数、变量等的局部说明,以及用以完成规定算法或者转换的顺序语句,并以关键词END FUNCTION以及函数名结尾。一旦函数被调用,就将执行这部分语句。
例4.34
函数是从IEEE.STD_LOGIC_ARITH库中调用的,在程序包体中的最大整型数检出函数MAXIUM只有函数体,没有函数首,这是因为它只在程序包体内调用。
例4.35
通过此例,不但可以从中看到在程序包中完整的函数置位形式,而且还将注意到,在函数首的3个函数名都是同名的,即都是以加法运算符“+”作为函数名。以这种方式定义函数即所谓运算符重载。对运算符重载(即对运算符重新定义)的函数称为重载函数。
实用中,如果已用“USE”语句打开了程序包STD_LOGIC_UNSIGNED,这时,如果设计实体中有一个STD_LOGIC_VECTOR位矢和一个整数相加,程序就会自动调用第一个函数,并返回位矢类型的值。若是一个位矢与STD_LOGIC数据类型的数相加,则调用第三个函数,并以位矢类型的值返回。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。