Leçon 3 sur 22

Chapitre 3 — Structure générale d’une description VHDL

Objectif — Finalité du chapitre

Comprendre comment un fichier VHDL est organisé, distinguer les principales unités de conception et savoir écrire, compiler puis simuler les premières descriptions de portes logiques.

Objectifs pédagogiques

À la fin de ce chapitre, l’étudiant devra être capable de :

  • identifier les principales unités de conception d’un projet VHDL ;
  • expliquer le rôle d’une bibliothèque, d’un paquetage, d’une entité et d’une architecture ;
  • déclarer correctement les bibliothèques IEEE nécessaires ;
  • définir l’interface d’un composant à l’aide d’une entité ;
  • choisir un mode de port adapté : in, out, inout ou buffer ;
  • écrire la partie interne d’un composant dans une architecture ;
  • utiliser des instructions concurrentes simples ;
  • décrire des portes AND, OR, XOR et NOT ;
  • compiler une description VHDL et interpréter les erreurs élémentaires ;
  • construire un banc de test et vérifier le comportement d’un circuit par simulation.

Prérequis

  • algèbre de Boole et tables de vérité ;
  • portes logiques élémentaires ;
  • principes généraux d’un langage de description matérielle ;
  • notions de simulation et de synthèse présentées au chapitre précédent.

Organisation du chapitre

Section

Contenu principal

Compétence visée

3.1Unités de conceptionReconnaître les briques d’un projet VHDL
3.2Bibliothèques et paquetagesRendre les types et fonctions visibles
3.3EntitéDéfinir l’interface d’un composant
3.4ArchitectureDécrire son fonctionnement interne
3.5Premiers exemplesCompiler et simuler des portes logiques
TP 1Premiers circuits en VHDLDévelopper et vérifier un mini-projet

 

Principe — Idée directrice

Une description VHDL sépare généralement l’interface externe du composant, décrite par l’entité, et son fonctionnement interne, décrit par une architecture. Cette séparation facilite la réutilisation et la validation des blocs.

 


 

 

3.1 Unités de conception

Une unité de conception est un élément VHDL analysé séparément par le compilateur et enregistré dans une bibliothèque de travail. Les unités de conception permettent d’organiser un projet en composants réutilisables, en interfaces clairement définies et en ressources partagées.

3.1.1 Vue d’ensemble

Unité

Rôle

Exemple d’utilisation

BibliothèqueConteneur logique regroupant des unités compilées.IEEE, work, bibliothèque propriétaire
PaquetageRegroupe des types, constantes, fonctions et déclarations communes.Types de bus, fonctions de conversion
EntitéDécrit l’interface externe d’un composant.Entrées, sorties et paramètres génériques
ArchitectureDécrit le fonctionnement interne associé à une entité.Équations logiques, processus, instanciations
ConfigurationSélectionne l’architecture ou les composants utilisés.Choix entre plusieurs implémentations
Corps de paquetageContient l’implémentation des sous-programmes déclarés dans le paquetage.Corps d’une fonction ou d’une procédure

 

Repère — Ordre logique

Dans un fichier VHDL simple, on trouve souvent : 1) les clauses library et use, 2) l’entité, puis 3) une architecture associée. Les paquetages et configurations deviennent plus utiles lorsque le projet grandit.

 

3.1.2 Bibliothèque

Une bibliothèque VHDL est un espace logique dans lequel le compilateur stocke les unités de conception déjà analysées. Elle ne correspond pas nécessairement à un simple dossier visible par l’utilisateur : l’outil de développement gère l’association entre le nom logique de la bibliothèque et son emplacement physique.

  • La bibliothèque IEEE contient les paquetages standards largement utilisés.
  • La bibliothèque work représente la bibliothèque de travail courante.
  • Une organisation peut créer ses propres bibliothèques pour partager des composants validés.
  • Une unité doit être compilée avant de pouvoir être utilisée depuis une bibliothèque.
Déclaration d’une bibliothèque  |  VHDL
library IEEE;
library work;

 

3.1.3 Paquetage

Un paquetage, ou package, regroupe des déclarations destinées à être partagées par plusieurs unités : types, sous-types, constantes, composants, fonctions et procédures. Il joue un rôle comparable à une interface commune, sans être un programme exécuté.

Exemple de paquetage  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

package logique_pkg is
    constant NIVEAU_ACTIF : std_logic := '1';

    function inverse_bit(
        x : std_logic
    ) return std_logic;
end package logique_pkg;

 

3.1.4 Entité

L’entité décrit ce que le composant montre au monde extérieur. Elle définit son nom, ses paramètres génériques éventuels et ses ports. Elle ne précise pas encore comment le résultat est calculé.

Squelette d’une entité  |  VHDL
entity nom_composant is
    port (
        entree_a : in  std_logic;
        entree_b : in  std_logic;
        sortie_s : out std_logic
    );
end entity nom_composant;

 

3.1.5 Architecture

L’architecture décrit comment l’entité est réalisée. Une même entité peut posséder plusieurs architectures, par exemple une version comportementale destinée à la simulation et une version structurelle construite avec des sous-composants.

