Cours introduction synthèse logique v.h.d.l. vhdl VHDL Téléc
Télécharger PDFIntroduction à la Synthèse logique VHDL
I) Introduction
Pourquoi avoir créé un langage de description de structures électroniques (Hardware Description Language - HDL) comme le VHDL ? L'abréviation VHDL signifie VHSIC Hardware Description Language (VHSIC : Very High Speed Integrated Circuit).
Ce langage a été initialement développé dans les années 70 pour la simulation de circuits électroniques. Il a ensuite été enrichi avec des extensions permettant la conception (synthèse) de circuits logiques programmables (PLD - Programmable Logic Device).
Auparavant, pour décrire le fonctionnement d'un circuit électronique programmable, les techniciens et ingénieurs utilisaient des langages de bas niveau (ABEL, PALASM, etc.) ou des outils de saisie de schémas. Aujourd'hui, la densité des fonctions logiques (portes et bascules) intégrées dans les PLD est si élevée (plusieurs milliers, voire des millions de portes) qu'il n'est plus envisageable d'utiliser les outils d'autrefois.
Les entreprises de développement et les ingénieurs ont souhaité s'affranchir des contraintes technologiques des circuits. Ils ont ainsi créé des langages de haut niveau tels que VHDL et VERILOG. Ces langages permettent de s'abstraire des spécificités technologiques des PLD, rendant le code écrit portable ; une description élaborée pour un circuit peut être facilement adaptée pour un autre.
Il est crucial de comprendre que ces langages de haut niveau permettent de matérialiser les structures électroniques d'un circuit. En effet, les instructions écrites dans ces langages se traduisent par une configuration logique de portes et de bascules intégrée aux circuits PLD. C'est pourquoi il est plus précis de parler de "description VHDL ou VERILOG" que de "langage VHDL ou VERILOG".
Dans ce document, nous nous concentrerons uniquement sur le VHDL et ses fonctionnalités de base utilisées lors des phases de conception ou de synthèse, c'est-à-dire pour la création de PLD.
II) Relation entre une description VHDL et les circuits logiques programmables
Décrire le fonctionnement d'un circuit logique programmable est essentiel, mais comment établir le lien avec sa structure physique ? L'implantation d'une ou plusieurs descriptions VHDL dans un PLD dépendra de l'affectation des broches d'entrées/sorties et des structures de base du circuit logique programmable.
II.1) Schéma fonctionnel d'implantation de descriptions VHDL dans un circuit logique programmable
Lors de la phase de synthèse, chaque bloc fonctionnel décrit en VHDL sera matérialisé par des portes logiques et/ou des bascules. La phase suivante consiste à implanter ces portes et bascules à l'intérieur du circuit logique. Cette tâche est réalisée par le logiciel de placement/routage (souvent appelé "Fitter"), durant laquelle les entrées et sorties sont affectées à des numéros de broches spécifiques.
Souvent, dans la description fonctionnelle d'un PLD, une fonction de synchronisation est nécessaire pour cadencer l'ensemble du fonctionnement. Celle-ci est très fréquemment réalisée par une machine d'états synchronisée par une horloge.
II.2) L'affectation des broches d'entrées/sorties
L'affectation des broches peut être réalisée de plusieurs manières :
- 1) L'affectation automatique : Le synthétiseur et le "Fitter" du fabricant du circuit implantent automatiquement la structure correspondant à la description VHDL. Les numéros de broches sont alors choisis de façon autonome par l'outil.
- 2) L'affectation manuelle : Les numéros de broches sont définis explicitement dans la description VHDL, sur un schéma bloc décrivant les liaisons entre les différents blocs VHDL, ou dans un fichier texte propre au fabricant. Les numéros de broches sont affectés selon les consignes spécifiées par l'utilisateur.
II.3) Organisation fonctionnelle de développement d’un PLD
Le développement d'un PLD suit généralement un processus structuré, incluant plusieurs étapes clés :
- Entrée de la description : La conception peut être saisie sous forme schématique ou textuelle via des langages HDL comme le VHDL. Il est aussi possible d'utiliser des diagrammes d'états.
- Vérification initiale : Un contrôle des erreurs et de la syntaxe VHDL est effectué pour s'assurer de la validité du code.
- Simulation comportementale : Avant la synthèse, une simulation comportementale (à l'aide de "stimuli" ou "testbenches") permet de vérifier le fonctionnement logique de la description VHDL, sans tenir compte des délais physiques.
- Synthèse : Le synthétiseur convertit la description VHDL en un ensemble de portes logiques et de bascules de base, adapté au circuit cible (CPLD ou FPGA). Il est possible de spécifier des contraintes de technologie, comme la vitesse de fonctionnement.
- Placement et routage : Des outils spécifiques au fabricant prennent le relais pour optimiser le placement des portes et bascules sur la puce et réaliser le routage des interconnexions au sein du circuit choisi.
- Simulation temporelle : Après le placement et le routage, une nouvelle simulation (temporelle) est réalisée pour vérifier le fonctionnement du circuit en tenant compte des retards de propagation réels.
- Programmation du circuit : Le circuit est programmé soit en utilisant un programmateur externe, soit en téléchargeant le code JEDEC directement sur le dispositif technique (via JTAG ou ISP).
III) Structure d’une description VHDL simple
Une description VHDL est composée de deux parties indissociables :
- L'entité (ENTITY) : Elle définit l'interface externe du circuit, c'est-à-dire ses entrées et ses sorties.
- L'architecture (ARCHITECTURE) : Elle contient les instructions VHDL qui décrivent le fonctionnement interne du circuit pour réaliser la logique attendue.
Exemple : Un décodeur 1 parmi 4
library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;
-- Déclaration des bibliothèques
-- Commentaires, en VHDL ils commencent par --
-- Déclaration de l’entité du décodeur
entity DECOD1_4 is
port(IN0, IN1: in std_logic;
D0, D1, D2, D3: out std_logic);
end DECOD1_4;
-- Déclaration de l’architecture du décodeur
architecture DESCRIPTION of DECOD1_4 is
begin
D0 <= (not(IN1) and not(IN0));
D1 <= (not(IN1) and IN0);
D2 <= (IN1 and not(IN0));
D3 <= (IN1 and IN0);
end DESCRIPTION;
III.1) Déclaration des bibliothèques
Toute description VHDL destinée à la synthèse nécessite l'utilisation de bibliothèques. L'IEEE (Institute of Electrical and Electronics Engineers) a normalisé ces bibliothèques, notamment la bibliothèque IEEE1164. Elles contiennent les définitions des types de signaux électroniques, ainsi que des fonctions et sous-programmes permettant de réaliser des opérations arithmétiques et logiques.
Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;
Use ieee.std_logic_unsigned.all; -- Cette dernière bibliothèque est souvent utilisée pour l’écriture de compteurs
La directive Use permet de sélectionner les bibliothèques nécessaires à la compilation et à la synthèse du code.
III.2) Déclaration de l’entité et des entrées/sorties (I/O)
L'entité sert à définir le nom de la description VHDL et ses broches d'entrées/sorties. L'instruction clé pour cette définition est port.
Syntaxe :
entity NOM_DE_L_ENTITE is
port (
Description des signaux d’entrées/sorties
);
end NOM_DE_L_ENTITE;
Exemple :
entity SEQUENCEMENT is
port (
CLOCK : in std_logic;
RESET : in std_logic;
Q : out std_logic_vector(1 downto 0)
);
end SEQUENCEMENT;
Remarque : Après la dernière définition de signal dans l'instruction port, il ne faut jamais mettre de point-virgule.
L'instruction port requiert la définition de chaque signal avec son nom, son sens et son type.
Syntaxe pour un signal :
NOM_DU_SIGNAL : sens type;
Exemple :
CLOCK: in std_logic;
BUS : out std_logic_vector (7 downto 0);
III.2.1) Le NOM_DU_SIGNAL
Le nom d'un signal est composé de caractères. Le premier caractère doit être une lettre. Sa longueur est quelconque, mais il ne doit pas dépasser une ligne de code. VHDL n'est pas sensible à la "casse", c'est-à-dire qu'il ne fait pas de distinction entre les majuscules et les minuscules.
III.2.2) Le SENS du signal
Le sens d'un signal détermine sa direction par rapport à l'entité :
in: pour un signal en entrée.out: pour un signal en sortie.inout: pour un signal bidirectionnel (entrée/sortie).buffer: pour un signal en sortie qui peut être lu à l'intérieur de la même architecture (utilisé comme entrée interne).
III.2.3) Le TYPE
Les types les plus couramment utilisés pour les signaux d'entrées/sorties sont :
std_logic: pour un signal unique (1 bit).std_logic_vector: pour un bus composé de plusieurs signaux (plusieurs bits).
Par exemple, un bus bidirectionnel de 5 bits s'écrira :
LATCH : inout std_logic_vector (4 downto 0);
Dans cet exemple, LATCH(4) correspond au bit de poids fort (MSB) et LATCH(0) correspond au bit de poids faible (LSB).
Les valeurs que peut prendre un signal de type std_logic sont :
'0'ou'L': pour un niveau bas.'1'ou'H': pour un niveau haut.'Z': pour un état haute impédance.'-': Quelconque (don't care), c'est-à-dire '0' ou '1'. Cette valeur est très utilisée avec les instructions conditionnelles commewhen...elseetwith...select.
III.2.4) Affectation des numéros de broches en utilisant des attributs supplémentaires
La définition des numéros de broches via des attributs supplémentaires est spécifique au logiciel de développement utilisé.
Exemple de syntaxe pour l'affectation de broches (peut varier selon l'outil) :
entity AFFICHAGE is
port( CLK, RESET, DATA: in std_logic;
S: buffer std_logic_vector(9 downto 0));
-- C’est la ligne ci-dessous qui définit les numéros de broches
attribute pin_numbers of AFFICHAGE:entity is "S(9):23 S(8):22 S(7):21 S(6):20 S(5):19 S(4):18 S(3):17 S(2):16 S(1):15 S(0):14";
end AFFICHAGE;
Autre exemple d'affectation manuelle de broches :
entity DECODAGE is
port ( ADRESSE : in std_logic_vector (15 downto 10);
RAM0 : out std_logic;
RAM1 : out std_logic;
RAM2 : out std_logic;
RAM3 : out std_logic;
ROM : out std_logic;
INTER1 : out std_logic;
INTER2 : out std_logic;
INTER3 : out std_logic);
-- Ce sont les lignes ci-dessous qui définissent les numéros de broches
-- Assignation manuelle des broches
attribute PLDPIN:string;
attribute PLDPIN of ADRESSE: signal is "7,6,5,4,3,2"; -- Attention : LSB en premier !
attribute PLDPIN of RAM0: signal is "19";
attribute PLDPIN of RAM1: signal is "18";
attribute PLDPIN of RAM2: signal is "17";
attribute PLDPIN of RAM3: signal is "16";
attribute PLDPIN of ROM: signal is "15";
attribute PLDPIN of INTER1: signal is "14";
attribute PLDPIN of INTER2: signal is "13";
attribute PLDPIN of INTER3: signal is "12";
end DECODAGE;
III.2.5) Exemples de description d’entités
entity COUNT is
port(CLK, RST: in std_logic;
CNT: inout std_logic_vector(2 downto 0));
end COUNT;
entity MAGNITUDE is
port( A, B: in std_logic_vector(7 downto 0);
AGRB: buffer std_logic));
end MAGNITUDE;
entity 7SEG is
port ( A : in std_logic;
B : in std_logic;
C : in std_logic;
D : in std_logic;
SA : out std_logic;
SB : out std_logic;
SC : out std_logic;
SD : out std_logic;
SE : out std_logic;
SF : out std_logic;
SG : out std_logic
);
end 7SEG;
entity IMAGE3 is
port (CLK : in std_logic;
S,I : out std_logic);
end IMAGE3;
entity COMP4BIT is
port (A,B :in std_logic_vector(3 downto 0);
PLUS,MOINS,EGAL :out std_logic);
end COMP4BIT;
entity COMPT_4 is
port (H,R :in std_logic;
Q :out std_logic_vector(3 downto 0));
end COMPT_4;
entity DECAL_D is
port (H,R,IN_SERIE :in std_logic;
OUT_SERIE :out std_logic);
end DECAL_D;
III.3) Déclaration de l’architecture correspondante à l’entité : description du fonctionnement
L'architecture décrit le fonctionnement souhaité pour un circuit ou une partie de celui-ci. Le fonctionnement d'un circuit est souvent décomposé en plusieurs modules VHDL, où un "module" désigne le couple Entité/Architecture. Dans le cas de PLD simples, on retrouve fréquemment un seul module. L'architecture établit, par le biais d'instructions, les relations entre les entrées et les sorties. Elle peut implémenter un fonctionnement purement combinatoire, séquentiel, ou une combinaison des deux.
Exemples :
Opérateurs logiques de base
entity PORTES is
port (A,B :in std_logic;
Y1,Y2,Y3,Y4,Y5,Y6,Y7:out std_logic);
end PORTES;
architecture DESCRIPTION of PORTES is
begin
Y1 <= A and B;
Y2 <= A or B;
Y3 <= A xor B;
Y4 <= not A;
Y5 <= A nand B;
Y6 <= A nor B;
Y7 <= not(A xor B);
end DESCRIPTION;
Décodeur 7 segments
entity DEC7SEG4 is
port (DEC :in std_logic_vector(3 downto 0);
SEG:out std_logic_vector(0 downto 6));
end DEC7SEG4;
architecture DESCRIPTION of DEC7SEG4 is
begin
SEG <= "1111110" when DEC = 0 else -- 0
"0110000" when DEC = 1 else -- 1
"1101101" when DEC = 2 else -- 2
"1111001" when DEC = 3 else -- 3
"0110011" when DEC = 4 else -- 4
"1011011" when DEC = 5 else -- 5
"1011111" when DEC = 6 else -- 6
"1110000" when DEC = 7 else -- 7
"1111111" when DEC = 8 else -- 8
"1111011" when DEC = 9 else -- 9
"-------"; -- Autres valeurs (don't care)
end DESCRIPTION;
Décodage d’adresses
Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;
entity DECODAGE is
port ( A15, A14, A13, A12, A11, A10 : in std_logic;
RAM0 : out std_logic;
RAM1 : out std_logic;
RAM2 : out std_logic;
RAM3 : out std_logic;
ROM : out std_logic;
INTER1 : out std_logic;
INTER2 : out std_logic;
INTER3 : out std_logic);
end DECODAGE;
architecture DESCRIPTION of DECODAGE is
signal ADRESSE: std_logic_vector(15 downto 0);
begin
-- Définition du bus d’adresses, complété par des '0' pour les bits inférieurs
ADRESSE <= A15 & A14 & A13 & A12 & A11 & A10 & "0000000000";
-- Affectation des signaux de sélection en fonction des plages d'adresses
ROM <= '0' when (ADRESSE >= x"E000") and (ADRESSE <= x"FFFF") else '1';
RAM0 <= '0' when (ADRESSE >= x"0000") and (ADRESSE <= x"03FF") else '1';
RAM1 <= '0' when (ADRESSE >= x"0400") and (ADRESSE <= x"07FF") else '1';
RAM2 <= '0' when (ADRESSE >= x"0800") and (ADRESSE <= x"0BFF") else '1';
RAM3 <= '0' when (ADRESSE >= x"0C00") and (ADRESSE <= x"0FFF") else '1';
INTER1 <= '0' when (ADRESSE >= x"8000") and (ADRESSE <= x"8001") else '1';
INTER2 <= '0' when (ADRESSE >= x"A000") and (ADRESSE <= x"A001") else '1';
INTER3 <= '0' when (ADRESSE >= x"C000") and (ADRESSE <= x"C00F") else '1';
end DESCRIPTION;
IV) Les instructions de base (mode « concurrent »), logique combinatoire
Qu'est-ce que le mode « concurrent » ? Dans une description VHDL, toutes les instructions sont évaluées et affectent les signaux de sortie simultanément. L'ordre dans lequel elles sont écrites n'a aucune importance. En effet, la description VHDL génère des structures électroniques matérielles, ce qui constitue une différence fondamentale avec un langage informatique classique où les instructions sont exécutées séquentiellement.
Avec VHDL, il est essentiel de visualiser la structure matérielle qui sera générée par le synthétiseur lors de la rédaction de la description, ce qui n'est pas toujours intuitif pour les débutants.
Exemple : Pour un décodeur 1 parmi 4, l'ordre des instructions est indifférent.
architecture DESCRIPTION of DECOD1_4 is
begin
D0 <= (not(IN1) and not(IN0)); -- Première instruction
D1 <= (not(IN1) and IN0); -- Deuxième instruction
D2 <= (IN1 and not(IN0)); -- Troisième instruction
D3 <= (IN1 and IN0); -- Quatrième instruction
end DESCRIPTION;
L'architecture ci-dessous est équivalente, malgré un ordre différent des affectations :
architecture DESCRIPTION of DECOD1_4 is
begin
D1 <= (not(IN1) and IN0); -- Deuxième instruction
D2 <= (IN1 and not(IN0)); -- Troisième instruction
D0 <= (not(IN1) AND not(IN0)); -- Première instruction (déplacée)
D3 <= (IN1 AND IN0); -- Quatrième instruction
end DESCRIPTION;
L'instruction définissant l'état de D0 ayant été déplacée à la troisième ligne, la synthèse de cette architecture produira un circuit équivalent à la première.
IV.1) Les opérateurs
IV.1.1) L’affectation simple : <=
Dans une description VHDL, l'opérateur <= est probablement le plus couramment utilisé. Il permet de modifier l'état d'un signal en fonction d'autres signaux et/ou d'opérateurs.
Exemple avec des portes logiques :
S1 <= E2 and E1;
Les valeurs numériques que l'on peut affecter à un signal sont les suivantes :
'1'ou'H': pour un niveau haut (signal de 1 bit).'0'ou'L': pour un niveau bas (signal de 1 bit).'Z': pour un état haute impédance (signal de 1 bit).'-': pour un état quelconque ('0' ou '1'). Cette valeur est souvent utilisée avec les instructions conditionnelleswhen...elseetwith...select.
Pour les signaux composés de plusieurs bits (bus), on utilise les guillemets "...". Les bases numériques utilisées pour les bus peuvent être :
- BINAIRE : Exemple :
BUS <= "1001";-- BUS = 9 en décimal - HEXADÉCIMAL : Exemple :
BUS <= X"9";-- BUS = 9 en décimal - OCTAL : Exemple :
BUS <= O"11";-- BUS = 9 en décimal
Remarque : La base décimale ne peut pas être utilisée directement lors de l'affectation de signaux sous forme de littéraux. Elle peut seulement être employée avec certains opérateurs arithmétiques comme + et -.
FAQ
Qu'est-ce que le VHDL et à quoi sert-il ?
Le VHDL (VHSIC Hardware Description Language) est un langage de description matérielle (HDL) utilisé pour la conception, la simulation et la synthèse de circuits électroniques numériques, notamment les circuits logiques programmables (PLD, FPGA). Il permet de décrire le comportement et la structure de ces circuits à un niveau d'abstraction élevé.
Quelles sont les deux parties principales d'une description VHDL ?
Une description VHDL est composée de deux parties indissociables : l'Entité (ENTITY), qui définit l'interface externe du circuit (ses entrées et sorties), et l'Architecture (ARCHITECTURE), qui décrit le fonctionnement interne du circuit en spécifiant la logique de ses opérations.
Quelle est la différence fondamentale entre le mode "concurrent" du VHDL et un langage de programmation classique ?
Dans le mode "concurrent" du VHDL, toutes les instructions sont évaluées et exécutées simultanément, comme des composants matériels fonctionnant en parallèle. En revanche, un langage de programmation classique exécute les instructions séquentiellement, les unes après les autres. Le VHDL modélise le parallélisme inhérent au matériel, tandis que les langages de programmation modélisent le flux d'exécution sériel.