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.

TypeLibrairieUsage typique
std_logicSTD_LOGIC_1164Signal 1 bit
std_logic_vectorSTD_LOGIC_1164Bus N bits (sans arithmétique)
unsignedNUMERIC_STDBus N bits non signé (arithmétique)
signedNUMERIC_STDBus N bits signé complément à 2
integerSTD (natif)Entier — simulation, paramètres
booleanSTD (natif)true / false
bitSTD (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 :

ValeurSignification
'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édance

std_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 fort

Convention : 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 → Versstd_logic_vectorunsignedsignedinteger
std_logic_vectorunsigned(x)signed(x)to_integer(unsigned(x))
unsignedstd_logic_vector(x)signed(x)to_integer(x)
signedstd_logic_vector(x)unsigned(x)to_integer(x)
integerstd_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.