Squelette d’une architecture  |  VHDL
architecture rtl of nom_composant is
    -- Zone déclarative
begin
    -- Corps de l'architecture
    sortie_s <= entree_a and entree_b;
end architecture rtl;

 

3.1.6 Configuration

Une configuration permet de choisir explicitement l’architecture associée à une entité ou de préciser les liaisons utilisées dans une description structurelle. Dans les petits projets modernes, l’instanciation directe d’entité réduit souvent le besoin de configurations explicites.

Configuration minimale  |  VHDL
configuration cfg_principale of nom_composant is
    for rtl
    end for;
end configuration cfg_principale;

 

3.1.7 Corps de paquetage

Le corps de paquetage contient l’implémentation des fonctions et procédures déclarées dans le paquetage. Les éléments simples, comme les types ou les constantes, restent généralement dans la déclaration du paquetage.

Corps du paquetage logique_pkg  |  VHDL
package body logique_pkg is

    function inverse_bit(
        x : std_logic
    ) return std_logic is
    begin
        return not x;
    end function inverse_bit;

end package body logique_pkg;

 

3.1.8 Dépendances entre les unités

Unité utilisatrice

Dépendance possible

Commentaire

ArchitectureEntitéL’architecture est toujours associée à une entité.
ArchitecturePaquetageElle peut utiliser les types et fonctions rendus visibles.
Corps de paquetagePaquetageIl implémente les sous-programmes déclarés.
ConfigurationEntité et architectureElle choisit l’implémentation à utiliser.
Banc de testEntité testéeIl instancie le composant à vérifier.

 


 

 

3.2 Déclaration des bibliothèques

Avant d’utiliser un type, une fonction ou une constante définie dans un paquetage, l’unité de conception doit rendre ce paquetage visible. Les clauses library et use sont donc généralement placées avant l’entité ou l’architecture concernée.

3.2.1 Déclaration standard IEEE

Bibliothèque et paquetage logiques standards  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

 

La première ligne indique que la bibliothèque logique IEEE sera référencée. La seconde rend visibles tous les éléments publics du paquetage STD_LOGIC_1164 grâce au suffixe ALL.

3.2.2 Rôle de la bibliothèque IEEE

La bibliothèque IEEE rassemble des paquetages normalisés indispensables à la conception numérique. Son utilisation améliore la portabilité du code entre simulateurs, synthétiseurs et fabricants de FPGA.

Paquetage IEEE

Contenu principal

Usage typique

STD_LOGIC_1164Types std_logic et std_logic_vector, opérateurs logiques.Signaux numériques à plusieurs états
NUMERIC_STDTypes signed et unsigned, opérations arithmétiques.Compteurs, additionneurs, comparaisons
MATH_REALFonctions mathématiques sur les réels.Calculs de constantes, surtout en simulation
FIXED_PKGTypes et opérations en virgule fixe.Traitement numérique du signal
FLOAT_PKGReprésentation en virgule flottante.Modèles avancés et calculs numériques

 

Attention — Bonne pratique

Pour l’arithmétique synthétisable, utiliser IEEE.NUMERIC_STD plutôt que des paquetages anciens ou propriétaires tels que STD_LOGIC_ARITH et STD_LOGIC_UNSIGNED.

 

3.2.3 Utilisation d’un paquetage

La clause use suit généralement la forme suivante : nom_bibliothèque.nom_paquetage.élément. L’élément peut être un nom précis ou le mot ALL.

Deux manières de rendre des éléments visibles  |  VHDL
library IEEE;

-- Tous les éléments publics du paquetage
use IEEE.STD_LOGIC_1164.ALL;

-- Seulement certains éléments
use IEEE.STD_LOGIC_1164.std_logic;
use IEEE.STD_LOGIC_1164.rising_edge;

 

L’importation globale avec ALL est concise et très fréquente dans les supports pédagogiques. Dans les projets importants, importer seulement les éléments nécessaires peut faciliter la lecture et éviter certaines ambiguïtés de noms.

3.2.4 Visibilité des déclarations

Une clause de contexte placée avant une unité de conception s’applique à cette unité. Dans un même fichier contenant plusieurs entités ou architectures, il peut être nécessaire de répéter les clauses library et use avant chaque unité indépendante.

Visibilité limitée à une unité  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity porte_et is
    port (a, b : in std_logic; s : out std_logic);
end entity porte_et;

architecture rtl of porte_et is
begin
    s <= a and b;
end architecture rtl;

-- Selon l'outil et l'organisation du fichier,
-- on répète les clauses de contexte avant l'unité suivante.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity porte_ou is
    port (a, b : in std_logic; s : out std_logic);
end entity porte_ou;

 

3.2.5 Bibliothèque de travail work

La bibliothèque work désigne la bibliothèque dans laquelle l’unité courante est compilée. Son nom physique peut être différent, mais le mot work reste le moyen standard de référencer la bibliothèque active.

Instanciation directe depuis work  |  VHDL
U1 : entity work.porte_et(rtl)
    port map (
        a => x,
        b => y,
        s => z
    );

 

3.2.6 Erreurs fréquentes

Erreur

Cause probable

Correction

