430 likes | 537 Views
第五章 并行语句 ( Concurrent ). 并行语句 1. 构造体. signal. 并行语句 2. signal. 并行语句 3. 并行语句. VHDL 语言与传统软件描述语言最大的不同 有多种语句格式,包括:并行信号赋值语句、进程语句、块语句、并行过程调用语句、 元件例化语句、生成语句 各种并行语句在结构体中的执行是同步进行的,或者说是并行运行的,其执行方式与书写的顺序无关。 在执行中,并行语句之间可以有信息往来,也可以是互为独立、互不相关、异步运行的 ( 如多时钟情况 ) 。
E N D
第五章 并行语句(Concurrent) 并行语句1 构造体 signal 并行语句2 signal 并行语句3
并行语句 • VHDL语言与传统软件描述语言最大的不同 • 有多种语句格式,包括:并行信号赋值语句、进程语句、块语句、并行过程调用语句、 元件例化语句、生成语句 • 各种并行语句在结构体中的执行是同步进行的,或者说是并行运行的,其执行方式与书写的顺序无关。 • 在执行中,并行语句之间可以有信息往来,也可以是互为独立、互不相关、异步运行的(如多时钟情况)。 • 每一并行语句内部的语句运行方式可以有两种不同的方式,即并行执行方式(如块语句)和顺序执行方式(如进程语句)。
s 2 a x b mux c d 一、并行信号赋值语句 • 1、简单并行信号赋值语句 • 信号 <=表达式;y <= a OR b OR c; • x <=(a AND NOT(s(1)) AND NOT(s(0))) OR (b AND NOT(s(1)) AND s(0)) OR (c AND s(1) AND NOT(s(0))) OR (d AND s(1) AND s(0)) ;
2、条件信号赋值语句( When_Else) • 格式:目的信号量<=表达式1 WHEN 条件1 • ELSE 表达式2 WHEN 条件2 • ELSE 表达式3 WHEN 条件3 • : • ELSE 表达式n; • 根据指定条件对信号赋值,条件可以为任意表达式 • 根据条件的出现的先后次序隐含优先权 • 最后一个 ELSE子句隐含了所有未列出的条件 • 每一子句的结尾没有标点,只有最后一句有分号
隐含了优先权 隐含了所有未列出的条件 s 2 a x b mux c d When_Else语句举例 x <= a when (s = “00”) else b when (s = “01”) else c when (s = “10”) else d ;
允许有多个控制信号 When_Else语句举例 j <= w when (a = ‘1’) else x when (b = ‘1’) else y when (c = ‘1’) else z when (d = ‘1’) else ‘0’ ;
优先级编码器 encode <= “111” when D(7) = ‘1’ else “110” when D(6) = ‘1’ else “101” when D(5) = ‘1’ else “100” when D(4) = ‘1’ else “011” when D(3) = ‘1’ else “010” when D(2) = ‘1’ else “001” when D(1) = ‘1’ else “000” when D(0) = ‘1’ else “000”;
3、选择信号赋值语句 (With_Select_Then) WITH 表达式样 SELECT 目的信号量<=表达式1 WHEN 条件1, 表达式2 WHEN 条件2, : 表达式n WHEN 条件n; • 所有的“WHEN”子句必须是互斥的 • 一般用 “When Others”来处理未考虑到的情况 • 只有一个参考信号和赋值符 (<=) • 每一子句结尾是逗号,最后一句是分号
s 2 a x b mux c d 加Others语句 With_Select_Then语句举例 LIBRARY ieee; USE ieee.std_logic_1164.all; ENTITY cmpl_sig IS PORT ( a, b,c,d,s : IN STD_LOGIC; x : OUT STD_LOGIC); END cmpl_sig; ARCHITECTURE logic OF cmpl_sig IS BEGIN WITH s SELECT x <=a WHEN “00”, b WHEN “01”, c WHEN “10”, d WHEN OTHERS;
With_Select_Then语句举例 • 每个WHEN子句可以包含多个条件: WITH s SELECT x <= a WHEN ”000” | “001” | “010”, b WHEN "101" | "111", c WHEN OTHERS;
并行语句中的条件赋值语句和选择赋值语句分别等价于只含有条件结构(if)和选择结构(case)的进程。并行语句中的条件赋值语句和选择赋值语句分别等价于只含有条件结构(if)和选择结构(case)的进程。 • 要注意并行语句中没有if和case语句的形式,而条件赋值和选择赋值语句也只能出现在Architecturehe和block结构中,而不能出现在进程和子程序。
二、进程语句 • VHDL中最重要的语句,具有并行和顺序行为的双重性 • 进程和进程语句之间是并行关系 • 进程内部是一组连续执行的顺序语句 • 进程语句与构造体中的其余部分进行信息交流是靠信号完成的 [进程标号:] PROCESS [(信号敏感表)] IS 〈说明区〉BEGIN 〈顺序语句〉END PROCESS [进程标号];
ARCHITECTURE 一个构造体可以有多个进程语句 PROCESS1 进程和进程之间是并行的 进程和进程之间的数据交换通过信号完成 进程内部是顺序语句 signal signal PROCESSn 进程语句
2. 进程的激活与挂起 进程有两种状态:激活与挂起。 如果当前正在执行某个进程,我们则说该进程是活跃的,否则说该进程被挂起。 每个进程可以在任何时刻被激活,所有被激活的进程并行执行。整个运行过程中激活与挂起交替进行,直到运行结束。
进程的激活与挂起由等待语句wait控制。 • 运行开始(初始化)时,所有进程均被激活,并执行。当执行到等待语句时,进程挂起。当等待语句条件满足时,进程再次被激活,并从等待语句处接着运行,直到遇到下一个等待语句,进程再次被挂起如此循环反复,直到运行结束。VHDL规定,当执行完最后一条语句后,返回第一条语句接着执行。 若无等待语句,则有一个敏感信号表,敏感信号的变化激活该进程,并从第一条语句继续执行。当执行到最后一条语句时,进程挂起,等待敏感信号的变化。 进程挂起时,进程中的信号、变量的状态保持不变。
对含有敏感信号表的进程,其执行过程相当于进程末尾有一个关于敏感信号的wait语句。下面的两个进程是等价的:process (A, B)beginOutput <= A or B;end process;processbeginOutput <= A or B;wait on A, B;end process; · 若有敏感信号指定,则不能有wait语句。· 各进程之间并行执行,与描述中出现的顺序无关。· 各进程内部顺序执行。
信号敏感表 • 进程赖以启动的敏感表。对于表中列出的任何信号的改变,都将启动进程,执行进程内相应顺序语句 • 一些VHDL综合器,综合后,对应进程的硬件系统对进程中的所有输入的信号都是敏感的,不论在源程序的进程中是否把所有的信号都列人敏感表中 • 为了使软件仿真与综合后的硬件仿真对应起来,应当将进程中的所有输人信号都列入敏感表中
进程的运行依赖于敏感表内参数的变化 两个进程是并发的 进程语句举例 case_label: PROCESS(a, b, c, d, sel)BEGINCASE sel ISWHEN "00" =>z <= a;WHEN "01" =>z <= b;WHEN "10" =>z <= c;WHEN "11" =>z <= d;WHENOTHERS =>z <= '0';ENDCASE;ENDPROCESS case_label;END logic; LIBRARY ieee; USE ieee.std_logic_1164.all; ENTITY if_case IS PORT ( a, b, c, d : IN Std_Logic; sel : IN Std_Logic_Vector(1 downto 0); y, z : OUT Std_Logic); END if_case; ARCHITECTURE logic OF if_case IS BEGIN if_label: PROCESS(a, b, c, d, sel) BEGIN IF sel="00" THEN y <= a; ELSIF sel="01" THEN y <= b; ELSIF sel="10" THEN y <= c; ELSE y <= d; END IF; END PROCESS if_label;
仿真结果错误 敏感表举例 latchlabel: PROCESS(oe) BEGIN IF oe=‘1’ THEN y <= a; END IF; END PROCESS if_label;
仿真结果正确 敏感表举例 latchlabel: PROCESS(oe,a) BEGIN IF oe=‘1’ THEN y <= a; END IF; END PROCESS if_label;
三、 块( BLOCK) 一个大规模的电原理图通常可以分割成多张子原理图,以便于设计和存档。同样,在VHDL程序设计中,结构体对应整个电原理图,而结构体可由多个BLOCK块组成,每一个BLOCK块则对应一张子原理图。电原理图的分割关系和VHDL程序中用BLOCK块分割结构体的关系是一一对应的。 BLOCK语句的语法格式为: 块标号:BLOCK [(块保护表达式)] [说明语句]; BEGIN [并行语句]; END BLOCK 标号名; • 保护表达式是可选项,它是一个布尔表达式。保护表达式的作用是:只有当其为真时,该块中的语句才被启动执行;否则,该块中的语句不被执行。 • BLOCK语句中所描述的各个语句是可以并行执行的,它和书写顺序无关。
u1 tmp1 d0 u3 q tmp3 d1 tmp2 u2 sel 2选1 数据选择器 例: 用BLOCK语句描述2选1电路的程序。 ENTITY mux2_1 IS PORT(d0, d1, sel : IN STD_LOGIC; q : OUT STD_LOGIC); END mux2_1; ARCHITECTURE amux OF mux2_1 IS SIGNAL tmp1,tmp2,tmp3 : STD_LOGIC; BEGIN cale: BLOCK BEGIN tmp1<=d0 AND sel; tmp2<=d1 AND (not sel); tmp3<=tmp1 OR tmp2; q<=tmp3; END BLOCK cale; END amux; 上述结构体中只有一个 BLOCK块,若电路复杂时可由几个BLOCK块组成。
四、并行过程调用语句 • 并行过程调用语句的形式与顺序调用语句相同。 并行过程调用语句等价于一个进程,其中含有相同形式的顺序调用语句,敏感信号为输入参数的信号。 由于并行过程调用语句只出现在结构体中和块结构中,因而输入输出实际参数中不能有变量。
五、元件例化语句 • 一个实体的结构体中引用某些元件,称为元件例化(Component instantiation),用元件例化语句表示。该元件称为实例元件或例化元件(instance)。各元件例化语句的执行顺序与书写顺序无关。
1. 元件声明——声明要调用某种模型的元件 • 要引用的元件必须预先声明,称为元件声明。元件声明通常放在该结构体的声明部分,也可以放在一个程序包中。 元件声明指明了所引用元件的类属参数与端口的声明,但并不明确指定是哪个实体,不指定内部的功能或结构。因而,元件声明只是一个虚拟的元件模型。元件例化语句指定一个实例元件对应哪个元件模型。当然,还需要在指定实例元件或元件模型与哪个实体相对应。这需要配置指定语句或配置声明单元来实现,我们在本节后面将详细说明。
component元件模型名port (输入端口表:[in] 类型;… )endcomponent;元件声明中的端口声明与实体声明中的端口声明格式相同。例如:component And2port(I1, I2:Bit;O1: out Bit);end component;
2. 元件例化语句──用来引用元件的并行语句 • 当一个实体引用一个元件时,使用元件例化语句。元件例化语句指定该实例元件对应的元件模型,并且指定了元件模型端口与实体中信号的关联关系。 元件例化语句的一般格式是: 标号标识符: 元件符号port map关联表;
package Comp_decls iscomponent And2port(Il, I2: Bit; • O1: out Bit);end eompanentend Comp_decls;use Work.Comp_decls;architecture Parent_body of Parent issignal S1,S2,S3:Bit; begin: Child:And2port map(I1=>S1,I2=>S2,O1=>S3);end Parent_body;
1. 语句标号不可缺,作为实例元件名。 • 2. 参数关联指定和端口联接指定要与component中指定的参数与端口相对应。 • 3. 元件例化语句为并行语句,不能出现在进程和子程序中。
3. 关联指定 • ·元件声明中的端口称为局部端口。在元件例化语句中,端口关联表必须将每个局部端口与实际对象联系起来。这个实际对象必须是信号类型,可以有以下两种情况:·实际对象是已被声明的信号。可以在程序包中、结构体中或实体声明中被声明。·实际对象是已在实体声明中被声明的形式端口,该实体声明必须与包含此元件例化语句的结构体相对应。
关联表中的端口对应关系有下面几种情况:◇位置对应:port map (X, Y, Out1, Out2); • ◇显式指定:port map (a =>X, c=> Out1, b=>Y, d=>Out2)。 • 其中符号“=>”左边为元件声明中指定的端口信号。 • ◇混合指定:port map (X, c=>Out1, b=>Y, d=>Out2)。 • 前面用位置对应,后面用显式指定。一旦有一个显式指定,则后面不能再出现位置对应指定。VHDL对于实际对象和局部端口之间的关联施加以下3种限制: ◇数据类型一致。 ◇数据流方向一致(或不冲突)。 • 例如,一个模式为in的实际对象不能与一个模式为out或inout的局部端口相关联。
六、生成语句 • 生成语句是规则结构并行语句的简写形式。共有两种形式,if和for。IF生成语句: 标号:if生成条件 generate 并行语句;end generate 标号;FOR生成语句: 标号:for生成标识符 in离散范围 generate 并行语句;end generate标号;
IF形式中,生成条件是一个条件表达式,其中有一个控制变量,条件表达式决定该控制变量的离散范围。其中的并行语句中利用该控制变量作为参数。IF形式中,生成条件是一个条件表达式,其中有一个控制变量,条件表达式决定该控制变量的离散范围。其中的并行语句中利用该控制变量作为参数。 • FOR形式中,生成标识符是控制变量,并在关键字in后显式指定其离散范围。带有控制变量的并行语句可以看成将离散范围中各个离散值分别代入控制变量而得到的并行语句的集合。这些并行语句不受顺序的影响。 • 注意IF和FOR的生成语句不是语句顺序的控制结构,与顺序语句中用的IF和For…loop完全不同。
G3: if I=0 generateTFF_0: TFF portmap (CLK, Tied_High, Dout(I));S(I) <= Dout(I); endgenerate; --等价于:TFF_0: TFF portmap (CLK, Tied_High, Dout(0)); -- S(0) <= Dout(0);G4: if I>0 and I<7 generate -- I = 1,2,3,4,5,6And_1: And2 portmap (S(I-1), Dout(I), S(I));TFF_1: TFFportmap (CLK, S(I-1), Dout(I));S(I) <= Dout(I);endgenerate • endgenerate; • end Counter; entity Cunter isport (CLK, Carry: Bit; Dout: buffer Bit_Vector(7 downto 0));end Cunter;architecture Counter of Counter iscomponent TFF port (CLK, T:Bit; Q: buffer Bit); endcomponent;component And2 port(I1, I2: Bit; O1: out Bit);endcomponent;signal S: Bit_Vector(7 downto 0);signal Tied_High: Bit:='1';beginG1: for I in 7 downto 0 generateG2: if I=7 generateTFF_7: TFF portmap (CLK, S(I-1), Dout(I)); endgenerate --等价于:TFF_7: TFF portmap (CLK, S(6), Dout(7));
-- 等价于:-- And_1: And2 portmap (S(0), Dout(1), S(1)); -- And_2: And2 portmap (S(1), Dout(2), S(2)); -- And_3: And2 portmap (S(2), Dout(3), S(3)); -- And_4: And2 portmap (S(3), Dout(4), S(4)); -- And_5: And2 portmap (S(4), Dout(5), S(5)); -- And_6: And2 portmap (S(5), Dout(6), S(6)); -- TFF_1: TFF portmap (CLK, S(0), Dout(1)); -- TFF_2: TFF portmap (CLK, S(1), Dout(2)); -- TFF_3: TFF portmap (CLK, S(2), Dout(3)); -- TFF_4: TFF portmap (CLK, S(3), Dout(4)); -- TFF_5: TFF portmap (CLK, S(4), Dout(5)); -- TFF_6: TFF portmap (CLK, S(5), Dout(6)); -- S(1) <= Dout(1); -- S(2) <= Dout(2); -- S(3) <= Dout(3); -- S(4) <= Dout(4); -- S(5) <= Dout(5); -- S(6) <= Dout(6);
上面的描述等价于下面的描述: architecture Counter of Counter iscomponent TFF port (CLK, T:Bit; Q: buffer Bit); endcomponent;component And2 port(I1, I2: Bit; O1: out Bit);endcomponent;signal S: Bit_Vector(7 downto 0);signal Tied_High: Bit:='1';beginTFF_0: TFF port map (CLK, Tied_High, Dout(0));TFF_1: TFF port map (CLK, S(0), Dout(1));TFF_2: TFF port map (CLK, S(1), Dout(2));TFF_3: TFF port map (CLK, S(2), Dout(3));TFF_4: TFF port map (CLK, S(3), Dout(4));TFF_5: TFF port map (CLK, S(4), Dout(5));TFF_6: TFF port map (CLK, S(5), Dout(6));TFF_7: TFF port map (CLK, S(6), Dout(7));S(0) <= Dout(0);S(1) <= Dout(1);S(2) <= Dout(2);S(3) <= Dout(3);S(4) <= Dout(4);S(5) <= Dout(5);S(6) <= Dout(6);And_1: And2 port map (S(0), Dout(1), S(1));And_2: And2 port map (S(1), Dout(2), S(2));And_3: And2 port map (S(2), Dout(3), S(3));And_4: And2 port map (S(3), Dout(4), S(4));And_5: And2 port map (S(4), Dout(5), S(5));And_6: And2 port map (S(5), Dout(6), S(6));end Counter;
〖本章小结〗 • 本章以较大的篇幅介绍硬件描述语言VHDL。VHDL与常见的程序语言不同,它是用来描述硬件的设计的。VHDL是IEEE颁布的国际通用的硬件描述语言标准之一。VHDL既能描述硬件的结构,也能描述硬件的行为。它涵盖了常用程序设计语言的几乎所有的语言结构,同时为了描述硬件的需要,增加了关于描述硬件模块化、层次化结构所需要的并行语句部分。VHDL的描述是一些实体的集合,每个实体含有一个实体声明和多个结构体,每个结构体分别表示该硬件的一种行为的或结构的实现。结构体中包含有进程语句、简单并行语句、例化语句、块语句和生成语句。这些语句都是并行执行的,执行顺序与书写的顺序无关,它们靠信号来互相联系。进程是由若干顺序语句组成的一段完整的程序,这些语句顺序执行。 进程有激活和挂起两种状态。在挂起状态下,所有的内部状态包括变量值、运行中的语句位置、循环的计数等都保持不变,待激活时接着运行。我们可以认为进程在运行过程中时不停止的。因此进程中的变量初值只在启动时赋值一次。 信号是进程与进程之间、进程与其他并行语句之间交换数据的数据通路。信号只能在端口中、结构体内和块结构内定义,而不能在进程内部定义。有些公共信号也能在各实体使用的程序包中定义。一般来说,变量只能在进程和子程序中定义,而不能在进程之外定义。信号的赋值有延时特性,而变量在执行赋值语句之后立即得到其新值。关于信号,还有事项处理和事件的概念,它们决定描述程序的运行过程。读者一定要把进程和信号的概念搞清楚,这是掌握VHDL语言的关键。 硬件的层次化结构是通过配置来实现的。配置将一个结构体中的实例语句、元件模板与真正的实体结合起来,形成层次化结构。 限于篇幅,本书介绍的只是VHDL语言最基本的部分,着重于讲清概念,掌握硬件描述语言的特点。更详细的语法要求请参看VHDL参考手册。同时对于设计者来说,仅仅掌握其语法的要求还是不够的,请参阅有关指导描述具体硬件的使用书籍,设计者也可以在实践过程中,逐步掌握其描述方法。 读者可以参考第8章,通过利用实际EDA工具,掌握本章的内容。但要注意,所有的EDA工具几乎都只能提供VHDL的一个子集。尤其对于综合工具来说,有些语句或部分特性是不能综合的。各工具所能综合的子集也都不相同。读者在使用这些工具时,一定要参考这些工具的参考手册,或者借助于这些工具中的帮助,避免使自己的描述超出规定范围。
第六章VHDL语言的描述风格 • 有三种描述方式:行为描述,RTL描述和ASIC描述
1、行为描述 • PROCESS (clock, clear) BEGIN IF clear = ‘0’ THEN q <= 0; ELSIF clock’EVENT and clock = ‘1’ THEN q <= q+1; END IF; END PROCESS;
2、数据流描述方式 • y <= a OR b OR c; • x <=(a AND NOT(s(1)) AND NOT(s(0))) OR (b AND NOT(s(1)) AND s(0)) OR (c AND s(1) AND NOT(s(0))) OR (d AND s(1) AND s(0)) ;
G3: if I=0 generateTFF_0: TFF portmap (CLK, Tied_High, Dout(I));S(I) <= Dout(I); endgenerate; --等价于:TFF_0: TFF portmap (CLK, Tied_High, Dout(0)); -- S(0) <= Dout(0);G4: if I>0 and I<7 generate -- I = 1,2,3,4,5,6And_1: And2 portmap (S(I-1), Dout(I), S(I));TFF_1: TFFportmap (CLK, S(I-1), Dout(I));S(I) <= Dout(I);endgenerate • endgenerate; • end Counter; entity Cunter isport (CLK, Carry: Bit; Dout: buffer Bit_Vector(7 downto 0));end Cunter;architecture Counter of Counter iscomponent TFF port (CLK, T:Bit; Q: buffer Bit); endcomponent;component And2 port(I1, I2: Bit; O1: out Bit);endcomponent;signal S: Bit_Vector(7 downto 0);signal Tied_High: Bit:='1';beginG1: for I in 7 downto 0 generateG2: if I=7 generateTFF_7: TFF portmap (CLK, S(I-1), Dout(I)); endgenerate --等价于:TFF_7: TFF portmap (CLK, S(6), Dout(7));
architecture Counter of Counter iscomponent TFF port (CLK, T:Bit; Q: buffer Bit); endcomponent;component And2 port(I1, I2: Bit; O1: out Bit);endcomponent;signal S: Bit_Vector(7 downto 0);signal Tied_High: Bit:='1';beginTFF_0: TFF port map (CLK, Tied_High, Dout(0));TFF_1: TFF port map (CLK, S(0), Dout(1));TFF_2: TFF port map (CLK, S(1), Dout(2));TFF_3: TFF port map (CLK, S(2), Dout(3));TFF_4: TFF port map (CLK, S(3), Dout(4));TFF_5: TFF port map (CLK, S(4), Dout(5));TFF_6: TFF port map (CLK, S(5), Dout(6));TFF_7: TFF port map (CLK, S(6), Dout(7));S(0) <= Dout(0);S(1) <= Dout(1);S(2) <= Dout(2);S(3) <= Dout(3);S(4) <= Dout(4);S(5) <= Dout(5);S(6) <= Dout(6);And_1: And2 port map (S(0), Dout(1), S(1));And_2: And2 port map (S(1), Dout(2), S(2));And_3: And2 port map (S(2), Dout(3), S(3));And_4: And2 port map (S(3), Dout(4), S(4));And_5: And2 port map (S(4), Dout(5), S(5));And_6: And2 port map (S(5), Dout(6), S(6));end Counter;