END IF;
END PROCESS;
在敏感信号表中,信号Rd,CLK被列为敏感信号,当此两个信号只要有一个发生变化时, 此进程就被执行。注意EN并没有被列入敏感表,这是因为EN起作用必须发生在时钟的上升沿这时CLK必定发生变化,引起进程的执行。同样,若为同步清零,敏感表中可无Rd信号,
此时进程如下:
PROCESS ( CLK ) --进程(敏感信号表) BEGIN
IF (CLK. EVENT AND CLK=.1.) THEN IF (Rd=.0.) THEN Q<= “0000”; ELSIF (EN=.1.) then Q <= Q+1; ENDIF; END IF;
END PROCESS; 小提示:
一个结构体可以包含多个进程,他们之间是并行执行的,但是进程结构中的语句是顺 序执行的。进程间通过信号来实现通信,进程信号的赋值语句是顺序执行的,但是赋 值是最后并行执行的。
1.4.2 元件(COMPONET)定义语句和元件例化(PORT MAP)语句
在VHDL程序设计中,一个完整的VHDL设计程序包括实体和结构体,实体提供设计单 元的端口信息,结构体描述设计单元的结构和功能,设计程序通过综合、仿真等一系列操作 后,其最终的目的是得到一个具有特定功能的电路元件,因此,把这种设计好的程序定义为 一个元件。这种元件可以是一个描述简单门电路的程序,也可以是一个描述一位全加器的程 序,或者是其他复杂电路的描述。这些元件设计好后保存在当前工作目录中,其他设计体可 以通过元件例化的方法调用这些元件。 小提示:
当前设计实体相当于一个较大(较大时相比于以前设计的实体而言)的电路系统,所 声明的例化元件相当于系统板上的芯片,而当前设计实体的“端口”相当于要插入这 个电路这块电路板上准备接受此芯片的一个插座。
元件(COMPONET)定义语句和元件例化(PORT MAP)语句就是用于在一个结构体 中定义元件和实现元件调用的两条语句,两条语句分别放在一个结构体中的不同的位置,元 件定义(COMPONET)语句放在结构体的ARCHITECTURE和BEGIN之间,指出该结构体调用哪一个具体的元件,元件调用时必须要进行数据交换,元件例化语句中的PORT MAP 是端口映射的意思,表示结构体与元件端口之间交换数据的方式。其语法结构格式为: (1)元件定义(COMPONET)语句的格式为: COMPONENT 元件名称 IS
GENERIC 常量定义信息 (同该元件源程序实体中的GENERIC部分) PORT 元件端口信息(同该元件源程序实体中的PORT部分) END COMPONET; 小提示:
元件声明与实体声明基本一致,元件就是一个实体。
(2)元件例化(PORT MAP)语句的格式为: 例化名:元件名称 PORT MAP 元件端口列表
例1-4-1用元件定义(COMPONET)和元件例化语句实现四位全加器的程序设计,调用的 元件是一位全加器,元件名称是fulladder,用VHDL描述的程序的文件名是fulladder.VHD, 四位全加器电路图如图1-4-1所示。
图1-4-1 四位全加器电路图
四位全加器的程序文件名为adder4.VHD,内容如下: LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY adder4 IS PORT (
A, B : IN STD_LOGIC_VECTOR(3 DOWNTO 0); CI : IN STD_LOGIC;
S : OUT STD_LOGIC_VECTOR(3 DOWNTO 0); C : BUFFER STD_LOGIC_VECTOR(4 DOWNTO 1) );
END adder4;
ARCHITECTURE a OF adder4 IS
COMPONENT fulladder --元件定义,fulladder是元件名称 PORT( --端口名表 A, B, Ci : IN STD_LOGIC; Co, S : OUT STD_LOGIC );
END COMPONENT;
BEGIN
U0: fulladder PORT MAP (A(0),B(0),CI,C(1),S(0)); --元件例化 U1: fulladder PORT MAP (A(1),B(1),C(1),C(2),S(1)); U2: fulladder PORT MAP (A(2),B(2),C(2),C(3),S(2)); U3: fulladder PORT MAP (A(3),B(3),C(3),C(4),S(3));
END a;
在上面程序的元件定义(COMPONET)语句中,COMPONET语句后面的元件名称是 fulladder,其在PORT中的端口信号信息与描述一位全加器的程序名fulladder.VHD在实体
中PORT部分的端口信号信息必须相同,包括端口信号名称、端口信号的输入/输出状态和端口信号的数据类型等。COMPONET语句放在结构体的ARCHITECTURE和BEGIN之间。 在PORT MAP部分,元件名称fulladder必须与COMPONT中的元件名称一致,U0、U1、 U2、U3是四个元件例化名,表明在这个结构体中对fulladder单元的四次不同的调用。 PORT MAP中所列的端口信号列表表示当前设计单元与元件的端口连接方式,在VHDL 设计中有两种连接方式,一种是位置关联方式,如
U0: Fulladder PORT MAP (A(0),B(0),Ci,C(1),S(0));
PORT MAP列出的端口信号名与COMPONET中的PORT端口信号名称在顺序、端口状态 和数据类型上必须一致,各个端口信号的意义取决于它的位置而不是它的名称;另一种是 端口信号名称关联方式,在这种关联方式下,用符号 “=>”连接元件端口和设计电路的端口,如上例U1中, PORT MAP列出的端口信号名称是A(1),B(1),C(0),C(1)和S(1),PORT MAP语句可以写成如下形式:
U1: Fulladder PORT MAP (A=>A(1), B=>B(1), Ci=>C(1), Co=>C(2), S=>S(1)); 这时,各个端口的意义取决于端口的名称,与位置无关。
元件例化语句与BLOCK语句一样属于并行语句,但是元件和元件例化在设计项目中是分 层次的,每个元件就是一个独立的设计实体,这样就可以把一个复杂的设计实体划分成多个 简单的元件来设计。 1.4.3 生成(GENERATE)语句
生成语句是一种循环语句,具有复制电路的功能。当设计一个由多个相同单元模块组成 的电路时,就可以用生成语句来描述。生成语句有FOR-GENERATE和IF-GENERATE两种 形式,分别说明如下:
(1)FOR-GENERATE语句格式为:
标号:FOR 循环变量 IN 取值范围 GENERATE 并行语句 END GENERATE [标号];
FOR-GENERATE语句与FOR-LOOP语句不同,FOR-GENERATE中所列的语句是并行信 号赋值语句、元件例化、块语句和子程序等并行语句。循环变量是一个局部变量,其取值范 围可以选择递增和递减两种形式,如0 TO 5和3 DOWNTO 1等。生成语句所复制的单元模块是按照一定的顺序排列的,而单元模块之间的关系却是并行的。所以生成语句属于并行语句。
例1-4-2用FOR-GENERATE语句实现四位全加器的程序设计如下: LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY adder4 IS PORT(
A, B : IN STD_LOGIC_VECTOR(3 DOWNTO 0); Ci : IN STD_LOGIC;
S : OUT STD_LOGIC_VECTOR(3 DOWNTO 0); C : BUFFER STD_LOGIC_VECTOR(4 DOWNTO 0) );
END adder4;
ARCHITECTURE a OF adder4 IS
COMPONENT fulladder
PORT ( A, B, Ci : IN STD_LOGIC; Co, S : OUT STD_LOGIC); END COMPONENT; BEGIN C(0) <= Ci;
gen1: FOR I IN 0 TO 3 GENERATE
addx: fulladder PORT MAP (A(I),B(I),C(I),C(I+1),S(I)); --产生四位串行全加器 END GENERATE ;
END a;
例1-4-3 用生成语句描述用四个D触发器组成一个四位移位寄存器,电路图如图1-4-2所 示。D触发器用元件定义和元件例化语句调用。元件名称是dff1,用VHDL描述的D触发器的
程序参见例1-3-4,程序的文件名是dff1.VHD。
图1-4-2 四位移位寄存器
四位移位寄存器的文件名为shift.VHD,内容如下: LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY shift IS PORT(
DIN, CLK : IN STD_LOGIC;
DOUT : OUT STD_LOGIC;
Q : BUFFER STD_LOGIC_VECTOR(3 DOWNTO 0) );
END shift;
ARCHITECTURE B OF shift IS COMPONENT dff1
PORT ( D, CLK : IN STD_LOGIC; Q : OUT STD_LOGIC ); END COMPONENT;
SIGNAL D : STD_LOGIC_VECTOR(0 TO 4); BEGIN
D(0)<= DIN;
gen2: FOR I IN 0 TO 3 GENERATE fx: dff1 PORT MAP (D(I),CLK,D(I+1));
END GENERATE ; Q(0) <= D(1); Q(1) <= D(2); Q(2) <= D(3); Q(3) <= D(4); DOUT<=D(4)
END B; 小提示:
从上例可以看出,FOR-GENERATE用来处理规则的单元模块,对于不规则的单元模块 用IF-GENERATE格式。
(2)IF-GENERATE语句带有条件选择项,其格式为: 标号: IF 条件 GENERATE 并行语句 END GENERATE [标号];
例1-4-4用IF-GENERATE语句描述的四位移位寄存器,其结构体部分程序如下: ARCHITECTURE C OF shift IS COMPONENT DFF1 PORT (
DIN, CLK : IN STD_LOGIC; Q : OUT STD_LOGIC );
END COMPONENT;
SIGNAL D : STD_LOGIC_VECTOR(0 TO 4); BEGIN
gen3: FOR I IN 0 TO 3 GENERATE IF I = 0 GENERATE
fx: dff1 PORT MAP (DIN,CLK,D(I+1)); END GENERATE ; IF I /= 0 GENERATE
fx: dff1 PORT MAP (D(I),CLK, D(I+1)); END GENERATE ; END GENERATE ; Q(0) <= D(1); Q(1) <= D(2); Q(2) <= D(3); Q(3) <= D(4);
END B;
1.4.4 子程序(SUBPROGRAM)
子程序是一个VHDL程序模块,它是由一组顺序语句组成的。主程序调用子程序,子程 序将处理结果返回给主程序,其含义与其它高级计算机语言中的子程序相同。子程序可以在 程序包、结构体和进程中定义,子程序必须在被定义后才能被调用,主程序和子程序之间通 过端口参数列表位置关联方式进行数据传送,子程序可以被多次调用完成重复性的任务。在 VHDL中的子程序有两种类型:过程(Procedure)和函数(Function),他们在被调用后返 回数据的方式不同。