std_logic inconnuSTD_LOGIC_1164 non rendu visible.Ajouter library IEEE et use IEEE.STD_LOGIC_1164.ALL.
signed ou unsigned inconnuNUMERIC_STD absent.Ajouter use IEEE.NUMERIC_STD.ALL.
Un composant est introuvableUnité non compilée ou mauvaise bibliothèque.Vérifier l’ordre de compilation et le nom de bibliothèque.
Nom ambiguPlusieurs paquetages exportent le même identifiant.Qualifier le nom ou limiter les clauses use.
Erreur après regroupement de fichiersContexte non répété pour une nouvelle unité.Ajouter les clauses avant chaque unité concernée.

 

3.2.7 Exemple complet avec arithmétique

Additionneur 4 bits utilisant NUMERIC_STD  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity additionneur_4bits is
    port (
        a : in  unsigned(3 downto 0);
        b : in  unsigned(3 downto 0);
        s : out unsigned(4 downto 0)
    );
end entity additionneur_4bits;

architecture rtl of additionneur_4bits is
begin
    s <= ('0' & a) + ('0' & b);
end architecture rtl;

 

Explication — Lecture du code

Les deux opérandes sont étendus à 5 bits par concaténation d’un zéro. Le résultat peut ainsi représenter la retenue issue de l’addition de deux valeurs sur 4 bits.

 


 

 

3.3 Entité

L’entité constitue le contrat d’interface du composant. Toute unité qui instancie ce composant doit respecter les noms, types, dimensions et modes des ports définis par cette entité.

3.3.1 Définition de l’interface du composant

L’interface décrit les signaux qui entrent dans le composant et ceux qui en sortent. Elle peut également comporter des paramètres génériques qui ajustent la taille ou le comportement du bloc sans modifier son code interne.

Forme générale d’une entité  |  VHDL
entity nom_entite is
    generic (
        LARGEUR : positive := 8
    );
    port (
        entree  : in   std_logic_vector(LARGEUR-1 downto 0);
        sortie  : out std_logic_vector(LARGEUR-1 downto 0)
    );
end entity nom_entite;

 

3.3.2 Nom du composant

Le nom de l’entité doit être explicite et cohérent avec sa fonction. VHDL n’est pas sensible à la casse : porte_et, PORTE_ET et Porte_Et désignent le même identifiant.

  • Commencer par une lettre.
  • Utiliser des lettres, chiffres et caractères de soulignement.
  • Éviter deux caractères de soulignement consécutifs.
  • Éviter les noms trop génériques comme bloc1 ou test.
  • Choisir une convention stable : porte_et, compteur_modulo, uart_tx.

Nom recommandé

Nom à éviter

Pourquoi

compteur_modulo_10c1Le premier nom décrit la fonction.
registre_decalageregLe nom précis facilite la maintenance.
decodeur_7segmentsdecodeLa destination du décodeur est claire.
uart_emetteurmodule_uartLe sens de communication est explicite.

 

3.3.3 Ports d’entrée et de sortie

La clause port contient une liste d’objets signaux. Plusieurs ports partageant le même mode et le même type peuvent être regroupés sur une seule ligne.

Déclaration de ports regroupés  |  VHDL
entity porte_majorite is
    port (
        a, b, c : in  std_logic;
        y       : out std_logic
    );
end entity porte_majorite;

 

3.3.4 Mode in

Un port in est lu par le composant. Il représente une entrée reçue depuis l’environnement extérieur. Une architecture ne doit pas piloter directement ce port.

Entrées d’une porte ET  |   VHDL
port (
    a : in std_logic;
    b : in std_logic
);

 

Matériel — Interprétation matérielle

Un port in correspond généralement à une broche d’entrée, à la sortie d’un autre composant ou à un signal interne du niveau hiérarchique supérieur.

 

3.3.5 Mode out

Un port out est piloté par le composant. Il représente une sortie produite par l’architecture. En VHDL-2008, un port out peut être relu dans l’architecture ; dans les versions plus anciennes, on utilise souvent un signal interne pour éviter les problèmes de compatibilité.

Sortie avec signal interne compatible  |  VHDL
architecture rtl of exemple is
    signal resultat_i : std_logic;
begin
    resultat_i <= a and b;
    resultat   <= resultat_i;
end architecture rtl;

 

3.3.6 Mode inout

Un port inout peut être lu et piloté. Il est principalement utilisé pour les bus bidirectionnels ou les broches trois états. Son usage doit être justifié, car plusieurs pilotes peuvent provoquer des conflits.

Principe d’un bus bidirectionnel trois états  |  VHDL
bus_data <= donnee_sortie when autorisation = '1'
            else (others => 'Z');

donnee_entree <= bus_data;

 

Attention — Limite pratique

Dans la plupart des FPGA, les véritables signaux trois états sont disponibles surtout au niveau des broches d’entrée-sortie. À l’intérieur du FPGA, l’outil transforme souvent la logique en multiplexeurs.

 

3.3.7 Mode buffer

Un port buffer est une sortie qui peut aussi être relue à l’intérieur de l’entité. Ce mode existe dans le langage, mais il est moins utilisé dans les styles modernes. Un signal interne associé à un port out offre généralement une meilleure compatibilité et une hiérarchie plus souple.

