Conception de systèmes numériques avec VHDL : Du concept à l'implémentation FPGA

Le VHDL (VHSIC Hardware Description Language) est un langage standardisé pour la description, la simulation et la synthèse de circuits électroniques numériques. Il est largement employé pour le développement sur FPGA et la conception d'ASIC. Cet article présente un guide technique couvrant les fondamentaux du langage, les structures de conception combinatoire et séquentielle, ainsi que les flux de travail intégrés aux environnements d'outisl modernes comme Vivado et Quartus.

  1. Structures fondamentales du VHDL et modélisation matérielle

La construction d'un module en VHDL repose sur deux concepts clés : l'entité (Entity) et l'architecture (Architecture). L'entité définit l'interface du composant, c'est-à-dire ses ports d'entrée et de sortie. La'rchitecture décrit le comportement interne ou la structure du composant. Ce modèle favorise la réutilisation et une conception modulaire.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Porte_ET is
    port ( EntA, EntB : in  std_logic;
           SortieY    : out std_logic);
end entity Porte_ET;

architecture Comportementale of Porte_ET is
begin
    SortieY <= EntA and EntB;  -- Affectation concurrente
end architecture Comportementale;

Cet exemple minimaliste décrit une porte logique ET à deux entrées. Le type std_logic de la bibliothèque IEEE standard supporte neuf valeurs logiques (dont '0', '1', 'Z', 'X'), ce qui permet une modélisation précise des états de haute impédance et des conflits dans les simulations.

  1. Système de types, signaux et mécanismes d'affectation

Le VHDL est un langage fortement typé. Chaque signal, variable ou constante doit être déclaré avec un type précis. Cette contrainte garantit une correspondance directe avec les ressources matérielles lors de la synthèse. Par exemple, un std_logic_vector sera généralement synthétisé en une largeur de bus fixe, tandis qu'un integer avec une plage définie sera mappé sur un nombre spécifique de bits.

type type_pixel is record
    rouge, vert, bleu : integer range 0 to 255;
end record;

function "+" (a, b : type_pixel) return type_pixel is
begin
    return (rouge => a.rouge + b.rouge,
            vert  => a.vert  + b.vert,
            bleu  => a.bleu  + b.bleu);
end function;

Les opérateurs peuvent être surchargés pour prendre en charge des types utilisateurs, comme montré ici pour l'addition de deux structures de type "pixel". Cette fonctionnalité étend considérablement l'expressivité du langage.

L'affectation à un signal (<=) a une sémantique de délai. La valeur n'est pas mise à jour instantanément mais est programmée pour une période delta (Δ) ou un temps ultérieur. Cette caractéristique modélise fidèlement les temps de propagation dans un circuit réel et peut entraîner des comportements non intuitifs pour les novices.

  1. Conception de logique combinatoire

La logique combinatoire est définie par des fonctions dont les sorties ne dépendent que des entrées actuelles, sans mémoire. En VHDL, elle peut être modélisée de manière structurelle (en instanciant des portes logiques) ou comportementale (en utilisant des affectations conditionnelles).

architecture Behaviorale of Multiplexeur_4_1 is
begin
    Sortie <= Entree0 when Selecteur = "00" else
              Entree1 when Selecteur = "01" else
              Entree2 when Selecteur = "10" else
              Entree3;
end architecture Behaviorale;

Le langage propose plusieurs structures pour décrire la sélection, comme when-else (ci-dessus) ou with-select. Le choix influenec la structure de synthèse. Un outil comme Vivado convertira typiquement une chaîne when-else profonde en une arborescence de multiplexeurs, ce qui peut impacter le chemin critique.

  1. Structures séquentielles et mécanisme des processus

La logique séquentielle, comme les bascules et les compteurs, est modélisée à l'aide de processus. Un processus est une liste d'instructions exécutées de manière séquentielle, mais qui s'exécute en parallèle avec tous les autres processus et instructions concurrents du design. Il est déclenché par les changements de signaux listés dans sa liste de sensibilité.

process (Horloge, Reset_Asynchrone)
begin
    if Reset_Asynchrone = '0' then  -- Reset asynchrone actif bas
        Registre <= (others => '0');
    elsif rising_edge(Horloge) then
        Registre <= Entree_Donnee;
    end if;
end process;

Cette structure génère une bascule D avec un reset asynchrone. Le comportement de la synthèse diffère nettement selon que le reset est asynchrone (agit immédiatement) ou synchrone (attend un front d'horloge). La synchronisation des signaux de contrôle asynchrones est une pratique courante pour éviter les problèmes de métastabilité.

  1. Hiérarchie, packages et intégration IP

Des conceptions complexes sont structurées de manière hiérarchique, où une entité de niveau supérieur instancie et connecte des composants de niveau inférieur. Les packages permettent de partager des déclarations de types, de constantes et de sous-programmes entre plusieurs unités de conception.

-- Dans le fichier 'composants_utiles.vhd'
package definitions_types is
    type type_etat is (ATTENTE, CHARGEMENT, TRAITEMENT, FIN);
end package definitions_types;

-- Utilisation dans un autre fichier
library work;
use work.definitions_types.all;

architecture FSMD of Controleur is
    signal etat_courant : type_etat;
begin ...

Pour des fonctions complexes et optimisées (filtres DSP, contrôleurs de mémoire, interfaces série...), il est fréquent d'utiliser des blocs de propriété intellectuelle (IP) fournis par les fabricants de FPGA ou des tiers. Ces IP sont généralement intégrées via des catalogues graphiques (IP Catalog dans Vivado, MegaWizard dans Quartus) et peuvent être instanciées dans le code VHDL comme des composants standard.

  1. Flot de travail de développement FPGA complet

Le passage d'un design VHDL à un circuit opérationnel sur FPGA implique plusieurs étapes automatisées par les outils EDA :

  1. Analyse et Élaboration : Vérification de la syntaxe et construction de la hiérarchie.
  2. Synthèse : Transformation du code RTL en une netlist de primitives logiques (LUT, FF, BRAM) de la technologie cible.
  3. Implémentation (Place & Route) : Placement des primitives sur le plan du circuit et routage des interconnexions physiques.
  4. Configuration (Bitstream) : Génération du fichier binaire qui sera chargé dans la mémoire de configuration du FPGA.
-- Exemple d'attribut pour guider la synthèse
attribute KEEP_HIERARCHY : string;
attribute KEEP_HIERARCHY of mon_module : label is "YES";

-- Instanciation d'une IP Block RAM
U_BRAM : entity work.blk_mem_gen_0
    port map (
        clka  => clk,
        wea   => ecriture,
        addra => adresse,
        dina  => donnee_in,
        douta => donnee_out
    );

Des attributs spécifiques peuvent être utilisés pour influencer les décisions des outils de synthèse et d'implémentation, comme préserver la hiérarchie ou forcer l'utilisation d'un type de ressource (ex: ram_style = "block" pour une RAM distribuée).

Étiquettes: VHDL FPGA Synthesis Digital Design Hardware Description Language

Publié le 8 juin à 01h20