Data Types
VHDL fundamental types: std_logic, std_logic_vector, integer, unsigned, signed.
Type Overview
VHDL is strongly typed: each signal, variable, or port has a fixed type. Conversions must be explicit.
| 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 — simulation, parameters |
boolean | STD (native) | true / false |
bit | STD (native) | 0 or 1 — avoid in synthesis |
std_logic
The most used type in synthesizable VHDL. It models an electrical wire with 9 possible values:
| 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 |
In synthesis, only '0', '1' and 'Z' have physical meaning.
signal w_enable : std_logic;
signal r_data : std_logic;
w_enable <= '1';
r_data <= 'Z'; -- high impedancestd_logic_vector
N-bit bus. No arithmetic operations available directly.
signal w_bus : std_logic_vector(7 downto 0); -- 8 bits, bit 7 = MSB
signal w_adr : std_logic_vector(0 to 7); -- 8 bits, bit 0 = MSB (rare)
-- Assignment
w_bus <= "10110011"; -- binary
w_bus <= x"B3"; -- hexadecimal
w_bus <= (others => '0'); -- all bits to 0
-- Bit or sub-vector access
w_bit3 <= w_bus(3); -- bit 3
w_nibble := w_bus(7 downto 4); -- 4 MSBsConvention: always use
downto(7 downto 0) — this is the standard convention.
unsigned and signed
These types enable arithmetic operations on bit vectors.
library IEEE;
use IEEE.NUMERIC_STD.ALL;
signal r_counter : unsigned(7 downto 0);
signal w_diff : signed(8 downto 0);
-- Arithmetic
r_counter <= r_counter + 1;
r_counter <= r_counter + to_unsigned(5, 8);
-- Comparison
if r_counter = to_unsigned(255, 8) then
-- ...
end if;Type Conversions
Conversions are mandatory and explicit in VHDL.
std_logic_vector ←→ unsigned : direct cast (same binary structure)
std_logic_vector ←→ signed : direct cast
unsigned ←→ integer : to_integer() / to_unsigned()
signed ←→ integer : to_integer() / to_signed()signal w_vec : std_logic_vector(7 downto 0);
signal w_uns : unsigned(7 downto 0);
signal w_sig : signed(7 downto 0);
signal w_int : integer;
-- std_logic_vector ↔ unsigned
w_uns <= unsigned(w_vec);
w_vec <= std_logic_vector(w_uns);
-- unsigned ↔ integer
w_int <= to_integer(w_uns);
w_uns <= to_unsigned(w_int, 8); -- 8 = number of bits
-- signed ↔ integer
w_int <= to_integer(w_sig);
w_sig <= to_signed(w_int, 8);integer
Native type for parameters and counters in simulation. Avoid in synthesizable entity ports.
constant c_MAX_COUNT : integer := 100;
signal w_index : integer range 0 to 255; -- constrained = better synthesis
-- In generics (common usage)
generic (
g_WIDTH : integer := 8;
g_DEPTH : integer := 256
);Conversion Reference Table
| 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) | — |
Enumeration Types
Enumeration types let you name states or codes explicitly. This is the type used in state machines.
-- Declared in the architecture declarative region
type 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 process
process(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;Enumeration types are automatically encoded by the synthesizer (binary or one-hot depending on the tool). Encoding can be forced through synthesis attributes.
User-Defined Array Types
VHDL lets you define multi-dimensional arrays or arrays of custom types.
-- 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×- 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;-- Synchronous RAM inferred from an array
process(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;Record Type
A record groups multiple fields of different types under one name. Equivalent to a struct in C.
-- 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;
-- Usage
signal r_pixel_in : t_pixel;
signal r_pixel_out : t_pixel;
-- Individual field assignment
r_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 assignment
r_pixel_out <= (red => x"FF", green => x"80", blue => x"00", valid => '1');
-- Full record copy
r_pixel_out <= r_pixel_in;Records are very useful for bus interfaces (AXI, structured data) and for passing related signals together through a port map.
When records are used in entity ports, they must be declared in a shared package visible to all files.