1第11章函数和过程函数(function)和过程(procedure)统称为子程序(subprogram)。子程序与进程的相同点:内部包含的都是顺序描述代码,使用相同的顺序描述语句,如if,case和loop(wait语句除外)。子程序与进程语句的区别:在使用目的上:进程可以直接在主代码中使用;而子程序一般在建库时使用,以便代码重用和代码共享。当然子程序也是可以在主代码中直接建立和使用的。在使用方法上:1、子程序不能从结构体的其余部分直接读写信号,所有通信都是通过子程序的接口来完成的;进程可以直接读写结构体内的其它信号。2、子程序中不允许使用wait语句。2子程序的存放位置:Package、Architecture、Process子程序与硬件规模:与普通软件中子程序调用的区别:普通软件子程序调用增加处理时间;VHDL中每调用一次子程序,其综合后都将对应一个相应的电路模块。子程序调用次数与综合后的电路规模成正比。设计中应严格控制子程序调用次数。知识点补充(1):3子程序的类型:过程(Procedure):0个或多个in、inout、或out参数。可获得多个返回值。函数(Function):0个或多个in参数,一个return值。只能获得一个返回值。过程可作为一种独立的语句结构而单独存在,函数通常作为表达式的一部分来调用。子程序包含两部分:子程序声明和子程序主体。知识点补充(2):4每次调用子程序时,都要首先对其进行初始化,即一次执行结束后再调用需再次初始化。因此,子程序内部的值是不能保持的。知识点补充(3):511.1函数(function)一个函数就是一段顺序描述的代码。对于一些经常遇到的具有共性的设计问题,如数据类型转换、算术运算等,希望将其功能实现的代码被共享和重用,使主代码简洁并易于理解---函数。注意:由于在于每次调用函数时,都要首先对其进行初始化,即一次执行结束后再调用需再次初始化,即函数内部的值是不能保持的,因此在函数中禁止进行信号声明和元件实例化。函数的使用过程:先创建函数,再调用函数。6函数的创建:Function函数名[参数列表]return数据类型IS[声明]BEGIN(顺序描述代码)END函数名;(输入)参数列表=[constant]常量名:常量类型;(输入)参数列表=SIGNAL信号名:信号类型;参数列表指明函数的输入参数:•输入参数的个数是任意的,也可以没有参数;•输入参数的类型:变量不能作为参数,可以是常量和信号,语法如下:7在VHDL语言中,FUNCTION语句只能计算数值,不能改变其参数的值,所以其参数的模式只能是IN,通常可以省略不写。FUNCTION的输入值由调用者拷贝到输入参数中,如果没有特别指定,在FUNCTION语句中按常数或信号处理。因此输入参数不能为变量类型。另外,由于FUNCTION的输入值由调用者拷贝到输入参数中,因此输入参数不能指定取值范围。8函数的输出:使用RETURN语句,语法结构如下:return[表达式];return语句只能用于子程序(函数或过程)中,并用来终止一个子程序的执行。当用于函数时,必须返回一个值。返回值的类型由return后面的数据类型指定。9创建一个函数的例子:创建名为f1的函数,有3个输入参数a,b,c,其中a,b是常量(关键字constant可以省略),c为信号。输出参数(只能有一个),是boolean类型的。functionf1(a,b:integer;signalc:std_logic_vector)returnbooleanISBEGIN(顺序描述代码)ENDf1;不能指定范围不能有变量类型10函数的调用:函数可以单独构成表达式,也可以作为表达式的一部分被调用。例:x=conv_integer(a);--单独构成表达式;ifxmax(a,b)....--表达式的一部分;11例11.1:positive_edge()函数时钟上升沿检测函数,可用于D触发器的设计:---------------函数的创建-------------------functionpositive_edge(signals:std_logic)returnbooleanisbeginreturn(s’eventands=‘1’);endpositive_edge;----------------函数的调用---------------........ifpositive_edge(clk)then....12例11.2:conv_integer()函数,将std_logic_vector类型的数据转换为integer类型,可处理任意宽度和方向的输入矢量:---------------函数的创建-------------------functionconv_integer(signalvector:std_logic_vector)returnintegerisvariableresult:integerrange0to2**vector’length-1;beginif(vector(vector’high)=‘1’)thenresult:=1;elseresult:=0;endif;foriin(vector’high-1)downto(vector’low)loopresult:=result*2;if(vector(i)=‘1’)thenresult:=result+1;endif;endloop;returnresult;endconv_integer;----------------函数的调用---------------........y=conv_integer(a);....注意:在输入参数列表中仍然不能指定信号的范围注意:内部不能声明信号注意:虽然不知道输入信号的范围,但可以函数被调用时使用s’length来获取输入参数的具体范围1311.2函数的存放函数和过程的存放位置包集(+包体)主代码LIBRARYARCHITECTURE(声明部分)实体必须!14例11.3:在主代码中定义函数,可以出现在entity中,也可以出现在architecture中。如存放于architecture中的声明:libraryieee;useieee.std_logic_1164.all;entitydffisport(d,clk,rst:instd_logic;q:outstd_logic);enddff;architecturemy_archofdffisfunctionpositive_edge(signals:std_logic)returnbooleanisbeginreturn(s’eventands=‘1’);endpositive_edge;beginprocess(clk,rst)beginif(rst=‘1’)thenq=‘0’;elsepositive_edge(clk)thenq=d;endif;endprocess;endmy_arch;15例11.4(1):在包集中定义函数,可以方便地被其它设计所重用和共享。注意:函数在package中声明,在packagebody中定义。---------------在包集中定义函数-------------------libraryieee;useieee.std_logic_1164.all;packagemy_packageisfunctionpositive_edge(signals:std_logic)returnboolean;endmy_package;packagebodymy_packageisfunctionpositive_edge(signals:std_logic)returnbooleanisbeginreturn(s’eventands=‘1’);endpositive_edge;endmy_package;要先声明再定义16例11.4(2):在主代码中调用在包集中定义的函数。---------------在主代码中调用包集中定义的函数-------------------libraryieee;useieee.std_logic_1164.all;usework.my_package.all;entitydffisport(d,clk,rst:instd_logic;q:outstd_logic);enddff;architecturemy_archofdffisbeginprocess(clk,rst)beginif(rst=‘1’)thenq=‘0’;elsifpositive_edge(clk)thenq=d;endif;endprocess;endmy_arch;17例11.5:在包集中定义conv_integer()函数libraryieee;useieee.std_logic_1164.all;packagemy_packageisfunctionconv_integer(signalvector:std_logic_vector)returninteger;endmy_package;packagebodymy_packageisfunctionconv_integer(signalvector:std_logic_vector)returnintegerisvariableresult:integerrange0to2**vector’length-1;beginif(vector(vector’high)=‘1’)thenresult:=1;elseresult:=0;endif;foriin(vector’high-1)downto(vector’low)loopresult:=result*2;if(vector(i)=‘1’)thenresult:=result+1;endif;endloop;returnresult;endconv_integer;endmy_package;-------在主代码中调用包集中定义的函数-------------------libraryieee;useieee.std_logic_1164.all;usework.my_package.all;entityconv_int2isport(a:instd_logic_vector(0to3);y:outintegerrange0to15);endconv_int2;architecturemy_archofconv_int2isbeginy=conv_integer(a);endmy_arch;18例11.6:“+”函数:•功能描述:扩展预定义的“+”操作符,进行std_logic_vector类型数据的加法运算。•实现方式:在包集中定义函数,在主代码中调用。-----------在包集中定义函数-----------libraryieee;useieee.std_logic_1164.all;packagemy_packageisfunction“+”(a,b:std_logic_vector)returnstd_logic_vector;endmy_package;packagebodymy_packageisfunction“+”(a,b:std_logic_vector)returnstd_logic_vectorisvariableresult:std_logic_vector(3downto0);variablecarry:std_logic;begincarry:=‘0’;foriina’reverse_rangeloopresult(i):=a(i)XORb(i)XORcarry;carry:=(a(i)ANDb(i))OR(a(i)ANDcarry)OR(b(i)ANDcarry);endloop;returnresult;end“+”;endmy_package;比较特殊的函数名称19-------在主