4.1.7 数据对象
在逻辑综合中,VHDL语言常用的数据对象为信号、常量、变量。 ·信号(Signal)
用于声明内部信号,而非外部信号(外部信号对应为in, out, inout, buffer),其在元件之间起互联作用,可以赋值给外部信号。 信号也可在状态机中表示状态变量。信号赋值符号为“<=”。 ·常量
常量在设计描述中保持某一规定类型的特定值不变。如利用它可设计不同模值的计数器,模值存于一常量中,不同的设计,改变模值仅需改变此常量值。 常量在定义时赋初值,赋值符号为“:=”。
·变量
变量只在给定的进程中用于声明局部值或用于子程序中。变量的赋值符号为“:=”。
下例为一位BCD码的加法器,从中可看出信号、常量、变量的定义及使用方法。
ENTITY bcdadder IS PORT (op1, op2 : IN integer range 0 to 9; result : OUT integer range 0 to 31 ); END bcdadder;
ARCHITECTURE behavior OF bcdadder IS
constant adjustnum : integer:=6; --定义一常量:整数型,值为6
signal binadd : integer range 0 to 18;
--定义一个信号,以保存两数二进制相加的和 BEGIN
binadd<=op1+op2; --信号赋值 process(binadd)
variable tmp:integer:=0; --定义一变量,并赋初值为0 begin
if binadd>9 then
tmp:=adjustnum; --变量赋值,立即起作用。 else
tmp:=0; end if;
result <= binadd+tmp; end process;
130 — —
END behavior;
注意,信号与变量赋值是不同的。在进程中,信号赋值在进程结束时起作用,而变量赋值是立即起作用的。如下面两个进程:
p1: process(A,B,C) p2: process(A,B,C) begin variable d:std_logic;
D<=A; --D为外部定义的信号 begin
D:=A; --立即赋值 X<=B+D;
D<=C; X<=B+D; Y<=B+D; D:=C; end process p1; Y<=B+D; 在进程结束更新时,D的值为C因此执行 end process p2; 结果X<=B+C; Y<=B+C; 此执行结果X<=B+A; Y<=B+C;
若使用synplify对p1进程进行逻辑综合可出现如下警告信息:
“Input a is unused”
4.1.8 VHDL常用语句
·VHDL常用语句分并行(Concurrent)语句和顺序(Sequential)语句: 并行语句(Concurrent):
并行语句总是处于进程(PROCESS)的外部。所有并行语句都 是并行执行的,即与它们出现的先后次序无关。 如when..else语句 顺序语句(Sequential):
顺序语句总是处于进程(PROCESS)的内部,并且从仿真的角度 来看是顺序执行的。如if-then-else语句。
下面先看一下进程:
131 — —
4.1.8.1进程Process
进程(PROCESS)用于描述顺序(sequential)事件并且包含在结构中。一个结构体可以包含多个进程语句。以下为进程语句的构成:
进程(Process) 声明区(Declarations) 内部变量声明;声明用于该进程的常数,元件,子程序。 顺序语句 信号赋值(<=) 过程调用 变量赋值(:=) loop语句(循环) next语句(跳过剩余循环) exit语句(退出循环) if语句 wait语句(等待时钟信号) case语句
null语句(空语句,值保持不变) 以下为进程语句的语法描述:
--此处声明局部变量,数据类型及其他局部声明(用于进程中) begin --进程开始
--进程中为顺序语句,如:
--signal and variable assignments 信号与变量的赋值
--if and case statements --if-then-else语句 case-when语句 --while and for loops
--function and procedure calls 函数,过程调用 end process
132 — —
其中,进程标号是可选项,可有可无。
敏感表(Sensitivity list)包括进程的一些信号,当敏感表中的某个信号变化时进程才被激活。如上述计数器为例:
PROCESS (clk,nreset) --进程(敏感表)
BEGIN IF(nreset='0') THEN --顺序语句 异步清零
qcnt<=\
ELSIF (clk'EVENT AND clk = '1') THEN if(ci='1') then qcnt<=qcnt+1; end if; END IF; --end if _reset END PROCESS; 在敏感表中,信号nreset,clk被列为敏感信号,当此两个信号变化时,此进程才被执行。注意信号ci并没有被列入敏感表,这是因为,ci起作用必须发生在时钟的上升沿,这时clk必定发生变化,引起进程的执行。同样,若为同步清零,敏感表中也可无nreset信号,此时进程如下:
PROCESS (clk) --进程(敏感表)
BEGIN
IF (clk'EVENT AND clk = '1') THEN --顺序语句 IF(nreset='0') THEN 同步清零
qcnt<=\
elsif(ci='1') then qcnt<=qcnt+1; end if; --end if _reset END IF; END PROCESS;
4.1.8.2 并行(Concurrent)语句和顺序(Sequential)语句
一个设计既可用并行语句描述也可用顺序语句描述。以下以四选一的数据选择器为例说明各常用语句。
□ 并行(Concurrent)语句
并行语句之间值的更新是同时进行的,与语句所在的顺序无关。并行语句包括: ·布尔方程
·条件赋值(如when—else—语句)
133 — —
·例化语句
一、布尔方程
四选一的数据选择器的库声明、程序包声明及实体定义如下: library ieee;
use ieee.std_logic_1164.all; entity mux4 is port ( s :in std_logic_vector(1 downto 0); a0,a1,a2,a3 :in std_logic; y :out std_logic); end mux4;
以布尔方程实现的结构体如下: architecture archmux of mux4 is begin
y<=((((a0 and not(s(0))) or (a1 and s(0)))) and not(s(1)))
or (((a2 and not(s(0))) or (a3 and s(0))) and s(1)); end archmux;
二、条件赋值
并行语句中条件赋值语句为:WITH-SELECT-WHEN语句及WHEN-ELSE语句。分别
如下:
--采用WITH-SELECT-WHEN实现的结构体
architecture archmux of mux4 is begin
with s select
y<= a0 when \ a1 when \ a2 when \ a3 when others; end archmux;
注意:WITH-SELECT-WHEN语句必须指明所有互斥条件,在这里即“s”的所有取值组合,因为“s”的类型为“std_logic_vector”,取值组合除了00,01,10,11外还有0x,0z,x1…等。虽然这些取值组合在实际电路中不出现,但也应列出。为避免此麻烦可以用“others”代替其他各种组合。
--采用WHEN-ELSE实现的结构体
134 — —