next up previous contents
Next: 2.6 Additional Signal Characteristics Up: 2. Basic VHDL Concepts Previous: 2.4 Configuration Declaration

Subsections

2.5 Packages

A packages is used as a collection of often used datatypes, components, functions, and so on. Once these object are declared and defined in a package, they can be used by different VHDL design units. In particular, the definition of global information and important shared parameters in complex designs or within a project team is recommended to be done in packages.

It is possible to split a package into a declaration part and the so-called body. The advantage of this splitting is that after changing definitions in the package body only this part has to be recompiled and the rest of the design can be left untouched. Therefore, a lot of time consumed by compiling can be saved.

2.5.1 Package Declaration

As the name implies, a package declaration includes all globally used declarations of types, components, procedures and functions. A possible package declaration is presented by means of an example:

Example:
package MY_PACK is
  type SPEED is (STOP, SLOW, MEDIUM, FAST);
  component HA
    port (I1, I2 : in bit; S, C : out bit);
  end component;
  constant DELAY_TIME : time;
  function INT2BIT_VEC (INT_VALUE : integer)
    return bit_vector;
end MY_PACK;

The name of this package is MY_PACK. It consists of different declarations, such as a type SPEED, a component HA, and so on. Attention should be paid to the declaration of the constant DELAY_TIME and the function INT2BIT_VEC which are declared but are not defined. Their definitions will be done in the package body but it would be possible to define the constant DELAY_TIME in the package declaration part as well. The definition of functions must be done in a package body.

If the above package had been compiled into the library MY_LIB (Section 2.7) then the following statements were also needed in the VHDL model which uses this package:

Example:
library MY_LIB;
use MY_LIB.MY_PACK.all;
entity EXAMPLE is
  ...

The library statement makes the library MY_LIB accessible for the following VHDL description. With the subsequent use statement all elements (indicated by the keyword all) from the package MY_PACK are included in the entity of the module EXAMPLE.

2.5.2 Package Body

In the package body the definition of functions and procedures that were only declared in the package declaration must be specified. Constants which were declared only must get a value assigned to them in the package body.

The body of the package MY_PACK could be defined as:

Example:
package body MY_PACK is
  constant DELAY_TIME : time := 1.25 ns;
  function INT2BIT_VEC (INT_VALUE : integer)
    return bit_vector is
  begin
    - sequential behavioral description (omitted here)
  end INT2BIT_VEC;
end MY_PACK;

The binding between the package declaration and the body is established by using the same name. In the above example it is the package name MY_PACK.

   
2.5.3 Important Packages

There are four important packages often used in VHDL descriptions.

STANDARD:
The package STANDARD is usually integrated directly in the simulation or synthesis program and, therefore, it does not exist as a VHDL description. It contains all basic types: boolean, bit, bit_vector, character, integer, and the like. Additional logical, comparison and arithmetic operators are defined for these types within the package. The package STANDARD is a part of the STD library. Thus, it does not have to be explicitly included by the use statement.

TEXTIO:
The package TEXTIO contains procedures and functions which are needed to read from and write to text files.

This package is also a part of the library STD. It is not included in every VHDL description by default. Therefore, if required, it has to be included by the statement use STD.TEXTIO.all;.

STD_LOGIC_1164:
The STD_LOGIC_1164 package has been developed and standardized by the IEEE. It introduces a special type called std_ulogic which has nine different logic values. The reason for this enhancement is that the type bit is not suitable for the precise modeling of digital circuits due to the missing values, such as uninitialized or high impedance.

The type std_ulogic consists of the following elements:

Declaration:
type std_ulogic is (
          'U',    - uninitialized
          'X',    - forcing unknown
          '0',    - forcing 0
          '1',    - forcing 1
          'Z',    - high impedance
          'W',    - weak unknown
          'L',    - weak 0
          'H',    - weak 1
          '-' );  - "don't care"

Besides this type used for modeling single wires other types are declared in the STD_LOGIC_1164 package. Frequently used in descriptions of bus systems are the types std_ulogic_vector and std_logic_vector. In addition, the also includes the definitions of resolution functions (see Section 2.6.2) and simple boolean functions.

The use of the types std_ulogic and std_logic is strongly recommended. The package STD_LOGIC_1164, if it is available on the system installation, is usually be kept in the logical library IEEE. It could be referenced with the two statements:

Syntax:
library IEEE;
use IEEE.STD_LOGIC_1164.all;

STD_LOGIC_ARITH or NUMERIC_STD:
Two additional packages,
STD_LOGIC_ARITH (provided by SYNOPSYS) and NUMERIC_STD (provided by the IEEE), represent an additional part for the STD_LOGIC_1164 package. They contain basic arithmetic functions to enable calculations and comparisons based on the types std_ulogic_vector and std_logic_vector. These types represent buses - a bunch of signal lines - whose state can be interpreted as a binary or as a two's complement number. Therefore, it is necessary to specify which number representation is valid for a given bus system. This can be done by a conversion into the data types unsigned and signed. The appropriate conversion functions are also defined in these packages.

Example:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
architecture DETAILED of EXAMPLE is
  signal A, B :   std_logic_vector (7 downto 0);
  signal SUM :    std_logic_vector (8 downto 0);
  signal SUM_S : signed (8 downto 0);
  signal PROD :   std_logic_vector (15 downto 0);
  signal PROD_S :signed (15 downto 0);
begin
  - extension by one digit, conversion into a two's
  - complement number and calculation of the sum:
  SUM_S <= signed(A(7) & A) + signed(B(7) & B);
  - conversion to 9 bit std_logic_vector:
  SUM <= conv_std_logic_vector(SUM_S, 9);
  - calculation of the product:
  PROD_S <= signed(A) * signed(B);
  - conversion to 16 bit std_logic_vector:
  PROD <= conv_std_logic_vector(PROD_S, 16);
end DETAILED;
In the above example the sum and the product of the two busses A and B are calculated. Because the width of the resulted sum is the same as those of the operands, the width of A and B has to be extended by one bit in order to avoid an overflow. Since both A and B are two's complement numbers their MSB's have to be doubled. This is achieved by the catenations A(7) & A and B(7) & B. After converting signals A and B with the signed(...) and adding, the result is assigned to a temporary signal SUM_S. This signal is then converted back to a 9 bit wide bus of the type std_logic_vector with the function conv_std_logic_vector(SUM_S, 9). For the multiplication, the width of the result is 16 bit, which is equal to the sum of the widths of the operands A and B. The appropriate information is required in the conversion of PROD_S to PROD.


next up previous contents
Next: 2.6 Additional Signal Characteristics Up: 2. Basic VHDL Concepts Previous: 2.4 Configuration Declaration
Richard Geissler
1998-10-07