VHDL fundamental types: std_logic, std_logic_vector, integer, unsigned, signed.
A type determines an object's possible values and supported operations. Choose it for the signal's role: logic level, bit collection, number or group of fields.
Type
Library
Typical Usage
std_logic
STD_LOGIC_1164
1-bit signal
std_logic_vector
STD_LOGIC_1164
N-bit bus (no arithmetic)
unsigned
NUMERIC_STD
N-bit unsigned bus (arithmetic)
signed
NUMERIC_STD
N-bit signed bus (two's complement)
integer
STD (native)
Integer - parameters, indexes and counters
boolean
STD (native)
true / false
bit
STD (native)
0 or 1; no unknown simulation states
Distinguish signals from numbers
std_logic models a signal with nine values, useful for observing uninitialized states and driver conflicts in simulation:
Value
Meaning
'0'
Logic zero
'1'
Logic one
'Z'
High impedance (tristate)
'U'
Uninitialized (simulation)
'X'
Unknown - driver conflict (simulation)
'W', 'L', 'H', '-'
Weak values, don't care
'0' and '1' represent logic levels. 'Z' represents high impedance, implemented where supported, particularly at I/O. Other values serve simulation or synthesis conventions; 'X' is not an extra physical level.
signal w_enable : std_logic;signal r_data : std_logic;w_enable <= '1';r_data <= 'Z'; -- high impedance
std_logic_vector collects bits without specifying a numeric interpretation:
signal w_bus : std_logic_vector(7 downto 0); -- 8 bits, bit 7 = MSBsignal w_adr : std_logic_vector(0 to 7); -- 8 bits, bit 0 = MSB (rare)signal w_bit3 : std_logic;signal w_nibble : std_logic_vector(3 downto 0);-- Assignmentw_bus <= "10110011"; -- binaryw_bus <= x"B3"; -- hexadecimalw_bus <= (others => '0'); -- all bits to 0-- Bit or sub-vector accessw_bit3 <= w_bus(3); -- bit 3w_nibble <= w_bus(7 downto 4); -- 4 MSBs
Both downto and to ranges are legal. These courses normally use downto for numeric buses; always identify the most significant index.
unsigned and signed provide arithmetic interpretations through numeric_std:
A vector cast retains bits while changing their interpretation. Conversions to or from an integer must also respect the selected range and width.
From → To
std_logic_vector
unsigned
signed
integer
std_logic_vector
-
unsigned(x)
signed(x)
to_integer(unsigned(x))
unsigned
std_logic_vector(x)
-
signed(x)
to_integer(x)
signed
std_logic_vector(x)
unsigned(x)
-
to_integer(x)
integer
std_logic_vector(to_unsigned(x,N))
to_unsigned(x,N)
to_signed(x,N)
-
Use types suited to behavior
integer supports parameters, indexes and counters in simulation and, where supported, synthesis. Constrain its range to make limits visible. Vector ports are often preferable when the interface width needs to be explicit.
boolean contains true and false; comparisons produce this type. An enumeration gives states or codes meaningful names:
-- Declared in the architecture declarative regiontype t_state is (IDLE, INIT, RUN, DONE, ERROR);type t_color is (RED, ORANGE, GREEN);type t_dir is (NORTH, SOUTH, EAST, WEST);signal r_state : t_state := IDLE;signal r_color : t_color := RED;
-- Used inside a processprocess(i_clk)begin if rising_edge(i_clk) then case r_state is when IDLE => r_state <= INIT; when INIT => r_state <= RUN; when RUN => if i_done = '1' then r_state <= DONE; end if; when others => r_state <= IDLE; end case; end if;end process;
Synthesis chooses an encoding, such as binary or one-hot. Tool-specific attributes can guide that choice.
Group and size data
Array types describe ROM, RAM or matrices:
-- Array of 8 bytes (simple ROM)type t_rom_8x8 is array (0 to 7) of std_logic_vector(7 downto 0);constant c_ROM : t_rom_8x8 := ( x"00", x"1F", x"3C", x"7E", x"FF", x"7E", x"3C", x"1F");-- 2D array (4 × 4 bit matrix)type t_matrix is array (0 to 3, 0 to 3) of std_logic;-- Array of std_logic_vector (inferred RAM)type t_ram is array (0 to 255) of std_logic_vector(7 downto 0);signal r_mem : t_ram;
A synchronous access pattern permits memory inference within the target's capabilities and options:
-- Synchronous RAM inferred from an arrayprocess(i_clk)begin if rising_edge(i_clk) then if i_we = '1' then r_mem(to_integer(unsigned(i_addr))) <= i_data; end if; o_data <= r_mem(to_integer(unsigned(i_addr))); end if;end process;
An unconstrained array defers its range until the object declaration:
subtype t_byte is std_logic_vector(7 downto 0);type t_byte_array is array (natural range <>) of t_byte;signal r_window : t_byte_array(0 to 3);signal r_fifo : t_byte_array(0 to 15);
The subtype gives a byte a reusable name. The element type can also be written directly:
type t_byte_array is array (natural range <>) of std_logic_vector(7 downto 0);
To name a constrained std_logic_vector, declare a subtype rather than type t_byte is std_logic_vector(7 downto 0);. The same t_byte_array can then describe four bytes, sixteen bytes or a larger table:
This flexibility suits generics, packages and variable-size functions.
A record groups fields of different types, much like a C struct:
-- Record declaration (in a package or architecture)type t_pixel is record red : unsigned(7 downto 0); green : unsigned(7 downto 0); blue : unsigned(7 downto 0); valid : std_logic;end record t_pixel;-- Usagesignal r_pixel_in : t_pixel;signal r_pixel_out : t_pixel;-- Individual field assignmentr_pixel_in.red <= to_unsigned(255, 8);r_pixel_in.green <= to_unsigned(128, 8);r_pixel_in.blue <= to_unsigned(0, 8);r_pixel_in.valid <= '1';-- Aggregate assignmentr_pixel_out <= (red => x"FF", green => x"80", blue => x"00", valid => '1');-- Full record copyr_pixel_out <= r_pixel_in;
A complete reset aggregate helps avoid missing a field after changes:
constant c_PIXEL_RESET : t_pixel := ( red => (others => '0'), green => (others => '0'), blue => (others => '0'), valid => '0');r_pixel_out <= c_PIXEL_RESET;
Records make bus interfaces and port map associations easier to read. For records in ports, declare the type in a package visible to the relevant units.