Types de données
Les types fondamentaux du VHDL : std_logic, std_logic_vector, integer, unsigned, signed.
Vue d'ensemble des types
VHDL est fortement typé : chaque signal, variable ou port a un type fixe. Les conversions doivent être explicites.
| Type | Librairie | Usage typique |
|---|---|---|
std_logic | STD_LOGIC_1164 | Signal 1 bit |
std_logic_vector | STD_LOGIC_1164 | Bus N bits (sans arithmétique) |
unsigned | NUMERIC_STD | Bus N bits non signé (arithmétique) |
signed | NUMERIC_STD | Bus N bits signé complément à 2 |
integer | STD (natif) | Entier — simulation, paramètres |
boolean | STD (natif) | true / false |
bit | STD (natif) | 0 ou 1 — éviter en synthèse |
std_logic
Le type le plus utilisé en VHDL synthétisable. Il modélise un fil électrique avec 9 valeurs possibles :
| Valeur | Signification |
|---|---|
'0' | Zéro logique |
'1' | Un logique |
'Z' | Haute impédance (tristate) |
'U' | Non initialisé (simulation) |
'X' | Inconnu — conflit de drivers (simulation) |
'W', 'L', 'H', '-' | Valeurs faibles, don't care |
En synthèse, seuls '0', '1' et 'Z' ont un sens physique.
signal w_enable : std_logic;
signal r_data : std_logic;
w_enable <= '1';
r_data <= 'Z'; -- haute impédancestd_logic_vector
Bus de N bits. Aucune opération arithmétique disponible directement.
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)
-- Affectation
w_bus <= "10110011"; -- binaire
w_bus <= x"B3"; -- hexadécimal
w_bus <= (others => '0'); -- tous les bits à 0
-- Accès à des bits ou sous-vecteurs
w_bit3 <= w_bus(3); -- bit 3
w_nibble := w_bus(7 downto 4); -- 4 bits de poids fortConvention : toujours utiliser
downto(7 downto 0) — c'est la convention standard.
unsigned et signed
Ces types permettent les opérations arithmétiques sur des vecteurs de bits.
library IEEE;
use IEEE.NUMERIC_STD.ALL;
signal r_counter : unsigned(7 downto 0);
signal w_diff : signed(8 downto 0);
-- Arithmétique
r_counter <= r_counter + 1;
r_counter <= r_counter + to_unsigned(5, 8);
-- Comparaison
if r_counter = to_unsigned(255, 8) then
-- ...
end if;Conversions de types
Les conversions sont obligatoires et explicites en VHDL.
std_logic_vector ←→ unsigned : cast direct (même structure binaire)
std_logic_vector ←→ signed : cast direct
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 = nombre de bits
-- signed ↔ integer
w_int <= to_integer(w_sig);
w_sig <= to_signed(w_int, 8);integer
Type natif pour les paramètres et compteurs en simulation. Éviter dans les ports d'entité synthétisables.
constant c_MAX_COUNT : integer := 100;
signal w_index : integer range 0 to 255; -- contraint = meilleure synthèse
-- En générique (usage courant)
generic (
g_WIDTH : integer := 8;
g_DEPTH : integer := 256
);boolean
signal w_valid : boolean;
w_valid <= true;
w_valid <= (r_counter = to_unsigned(0, 8)); -- comparaison retourne boolean
if w_valid then
-- ...
end if;Tableau récapitulatif des conversions
| De → Vers | 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) | — |
Types énumérés (enumeration)
Les types énumérés permettent de nommer des états ou des codes de façon explicite. C'est le type utilisé dans les machines à états.
-- Déclaration dans la zone architecturale
type t_state is (IDLE, INIT, RUN, DONE, ERROR);
type t_couleur is (ROUGE, ORANGE, VERT);
type t_direction is (NORD, SUD, EST, OUEST);
signal r_state : t_state := IDLE;
signal r_couleur : t_couleur := ROUGE;-- Utilisation dans un 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;Les types énumérés sont automatiquement encodés par le synthétiseur (binaire ou one-hot selon les outils). Il est possible de forcer un encodage particulier via des attributs de synthèse.
Types tableaux définis par l'utilisateur
VHDL permet de définir des tableaux multi-dimensionnels ou des tableaux de types personnalisés.
-- Tableau de 8 octets (ROM simple)
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"
);
-- Tableau 2D (matrice 4×- de bits)
type t_matrice is array (0 to 3, 0 to 3) of std_logic;
-- Tableau de std_logic_vector (RAM inférée)
type t_ram is array (0 to 255) of std_logic_vector(7 downto 0);
signal r_mem : t_ram;-- RAM synchrone inférée à partir d'un tableau
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;Type record
Un record regroupe plusieurs champs de types différents sous un même nom. Équivalent d'un struct en C.
-- Déclaration du record (dans un package ou l'architecture)
type t_pixel is record
rouge : unsigned(7 downto 0);
vert : unsigned(7 downto 0);
bleu : unsigned(7 downto 0);
valide : std_logic;
end record t_pixel;
-- Utilisation
signal r_pixel_in : t_pixel;
signal r_pixel_out : t_pixel;
-- Affectation individuelle des champs
r_pixel_in.rouge <= to_unsigned(255, 8);
r_pixel_in.vert <= to_unsigned(128, 8);
r_pixel_in.bleu <= to_unsigned(0, 8);
r_pixel_in.valide <= '1';
-- Affectation globale (agrégat)
r_pixel_out <= (rouge => x"FF", vert => x"80", bleu => x"00", valide => '1');
-- Affectation complète depuis un autre record
r_pixel_out <= r_pixel_in;Les records sont très utiles pour les interfaces de bus (AXI, données structurées) et pour passer plusieurs signaux liés dans un port map.
Lorsque les records sont utilisés dans les ports d'entité, ils doivent être déclarés dans un package partagé entre les fichiers.