VHDL设计深入 课件_第1页
VHDL设计深入 课件_第2页
VHDL设计深入 课件_第3页
VHDL设计深入 课件_第4页
VHDL设计深入 课件_第5页
已阅读5页,还剩79页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

EDA技术与VHDL实用教程第5章VHDL设计深入<<EDA技术与VHDL实用教程>>EDA技术与VHDL实用教程

要求理解VHDL语言的一些高级特性与方法,提高运用VHDL分析、设计电路的能力。

知识点理解VHDL子程序和块语句的应用进一步理解VHDL库与程序包的应用理解QuartusII的HDL设计中的LPM函数的应用理解VHDL层次化文件设计

重点和难点VHDL块语句和子程序的应用理解QuartusII的HDL设计中的LPM函数的应用VHDL层次化文件设计EDA技术与VHDL实用教程引言本章在第四章的基础上,对QuartusII的VHDL文本输入设计法作进一步的讨论。本章主要讨论VHDL文本输入法中的子程序与子程序调用语句、VHDL库与程序包、块语句结构、VHDL设计中LPM函数的应用和VHDL层次化文件设计。EDA技术与VHDL实用教程第五章VHDL设计深入深入VHDL程序结构

5.1VHDL层次化文件设计5.3VHDL设计中LPM函数的应用5.25.1深入VHDL程序结构一、子程序与子程序调用语句1.子程序的一般特点子程序是一个VHDL程序模块,它内部由顺序语句组成,可把需要重复完成的设计工作写成子程序,这样可以在需要的地方多次调用。子程序有两种类型,即函数和过程。函数的调用只能返回一个值,而过程可以不返回任何值,也可以返回多个值。在函数的接口中,所有参数都是输入参数,而过程有输入参数、输出参数和双向参数。函数通常作为表达式的一部分,而过程则一般被用作一种语句结构。函数通常作为语句的一部分调用,而过程可以单独存在。在子程序体可以有返回语句,用来结束当前子程序体的执行。其语句格式如下:

RETURN[表达式];返回语句用于函数时,必须有表达式,只能并且必须返回一个值。每一函数必须至少包含一个以上的返回语句,但是在函数调用时,只有其中一个返回语句可以将值带出。返回语句用于过程时,表达式缺省,不返回任何值。

VHDL子程序具有可重载的特性,即允许有许多个重名的子程序,但这些子程序的参数类型及返回值数据类型是不同的,开发工具根据子程序的参数类型及返回值数据类型来区分各个重载的子程序。[重点提示]综合后的子程序将映射成目标芯片中的一个相应的电路模块,且每一次调用又将在硬件结构中产生具有相同结构的不同模块,这一点与普通的软件中调用子程序有很大的不同。2.函数

(1)

函数及声明函数是用来描述重复使用的返回单一值的顺序算法的子程序。函数中应至少有一个返回语句,通过其中一个返回语句返回所要求返回的值。函数声明分函数首声明和函数体声明两部分,同一个函数的函数首和函数体应具有相同的名字。函数首的声明格式如下:

FUNCTION

函数名(参数表)RETURN

数据类型;函数体声明格式如下:FUNCTION

函数名(参数表)RETURN

数据类型IS[说明部分];

BEGIN

顺序语句;END[FUNCTION]