Exemple historique avec buffer  |  VHDL
entity compteur_simple is
    port (
        clk : in     std_logic;
        q   : buffer std_logic_vector(3 downto 0)
    );
end entity compteur_simple;

 

3.3.8 Comparaison des modes de ports

Mode

Lu dans l’entité

Piloté par l’entité

Usage principal

Recommandation

inOuiNonEntrées de données, commande, horlogeTrès courant
outSelon version VHDLOuiRésultat ou commande de sortieÀ privilégier pour les sorties
inoutOuiOuiBus bidirectionnel, E/S trois étatsUtiliser seulement si nécessaire
bufferOuiOuiSortie relue localementSouvent remplacé par out + signal interne

 

3.3.9 Types des ports

Le type d’un port détermine les valeurs qu’il peut transporter et les opérations applicables. Pour la logique numérique, std_logic et std_logic_vector sont les types les plus fréquents.

Ports scalaires et vectoriels  |  VHDL
entity unite_logique is
    port (
        selection : in  std_logic_vector(1 downto 0);
        a, b      : in   std_logic_vector(7 downto 0);
        zero      : out std_logic;
        resultat  : out std_logic_vector(7 downto 0)
    );
end entity unite_logique;

 

3.3.10 Valeurs par défaut et génériques

VHDL permet d’associer des valeurs par défaut à certains génériques et ports. Ces valeurs améliorent la réutilisabilité, mais elles ne remplacent pas une connexion explicite lorsque le comportement du système doit rester évident.

Entité paramétrable  |  VHDL
entity registre is
    generic (
        N : positive := 8
    );
    port (
        clk    : in   std_logic;
        reset  : in   std_logic := '0';
        d      : in   std_logic_vector(N-1 downto 0);
        q      : out std_logic_vector(N-1 downto 0)
    );
end entity registre;

 

3.3.11 Erreurs fréquentes dans une entité

Erreur

Conséquence

Correction

Point-virgule après le dernier portErreur de syntaxe selon la forme écrite.Ne pas mettre de séparateur inutile avant la parenthèse fermante.
Type non visibleLe compilateur ne reconnaît pas std_logic.Importer STD_LOGIC_1164.
Dimensions incompatiblesÉchec lors du port map.Aligner les tailles ou effectuer une conversion.
Mauvais mode de portLecture ou pilotage interdit.Choisir in, out ou inout selon le besoin.
Nom de fin incohérentErreur de compilation ou code confus.Utiliser le même nom après end entity.

 

3.4 Architecture

L’architecture décrit la réalisation interne d’une entité. Elle est composée d’une zone déclarative, située avant le mot begin, et d’un corps contenant des instructions concurrentes.

3.4.1 Forme générale

Structure d’une architecture  |  VHDL
architecture nom_architecture of nom_entite is
    -- Zone déclarative :
    -- signaux, constantes, types, composants, fonctions...
begin
    -- Corps de l'architecture :
    -- instructions concurrentes
end architecture nom_architecture;

 

3.4.2 Nom de l’architecture

Le nom de l’architecture décrit souvent le style ou l’intention de l’implémentation : rtl, comportementale, structurelle, flot_donnees ou simulation. Il ne doit pas être confondu avec le nom de l’entité.

Nom

Sens courant

Contexte

rtlRegister Transfer LevelDescription synthétisable de registres et de logique
comportementaleDescription du comportement attenduModélisation ou logique algorithmique
structurelleAssemblage de sous-composantsConception hiérarchique
flot_donneesÉquations et affectations concurrentesCircuits combinatoires
simulationModèle destiné à la vérificationPeut contenir des éléments non synthétisables

 

3.4.3 Zone déclarative

La zone déclarative contient les objets et ressources internes nécessaires au corps de l’architecture. Elle peut être vide dans un circuit très simple.

  • signaux internes ;
  • constantes ;
  • types et sous-types locaux ;
  • déclarations de composants ;
  • fonctions et procédures locales ;
  • alias, fichiers ou attributs selon les besoins.
Zone déclarative avec signal interne  |  VHDL
architecture rtl of porte_complexe is
    signal terme_1 : std_logic;
    signal terme_2 : std_logic;
begin
    terme_1 <= a and b;
    terme_2 <= c and d;
    y <= terme_1 or terme_2;
end architecture rtl;

 

3.4.4 Corps de l’architecture

Le corps commence après begin et se termine avant end architecture. Les instructions placées directement dans ce corps sont concurrentes : elles décrivent du matériel qui fonctionne en parallèle.

Trois affectations concurrentes  |  VHDL
architecture rtl of circuit is
begin
    n_a <= not a;
    et1 <= a and b;
    y    <= et1 or c;
end architecture rtl;

 

Concept clé — Concurrence

L’ordre textuel de ces trois lignes ne signifie pas qu’elles sont exécutées l’une après l’autre. Chaque affectation représente une relation matérielle active en permanence.

 

3.4.5 Instructions concurrentes

Les principales instructions concurrentes rencontrées au début d’un cours VHDL sont les affectations de signaux, les processus et les instanciations de composants.

