Packages are intended to hold commonly-used declarations such as constants, type declarations and global subprograms. Packages can be included within the same source file as other design units (such as entities and architectures) or may be placed in a separate source file and compiled into a named library. This latter method (described in the section Design Libraries) is useful when you will be using the contents of a package throughout a large design or in multiple projects.

 

Packages may contain the following types of objects and declarations:

 

•  Type and subtype declarations

•  Constant declarations

•  File and alias declarations

•  Component declarations

•  Attribute declarations

•  Functions and procedures

•  Shared variables

 

When items from the package are required in other design units, you must include a use statement to make the package and its contents visible for each design unit.

 

The following is an example of a package declaration and its corresponding use statements:

 

library ieee;

use ieee.std_logic_1164.all;

package my_types is

    subtype byte is std_logic(0 to 7);

    constant CLEAR: byte := (others=>‘0’);

end my_types;

 

use work.mytypes.all;

use ieee.std_logic_1164.all;

entity rotate is

    port(Clk, Rst, Load: in std_logic;

            Data: in byte;

            Q: out byte);

end rotate;

 

architecture rotate4 of rotate is

    signal Qreg: byte;

begin

 

    Qreg <= Data when (Load = ‘1’) else

                  Qreg(1 to byte’LENGTH-1) & Qreg(0);

 

    dff(Rst, Clk, Qreg, Q);

 

end rotate4;

 

In this example, the package my_types includes declarations for a subtype (byte) and constant (CLEAR) that will be used throughout the subsequent design description. The statement use work.mytypes.all specifies that all contents of the package mytypes should be loaded from the default library (work). (As we will see later in this chapter, the work library is a special library described in the VHDL specification as one that does not require a library statement and into which all design units are analyzed by default.)  An alternative to using the all keyword in the use statement would be to specify precisely which items in the default library are to be made visible, as in use work.mytypes.byte and use work.mytypes.CLEAR.

 

How Are Packages Used?

When you create your own VHDL design descriptions, you can use packages in a number of ways. First, you can dramatically simplify your designs by placing commonly-used declarations (such as byte and CLEAR in the previous example) into packages that are used throughout your project. You will probably find that using libraries to collect such packages in one place will simplify the design even further and make it easier to share commonly-used declarations between different design descriptions.

 

Another way you can use packages is to reference pre-written packages that have been provided for you. One example of such a package is found in the IEEE 1164 Standard Logic standard. The IEEE 1164 standard provides a standard package named std_logic_1164 that includes declarations for the types std_logic, std_ulogic, std_logic_vector and std_ulogic_vector, as well as many useful functions related to those data types.

 

Packages may also be provided to you by vendors of synthesis and simulation tools. Synthesis tools, for example, often include packages containing synthesizable type conversion functions, synthesizable procedures for flip-flops and latches, and other useful design elements.

 

Finally, there is a standard package that includes declarations for all the standard data types (bit, bit_vector, integer and so on). This standard package is defined by the IEEE 1076 standard and automatically made visible to all design units. (You do not have to specify a use clause for the standard package.)

 

Package Bodies

Packages that include global subprograms (functions or procedures) or deferred constants (see Chapter 3, Exploring Objects and Data Types) must defer part of their declaration (the part that must be analyzed during simulation) to a separate design unit called a package body. Every package can have, at most, one corresponding package body. Package bodies are optional and are only required when a package includes subprograms or deferred constants.

 

The following example shows how a package body must be used when a subprogram (in this case, a procedure describing the behavior of a D flip-flop) is declared in a package:

 

package my_reg8 is

    subtype byte8 is std_logic_vector(0 to 7);

    constant CLEAR8: byte8 := (others=>‘0’);

    procedure dff8 (signal Rst, Clk: in std_logic;

                              signal D: in byte;

                              signal Q: out byte);

end my_reg8;

 

package body my_reg8 is

    procedure dff8 (signal Rst, Clk: in std_logic;

                               signal D: in byte8;

                               signal Q: out byte8) is

    begin

        if Rst = ‘1’ then

            Q <= CLEAR8;

        elsif Clk = ‘1’ and Clk’event then

            Q <= D;

        end if;

    end dff;

end my_reg8;

 

In this example, the procedure dff8 is declared initially in the package my_reg8. This first declaration is somewhat akin to a "function prototype" as used in the C or C++ languages, and it defines the interface to the procedure. The package body that corresponds to package my_reg8 (and shares its name) contains the complete description of the procedure.

 

image\diamond.gif  Design Libraries

image\diamond.gif  Functions and Procedures