函数名;函数首是由函数名、参数表和返回值的数据类型三部分组成。函数名需放在关键词FUNCTION之后,它可以是普通的标识符,也可以是运算符,当是运算符时必须加上双引号,这是运算符的重载。函数的参数表中的参数只能是IN模式,用来定义输入值,它只能是信号或常数,参数名需放在关键词CONSANT或SIGNAL之后,若没有特别的说明,则参数被默认为常数。信号或常数的数据类型不能是类似“STD_LOGIC_VECTOR(7DOWNTO0)”或“INTEGERRANGE3DOWNTO0”的加范围限制的形式,只能使用类似STD_LOGIC_VECTOR和INTEGER的非限制的形式。下面是三个不同的函数首声明例子:FUNCTIONFUNC1(A,B,C:REAL)RETURNREAL;----参量前没注明CONSANT或SIGNAL默认为常数。FUNCTION“*”(CONSANTA,B:INTEGER)RETURNINTEGER;----注意重载运算符函数名*要用引号括起来。FUNCTIONAS2(SIGNALIN1,IN2:REAL)RETURNREAL;----注意信号参量前要注明SIGNAL。函数体的说明部分包括对数据类型、常量、变量等的局部说明,其顺序语句部分则是描述用以完成规定算法或者转换的顺序语句,通常函数体内的顺序语句部分含有返回语句:RETURN表达式,用来在该处返回所要求返回的值。函数体的说明以关键词ENDFUNCTION以及函数名结尾。一旦函数被调用,就将执行函数体内的顺序语句部分的语句。下面是一个函数体声明的例子:

FUNCTIONSAM(x,y,z:BIT)RETURNBITIS----定义函数SAM,该函数无函数首

BEGINRETURN(xORz)ANDy;ENDFUNCTIONSAM;

(2)函数声明的地方可在结构体的声明部分、进程的声明部分或程序包中声明函数。在结构体或进程中声明函数,只能在结构体或进程中调用函数,而在程序包中声明函数则可通过声明引用程序包,在不同的实体的各个结构体内的调用函数。(3)函数的调用

例5.1libraryieee;useieee.std_logic_1164.all;entitydec3_8isport(a:instd_logic_vector(2downto0);y:outstd_logic_vector(7downto0));enddec3_8;architectureaofdec3_8isfunctionto_integer(arg:std_logic_vector)returnintegerisvariabletemp:natural:=0;variablej:natural:=arg’length-1;---arg’length是arg的位长VHDL语言不区分大小写beginifarg’length>=32thenreturntemp;endif;----不能超过整数范围foriinarg’rangeloopifarg(i)=’1’thentemp:=temp+2**j;---某一位不为零,则贡献一部分和endif;ifj>0thenj:=j-1;endif;endloop;returntemp;endfunctionto_integer;beging1:forkin7downto0generatey(k)<=’0’whento_integer(a)=kelse‘1’;endgenerateg1;enda;其仿真波形如图5-1。这是使用数据转换函数to_integer描写的3-8译码器,转换函数to_integer将STD_LOGIC_VECTOR类型转换为INTEGER类型。注意这里函数调用的方法是把实际参数代入形式参数的位置,这称位置连接映射。还可以使用指名连接映射,to_integer(arg=>a)。函数调用格式如下:函数名(实际函数参数表)其中函数参数表可以是位置连接映射形式(a1,a2,…..an)或者指名连接映射形式(x1=>a1,x2=>a2,…..xn=>an)。3.过程

(1)

过程及其声明在VHDL源代码中,如果在多处出现重复的模块,可使用过程来描述。过程声明分过程首声明和过程体声明两部分,同一个过程的过程首和过程体应具有相同的名字。过程首的声明格式如下:

PROCEDURE

过程名(参数表);过程体的声明格式如下:

PROCEDURE

过程名(参数表)IS[说明部分];

BEGIN顺序语句;

END[PROCEDURE]

过程名;过程首由过程名和参数表组成。参数表用于对常数、变量和信号三类形式参量作出说明,并用关键词IN、OUT和INOUT定义这些参数的信息的流向。如果只定义了IN模式而未定义形式参量的数据对象类型,则默认为常量;若只定义了INOUT或OUT,则默认形式参量是变量。下面是过程首声明的例子:PROCEDUREPRO1(SIGNALa,b:INOUTBIT);PROCEDUREPRO2(CONSTANTa1:ININTEGER;VARIABLEb1:OUTINTEGER);PROCEDUREPRO3(SIGNALy:OUTBIT);

