10.1 概述
经常使用的代码可以以元件(component)、函数(function)或过程(procedure)等形式放到(package)中,然后被编译到目标LIBRARY中,目的是实现常用代码的共享。
使用这种方法非常重要的原因是他允许代码分割、代码共享和代码重用。
10.2 包集
除了COMPONENT,FUNCTION和PROCEDURE之外,PACKAGE中还包含类型(TYPE)和常量(CONSTANT)的定义。
其语法格式如下:
PACKAGE package_name is
(declarations) --声明
END package_name;
[PACKAGE BODY package_name is
(FUNCTION/PROCEDURE) --function和procedure描述
end package_name;]
上面的语法结构中包含两部分:PACKAGE和PACKAGE BODY。第一部分是必需的,包括所有声明语句(类型、常量、元件、函数或过程等)。如果在一部分中有一个或多个FUNCTION和PROCEDURE声明,那么在PACKAGE BODY中一定要存在对应的描述代码。PACKAGE和对应的的PACKAGE BODY的名称必须相同。
解释:因为FUNCTION和PROCEDURE都是一段顺序代码,当它们在PACKAGE中被声明后,一定要在PACKAGE BODY中进行对应的代码描述;而元件(component)被声明后,需要在另外的文件(.vhd)中进行描述。
例 内部包含类型、常量和函数的PACKAGE
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
-------------------------------------------------------------------------------
package my_package is
type state is (st1, st2, st3, st4); --类型
constant vec: std_logic_vector(7 downto 0) := "11111111"; --常量
function positive_edge(signal clk: std_logic)return boolean; --函数
end my_package;
package body my_package is
function positive_edge(signal clk: std_logic)return boolean is
begin
return(clk'event and clk = '1'); --函数描述
end positive_edge;
end my_package;
-------------------------------------------------------------------------------
PACKAGE BODY中对FUNCTION进行了描述:这个函数在时钟的上升沿出现时返回TURE。
上述例子中的PACKAGE可以被编译成work或其他任何一个库中的一部分。为了在VHDL代码中使用它,必须在主程序中加入一个新的USE子句,具体如下:
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.my_package.all; --use 子句
-------------------------------------------------------------------------------
entity...
...
architecture...
...
-------------------------------------------------------------------------------
10.3 元件
一个元件(COMPONENT)是一段结构完整的常用代码(包括库声明、实体和结构体这些基本组成部分)。
为了使用(实例化)一个元件,首先要对这个元件进行声明。其相应格式如下:
元件声明:
COMPONENT component_name is
PORT(
port_name1: signal_mode signal_type; --端口名称、端口模式、数据类型
port_name2: signal_mode signal_type;
...
);
END COMPONENT;
元件实例化:
label: component_name
PORT MAP(
port_list
);
可以看出,COMPONENT和ENTITY的声明格式一样,必须指出端口名称以及端口的模式(IN,OUT,BUFFER或INOUT)以及数据类型(STD_LOGIC_VECTOR,INTEGER和BOOLEAN等)。
实例化元件时,在元件名和端口映射声明的前面还需要加入一个标号,端口列表将元件预定义的端口和实例化时的实际端口关联起来。
声明一个元件有2种基本方法,如下图所示:
- 将元件设计完成并放到目标库中,然后在主代码中进行元件声明和实例化;
- 采用包集(PACKAGE)的方式进行声明,可以减少重复声明。(采用此方法时,主代码中需增加一条USE语句,用来使用包集。)
10.4 端口映射
另外,在元件的实例化过程中,有2种方法可以用来实现元件端口的映射:位置映射和名称映射。
例子如下:
----------------------example:-----------------------------
component inverter is
port(
a :in std_logic;
b :in std_logic;
c :out std_logic
);
end component;
-----------------------------------------------------------
U1:inverter
port map(x,y,z); --位置映射:端口x,y,z对应于a,b和c
-----------------------------------------------------------
U2:inverter
port map(
a => x, --名称映射:对于不需要的使用的端口
b => open, ------------可以使用关键字OPEN断开
c => z
);
-----------------------------------------------------------
10.5 GENERIC参数的映射
当元件实例化过程中需要说明和传递GENERIC参数时,需要进行如下的映射:
-----------------------------------------------------------
lable:component_name --实例化
generic map(
param.list --传递generic参数
)
port map(
port_list
);
-----------------------------------------------------------