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.1 | Unités de conception | Reconnaître les briques d’un projet VHDL |
| 3.2 | Bibliothèques et paquetages | Rendre les types et fonctions visibles |
| 3.3 | Entité | Définir l’interface d’un composant |
| 3.4 | Architecture | Décrire son fonctionnement interne |
| 3.5 | Premiers exemples | Compiler et simuler des portes logiques |
| TP 1 | Premiers circuits en VHDL | Dé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èque | Conteneur logique regroupant des unités compilées. | IEEE, work, bibliothèque propriétaire |
| Paquetage | Regroupe 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 |
| Architecture | Décrit le fonctionnement interne associé à une entité. | Équations logiques, processus, instanciations |
| Configuration | Sélectionne l’architecture ou les composants utilisés. | Choix entre plusieurs implémentations |
| Corps de paquetage | Contient 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 |
|---|---|---|
| Architecture | Entité | L’architecture est toujours associée à une entité. |
| Architecture | Paquetage | Elle peut utiliser les types et fonctions rendus visibles. |
| Corps de paquetage | Paquetage | Il implémente les sous-programmes déclarés. |
| Configuration | Entité et architecture | Elle choisit l’implémentation à utiliser. |
| Banc de test | Entité testée | Il 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_1164 | Types std_logic et std_logic_vector, opérateurs logiques. | Signaux numériques à plusieurs états |
| NUMERIC_STD | Types signed et unsigned, opérations arithmétiques. | Compteurs, additionneurs, comparaisons |
| MATH_REAL | Fonctions mathématiques sur les réels. | Calculs de constantes, surtout en simulation |
| FIXED_PKG | Types et opérations en virgule fixe. | Traitement numérique du signal |
| FLOAT_PKG | Repré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 inconnu | STD_LOGIC_1164 non rendu visible. | Ajouter library IEEE et use IEEE.STD_LOGIC_1164.ALL. |
| signed ou unsigned inconnu | NUMERIC_STD absent. | Ajouter use IEEE.NUMERIC_STD.ALL. |
| Un composant est introuvable | Unité non compilée ou mauvaise bibliothèque. | Vérifier l’ordre de compilation et le nom de bibliothèque. |
| Nom ambigu | Plusieurs paquetages exportent le même identifiant. | Qualifier le nom ou limiter les clauses use. |
| Erreur après regroupement de fichiers | Contexte 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_10 | c1 | Le premier nom décrit la fonction. |
| registre_decalage | reg | Le nom précis facilite la maintenance. |
| decodeur_7segments | decode | La destination du décodeur est claire. |
| uart_emetteur | module_uart | Le 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 |
|---|---|---|---|---|
| in | Oui | Non | Entrées de données, commande, horloge | Très courant |
| out | Selon version VHDL | Oui | Résultat ou commande de sortie | À privilégier pour les sorties |
| inout | Oui | Oui | Bus bidirectionnel, E/S trois états | Utiliser seulement si nécessaire |
| buffer | Oui | Oui | Sortie relue localement | Souvent 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 port | Erreur de syntaxe selon la forme écrite. | Ne pas mettre de séparateur inutile avant la parenthèse fermante. |
| Type non visible | Le 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 port | Lecture ou pilotage interdit. | Choisir in, out ou inout selon le besoin. |
| Nom de fin incohérent | Erreur 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 |
|---|---|---|
| rtl | Register Transfer Level | Description synthétisable de registres et de logique |
| comportementale | Description du comportement attendu | Modélisation ou logique algorithmique |
| structurelle | Assemblage de sous-composants | Conception hiérarchique |
| flot_donnees | Équations et affectations concurrentes | Circuits combinatoires |
| simulation | Modèle destiné à la vérification | Peut 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 simple | Décrit une relation logique directe. | s <= a and b; |
| Affectation conditionnelle | Sélectionne une valeur selon une condition. | y <= a when sel='0' else b; |
| Affectation sélectionnée | Choisit parmi plusieurs valeurs. | with sel select ... |
| Processus | Regroupe des instructions séquentielles. | process(a,b) begin ... end process; |
| Instanciation | Utilise un sous-composant. | U1 : entity work.porte_et ... |
| Generate | Ré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 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
| 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 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
| 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 |
|---|---|
| 0 | 1 |
| 1 | 0 |
| 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 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
| 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 fichier | Enregistrer porte_et.vhd. | Le fichier contient entité et architecture. |
| 2. Analyser | Compiler ou analyser le fichier. | Aucune erreur syntaxique. |
| 3. Élaborer | Sélectionner l’entité ou le testbench supérieur. | Le modèle hiérarchique est construit. |
| 4. Simuler | Lancer le testbench. | Les signaux sont calculés dans le temps. |
| 5. Observer | Ouvrir 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 ns | 0 | 0 | 0 |
| 10 à 20 ns | 0 | 1 | 0 |
| 20 à 30 ns | 1 | 0 | 0 |
| 30 à 40 ns | 1 | 1 | 1 |
3.5.10 Diagnostic des erreurs de compilation
Message ou symptôme | Explication probable | Action corrective |
|---|---|---|
| No declaration for std_logic | Le 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 found | L’entité n’a pas été analysée ou le nom est incorrect. | Compiler dans le bon ordre et vérifier le nom. |
| Port map mismatch | Nom, type ou largeur de port incompatible. | Comparer le port map avec l’entité. |
| Bound check failure | Vecteurs de tailles incompatibles. | Corriger les dimensions ou convertir explicitement. |
| Sortie U ou X | Signal 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; |
- Analyser le fichier avec le compilateur.
- Corriger toute erreur de syntaxe.
- Vérifier que l’entité compilée apparaît dans la bibliothèque de travail.
- 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é |
|---|---|---|---|---|
| 0 | 0 | |||
| 0 | 1 | |||
| 1 | 0 | |||
| 1 | 1 |
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
- Pourquoi les instructions y_and, y_or et y_xor peuvent-elles être évaluées en parallèle ?
- Quelle est la différence entre l’entité et l’architecture de porte_and ?
- Pourquoi la bibliothèque IEEE doit-elle être déclarée dans chaque fichier indépendant ?
- Quel avantage apporte l’utilisation de signaux internes dans circuit_multi ?
- Que se passe-t-il si le nom d’un port du port map ne correspond pas à celui de l’entité ?
- Pourquoi le banc de test ne possède-t-il pas de ports ?
- 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 fichiers | 2 |
| Porte AND correcte | 2 |
| Porte OR correcte | 2 |
| Porte XOR correcte | 2 |
| Circuit multi-entrées | 4 |
| Bancs de test et couverture des cas | 4 |
| Compilation, simulation et chronogrammes | 2 |
| Réponses aux questions et qualité du compte rendu | 2 |
| Total | 20 |
Synthèse du chapitre
Notion | À retenir |
|---|---|
| Bibliothèque | Contient des unités compilées et accessibles par un nom logique. |
| Paquetage | Partage des types, constantes, déclarations et sous-programmes. |
| Entité | Définit l’interface externe et les modes des ports. |
| Architecture | Décrit la réalisation interne de l’entité. |
| Configuration | Sélectionne une architecture ou des liaisons de composants. |
| Corps de paquetage | Implémente les fonctions et procédures déclarées. |
| library/use | Rendent accessibles une bibliothèque et les éléments d’un paquetage. |
| Instructions concurrentes | Représentent du matériel fonctionnant en parallèle. |
| Banc de test | Applique des stimuli et vérifie les sorties sans ports externes. |
| Simulation | Valide 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. |