To use the IEEE 1164 standard logic data types, you will need to add at least two statements to your VHDL source files. These statements (shown below) cause the IEEE 1164 standard library (named ieee) to be loaded and its contents (the std_logic_1164 package) made visible:

 

library ieee;

use ieee.std_logic_1164.all;

 

In most design descriptions, you will place these two statements at the top of your source file, and repeat them as needed prior to subsequent design units (entity and architecture pairs) in the file. If your source file includes more than one design unit, you need to repeat the use statement just prior to each design unit in order to make the contents of the standard library visible to each design unit, as shown below:

 

library ieee;

use ieee.std_logic_1164.all;

package my_package is

    . . .

end my_package;

 

use ieee.std_logic_1164.all;

entity first_one is

    . . .

end first_one;

 

use ieee.std_logic_1164.all;

architecture structure of first_one is

    . . .

end structure;

 

use ieee.std_logic_1164.all;

entity second_one is

    . . .

end second_one;

 

Note: VHDL has special visibility rules for architectures: it is not necessary to place a use statement prior to an architecture declaration if the corresponding entity declaration includes a use statement. In the above example, the use statement appearing prior to the architecture structure is not actually needed and could be omitted.

 

Once you have included the ieee library and made the std_logic_1164 package visible in your design description, you can make use of the data types, operators and functions provided for you as a part of the standard.

 

There are two fundamental data types provided for you in the std_logic_1164 package. These data types, std_logic and std_ulogic, are enumerated types defined with nine symbolic (single character) values. The following definition of std_ulogic is taken directly from the IEEE 1164 standard:

 

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

                            );

 

The std_ulogic data type is an unresolved type, meaning that it is illegal for two values (such as '0' and '1', or '1' and 'Z') to be simultaneously driven onto a signal of type std_ulogic. If you are not describing a circuit that will be driving different values onto a wire (as you might in the case of a bus interface), then you might want to use the std_ulogic data type to help catch errors (such as incorrectly specified, overlapping combinational logic) in your design description. If you are describing a circuit that involves multiple values being driven onto a wire, then you will need to use the type std_logic. Std_logic is a resolved type based on std_ulogic. Resolved types are declared with resolution functions, as described in the section Objects, Data Types and Operators. Resolution functions define the resulting behavior when an object is driven with multiple values simultaneously.

 

When using either of these data types, you will use them as one-for-one replacements for the built-in type bit. The following example shows how you might use the std_logic data type to describe a simple NAND gate coupled to an output enable:

 

library ieee;

use ieee.std_logic_1164.all;

entity nandgate is

    port (A, B, OE: in std_logic; Y: out std_logic);

end nandgate;

 

architecture arch1 of nandgate is

    signal n: std_logic;

begin

    n <= not (A and B);

    Y <= n when OE = '0' else 'Z';

end arch1;

 

Note: As written, it is not actually necessary for this circuit to be described using the resolved type std_logic for correct simulation. Operated as a stand-alone circuit, the output Y will never be driven with two different values. When connected through hierarchy into a larger circuit, however, it is highly likely that such a situation will occur, and std_logic will thus be required.

 

Std_logic_vector and Std_ulogic_vector

In addition to the single-bit data types std_logic and std_ulogic, IEEE Standard 1164 includes array types corresponding to each of these types. Both std_logic_vector and std_ulogic_vector are defined in the std_logic_1164 package as unbounded arrays similar to the built-in type bit_vector. In practice, you will probably use std_logic_vector or std_ulogic_vector with an explicit width, or you will use a subtype to create a new data type based on std_logic_vector or std_ulogic_vector of the width required. The following sample design description uses a subtype (defined in an external package) to create an 8-bit array based on std_ulogic_vector:

 

library ieee;

use ieee.std_logic_1164.all;

 

package my_types is

    subtype std_byte is std_ulogic_vector(7 downto 0);

end my_types;

 

use ieee.std_logic_1164.all;

entity shiftl is

    port (DataIN: in std_byte; DataOUT: out std_byte; Err: out std_ulogic);

end shiftl;

 

architecture arch1 of shiftl is

    signal n: std_logic;

begin

    DataOUT <= DataIN(DataIN'left - 1 downto 0) & '0';    -- Shift left one bit

    Err <= DataIN(DataIN'left);    -- Check for overflow

end arch1;

 

In this example (an 8-bit shifter), the subtype std_byte is defined in terms of std_ulogic_vector and can be used to replace std_ulogic_vector(7 downto 0) throughout the design description. The circuit is described in such a way that the width of the shifter is dependent only on the width of the type std_byte, so it is easy to modify the width of the circuit later.