过程体中的说明部分的各种定义只能使用于过程体内部。过程体的顺序语句部分可以包含任何顺序执行的语句,包括WAIT语句。但如果一个过程是在进程中调用的,且这个进程已列出了敏感参量表,则不能在此过程中使用WAIT语句。下面是过程体声明的例子:

PROCEDUREhalfsub(SIGNALa,b:INBIT;SIGNALs,c:OUTBIT)ISBEGINs<=aXORbAFTER10ns;c<=(NOTa)ANDbAFTER10ns;ENDPROCEDUREhalfsub;PROCEDUREorgate(SIGNALa1,b1:INBIT;SIGNALo1:OUTBIT)ISBEGINo1<=a1ORb1;ENDPROCEDUREorgate;

(2)过程声明的地方可在结构体的声明部分、进程的声明部分或程序包中声明过程。在结构体或进程中声明的过程,只能在结构体或进程中调用,而在程序包中生命的过程则可通过声明引用程序包,在不同的实体的各个结构体内调用。

(3)过程的调用过程调用有两种方式,即顺序语句方式和并行语句方式。在顺序语句环境中,一个过程被执行,则属于顺序语句方式;在并行语句环境中,过程体中定义的任一IN或INOUT的目标参量发生改变时,将启动过程的调用,这时的调用是属于并行语句方式。过程与函数一样可以重复调用或嵌套式调用。例5.2其仿真波形如下图:上例描述的是一个全减器,先在结构体说明部分声明半减器halfsub过程体和或门orgate过程体,然后通过在结构体并行语句部分用这两个过程来实现全减器。从上例可看出过程调用格式如下:其中过程参数表可以是位置连接映射形式(a1,a2,….an)或者指名连接映射形式(x1=>a1,x2=>a2,……xn=>an)。[标号:]过程名(实际函数参数表);二、VHDL库与程序包VHDL库(library)是用来存储编译好的VHDL设计文件的仓库。常见的库有IEEE库、STD库、ASIC矢量库、WORK库和用户自定义库。VHDL库中存放的VHDL设计文件包含一个或多个VHDL设计单元,这些设计单元可以是实体声明、结构体、配置声明、程序包声明和程序包体等。下面重点介绍程序包声明、程序包体和各种VHDL设计单元的特点及其在文件中的组织和库中存储。

(一)程序包程序包包括程序包声明和程序包体两部分。1.程序包声明程序包声明亦称程序包首,是用来进行一系列共用的声明。在VHDL设计文件中,除了实体声明、结构体等设计单元外,还有程序包声明、程序包体这两种设计单元。一个程序包声明和与它对应的程序包体一起保存了一些经常用到的或在一个效大的工程项目中许多文件要用到的已定义的常数、数据类型、元件调用说明以及子程序接口等内容。程序包声明包含一系列可供其他设计单元共享的声明,它定义了程序包的接口,即定义了对其设计单元可见的条目。其声明格式如下:PACKAGE

程序包名IS程序包首声明部分END[PACKAGE]

程序包名;2.程序包体程序包体用来存储在相应的程序包声明中声明了的函数或过程的定义即函数或过程体,也可以用来存储出现的相应的程序包声明中的完整的常量声明。程序包体总是与程序包声明相对应的,并且一个程序包声明只能对应一个程序包体。程序包声明与对应一个程序包体的名字应相同。其格式如下:

PACKAGEBODY

程序包名IS程序包体说明部分程序包体内容部分

END[PACKAGEBODY]

程序包名;(二)各种VHDL设计单元的特点及其在文件中组织和库中存储VHDL设计单元有实体声明、结构体、配置声明、程序包声明和程序包体等类型。1.VHDL设计单元的特点

(1)

实体声明:在一个实体声明中声明的条目在与它相关联的各个结构体中是隐式可见的。(2)

