在规模较大的电路设计中,全部电路都用唯一的一个模块来描述是不方便的。为此,电路设计者总希望将整个电路分成若干个相对比较独立的模块来进行电路的描述。这样,一个构造体可以用若干个子结构,即相对比较独立的模块来构成。VHDL语言可以有以下3种形式的子结构描述语句:
★ BLOCK语句结构
★ PROCESS语句结构
★ SUBPROGRAMS结构
其中,process语句结构最常用。下面对上述3种子结构逐一说明。
一、BLOCK语句结构描述
人们在用计算机电路辅助设计工具输入电原理图时,往往将一个大规模的电原理图分割成多张子原理图,进行输入和存档。同样在VHDL语言中也不例外,电路的构造体对应整个电原理图,而构造体可以由多个BLOCK块构成,每一个BLOCK块对应一张子原理图。这样电原理图的分割关系和VHDL语言程序中用BLOCK分割构造体的关系是—一对应的。
在用其它高级语言编程时,总希望程序模块小一点,以利于编程和查错,也利于实现积木化结构。同理,在VHDL语言中采用BLOCK 语言对编程、查错、仿真及再利用都会带来莫大的好处。
1.BLOCK语句的结构
采用BLOCK语句描述局部电路的书写格式如下所示:
块结构名:
BLOCK
BEGIN
┇
END BLOCK块结构名;
如果采用BLOCK语句来描述二选一电路,那么用VHDL语言就可以书写为:
【例1】
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
-- ENTITY DECLARATION
ENTITY mux IS
PORT (d0,d1,sel:IN STD_LOGIC;
q:OUT STD_LOGIC);
END mux;
-- ARCHITECTURE BODY
ARCHITECTURE connect OF mux IS
SIGNAL tmp:STD_LOGIC;
BEGIN
blk:BLOCK
BEGIN
tmp <= (d0 AND sel) OR (d1 AND (NOT sel));
q <= tmp;
END BLOCK blk;
END connect;
上述程序的构造体中只有一个BLOCK块,如果电路复杂时可以由几个BLOCK块组成。
2.BLOCK内语句的并发性
在对程序进行仿真时,BLOCK语句中所描述的各个语句是可以并发执行的,它和书写顺序无关。在VHDL语言中将这样可以并行执行的语句称为并发语句(Concurrent Statement)。当然在构造体内直接书写的语句也是并发的。在VHDL语言中也存在只能顺序执行的语句,如process语句。
3.Guarded BLOCK
前面所述的BLOCK语句仅仅是将构造体划分成几个独立的程序模块,这和执行控制没有直接关系,在系统仿真时BLOCK语句将被无条件地执行。但是,在实际电路设计中,往往会碰到这样的情况,当满足条件时,BLOCK语句才可以被执行;条件不满足时BLOCK语句不能执行。这就是Guarded BLOCK,它可以实现BLOCK语句的执行控制。
例如,现在用BLOCK语句来描述一个锁存器的结构。该锁存器是一个D触发器,具有一个数据输入端d、时钟输入端clk、输出端q和反相输出端qb。众所周知,只有clk有效时(clk=“1”),输出端q和qb才会随D端输入数据变化而变化。此时,用Guarded BLOCK语句描述该锁存器结构的VHDL语言程序可以书写为:
ENTITY latch IS
PORT( d,clk:IN STD_LOGIC;
q,qb: OUT STD_LOGIC);
END latch;
ARCHITECTURE latch_guard OF latch IS
BEGIN
G:
BLOCK(cIk ==’1’)
BEGIN
q <= GUARDED d;
qb <= GUARDED NOT(d);
END BLOCK G;
END latch_guard;
如上述程序所示,Guarded BLOCK语句的格式为:
BLOCK [布尔表达式]
当布尔表达式为真时(例中clk=’1’为真时),该BLOCK语句被启动执行;而当卫式表达式为假时,该BLOCK语句将不被执行。
在BLOCK块中的两个信号赋值语句都写有关键词GUARDED,这表明只有布尔表达式为真时,这两个语句才被执行。
现在根据程序描述一下锁存器的工作过程。当端口clk的值为“1”时,布尔表达式为真。d端的输入值从q端输出,并且对d端的值取反后从qb端输出。当端口clk的值为“0”时,d端到q、qb端的信号传递通道被切断,q端和qb端的输出保持原状,不随d端值的变化而改变。
二、进程(PROCESS)语句结构描述
1.PROCESS语句的结构
采用PROCESS语句描述电路结构的书写格式如下:
[进程名] PROCESS(敏感信号1,敏感信号2,…)
BEGIN
┇
END PROCESS;
进程名可以有,也可以省略。PROCESS语句从PROCESS开始至END PROCESS结束。执行PROCESS语句时,通常带有若干个敏感信号量。这些信号量将在 PROCESS结构的语句中被使用。用PROCESS语句结构描述的程序如下所示:
【例2】
ENTITY mux IS
PORT(d0,d1,sel:IN STD_LOGIC;
q:OUT STD_LOGIC);
END mux;
ARCHITECTURE connect OF mux IS
BEGIN
PROCESS(d0,d1,sel)
VARIABLE tmp1,tmp2,tmp3:STD_LOGIC;
BEGIN
tmp1:= d0 AND sel;
tmp2:= dl AND(NOT sel);
tmp3:= tmp1 OR tmp2;
q <= tmp3;
END PROCESS;
END connect;
程序中,tmp1、tmp2和tmp3是变量,变量只在进程内部定义,详见后面阐述。
2.进程(PROCESS)中语句的顺序性
在VHDL中,与BLOCK语句一样,某个功能独立的电路,在设计时也可以用一个PROCESS语句结构来描述。与BLOCK语句不同的是,PROCESS结构中的语句是按顺序一条一条向下执行的,而不像BLOCK中的语句可以并行执行。在VHDL语言中,这种顺序执行的语句只在PROCESS和SUBPROGRAM的结构中使用。
3.PROCESS的启动
在PROCESS的语句中总是带有1个或几个信号量。这些信号量是PROCESS的输入信号,书写时跟在“PROCESS”后面的括号中。例如PROCESS(d0,d1,sel)。该语句中d0、d1、sel都是信号量,在VHDL语言中也称敏感信号量。这些信号无论哪一个发生变化(如由“1”变为“0”或者由“0”变为“1”)都将启动PROCESS语句。一旦启动以后, PROCESS中的语句将从上到下逐句执行一遍。当最后一个语句执行完毕以后,就返回到开始的PROCESS语句,等待信号量下一次变化的出现。这样,只要PROCESS中指定的信号变化一次,该PROCESS语句就会执行一遍。
三、SUBPROGRAM语句结构描述
所谓SUBPROGRAM(过程和函数)就是在主程序调用它以后能将处理结果返回主程序的程序模块,其含义和其它高级语言中的子程序概念相当。它可以反复调用,使用非常方便。子程序在调用时首先要进行初始化,执行结束后子程序就终止。再调用时要再进行初始化。因此子程序内部的值不能保持,子程序返回以后才能被再调用,它是一个非重入的程序。
在VHDL中SUBPROGRAM有两种类型:
★ 过程(Procedure)
★ 函数(Function)
其中“过程”与其它高级语言中的子程序相当;而“函数”与其它高级语言中的函数相当。
1.过程语句
在VHDL语言中,过程语句的书写格式如下:
PROCEDURE 过程名(参数1,参数2,…) IS
[定义语句]; (变量等定义)
BEGIN
[顺序处理语句]; (过程的语句)
END过程名;
在PROCEDURE结构中,参数可以是输入也可以是输出。也就是说,过程中的输入输出参数都应列在紧跟过程名的括号内。例如,在VHDL语言中,将位矢量转换为整数的程序可以由一个过程语句来实现。
PROCEDURE vector_to_Int
(z:IN STD_LOGIC_VECTOR;
x_flag:OUT BOOLEAN;
q:INOUT INTEGER) IS
BEGIN
q:=0;
x_flag:=FALSE;
FOR i IN z’ RANGE LOOP
q:=q*2;
IF(z(i)= 1) THEN
q:=q+1;
ELSIF(z(i)/= 0) THEN
x_flag:=TRUE;
END IF;
END LOOP;
END vector_to_int;
该过程调用后,如果x_flag=TRUE,则说明转换失败,不能得到正确的转换整数值。
在上例中,z是输入,x_flag是输出,q为输入输出。在没有特别指定的情况下,“IN”作为常数;而“OUT”和“INOUT”则看作“变量”进行拷贝。当过程的语句执行结束以后,在过程内所传递的输出和输入输出参数值,将拷贝到调用者的信号或变量中。此时输入输出参数如没有特别指定则按变量对待,将值传递给变量。如果调用者需要将输出和输入输出作为信号使用,则在过程参数定义时要指明是信号。例如
PROCEDURE shift(
din:IN STD_LOGIC_VECTOR;
SIGNAL dout:OUT STD_LOGIC_VECTOR);
END shift;
前面已经提到,PROCESS结构中的语句是顺序执行的,那么在过程结构中的语句也是顺序执行的。调用者在调用过程前应先将初始值传递给过程的输入参数。然后过程语句启动,按顺序自上至下执行过程结构中的语句,执行结束,将输出值拷贝到调用者的“OUT”和“INOUT”所定义的变量或信号中。
2.函数语句
在VHDL语言中,函数语句的书写格式如下:
FUNCTION 函数名(参数1,参数2,…)
RETURN 数据类型名 IS
[定义语句];
BEGIN
[顺序处理语句];
RETURN [返回变量名];
END[函数名];
在VHDL语言中,FUNCTION语句中括号内的所有参数都是输入参数或称输入信号。因此在括号内指定端口方向的“IN”可以省略。FUNCTION的输入值由调用者拷贝到输入参数中,如果没有特别指定,在FUNCTION语句中按常数处理。
通常各种功能的FUNCTION语句的程序都被集中在包集合(Package)中。
上面详细叙述了过程、函数的结构和使用方法。为了能重复使用这些过程和函数,这些程序通常组织在包集合、库中。它们与包集合和库具有这样的关系:即多个过程和函数汇集在一起构成包集合(Package),而几个包集合汇集在一起就形成一个库(Library)。有关包集合和库的详细内容在下一节文章中介绍。但是,需要指出的是,不同公司发布的包集合和库的使用方法各不相同。