Instruction

Rôle

Exemple

Affectation simpleDécrit une relation logique directe.s <= a and b;
Affectation conditionnelleSélectionne une valeur selon une condition.y <= a when sel='0' else b;
Affectation sélectionnéeChoisit parmi plusieurs valeurs.with sel select ...
ProcessusRegroupe des instructions séquentielles.process(a,b) begin ... end process;
InstanciationUtilise un sous-composant.U1 : entity work.porte_et ...
GenerateRépète ou conditionne une structure.gen : for i in ... generate

 

3.4.6 Architecture par flot de données

Le style flot de données exprime directement les équations reliant les entrées et les sorties. Il convient particulièrement aux circuits combinatoires simples.

Porte majoritaire à trois entrées  |  VHDL
architecture flot_donnees of porte_majorite is
begin
    y <= (a and b) or (a and c) or (b and c);
end architecture flot_donnees;

 

3.4.7 Architecture comportementale

Le style comportemental utilise généralement un processus. Les instructions à l’intérieur du processus sont séquentielles, mais le processus lui-même fonctionne en concurrence avec les autres instructions de l’architecture.

Multiplexeur comportemental  |  VHDL
architecture comportementale of mux2 is
begin
    process(a, b, sel)
    begin
        if sel = '0' then
            y <= a;
        else
            y <= b;
        end if;
    end process;
end architecture comportementale;

 

3.4.8 Architecture structurelle

Le style structurel relie des composants ou des entités déjà définis. Il permet de construire progressivement des systèmes complexes à partir de blocs plus simples.

Circuit structurel avec instanciation directe  |  VHDL
architecture structurelle of circuit_combine is
    signal s_et : std_logic;
begin
    U_ET : entity work.porte_et(rtl)
        port map (
            a => a,
            b => b,
            s => s_et
        );

    U_INV : entity work.inverseur(rtl)
        port map (
            a => s_et,
            s => y
        );
end architecture structurelle;

 

3.4.9 Plusieurs architectures pour une entité

Une entité peut être associée à plusieurs architectures. Cette possibilité est utile pour comparer deux implémentations, fournir un modèle de simulation ou sélectionner une version optimisée.

Deux architectures de la même porte  |  VHDL
architecture equation of porte_et is
begin
    s <= a and b;
end architecture equation;

architecture comportementale of porte_et is
begin
    process(a, b)
    begin
        if a = '1' and b = '1' then
            s <= '1';
        else
            s <= '0';
        end if;
    end process;
end architecture comportementale;

 

3.4.10 Signaux et dépendances combinatoires

Dans un circuit combinatoire, chaque sortie doit être définie pour toutes les combinaisons d’entrées. Une description incomplète à l’intérieur d’un processus peut conduire à l’inférence involontaire d’un verrou, ou latch.

Processus combinatoire complet  |  VHDL
process(a, b, sel)
begin
    y <= '0';  -- Valeur par défaut

    if sel = '0' then
        y <= a;
    else
        y <= b;
    end if;
end process;

 

Attention — Prévention des latches

Attribuer une valeur dans toutes les branches ou définir une valeur par défaut au début du processus. Pour une simple porte logique, une affectation concurrente est souvent plus claire.

 


 

 

3.5 Premier exemple VHDL

Cette section construit quatre portes élémentaires. Chaque description comporte les clauses de contexte, une entité et une architecture. Les fichiers peuvent être compilés séparément dans la bibliothèque de travail.

3.5.1 Description d’une porte ET

La porte ET produit 1 uniquement lorsque ses deux entrées valent 1.

a

b

s = a AND b

000
010
100
111

 

Fichier porte_et.vhd  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity porte_et is
    port (
        a : in  std_logic;
        b : in  std_logic;
        s : out std_logic
    );
end entity porte_et;

architecture rtl of porte_et is
begin
    s <= a and b;
end architecture rtl;

 

3.5.2 Description d’une porte OU

La porte OU produit 1 lorsqu’au moins une entrée vaut 1.

a

b

s = a OR b

000
011
101
111

 

Fichier porte_ou.vhd  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity porte_ou is
    port (
        a : in  std_logic;
        b : in  std_logic;
        s : out std_logic
    );
end entity porte_ou;

architecture rtl of porte_ou is
begin
    s <= a or b;
end architecture rtl;

 

3.5.3 Description d’un inverseur

L’inverseur produit le complément logique de son entrée.

a

s = NOT a

01
10

 

Fichier inverseur.vhd  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity inverseur is
    port (
        a : in  std_logic;
        s : out std_logic
    );
end entity inverseur;

architecture rtl of inverseur is
begin
    s <= not a;
end architecture rtl;

 

3.5.4 Description d’une porte XOR

La porte XOR produit 1 lorsque ses deux entrées sont différentes.

a

b

s = a XOR b

000
011
101
110

 

Fichier porte_xor.vhd  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity porte_xor is
    port (
        a : in  std_logic;
        b : in  std_logic;
        s : out std_logic
    );
end entity porte_xor;

architecture rtl of porte_xor is
begin
    s <= a xor b;
end architecture rtl;

 

