4.库(Library) 库是专门存放预先编译好的程序包(package),这样它们就可以在其他设计中被调用。它实际上对应一个目录,预编译程序包的文件就放在此目录中。用户自建的库即为设计文件所在的目录,库名与目录名的对应关系在编译软件中指定。 例如在上述计数器设计中开始部分有: library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; ieee是国际电工电子委员会的认定的标准库的标志名,下面两个use语句使得以下设计可使用程序包std_logic_1164.std_logic_unsigned中预定义的内容。 表1是IEEE两个标准库“std”gn “ieee”中所包含的程序包的简单解释。
在MAX+PLUSII软件系统中,在ALTERA库中提供如下两个程序包: maxplus2 定义了74系列各模块 megacore 定义了如FFT.8255.8251.ltu图像格式转换函数等宏块。 5.VHDL 运算符 VHDL为构造计算数值的表达式提供了许多预定义算符.预定义算符可分为四种类型: 算术运算符,关系运算符,逻辑运算符与连接运算符。分别叙述如下: 算术运算符(Arithmetic operators) + 加 -减 * 乘 / 除 ** 乘方 mod 求模 rem 求余 abs 求绝对值 关系运算符 = 等于 /= 不等于 < 小于 <= 小于或等于 > 大于 >= 大于或等于 注:其中’<=’操作符也用于表示信号的赋值操作 逻辑运算符与连接运算符 and 逻辑与 or 逻辑或 nand 与非 nor 或非 xor 异或 xnor 同或 not 逻辑非 连接运算符 & 连接,将两个对象或矢量连接成维数更大的矢量。 6.数据对象 在逻辑综合中,VHDL语言常用的数据对象为信号、常量、变量。 信号(Signal) 用于声明内部信号,而非外部信号(外部信号对应为in,out,inout,buffer),其在元件之间丰收互联作用,可以赋值给外部信号。 信号也右在状态机中表示状态变量。信号赋值符号为“<=” 常量 常量在设计描述中保持某一规定类型的特定值不变。如利用它可设计不同模值的计数器,模值存于一常量中,不同的设计,改变模值公需改变此常量值。 常量在定义时赋初值,赋值符号为“:=”。 变量 变量只给定的进程中用于声明局部值或用于子程序中。变量的赋值符号为“:=”。 下例为一位BCD码的加法器,从中可看出信号、常量、变量的定义及使用方法。 entity bcdadder is port (op1,op2:in integer range 0 to 9; result:out integer range 0 to31); 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; END behavior; 注意,信号与变量的赋值是不同的。在进程中,信号赋值在进程结束时作用,而变量赋值是立即起作用的。如下面两个进程: P1:process(A,B,C) P2:process(A,B,C) Begin Variable d:std_logic; D<=A;—D为外部定义的信号系统 Begin X<=B+D D:=A; 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”
—此处声明局部变量,数据类型及其他局部声明(用于进程中) begin —进程开始 —进程中为顺序语句,如: —signal and variable assignments 信号与变量的赋值 —if and case statements —if-then-else语句 case-when语句 —while and for loop —function and procedure calls 函数,过程调用 end process; —进程结束 其中,进程标号是可选项,可有可无。 敏感表(Sensitivity list)包括进程的一些信号,当敏感表中的某个信号变化时进程才被激活。如上述计数器为例: process(clk,nreset) —进程(敏感表) begin IF(nreset=’0’) then —顺序语句 异步清零 Qcnt<=“0000”; Elsif(clk’EVENT AND clk=’1’) then If (ci=’1’) then Qcnt<=qcnt+1; End if; End if; —end if_reset End process; 在敏感表中,信号reset,clk被作为敏感信号,当此两上信号变化时,此进程才被执行。注意信号ci并没有被列入敏感表,这是因为,ci起作用必须 发生在时钟的上升沿,这时clk必定发生变化,引起进程的执行。同样,若为同步清零,敏感表中也可无resets信号,引时进程如下: process(clk) begin if(clk’event and clk=’1’) then if (nreset=’0’) then Qcnt<=”0000”; Elsif (ci=’1’) then Qcnt<=qcnt+1; End if; —end if_reset End if; End process;
(2)并行(Concurrent)语句和顺序语句 一个设计既可用并行语句描述也可用顺序语句描述。以下以四选一的数据选择器为例说明各常用语句。 并行(Concurrent)语句和顺序(Sequential)语句 并行语句之间值的更新是同时进行的,与语句所在的顺序无关。并行语句包括 (1)、布尔方程 (2)、条件赋值(如when-else-语句) (3)、例化语句 1)布尔方程 四选一的数据选择器的库声明。程序包声明及实体定义如下: 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 : put 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 archmuc; 2)条件赋值 并行语句中条件赋值语句为:with-select-when语句及when-else语句。分别如下: —采用with-select-when实现的构造体 architecture archmux of mux4 is begin with s select y<= a0 when”00” a1 when”01” a2 when”10” a3 when others; end archmux; 注 意: with-select-when语句必须指明所有互斥条件,在这里即“s”的所有取值组合,因为“s”的类型为“std_logic_vector”, 取值组合除了00,01,10,11外还有0x,0z,x1···等。虽然这些取值组合在实际电路中不出现,但也应列出。为避免引起歧义,可以用 “others”代替其他各种组合。 —采用when-else实现的构造体 architecture archmux of mux4 is begin y<= a0 when s=”00” else a1 when s=”01” else a2 when s=”10” else a3; end archmx; 3)例化语句 即元件调用,可参见以下两节:“元件及元件例化”及“配置”。 最常用的顺序语句是if-then-else语句和case-when语句。顺序语句总是处于进程(process)的内部,并且从仿真的角度来看是顺序执行的。 If-then-else If-then-else语句只在进程中使用,它根据一个或一组条件的布尔运算而选择某一特定的执行步骤。例如: Architecture archmux of mux4 is Begin Process(s,a0,a1,a2,a3) Begin If s=“00” then Y<= a0; Elsif s=“01” then Y<= a1; Elsif s=“10” then Y<= a2; Else Y<= a3; End if; End process; End archmux;l Elsif可允许在一个语句中出现多重条件,每一个“if”语句都必须有一个对应的“end if”语句。“if”语句可嵌套使用,即在一个if语句中可调用另正值“if”语句。 case-when casw-when语句也只能在进程中使用。例如: architecture archmux of mux4 is begin process(s,a0,a1,a2,a3) begin case s is when”00”=>y<=a0; when”01”=>y<=a1; when”10”=>y<=a2; when”11”=>y<=a3; end case; end process; end archmux4; case-when语常用于状态机的描述中。此外还有“for-loop”语句。