Package File - VHDL Example
A package in VHDL is a collection of functions, procedures, shared variables, constants, files, aliases, types, subtypes, attributes, and components. A package file is often (but not always) used in conjunction with a unique VHDL library. Packages are most often used to group together all of the code specific to a Library. Packages can have two parts: a declaration and a body, though the body is not necessarily required. The declarations section contains the prototypes for the functions and procedures that are defined. The body section contains the actual implementation of the functions and procedures. If you've used C before, the declaration section is similar to a .h file.
Packages in combination with libraries are an excellent way that VHDL allows the digital designer to organize his or her code. By grouping functionality that belongs together, designs make much more sense and are leaner. They also allow you to write code that is reusable. You might find one particular package file being used again and again throughout your designs if it has some useful functions or constants.
Components in a Package File
It is preferable to put all of your component definitions in a single package file, rather than copy and pasting them everywhere the component is instantiated. This way, if the port map changes, only the package file and the actual instantiations need to be updated.
Constants and Types in a Package File
Constants and types that appear repeatedly throughout your code should likely be grouped together in a package file. (Or maybe be passed in your design using generics).
Functions and Procedures in a Package File
Functions and procedures need to exist both in the declaration section as well as the body section. As was said before, the declaration contains the prototype for the function or procedure and the body contains the actual implementation of the code. Below is an example package file that shows off some of the situations described above.
-- Package Declaration Section package example_package is constant c_PIXELS : integer := 65536; type t_FROM_FIFO is record wr_full : std_logic; rd_empty : std_logic; end record t_FROM_FIFO; component example_component is port ( i_data : in std_logic; o_rsult : out std_logic); end component example_component; function Bitwise_AND ( i_vector : in std_logic_vector(3 downto 0)) return std_logic; end package example_package; -- Package Body Section package body example_package is function Bitwise_AND ( i_vector : in std_logic_vector(3 downto 0) ) return std_logic is begin return (i_vector (0) and i_vector (1) and i_vector (2) and i_vector (3)); end; end package body example_package;
In order to use the constants, components, functions, etc that you created in your package file, you will need to tell your other code where to look for these things. This is done with the use clause. The .all at the end of the use clause tells the file to use everything inside of the package file, as opposed to one particular function for example.
library work; use work.example_package.all;