3.5.5 Compilation et simulation

La compilation comporte au minimum une phase d’analyse syntaxique. Le simulateur construit ensuite le modèle élaboré avant d’exécuter le banc de test. La procédure exacte dépend de l’outil utilisé.

Étape

Action

Résultat attendu

1. Créer le fichierEnregistrer porte_et.vhd.Le fichier contient entité et architecture.
2. AnalyserCompiler ou analyser le fichier.Aucune erreur syntaxique.
3. ÉlaborerSélectionner l’entité ou le testbench supérieur.Le modèle hiérarchique est construit.
4. SimulerLancer le testbench.Les signaux sont calculés dans le temps.
5. ObserverOuvrir le chronogramme.La sortie respecte la table de vérité.

 

3.5.6 Commandes GHDL

Compilation et élaboration avec GHDL  |  Terminal
ghdl -a --std=08 porte_et.vhd
ghdl -a --std=08 tb_porte_et.vhd
ghdl -e --std=08 tb_porte_et

 

Simulation et génération d’un chronogramme  |  Terminal
ghdl -r --std=08 tb_porte_et    --vcd=tb_porte_et.vcd    --stop-time=50ns

gtkwave tb_porte_et.vcd

 

3.5.7 Banc de test de la porte ET

Le banc de test n’a généralement aucun port. Il crée des signaux locaux, instancie le composant à vérifier et applique successivement les combinaisons d’entrées.

Fichier tb_porte_et.vhd — Partie 1  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity tb_porte_et is
end entity tb_porte_et;

architecture simulation of tb_porte_et is
    signal a : std_logic := '0';
    signal b : std_logic := '0';
    signal s : std_logic;
begin
    DUT : entity work.porte_et(rtl)
        port map (
            a => a,
            b => b,
            s => s
        );

 

Fichier tb_porte_et.vhd — Partie 2  |  VHDL
    stimuli : process
    begin
        a <= '0'; b <= '0'; wait for 10 ns;
        a <= '0'; b <= '1'; wait for 10 ns;
        a <= '1'; b <= '0'; wait for 10 ns;
        a <= '1'; b <= '1'; wait for 10 ns;

        wait;
    end process;
end architecture simulation;

 

3.5.8 Vérification automatique avec assert

Les assertions rendent le testbench auto-vérifiant. Le simulateur signale immédiatement un écart entre le résultat observé et la valeur attendue.

Stimuli avec assertions  |  VHDL
stimuli : process
begin
    a <= '0'; b <= '0'; wait for 1 ns;
    assert s = '0'
        report "Erreur pour a=0, b=0"
        severity error;

    a <= '0'; b <= '1'; wait for 1 ns;
    assert s = '0'
        report "Erreur pour a=0, b=1"
        severity error;

    a <= '1'; b <= '0'; wait for 1 ns;
    assert s = '0'
        report "Erreur pour a=1, b=0"
        severity error;

    a <= '1'; b <= '1'; wait for 1 ns;
    assert s = '1'
        report "Erreur pour a=1, b=1"
        severity error;

    report "Test de la porte ET termine avec succes"
        severity note;
    wait;
end process;

 

3.5.9 Lecture du chronogramme

Le chronogramme doit être lu horizontalement. À chaque intervalle de temps, on relève les entrées a et b, puis la sortie s. Un faible décalage d’un cycle delta peut apparaître entre l’affectation des entrées et la mise à jour de la sortie, même lorsqu’aucun retard physique n’est spécifié.

Temps indicatif

a

b

s attendu

0 à 10 ns000
10 à 20 ns010
20 à 30 ns100
30 à 40 ns111

 

3.5.10 Diagnostic des erreurs de compilation

Message ou symptôme

Explication probable

Action corrective

No declaration for std_logicLe paquetage STD_LOGIC_1164 n’est pas visible.Ajouter les clauses IEEE.
Missing ';'Point-virgule absent ou erreur située juste avant.Vérifier la fin de la déclaration précédente.
Entity not foundL’entité n’a pas été analysée ou le nom est incorrect.Compiler dans le bon ordre et vérifier le nom.
Port map mismatchNom, type ou largeur de port incompatible.Comparer le port map avec l’entité.
Bound check failureVecteurs de tailles incompatibles.Corriger les dimensions ou convertir explicitement.
Sortie U ou XSignal non initialisé ou conflit de pilotes.Initialiser les signaux et vérifier les connexions.

 

Travaux pratiques

TP 1 — Premiers circuits en VHDL

1. Objectifs du TP

  • créer un projet VHDL correctement organisé ;
  • écrire les entités et architectures de portes logiques ;
  • compiler chaque fichier et corriger les erreurs syntaxiques ;
  • construire un circuit combinatoire à plusieurs entrées ;
  • écrire un banc de test ;
  • vérifier les tables de vérité par chronogramme et assertions.

2. Matériel et logiciels

  • un ordinateur avec un éditeur de texte ou un environnement FPGA ;
  • GHDL et GTKWave, ou ModelSim/Questa, Vivado Simulator, Quartus Prime ;
  • un répertoire de travail nommé tp1_premiers_circuits ;
  • VHDL-2008 recommandé pour les exemples.