结构体:可以有多个结构体同属一个实体,或者说与同一个实体声明相关联。在一个结构体内声明的信号不能被其他设计单元引用。

(3)

配置声明:可以有多个结构体同属于一个实体时,应有配置声明。

(4)

程序包声明:在一个程序包声明的条目可通过LIBRARY和USE子句来提供给其他设计单元。程序包声明中声明的条目在相应的程序包体中隐式可见。

(5)

程序包体:程序包体名必须和它所对应的程序声明名字相同,因此一个程序包声明最多只有一个程序包体。一个程序包体内部声明的条目的作用范围局限在该程序包体的内部。2.各种设计单元的文件的组织

VHDL设计文件是一个包含VHDL源代码的文件,它可包含一个或多个设计单元,设计单元可以是上述的5种单元。

(1)

以上每种设计单元都可以放在一个独立的VHDL设计文件中。

(2)

一个VHDL设计实体的实体声明、结构体可以分开放在不同VHDL设计文件中,但值得推荐的做法是把一个VHDL设计实体的实体声明、结构体、配置声明可以放在同一个VHDL设计文件中,并且这个文件以实体名为名。

(3)

一个VHDL设计文件可包含多个设计实体的实体声明、结构体、配置声明,但若有顶层实体,这个VHDL设计文件命名的值得推荐的做法是用顶层实体名为名。

3、各种VHDL设计单元在设计库中的存储VHDL语言并没有详细规定VHDL设计单元的存储格式。值得推荐的方法是把要放在一个库的编译好的设计文件放在主机系统的一个文件夹里。可以有许多设计库,每个设计库有一个逻辑名。可以把上述的设计单元分为初级单元和二级单元两类:初级单元:包括实体声明、程序包声明和配置声明。二级单元:包括结构体和程序包体。二级单元一定要和它们所关联的初级单元存储在同一个设计库中。另外,配置声明虽然是初级单元,但它必须和它所配置的实体声明存储在同一个设计库中。在同一个设计库中,与不同初级单元相关联的二级单元可有相同的名字;一个二级单元也可以和它所关联的初级单元具有相同的名字;相对应的程序包声明和程序包体必须具有相同的名字。(三)VHDL库与程序包的引用1.VHDL库与程序包的引用方法在VHDL语言中,实体和程序包要引用别的库和程序包时,要在实体声明和程序声明的开始部分有LIBRARY子句和USE子句加以声明。一旦说明了库和程序包,整个设计实体或程序包都可以进入访问或调用,但其作用范围仅限于所说明的设计实体或程序包。每一个实体或程序包都必须有自己必须的库和程序包的说明语句。(1)LIBRARY子句在一个实体或程序包声明开始部分使用LIBRARY子句,使得在这个实体或程序包内部所声明的库的逻辑名变成可见。LIBRARY子句格式如下:LIBRARY

逻辑库名称列表;(2)USE子句USE子句的使用所说明的程序包中的条目对本实体或程序包是可见的。USE语句的使用格式有两种格式:USE

库名.程序包名.项目名;USE

库名.程序包名.ALL;前句格式的作用是,向本设计实体或程序包中开放指定库中的特定程序包内所选定项目。后句格式的作用是,向本设计实体或程序包开放指定库中的特定程序包内所有的内容。例如:LIBRARYieee;USEieee.std_logic_1164.ALL;---打开ieee库中的std_logic_1164程序包的所有内容USEieee.std_logic_unsigned.ALL;---打开ieee库中的std_logic_unsigned的所有内容

例如:LIBRARYieee;USEieee.std_logic_1164.std_logic;USEieee.std_logic_1164.rising_edge;---向当前设计实体打开std_logic_1164程序包中的rising_edge函数。但由于此函数必须用到数据类型std_logic,所以在上一条USE语句中打开同一程序包中的这一数据类型。STD库包含程序包STANDARD和TEXTIO。程序包STANDARD包含了CHARACTER、BOOLEAN、BIT_VECTOR和INTEGER等预定义类型的声明。程序包STANDARD使默认打开的不需要使用USE子句将它打开。但要使用TEXTIO程序包内的条目时还是需要使用USE子句将它打开,因为TEXTIO程序包并不是默认打开。2.在QuatrusⅡ中设定自定义库的方法

