Libraries and Packages in VHDL
Built-in Libraries and Packages.
In most vhdl programs you have already seen examples of packages and libraries. Here are two:
The packages are "std_logic_1164" and "std_logic_signed" and the library is "ieee". Since the "scope" of the library statement extends over the entire file, it is not necessary to repeat that for the second package.
It's instructive to show where the packages are physically located. For Altera Max+2 and Xilinx Foundation these locations typically are:
It is thus tempting to come to the conclusion that the "library ieee;" statement indicates the "directory" in which the std_logic_1164 package is located. Note, however, where it is in Synplicity:
In the latter there is no mention of "ieee" at all. It is thus more appropriate to think of "ieee" as a pointer to the location of the package. The directory structure shown in those three examples depicts the directories where the packages are loaded when the software is installed. The pointer "ieee" is hardcoded in the compilers and thus there is no need for the user to associate that pointer with the directory structure, nor is it possible to put the packages anywhere else after the software has been loaded.
The files "std1164.vhd" (Altera and Synplicty) and "std_logic_1164.vhd" (Xilinx) show a close resemblance to the package name as given in the "use" statement, but apparently they don't have to be the same as the package name. The actual package is in those files and shows up in there as the following statement:
package std_logic_1164 is
which is identical for all three .vhd files. That statement is reminiscent of the entity statement and indeed, a package is also considered a design unit, similar to an entity and an architecture.
It's in the "st_logic_1164" package that std_logic values, such as ‘1’, ‘0’, ‘Z’, etc. are defined. Open up one of those .vhd files with any ascii editor, and see how that is done. Make sure, however, not to make any changes in these files. So it'd be better to first copy them to a file with another name and look at that one, just to be on the safe side.
In addition to a "package", the file containing the package may also have a "package body", which is yet another design entity in the VHDL sense. An example is the definition of the "+" (addition) operator for use with std_logic_vectors. The language only defines "+" for integers and reals, thus a package in a library is needed to "overload", as it is called, the "+" operator so it can be applied to other things, e.g. std_logic_vector. The package std_logic_signed contains the definition of "+" for that case and the package body defines its functionality. Thus a package and a package body go together similarly to an entity and its architecture. However, a package may or may not have a package body, unlike an entity, which must have an architecture. Here is an example how that is arranged in the file containing the package std_logic_signed (in the file "signed.vhd" in both Altera and Synplicity and in the file "std_logic_signed.vhd" in Xilinx). The pertinent excerpt from that file is shown below:
package STD_LOGIC_SIGNED is
function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return
-- other similar function definitions
package body STD_LOGIC_SIGNED is
variable result. STD_LOGIC_VECTOR (length-1 downto 0);
result := SIGNED(L) + SIGNED(R); return std_logic_vector(result);
-- other similar function descriptions
The "L" and "R" stand for the left and right operand respectively, on either side of the operator "+". The "return" indicates the type of signal that results from the operation. The use of the "maximum" function allows the two operands to be of different length and makes the resultant signal width equal to the widest of the two vectors. Note, the function "maximum" must also be defined in the package body, as it is not an inherent part of the language. Note also that the .vhd file that contains a package need not be named the same as the package.
Constants, variables, types and subtypes are defined similarly in the various packages that come with the software. However, the contents of these packages is not identical and which items are defined where, may also differ from manufacturer to manufacturer. It is unfortunate that the standardization of the language does not extend to the contents of the packages or even their names. This may make the code non-portable. On the other hand, the concept of the "package" is powerful, especially since there is also a mechanism for setting up user
libraries and packages. which is shown in the following example.
User Libraries and Packages.
User libraries and packages are setup very similarly to the built-in ones. However, in that case, the user is responsible for the directory structure, the contents of the files, etc. Note that the user must then also set up the pointer to the package. The following shows a complete example of this arrangement. There are two ways to do this: 1) with the "work" directory; 2) with a user library.
With the "work" library (Max+2-specific)
First we define the "work" library. This is the pointer to the working directory, i.e. where all the design files are kept and the software "knows" which one that is, as it is set up by the project definition. Thus if the user were to put a .vhd file, containing a package, in the current working directory, the statement referencing that package would be:
library work; -- not needed, but OK to include.
Note that the first statement may be omitted, since the pointer "work" is built into the software. It is always the current working directory. An example of this structure follows:
entity myxor3 is
port(a,b,c:in std_logic; x:out std_logic);
end entity myxor3;
architecture struct of myxor3 is
u0: myxor port map(a,b,x_i);
u1: myxor port map(x_i,c,x);
end architecture struct;
There is no mention of a "component" myxor, because "myxor" is defined in the package "my_gates" and the compiler is told where that can be found through the "use.work. " statement. The file containing that package may be as follows:
end entity myxor;
architecture a_myxor of myxor is
f<=a xor b;
end archicture a_myxor;
Assuming the working directory is "mywork", then the structure is as follows:
Although the package file "mygates.vhd" may contain several component definitions, each one must have it's own ".vhd" file that contains the entity/architecture pair that describes that component. At least those are restrictions imposed by the Altera software.
The main drawback of this simple package arrangement is that the package(s) can only be accessed by the designer(s) who are using the same working directory. When multiple designers work on a project, it is desirable for each of them to have their own working directory and have access to a common user library. This is shown in the following example.
With a "user" directory.
This example uses Synplicity for the compiler, since it does not impose the restrictions of the Altera Max+2 compiler, but behaves as the language intends. Since the result of this compilation is an EDIF file, it can however, be exported to Max+2 and from then on used as any internal VHDL source file for simulation and implementation in an Altera FPGA.
Assuming the common user library is "usrlib01" (the "01" is to emphasize the fact that there my be several user libraries), the directory structure may be as follows.
\max2work\usr_a\. usr_a's .vhd files.
\max2work\usr_b\. usr_b's .vhd files.
more team member's files
\max2work\usrlib01\. package file.
There are four main differences with the previous, simpler, Altera-based. example:
A complete example is given below, including the commands needed for the library (pointer) setup. This example is a little more elaborate than the previous one as it shows the use of multiple components, which is more typical of a large design.
To clarify the structure, the code represents the circuit shown below:
We'll use a structural or hierarchical approach in the VHDL code, i.e. the architecture portion contains references to components MYAND2 and MYOR2. The entity/architecture pairs for these components will be described in a package file. The design requires a source file for the circuit, a package file, a package name, a pointer to the package, a working directory and a user library. It is possible to use the same name for some of these items, but here we'll use all different ones to make it clearer what is what. A list of the various constituents is shown on the next page