3. Organisation des fichiers

Arborescence proposée  |  Arborescence
tp1_premiers_circuits/
├── src/
│   ├── porte_and.vhd
│   ├── porte_or.vhd
│   ├── porte_xor.vhd
│   └── circuit_multi.vhd
└── sim/
    ├── tb_portes.vhd
    └── tb_circuit_multi.vhd

 

4. Partie A — Création d’une porte AND

Créer le fichier src/porte_and.vhd. Utiliser deux entrées a et b et une sortie y.

Correction attendue — porte_and.vhd  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity porte_and is
    port (
        a : in  std_logic;
        b : in  std_logic;
        y : out std_logic
    );
end entity porte_and;

architecture rtl of porte_and is
begin
    y <= a and b;
end architecture rtl;

 

  1. Analyser le fichier avec le compilateur.
  2. Corriger toute erreur de syntaxe.
  3. Vérifier que l’entité compilée apparaît dans la bibliothèque de travail.
  4. Relever les quatre lignes de la table de vérité.

5. Partie B — Création d’une porte OR

Créer src/porte_or.vhd en conservant la même interface et en modifiant uniquement l’opérateur logique.

Correction attendue — porte_or.vhd  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity porte_or is
    port (
        a : in  std_logic;
        b : in  std_logic;
        y : out std_logic
    );
end entity porte_or;

architecture rtl of porte_or is
begin
    y <= a or b;
end architecture rtl;

 

6. Partie C — Création d’une porte XOR

Créer src/porte_xor.vhd. La sortie doit valoir 1 uniquement lorsque les entrées sont différentes.

Correction attendue — porte_xor.vhd  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity porte_xor is
    port (
        a : in  std_logic;
        b : in  std_logic;
        y : out std_logic
    );
end entity porte_xor;

architecture rtl of porte_xor is
begin
    y <= a xor b;
end architecture rtl;

 

7. Partie D — Banc de test commun aux trois portes

Le banc de test suivant applique toutes les combinaisons de a et b et vérifie simultanément les trois sorties.

tb_portes.vhd — Déclarations et instanciations  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity tb_portes is
end entity tb_portes;

architecture simulation of tb_portes is
    signal a, b  : std_logic := '0';
    signal y_and : std_logic;
    signal y_or  : std_logic;
    signal y_xor : std_logic;
begin
    U_AND : entity work.porte_and(rtl)
        port map (a => a, b => b, y => y_and);

    U_OR : entity work.porte_or(rtl)
        port map (a => a, b => b, y => y_or);

    U_XOR : entity work.porte_xor(rtl)
        port map (a => a, b => b, y => y_xor);

 

tb_portes.vhd — Stimuli  |  VHDL
    stimuli : process
    begin
        a <= '0'; b <= '0'; wait for 10 ns;
        a <= '0'; b <= '1'; wait for 10 ns;
        a <= '1'; b <= '0'; wait for 10 ns;
        a <= '1'; b <= '1'; wait for 10 ns;

        report "Fin de la simulation des portes"
            severity note;
        wait;
    end process;
end architecture simulation;

 

8. Table des résultats à compléter

a

b

y_and observé

y_or observé

y_xor observé

00   
01   
10   
11   

 

9. Partie E — Circuit logique à plusieurs entrées

Réaliser le circuit défini par l’équation suivante :

y = (a AND b) OR (c XOR d)

Le circuit possède quatre entrées a, b, c et d. La première solution utilise une équation directe. Une seconde solution peut utiliser des signaux internes pour rendre la structure plus lisible.

circuit_multi.vhd — Solution avec signaux internes  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity circuit_multi is
    port (
        a, b, c, d : in  std_logic;
        y          : out std_logic
    );
end entity circuit_multi;

architecture rtl of circuit_multi is
    signal terme_et  : std_logic;
    signal terme_xor : std_logic;
begin
    terme_et  <= a and b;
    terme_xor <= c xor d;
    y         <= terme_et or terme_xor;
end architecture rtl;

 

10. Banc de test exhaustif du circuit multi-entrées

Quatre entrées binaires donnent seize combinaisons. Une boucle permet de les générer systématiquement. Le testbench utilise NUMERIC_STD pour convertir un entier en vecteur binaire.

tb_circuit_multi.vhd — Partie 1  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity tb_circuit_multi is
end entity tb_circuit_multi;

architecture simulation of tb_circuit_multi is
    signal entree : std_logic_vector(3 downto 0) :=
                    (others => '0');
    signal y      : std_logic;
begin
    DUT : entity work.circuit_multi(rtl)
        port map (
            a => entree(3),
            b => entree(2),
            c => entree(1),
            d => entree(0),
            y => y
        );

 

tb_circuit_multi.vhd — Partie 2  |  VHDL
    stimuli : process
        variable attendu : std_logic;
    begin
        for i in 0 to 15 loop
            entree <= std_logic_vector(to_unsigned(i, 4));
            wait for 1 ns;

            attendu :=
                (entree(3) and entree(2))
                or
                (entree(1) xor entree(0));

            assert y = attendu
                report "Erreur pour la combinaison "
                       & integer'image(i)
                severity error;

            wait for 9 ns;
        end loop;

        report "Toutes les combinaisons sont valides"
            severity note;
        wait;
    end process;