(1)对特定工程设定自定义库的方法有两种方法,一种是使用settings对话框的方法,另一种是在新建工程时进行设定的方法。

(2)对所有工程设定自定义库的方法3.在QuatrusⅡ中使用自定义库和程序包的方法

(1)使用WORK库中的自定义程序包将自定义程序包文件添加到要引用它的文件所在的工程中,在引用的文件的开始部分用USE子句加以声明即可。一般可把自定义程序包文件存储到要引用它的文件所存储的文件夹里。例5.3将下面两文件my_package.vhd和fullsub_work.vhd存储到文件夹fullsub_work内。my_package.vhd:PACKAGEmy_packageISPROCEDUREhalfsub(signala,b:inbit;signals,c:outbit);PROCEDUREorgate(signala1,b1:inbit;signalo1:outbit);ENDmy_package;PACKAGEBODYmy_packageISPROCEDUREhalfsub(signala,b:inbit;signals,c:outbit)ISBEGINs<=aXORbAFTER10ns;c<=(NOTa)ANDbAFTER10ns;ENDPROCEDUREhalfsub;PROCEDUREorgate(signala1,b1:inbit;signalo1:outbit)ISBEGINo1<=a1ORb1;ENDPROCEDUREorgate;ENDmy_package;

fullsub_work.vhd:USEWORK.my_package.ALL;ENTITYfullsub_workISPORT(i1,i2,c_in:inbit;fs,c_out:outbit);ENDfullsub_work;ARCHITECTUREaOFfullsub_workISSIGNALtemp_s,temp_c1,temp_c2:bit;BEGINU0:halfsub(i1,i2,temp_s,temp_c1);U1:halfsub(temp_s,c_in,fs,temp_c2);U2:orgate(temp_c1,temp_c2,c_out);ENDa;以fullsub_work为工程文件夹,fullsub_work.vhd为顶层文件新建一个工程项目,把my_package.vhd文件添加到工程中,即可通过编译与仿真。(2)使用自定义库中的自定义程序包把自定义程序包文件存储到自定义库所在的文件夹里,再将自定义程序包文件添加到要引用它的文件所在的工程中,在引用文件开始部分用LIBRARY子句和USE子句加以引用声明即可。例5.4分别将下面的两文件my_package.vhd和fullsub_work.vhd存储到文件夹mylib和fullsub_mylib中,以fullsub_work.vhd为顶层文件建立一工程fullsub_mylib,用上例添加程序包文件的方法把my_package.vhd文件添加到工程fullsub_mylib中,就可使下面VHDL代码通过编译和仿真。my_package.vhd:PACKAGEmy_packageISPROCEDUREhalfsub(signala,b:inbit;signals,c:outbit);PROCEDUREorgate(signala1,b1:inbit;signalo1:outbit);ENDmy_package;PACKAGEBODYmy_packageISPROCEDUREhalfsub(signala,b:inbit;signals,c:outbit)ISBEGINs<=NOT(aXOR(NOTb))AFTER10ns;c<=(NOTa)ANDbAFTER10ns;ENDPROCEDUREhalfsub;PROCEDUREorgate(signala1,b1:inbit;signalo1:outbit)ISBEGINo1<=a1ORb1;ENDPROCEDURE

