
[信息与通信]EDA课件6.ppt
50页第6讲 VHDL基本语句与基本设计 ----并行语句Ø6.1进程进程(PROCESS)语句语句Ø6.2块块(BLOCK)语句语句Ø6.3子程序子程序(SUBPROGRAM)语句语句Ø6.4断言断言(ASSERT)语句语句Ø6.5信号赋值信号赋值(SIGNAL ASSIGNMENT)语句语句Ø6.6参数传递参数传递(GENERIC)语句语句Ø6.7通用模块与元件调用通用模块与元件调用(COMPONENT)、端口映射、端口映射(PORT MAP)语句语句Ø6.8生成生成(GENERATE)语句 §6.1.进程.进程(PROCESS)语句语句 在VHDL程序中,PROCESS语句是描述硬件并行工作行为的最常用、最基本的语句 一个结构体中通常包含多个进程语句结构,这些进程语句之间是并行关系的,而每一进程的内部是由一系列顺序语句构成的PROCESS语句结构包含了一个描述设计实体中某一模块部分逻辑行为的、独立的顺序语句描述的部分PROCESS语句具有如下特点: (1) 进程结构中的所有语句都是按顺序执行的 (2) 多进程之间是并行执行的,并可存取结构体或实体中所定义的信号。
(3) 在进程结构中必须包含一个显式的敏感信号量表或者包含一个WAIT语句 (4) 进程之间的通信是通过信号量传递来实现的 PROCESS语句的一般书写结构、组织形式如下: [进程名:] PROCESS [敏感信号表][IS] [进程说明部分] BEGIN 顺序描述语句部分 END PROCESS [进程名]; 顺序描述语句部分可分为:(1) 信号赋值语句:在进程中将计算或处理的结果向信号赋值2) 变量赋值语句:在进程中以变量的形式存储计算的中间值3) 进程启动语句:当PROCESS的敏感信号表没有列出任何敏感量时,进程的启动只能通过进程启动语句这时可以利用WAIT语句监视信号的变化情况,以便决定是否启动进程WAIT语句可以看成是一种隐式的敏感信号表4) 子程序调用语句:对已定义的过程和函数进行调用,并参与计算5) 顺序描述语句:包括IF语句、CASE语句、LOOP语句和NULL语句等6) 进程跳出语句:包括NEXT语句和EXIT语句,用于控制进程的运行方向。
[例6.16]所示是一个时钟同步D触发器的VHDL描述 与其他语句相比,进程语句结构具有更多的特点,对进程的认识和进行进程的设计需要注意以下几方面的问题 (1) PROCESS为一无限循环语句在同一结构体中的任一进程是一个独立的无限循环程序结构进程只有两种运行状态,即执行状态和等待状态 (2) PROCESS中的顺序语句具有明显的顺序/并行运行双重性 [例6.17] SIGNAL sel:STD_LOGIC_VECTOR(3 DOWNTO 0); SIGNAL q:STD_LOGIC_VECTOR(2 DOWNTO 0); PROCESS(sel) VARIABLE so:STD_LOGIC_VECTOR(2 DOWNTO 0); BEGIN CASE sel IS --对sel的值进行判断,执行对应so的赋值语句 WHEN " 0000 " => so:= " 111 " WHEN "0001" => so:="110" WHEN " 0011 " => so:= " 101 " WHEN " 0111 " => so:= " 100 " WHEN " 1111 " => so:= " 011 " WHEN OTHERS => so:= " 000 " ; END CASE; q <=so& " 101 " ; END PROCESS; (3) 进程语句本身是并行语句。
(4) 信号是多个进程间的信息传递通道信号具有全局特性,它是进程间进行并行联系的重要途径在任一进程的进程说明部分不允许定义信号 在PROCESS语句中,信号的赋值不是即时生效,需要等到PROCESS语句执行到最后才会生效,而变量的赋值是及时有效的 §6.2.块.块(BLOCK)语句语句 块(BLOCK)语句是一个并行语句,它把许多并行语句包装在一起组成一个整体,目的是改变并行语句及其结构的可读性,可使结构体层次鲜明、结构明确 与进程语句相比:本身都是并行语句,但进程语句内部由顺序语句构成,块语句内部为并行语句构成 BLOCK语句的书写格式如下: 块标号:BLOCK [(块保护表达式)] {[类属子句 类属端口表;]} <[端口子句 端口端口表;]} <块说明部分> BEGIN <并行语句A> <并行语句B> … END BLOCK [块标号];例6.18所示为一个块语句的半加器VHDL描述实例 §6.3.子程序.子程序(SUBPROGRAM)语句语句 子程序是一个VHDL程序模块。
在一个VHDL的结构体中允许调用多个子程序,这些子程序可以并行运行在子程序模块内部利用顺序语句来定义和完成算法,子程序的使用方式只能通过子程序调用及与子程序的界面端口进行通信 子程序可以在VHDL程序的三个不同位置进行定义,即在程序包、结构体和进程中定义 VHDL子程序具有可重载的特点,即允许有重名的子程序,但这些子程序的参数类型及返回值数据类型是不同的 应该注意,综合后的子程序将映射于目标芯片中的一个相应的电路模块,且每一次调用都将在硬件结构中产生对应于具有相同结构的不同的模块 子程序有过程(PROCEDURE)语句和函数(FUNCTION)语句两种类型 1) 过程(PROCEDURE)语句 过程语句的一般书写格式如下: PROCEDURE 过程名(参数表) --过程声明语句 PROCEDURE 过程名(参数表) IS --过程体语句 [声明语句] BEGIN [顺序处理语句] END PROCEDURE 过程名; 在进程或结构体中的过程不必包含过程声明语句,在程序包中的过程则必须有过程声明语句。
例6.19所示为一个过程语句的示例 PROCEDURE comp ( a:IN STD_LOGIC_VECTOR; b:IN STD_LOGIC_VECTOR; q:OUT BOOLEAN) IS BEGIN IF (a>=b) THEN --如果a大于等于b,则q输出TRUE q:=TRUE; ELSIF (a < b) THEN --如果a小于b,则q输出FALSE q:=FALSE; END IF; END PROCEDURE comp;该过程的调用语句如下: SIGNAL sign:BOOLEAN; comp(“ 1001” ,“ 1100” ,sign); 执行该调用语句后,信号“sign”的值将为“FALSE” 过程调用语句可出现在结构体中,也可在进程之外执行过程调用语句 调用规则如下: (1) 并行过程调用语句是一个完整的语句,在它前面可以加标号 (2) 并行过程调用语句应带“IN”、“OUT”、“INOUT”参数,列于过程名后的括号内。
(3) 并行过程调用可以有多个返回值,这些返回值通过过程中所定义的输出参数返回 VHDL允许对过程进行重载,即两个或两个以上具有互不相同的参数数量或数据类型的过程取相同的过程名称系统通过参量数量和类型来区别用户调用的重载后的过程 例6.20所示是一个重载过程的调用示例[例6.20]PROCEDURE comp ( a,b:IN INTEGER; outl:INOUT BOOLEAN);PROCEDURE comp ( a,b:IN STD_LOGIC_VECTOR (3 DOWNTO 0); outl:INOUT BOOLEAN); comp(25,43,sign); --调用第一个过程comp comp(“ 1001001” ,“ 1001010” ,sign); --调用第二个重载过程comp 2) 函数“FUNCTION” 在VHDL中有多种函数形式,如用于不同目的的用户自定义函数和在库中现成的具有专用功能的预定义函数,如决断函数、转换函数等。
转换函数用于从一种数据类型到另一种数据类型的转换,如在元件例化语句中利用转换函数可允许不同数据类型的信号和端口间进行映射; 决断函数用于在多驱动信号时解决信号竞争问题 函数的语言表达格式如下: FUNCTION 函数名(参数表) RETURN 数据类型; --函数声明语句 FUNCTION 函数名(参数表) RETURN 数据类型 IS --函数体语句 [说明部分] BEGIN 顺序语句; END FUNCTION 函数名; 函数定义由两部分组成,即函数声明语句和函数体语句在进程或结构体中不必包含函数声明语句,而在程序包中必须包含函数声明语句(这时的函数声明就相当于函数的检索,声明该程序包中有对应的函数定义如果要将一个已编制好的函数并入程序包,则函数声明语句必须放在程序包的声明部分,而函数体需放在程序包的包体内如果只是在一个结构体中定义并调用函数,则仅需函数体即可 函数的名称就是函数的标志,需放在关键词FUNCTION之后,此名称可以是普通的标识符,或者是操作符,如果是操作符,则必须在操作符上加双引号,这就是所谓的操作符重载。
操作符重载就是对VHDL中的操作符进行重新定义,使操作符具有新的功能新功能的定义是靠函数体来完成的,函数的参数表是用来定义输入、输出参数的,所以不必设置参数的方向,函数参量可以是信号或常数,参数名需放在关键词CONSTANT或SIGNAL之后如果没有特别说明,则参数被默认为常数 FUNCTION 函数名(参数表) RETURN 数据类型; --函数声明语句 FUNCTION 函数名(参数表) RETURN 数据类型 IS --函数体语句 [说明部分] BEGIN 顺序语句; END FUNCTION 函数名; 例6.21所示为一个完整的实现逻辑矢量大小比较功能的函数定义语句 [例6.21] FUNCTION comp (a,b:IN STD_LOGIC_VECTOR) RETURN BOOLEAN; FUNCTION comp (a,b:IN STD_LOGIC_VECTOR) RETURN BOOLEAN IS BEGIN IF (a>=b) THEN --如果a大于等于b,则q输出TRUE RETURN TRUE; ELSIF (a < b) THEN --如果a小于b,则q输出FALSE RETURN FALSE; END IF; END FUNCTION comp; 该函数的调用语句如下: SIGNAL result:BOOLEAN; result<=comp("1001","1101"); 函数的调用方式与过程完全不同。
函数的调用是将所定义的函数作为语句中的一个因子,如一个操作数或一个赋值数据对象或信号等,而过程的调用是将所定义的过程名作为一条语句来执行 VHDL允许重载函数,即用相同的函数名定义函数,但重载函数中定义的参数必须有不同的数据类型,以便调用时用以分辨不同功能的同名函数 VHDL的IEEE库中的STD_LOGIC_UNSIGNED程序包中预定义的操作符如“+”、“-”、“*”、“=”、“>=”、“<=”、“>”、“<”、“/=”、“AND”和“MOD”等,对相应的数据类型“INTEGRE”、“STD_LOGIC”和“STD_LOGIC_VECTOR”的操作作了重载,赋予了新的数据类型操作功能,即通过重新定义操作符的方式,允许被重载的操作符能够对新的数据类型进行操作,或者允许不同的数据类型之间用此操作符进行操作 §6.4.断言.断言(ASSERT)语句语句 断言语句主要用于程序仿真与调试中的人机会话在仿真、调用过程中出现问题时,给出一个文字串作为提示信息提示信息分4类:失败(FAILURE)、错误(ERROR)、警告(WARNING)和注意(NOTE) 断言语句的书写格式如下: ASSERT 条件[REPORT报告信息] [SEVERITY出错级别]; 断言语句的使用规则如下; (1) 报告信息必须是用双引号括起来的字符串类型的文字。
(2) 出错级别必须是SEVERITY_LEVEL类型 (3) REPORT子句默认时,默认报告信息为ASSERTION VIOLATION,即违背断言条件 (4) 若SEVERITY子句默认,则默认出错级别为ERROR (5) 任何并行断言(ASSERT)语句的条件以表达式定义时,这个断言语句等价于一个无敏感信号的以WAIT语句结尾的进程它在仿真开始时执行一次,然后无限等待下去 (6) 延缓的并行断言(ASSERT)语句被映射为一个等价的延缓进程 (7) 被动进程语句没有输出,与其等价的并行断言语句的执行在电路模块上不会引起任何事情的发生8) 若断言为FALSE,则报告错误信息 (9) 并行断言语句可以放在实体、结构体和进程中,放在任何一个要观察、要调试的点上 §6.5.信号赋.信号赋值值(SIGNAL ASSIGNMENT)语语句句 赋值语句是VHDL的基本语句之一,其功能就是将一个值或一个表达式的运算结果传递给某一数据对象,当数据对象是信号时,赋值的过程是并行的 并行信号赋值语句的一般书写格式如下: 信号量<=信号量表达式; 常用的信号赋值语句有3种形式:简单信号赋值语句、条件信号赋值语句和选择信号赋值语句。
1) 简单信号赋值语句 代入符号右边的表达式可以是逻辑运算表达式、算术运算表达式和关系比较表达式 信号赋值语句允许的信号赋值目标有 标识符赋值目标、 数组单元素赋值目标、 段下标元素赋值目标和 集合块赋值目标等 (1) 标识符赋值目标标识符赋值目标是以简单的标识符作为被赋值的信号或变量名 例6.22所示就是并行信号赋值语句对标志符赋值的一个简单例子 [例6.22] ENTITY and2 IS PORT( a,b:IN STD_LOGIC; q:OUT STD_LOGIC); END ENTITY and2; ARCHITECTURE behav OF and2 IS q<=a AND b; END ARCHITECTURE; (2) 数组单元素赋值目标数组单元素赋值目标的表达形式如下: 数组类信号或变量名(下标名) 下标名可以是一个具体的数字,也可以是一个文字表示的数字名,它的取值范围在该数组元素个数范围内。
例如: SIGNAL a: STD_LOGIC_VECTOR(7 DOWNTO 0); a(1)<='1';是给8位矢量a中下标为1的位赋值为“1” (3) 段下标元素赋值目标和集合块赋值目标段下标元素赋值目标可用以下方式表示: 数组类信号(下标l TO/DOWNTO 下标2) 括号中的下标1和下标2必须用具体数值表示,并且其数值范围必须在所定义的数组下标范围内 例如: SIGNAL a:STD_LOGIC_VECTOR(7 DOWNTO 0); a(0 TO 3)<= “1100”;集合块赋值目标用于一次对集合块的全部内容进行赋值,例如: (second, minute, hour):=(45, 30, 8); 2) 条件信号赋值语句 条件信号赋值语句的格式如下: 目标信号<= 赋值l WHEN 条件1 ELSE 赋值2 WHEN 条件2 ELSE 赋值3 WHEN 条件3 ELSE … 赋值n WHEN 条件n ELSE 赋值n+1;例6.22所示为采用条件信号赋值语句描述一个8选1多路选通器的例子。
3) 选择信号赋值语句 选择信号赋值语句用于通过选择信号的值控制目标信号,其格式如下: WITH 表达式 SELECT 目标信号<=赋值1 WHEN 选择信号的值1 , 赋值2 WHEN 选择信号的值2, 赋值3 WHEN 选择信号的值3 , … 赋值n WHEN 选择信号的值n , 赋值n+1 when others;例6.23所示就是采用选择信号赋值语句对8选1多路选通器的描述,其功能与例6.22所示的完全相同 §6.6.参数传递.参数传递(GENERIC)语句语句 参数传递(GENERIC)语句用不同层次设计模块之间信息的传递和参数的传递,可用于位矢量的长度、数组的位长、器件的延时时间等参数的传递这些参数实际上都是整数类型,其他数据类型不能综合 使用GENERIC语句易于使器件模块化和通用化。
例6.24所示为使用参数传递语句的一个实例§6.7.通用模块与元件调用通用模块与元件调用(COMPONENT)语句语句 通用模块与元件的调用又称元件例化,就是将预先设计好的设计实体定义为一个元件,然后利用特定的语句将此元件与当前的设计实体中的指定端口相连接,从而为当前设计实体引入一个新的低一级的设计层次调用通用模块与元件类似于在图形输入方法中调用元件图形符号,可以使VHDL设计实体构成自上而下层次化,是自上而下分层设计的一种重要途径 通用模块和元件的调用与在一个结构体中调用子程序非常类似,但是也有明显的区别调用子程序是在同一层次内进行的,并没有因此而增加新的电路层次而元件的调用是多层次的,在一个设计实体中,被调用安插的元件本身也可以是一个低层次的当前设计实体,因而可以调用其他的元件,以便构成更低层次的电路模块因此,元件调用就意味着在当前结构体内定义了一个新的设计层次这个设计层次的总称叫元件,但它可以以不同的形式出现如上所述,这个元件可以是已设计好的一个VHDL设计实体,可以是来自FPGA元件库中的元件,也可以是别的硬件描述语言(Verilog HDL)设计实体该元件还可以是软IP核,或者是FPGA中的嵌入式硬IP核。
元件例化语句由两部分组成:前一部分是将一个现成的设计实体定义为一个元件的语句;第二部分则是此元件与当前设计实体中的端口映射说明以上两部分语句在元件例化中都是必须存在的 元件定义语句如下: COMPONENT 元件名 IS GENERIC(类属表) PORT(元件端口表) END COMPONENT 元件名; 元件的调用采用端口映射方式,端口映射语句的格式如下:元件对象名称:元件名 PORT MAP(元件端口名=>连接对象端口名,…); 元件定义语句: 相当于对一个现成的设计实体进行封装,使其只留出外面的接口界面 类属表可列出端口的数据类型和参数, 例化元件端口名表可列出对外通信的各端口名 元件定义语句可认为是某一型号元件的对外接口,可理解为电路设计中的集成块的型号、引脚说明,元件名就对应于集成块的型号,PORT端口表就是集成块的引脚列表 元件定义语句如下: COMPONENT 元件名 IS GENERIC(类属表) PORT(元件端口表) END COMPONENT 元件名; 元件调用端口映射语句: 元件对象名是必须存在的,综合程序需要靠元件对象名来区别同一元件的不同对象,该名称类似于电路原理中的元件编号,在同一个电路中可能有很多同一种型号的元件,为了区别它们,在绘制电路图时会给这些同型号的元件进行编号,例如用R1、R2等对电阻进行编号。
在VHDL中,采用元件对象名来区别多次调用的同一种型号的元件 元件名则是已定义好的元件的名称该名称类似于电路中的元件型号 PORT MAP是端口映射的意思,其中的例化元件端口名是在元件定义语句中的端口名表中已定义好的例化元件端口的名字,连接对象端口名则是当前系统与准备接入的例化元件对应端口相连的通信端口,类似于电路图设计中的网络列表 元件对象名称:元件名 PORT MAP(元件端口名=>连接对象端口名,…); 元件调用语句中所定义的例化元件的端口名与当前系统的连接实体端口名的接口表达有两种方式: 一种是名字关联方式,在这种关联方式下,例化元件的端口名和关联(连接)符号“=>”两者都是必须存在的,这时例化元件端口名与连接实体端口名的对应式在PORT MAP句中的位置可以是任意的; 另一种是位置关联方式,若使用这种方式,端口名和关联连接符号都可省去,在PORT MAP子句中,只要列出当前系统中的连接实体端口名就行了,但要求连接实体端口名的排列方式与所需例化的元件端口定义中的端口名一一对应 例6.25所示的就是一个使用元件调用语句的简单例子。
§6.8.生成.生成(GENERATE)语句语句 生成(GENERATE)语句用来产生多个相同的结构和描述规则结构,如块、元件调用或进程生成语句可以简化有规则设计结构的逻辑描述GENERATE语句有两种形式 1) FOR-GENERATE形式 FOR-GENERATE形式的生成语句的书写格式如下: 标号:FOR 循环变量 IN 连续区间 GENERATE <说明语句> BEGIN <并行生成语句> END GENERATE [标号名]; FOR-GENERATE形式的生成语句用于描述多重模式结构中所列举的是并行处理语句这些语句是并行执行的,而不是顺序执行的,因此结构中不能使用EXIT语句和NEXT语句 2) IF-GENERATE形式 IF-GENERATE形式的生成语句的一般书写格式如下: 标号:IF 条件 GENERATE <说明语句>BEGIN <并行生成语句> END GENERATE [标号名]; IF-GENERATE形式的生成语句用于描述结构的例外情况,如边界处发生的特殊情况 IF-GENERATE语句在IF条件为“真”时,才执行结构体内部的语句,因为是并行处理生成语句,所以与IF语句不同。
在这种结构中不能含有ELSE语句这两种语句格式都是由如下四部分组成的 (1) 生成语句头:有FOR语句结构或IF语句结构,用于规定并行语句的复制方式 (2) 说明部分:包括对元件数据类型、子程序和数据对象做一些局部说明 (3) 并行生成语句:用来复制的基本单元,主要包括元件、进程语句、块语句、并行过程调用语句、并行信号赋值语句甚至生成语句这表示生成语句允许存在嵌套结构,因而可用于生成元件的多维阵列结构 (4) 标号:生成语句中的标号并不是必需的,但如果在嵌套生成语句结构中就是很重要的 GENERATE语句典型的应用包括计算机存储阵列、寄存器阵列和仿真状态编译机例6.26所示即为生成语句的应用示例ENTITY counter IS PORT (clk,carry:IN STD_LOGIC; dout:OUT STD_LOGIC_VECTOR(7 DOWNTO 0) );END ENTITY counter;ARCHITECTURE stru OF counter IS COMPONENT tff is PORT (clk, t:STD_LOGIC; q:STD_LOGIC); END COMPONENT tff; COMPONENT and2 is PORT(a, b:STD_LOGIC; C: OUT BIT); END COMPONENT and2;SIGNAL s: BIT_VECTOR(7 DOWNTO 0);SIGNAL tied_high: BIT:=‘1’; BEGIN g1: FOR i IN 7 DOWNTO 0 GENERATE g2:IF i=7 GENERATE tff_7:tff PORT MAP (clk, s(i-1), dout(i)); END GENERATE g2; g3:IF i=0 GENERATE tff_0: tff PORT MAP (clk, tied_high, dout(i)); s(i) <= dout(i); END GENERATE g3; g4: IF i>0 AND i<7 GENERATE and_1: and2 PORT MAP (s(i-l), dout(i), s(i)); tff_1: tff PORT MAP (clk, s(i-1), dout(i)); s(i) <= dout(i); END GENERATE g4; END GENERATE g1; END ARCHITECTURE stru; 。









![2019版 人教版 高中语文 必修 上册《第一单元》大单元整体教学设计[2020课标]](http://img.jinchutou.com/static_www/Images/s.gif)