end architecture simulation;

 

11. Commandes de compilation du TP

Analyse de tous les fichiers sources  |  Terminal
ghdl -a --std=08 src/porte_and.vhd
ghdl -a --std=08 src/porte_or.vhd
ghdl -a --std=08 src/porte_xor.vhd
ghdl -a --std=08 src/circuit_multi.vhd

 

Simulation des portes  |  Terminal
ghdl -a --std=08 sim/tb_portes.vhd
ghdl -e --std=08 tb_portes
ghdl -r --std=08 tb_portes    --vcd=tb_portes.vcd    --stop-time=50ns

 

Simulation du circuit multi-entrées  |  Terminal
ghdl -a --std=08 sim/tb_circuit_multi.vhd
ghdl -e --std=08 tb_circuit_multi
ghdl -r --std=08 tb_circuit_multi    --vcd=tb_circuit_multi.vcd    --stop-time=170ns

 

12. Vérifications demandées

  • La compilation se termine sans erreur.
  • Les trois portes respectent leurs tables de vérité.
  • Le chronogramme contient a, b, y_and, y_or et y_xor.
  • Le circuit multi-entrées est correct pour les seize combinaisons.
  • Aucune assertion de niveau error n’apparaît.
  • Les fichiers sont correctement nommés et commentés.

13. Questions d’analyse

  1. Pourquoi les instructions y_and, y_or et y_xor peuvent-elles être évaluées en parallèle ?
  2. Quelle est la différence entre l’entité et l’architecture de porte_and ?
  3. Pourquoi la bibliothèque IEEE doit-elle être déclarée dans chaque fichier indépendant ?
  4. Quel avantage apporte l’utilisation de signaux internes dans circuit_multi ?
  5. Que se passe-t-il si le nom d’un port du port map ne correspond pas à celui de l’entité ?
  6. Pourquoi le banc de test ne possède-t-il pas de ports ?
  7. Quel est l’intérêt d’une assertion par rapport à la seule observation visuelle du chronogramme ?

14. Extensions proposées

  • Ajouter une porte NAND et une porte NOR.
  • Créer une entité unique produisant simultanément AND, OR, XOR et NOT.
  • Modifier circuit_multi pour réaliser y = NOT((a AND b) OR (c XOR d)).
  • Implémenter le circuit sur une carte FPGA avec quatre interrupteurs et une LED.
  • Créer une version structurelle de circuit_multi en instanciant les portes déjà développées.

15. Barème indicatif

Critère

Points

Organisation du projet et noms des fichiers2
Porte AND correcte2
Porte OR correcte2
Porte XOR correcte2
Circuit multi-entrées4
Bancs de test et couverture des cas4
Compilation, simulation et chronogrammes2
Réponses aux questions et qualité du compte rendu2
Total20

 

Synthèse du chapitre

Notion

À retenir

BibliothèqueContient des unités compilées et accessibles par un nom logique.
PaquetagePartage des types, constantes, déclarations et sous-programmes.
EntitéDéfinit l’interface externe et les modes des ports.
ArchitectureDécrit la réalisation interne de l’entité.
ConfigurationSélectionne une architecture ou des liaisons de composants.
Corps de paquetageImplémente les fonctions et procédures déclarées.
library/useRendent accessibles une bibliothèque et les éléments d’un paquetage.
Instructions concurrentesReprésentent du matériel fonctionnant en parallèle.
Banc de testApplique des stimuli et vérifie les sorties sans ports externes.
SimulationValide le comportement avant l’implantation matérielle.

 

Autoévaluation

1. Quelle unité décrit l’interface d’un composant ?

Réponse : L’entité.

2. Quelle unité décrit son fonctionnement interne ?

Réponse : L’architecture.

3. Quel paquetage définit std_logic ?

Réponse : IEEE.STD_LOGIC_1164.

4. Quel est le mode normal d’une entrée ?

Réponse : in.

5. Quel mode correspond à un bus bidirectionnel ?

Réponse : inout.

6. Les affectations placées directement dans une architecture sont-elles séquentielles ?

Réponse : Non, elles sont concurrentes.

7. Que représente work ?

Réponse : La bibliothèque de travail courante.

8. Pourquoi utiliser un testbench ?

Réponse : Pour appliquer des stimuli et vérifier le comportement du composant.

Mini-exercice de consolidation

Écrire l’entité et l’architecture d’un circuit possédant trois entrées a, b et c et une sortie y telle que : y = (a OR b) AND NOT(c).

Correction proposée  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity exercice_consolidation is
    port (
        a, b, c : in  std_logic;
        y       : out std_logic
    );
end entity exercice_consolidation;

architecture rtl of exercice_consolidation is
begin
    y <= (a or b) and (not c);
end architecture rtl;

 

Suite du cours — Transition vers le chapitre suivant

Après avoir maîtrisé la structure générale d’une description VHDL, l’étudiant peut approfondir les types de données, les objets du langage, les conversions et les opérations arithmétiques.