orgate;ENDmy_package;fullsub_mylib.vhd:LIBRARYmylib;USEmylib.my_package.ALL;ENTITYfullsub_mylibISPORT(i1,i2,c_in:inbit;fs,c_out:outbit);ENDfullsub_mylib;ARCHITECTUREaOFfullsub_mylibISSIGNALtemp_s,temp_c1,temp_c2:bit;BEGINU0:halfsub(i1,i2,temp_s,temp_c1);U1:halfsub(temp_s,c_in,fs,temp_c2);U2:orgate(temp_c1,temp_c2,c_out);ENDa;这是使用自定义库中的自定义程序包my_package.vhd编写的全减器VHDL代码。其仿真波形如下图示。三、块语句结构BLOCK语句属并行语句,BLOCK语句中所包含的语句也是并行语句。块语句有以下三种功能:

(1)

通过GUARDED信号来启用或禁止信号赋值;

(2)

描述一个相对独立的设计部分;

(3)

限制声明范围;块语句声明格式如下:块标号:BLOCK[(块保护表达式)][IS][块头][块声明]

BEGIN并行语句;

ENDBLOCK[块标号];块语句声明中的块头部分可包含由关键词GENERIC、PORT、GENERICMAP和PORTMAP引导的类属说明和接口说明,对BLOCK的接口设置以及与外界信号的连接状况加以说明。块的声明部分可以定义的项目主要有:USE语句、子程序、数据类型、子类型、常数、信号、元件。块中的并行语句部分可包含结构体中的任何并行语句结构包括块语句。1.通过GUARDED信号来启用或禁止信号赋值例5.5ENTITYlatch_blockISPORT(clock:INBIT;d:INBIT;q:BUFFERBIT);ENDlatch_block;ARCHITECTUREaOFlatch_blockISBEGINb:BLOCK(clock=’1’)BEGINq<=GUARDEDd;ENDBLOCKb;ENDa;执行Tools=>RTLViewer,打开RTL电路观察器可看到此电路的RTL原理图如下图示,可见此电路是一个门控电路(latch)。2.块语句用于描述一个相对独立的设计部分当一个VHDL设计文件由不止一个设计者来设计时,每个设计者的设计往往是相对独立的,这时可使用不同的块语句来描述不同人的设计。块中可以使用任意的常数和信号名称而不用担心与别人的工作冲突,只需要,通过块的类属说明和接口说明把这些名称和块的外界关联起来。例5.7其仿真波形如下图:在上例中,块U0用并行信号赋值语句描述一个半减器,类属和端口映射使得局部名称和外部名称相关联。块U1用进程语句描述一个半减器,而U2中描写或门的过程调用语句,合起来是一个全减器。3.块语句限制声明范围有时有些声明中只适合某些代码,这时,可把这些代码写进一个块语句,把这些声明写成块语句的块声明,就可把这些声明限制在块语句内部,起到限制声明范围的作用。这种用法比较简单,故不在举例说明。5.2VHDL设计中LPM函数的应用在Altera的开发工具QuatrusⅡ中,有一些内带的基本宏功能(Megafuncition/PLM)可供用户使用,本节主要介绍这些QuatrusⅡ内带的基本宏功能,而(MegaCore)则需另外授权和安装才能使用,在这就不介绍。基本宏功能可在原理图设计输入法中使用,也可在HDL设计输入法中使用,前者已经在第三章做过介绍,本节介绍的是在VHDL设计中的LPM使用方法。设计中使用LPM可在VHDL设计文件中通过端口和参数定义例化LPM,也可使用MegaWizardPlug-InManager对宏功能模块进行参数化并建立包装文件,然后可在后面的设计中使用此文件。一、通过端口和参数定义例化LPM下面以设计一个32位加法器为例,说明VHDL设计文件中通过端口和参数定义例化LPM的方法。例5.8其仿真波形如下图示:执行TOOLS=>RTLViewer,打开RTL电路观察可看到此电路的RTL原理图如下图。二、通过MegaWizardPlug-InManager例化LPM下面例子就是使用lpm_rom来描述例4.29所描述的电路中的译码电路模块。在此译码电路模块中,输入信号为Counter,输出信号为Dout,在下面例子中

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论