第六章 VHDL设计共享
主要内容 VHDL设计库 VHDL程序包 VHDL子程序与并行过程调用
6.1 VHDL设计库 6.1.1 库的种类 IEEE库 IEEE标准的程序包主要有STD_LOGIC_1164、NUMERIC_STD和NUMERIC_BIT 3个标准程序包,尤其是STD_LOGIC_1164是最重要的数字系统标准程序包,大部分基于数字系统设计的程序包都是以此程序包中设定的标准为基础的。 STD库 包含了两个标准程序包STANDARD和TEXTIO程序包。 WORK库 WORK库只是一个逻辑名,不存在WORK库的实名。 WORK库是用户的VHDL设计的现行工作库,用于存放用户设计和定义的一些设计单元和程序包。 VITAL库 VITAL程序包已经成为IEEE标准,并且已经并到IEEE库中,库中包含有VITAL_TIMING和VITAL_PRIMITIVES两个时序程序包。
6.1 VHDL设计库(续) 6.1.2 库的使用方法 库使用声明语句由关键词LIBRARY引导,指明所使用的库名;程序包使用语句由关键词USE引导,指明使用库中的哪一个程序包。 程序包使用语句USE的使用将其所说明的程序包对本设计实体可以部分开放或者全部开放,相应的也有两种使用格式: USE 库名.程序包名.项目名; USE 库名.程序包名.ALL; 库和程序包正确使用的示例: LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL;
6.2 VHDL程序包 程序包的结构由程序包的说明部分,即程序包首,和程序包的具体内容,即程序包体,两部分组成。一个完整的程序包中,程序包首和程序包体是同一个名字。 PACKAGE 程序包名 -- Type Declaration (optional) -- Subtype Declaration (optional) -- Constant Declaration (optional) -- Signal Declaration (optional) -- Component Declaration (optional) -- Subprogram Declaration (optional) END 程序包名; PACKAGE BODY 程序包名 IS -- Type Declaration (optional) -- Subtype Declaration (optional) -- Constant Declaration (optional) -- Function Declaration (optional) -- Procedure Declaration (optional) -- Function Body (optional) -- Procedure Body (optional) END 程序包名; 程序包的结构中少要包含数据类型声明、子类型声明、常数声明、信号声明、元件声明、子程序声明其中的一种。 程序包结构中,程序包体并非总是必须的,程序包首可以独立定义和使用。但是,当程序包首中作了子程序(函数和过程)或部件等声明后,程序包体是必须的。
6.2 VHDL程序包(续1) 例6.1 程序包定义示例。 LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; PACKAGE my_pkg IS --程序包首声明 TYPE byte IS INTEGER RANGE 0 TO 255; SUBTYPE helf_byte IS byte RANGE 0 TO 15; CONSTANT byte_max: byte:= 255; FUNCTION min (left, right: INTEGER) RETURN INTEGER; COMPONENT signed_adder --假定实体和结构体在WORK库中 GENERIC( data_width : NATURAL := 8); PORT( a : IN SIGNED((data_width-1) DOWNTO 0); b : IN SIGNED((data_width-1) DOWNTO 0); result : OUT SIGNED ((data_width-1) DOWNTO 0)); END COMPONENT; END my_pkg; PACKAGE BODY my_pkg IS --程序包体声明 FUNCTION min (left, right: INTEGER) RETURN INTEGER IS BEGIN IF left < right THEN RETURN left; ELSE RETURN right; END IF; END min;
6.2 VHDL程序包(续2) 例6.2 在设计实体前定义并立即使用的程序包示例。 LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; PACKAGE seg7 IS TYPE bcd IS INTEGER RANGE 0 TO 9; SUBTYPE segments IS STD_LOGIC_VECTOR(0 TO 6); END seg7; USE WORK.seg7.ALL; ENTITY bcd_to_segments IS PORT( input: IN bcd; drive: OUT segments ); END bcd_to_segments;
6.2 VHDL程序包(续3) 例6.2 在设计实体前定义并立即使用的程序包示例。 ARCHITECTURE bev OF bcd_to_segments IS BEGIN WITH input SELECT drive <= b"0000001" WHEN 0, b"1001111" WHEN 1, b"0010010" WHEN 2, b"0000110" WHEN 3, b"1001100" WHEN 4, b"0010010" WHEN 5, b"0010000" WHEN 6, b"0001111" WHEN 7, b"0000000" WHEN 8, b"0001100" WHEN 9, b"1111111" WHEN OTHERS; END bev;
6.3 VHDL子程序与并行过程调用 6.3.1 VHDL函数 1.函数首 2.函数体 3.函数调用 函数首由函数名、参数表和返回值的数据类型三部分组成。 FUNCTION 函数名(参数表) RETURN 数据类型; 2.函数体 函数体是函数具有实质性内容的部分,包含一个对数据类型、常数、变量等的局部说明,以及用以完成规定算法或转换的顺序语句部分。 FUNCTION 函数名(参数表) RETURN 数据类型 IS --函数体开始 说明部分 BEGIN 顺序语句; END FUNCTION 函数名; --函数体结束 3.函数调用 函数名(实参数表)
6.3.1 VHDL函数(续1) 例6.3 程序包中定义函数的示例。 LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; --函数首声明 PACKAGE pack_exam IS FUNCTION max(a, b: IN STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR; END pack_exam; --函数体声明 PACKAGE BODY pack_exam IS RETURN STD_LOGIC_VECTOR IS BEGIN IF a > b THEN RETURN a; --使用了返回语句 ELSE RETURN b; END IF; END FUNCTION C;
6.3.1 VHDL函数(续2) 例6.4 函数调用的应用示例。 LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE WORK.pack_exam.ALL; ENTITY func_exam IS PORT(data1, data2: IN STD_LOGIC_VECTOR(3 DOWNTO 0); data3, data4: IN STD_LOGIC_VECTOR(3 DOWNTO 0); out1, out2: OUT STD_LOGIC_VECTOR(3 DOWNTO 0)); END func_exam; ARCHITECTURE behavioral OF func_exam IS BEGIN out1 <= max( data1, data2 ); PROCESS(data3, data4) out2 <= max( data3, data4 ); END PROCESS; END behavioral;
6.3.1 VHDL函数(续3) 例6.4 函数调用的应用示例。 LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE WORK.pack_exam.ALL; ENTITY func_exam IS PORT(data1, data2: IN STD_LOGIC_VECTOR(3 DOWNTO 0); data3, data4: IN STD_LOGIC_VECTOR(3 DOWNTO 0); out1, out2: OUT STD_LOGIC_VECTOR(3 DOWNTO 0)); END func_exam; ARCHITECTURE behavioral OF func_exam IS BEGIN out1 <= max( data1, data2 ); PROCESS(data3, data4) out2 <= max( data3, data4 ); END PROCESS; END behavioral;
6.3.2 VHDL重载函数 VHDL中,可以对已经使用过的函数(表现形式当然是函数名),进行多次重新定义,这样的函数被称之为重载函数(Overloaded Function)。 例6.5 运算符重载示例。 PACKAGE STD_LOGIC_UNSIGNED IS FUNCTION "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; … PACKAGE BODY STD_LOGIC_UNSIGNED IS RETURN STD_LOGIC_VECTOR IS CONSTANT length: INTEGER := maximum(L'length, R'length); VARIABLE result : STD_LOGIC_VECTOR (LENGTH-1 DOWNTO 0); BEGIN result := UNSIGNED(L) + UNSIGNED(R); RETURN STD_LOGIC_VECTOR(result); END;
6.3.3 VHDL过程 过程与函数一样,都是VHDL中的子程序,也分为过 程首和过程体,分别放置在程序包首和程序包体中供VHDL 程序共享。 过程是一种语句结构而函数是表达式的一部分; 过程可以单独存在,而函数只是作为语句的一部分; 过程有输入参数、输出参数和双向参数,而函数入口处的 所有参数都是输入参数; 过程通过调用可以从其端口界面获得多个返回值,而函数 调用后只能返回一个值。
6.3.3 VHDL过程(续1) 1. 过程首 2.过程体 3. 过程的调用 PROCEDURE 过程名 ( 参数表 ); PROCEDURE 过程名 ( 参数表 ) IS 说明部分 BEGIN 顺序语句 END PROCEDURE 过程名; 进程或结构体中不必定义过程首,可直接定义过程体并使用。如: PROCEDURE produ1 ( VARIABLE a, b: INOUT STD_LOGIC ); 3. 过程的调用 过程名 ( 参数表 );
6.3.3 VHDL过程(续2) 例6.6 过程体的声明示例。 PROCEDURE count_zeros (A: IN BIT_VECTOR; SIGNAL Q: OUT INTEGER) IS VARIABLE zeros : INTEGER; BEGIN zeros := 0; FOR i IN A'RANGE LOOP IF A(i) = '0' THEN zeros := zeros +1; END IF; END LOOP; Q <= zeros; END count_zeros;
6.3.3 VHDL过程(续3) 例6.7 过程定义和调用的示例。 LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; PACKAGE pkg IS PROCEDURE nand_4 ( SIGNAL s1, s2, s3, s4: IN STD_LOGIC; SIGNAL y : OUT STD_LOGIC); END pkg; PACKAGE BODY pkg IS SIGNAL y : OUT STD_LOGIC) IS BEGIN y <= NOT( s1 AND s2 AND s3 AND s4 ); RETURN; END nand_4;
6.3.3 VHDL过程(续4) 例6.7 过程定义和调用的示例。 LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE WORK.pkg.ALL; ENTITY nand_8 IS PORT( a1, a2, a3, a4: IN STD_LOGIC; a5, a6, a7, a8: IN STD_LOGIC; f : OUT STD_LOGIC); END; ARCHITECTURE data_flow OF nand_8 IS SIGNAL middle1, middle2: STD_LOGIC; BEGIN nand_4( a1, a2, a3, a4, middle1); --并行过程调用 nand_4( a5, a6, a7, a8, middle2); --并行过程调用 f <= middle1 OR middle2; END data_flow;
6.3.3 VHDL过程(续5) 例6.7 过程定义和调用的示例。 LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE WORK.pkg.ALL; ENTITY nand_8 IS PORT( a1, a2, a3, a4: IN STD_LOGIC; a5, a6, a7, a8: IN STD_LOGIC; f : OUT STD_LOGIC); END; ARCHITECTURE data_flow OF nand_8 IS SIGNAL middle1, middle2: STD_LOGIC; BEGIN nand_4( a1, a2, a3, a4, middle1); --并行过程调用 nand_4( a5, a6, a7, a8, middle2); --并行过程调用 f <= middle1 OR middle2; END data_flow;
6.3.3 VHDL过程重载 与函数重载一样,两个或两个以上具有相同的过程名但参数数量及 数据类型互不相同的过程称为重载过程,重载过程也是靠参量类型来辨 别究竟调用哪一个过程。 例6.8 过程的重载示例。 PROCEDURE read(l:INOUT line; value: OUT BIT; good : OUT boolean); PROCEDURE read(l:INOUT line; value: OUT BIT); PROCEDURE read(l:INOUT line; value: OUT BIT_VECTOR; good : OUT boolean); PROCEDURE read(l:INOUT line; value: OUT BIT_VECTOR); PROCEDURE read(l:INOUT line; value: OUT boolean; good : OUT boolean); PROCEDURE read(l:INOUT line; value: OUT boolean);
本章小结 本章介绍了VHDL中的库、程序包和子程序的使用和构建 方法,目的是了解使用标准库中资源的正确方法,同时, 也可以将己定义的常数、数据类型、子程序、设计好的元 件等正确地添加到程序包中,以方便能够被其他的设计实 体调用和共享,提高设计的效率和质量。 函数和过程是VHDL设计中使用频率都非常高的部件,他 们同作为子程序有许多类似的地方,都可以定义在结构体 和程序包中,也都能够重载,但又有本质的不同,函数调 用只能作为表达式的一部分,只能返回一个值,而过程调 用是作为语句使用的,过程调用又分为顺序过程调用语句 和并行过程调用语句。