Sie sind auf Seite 1von 9

LE LANGAGE VHDL

I. PRÉSENTATION DU LANGAGE
I.1. Définition
- VHDL est l'acronyme de VHSIC Hardware Description Langage. (Langage de description
matérielle de VHSIC)
- VHSIC est un projet du DOD et signifie : Very High Speed Integrated Circuits. (Circuit
intégré à très haute vitesse).
- DOD : Département de la Défense Américaine. (Department of Défense)
- IEEE signifie : Institute of Electrical and Electronics Engineers (Institut des ingénieurs
d'électronique et d'électricité). C'est L'IEEE qui fixe les normes internationales en matière
d'électricité.
I.2. Le but du langage
Le but principal est de décrire un fonctionnement global de haut niveau, sans soucis des
détails d'implémentation, pour servir de cahier des charges pour la réalisation de projets
complexes.
Un langage de haut niveau est un langage, ou l'on ne s'intéresse par exemple pas ou vont
être stockées les données (exemple le langage C). L'assembleur est un langage de bas niveau.
Le langage VHDL n'était utilisé que pour faire des simulations de fonctions logiques
directement sur ordinateur. Mais après plusieurs évolutions il a permis de programmer des
composants programmable du genre PAL (Programmable Area Logic en français "espace
logique programmable").
I.3. La réalisation d'un programme
Un programme VHDL comporte deux parties
Au début, la partie ENTITY, où l'on déclare les entrées, les sorties ainsi que leurs types.
Ensuite la partie ARCHITECTURE où se situent les lignes de codes du programme.
La fin des lignes est constituée par des points virgules pour la fin des instructions et par des
virgules à l'intérieur d'une instruction.
Les commentaires sont obtenus à l'aide d'un double tiret suivi du commentaire. Bien entendu ils
ne sont pas pris en compte lors de la compilation. En VHDL les commentaires sont des
commentaires de fin de ligne, c'est-à-dire que dés que l'on a mis deux tirets ( -- ) toute la suite
de la ligne est un commentaire et la ligne suivante sera prise en compte dans le programme.

<= : symbole d'affectation se lit reçoit, exemple : a <= b+c; -- se lit : a reçoit b+c
Port : description des entrées et sorties.
Begin : en anglais début -> début d'une instruction.
& symbole de concaténation.
' symbole pour stocker une valeur.
" symbole pour stocker une chaîne de valeur (exemple bit_vector).
II. ENTÊTE DU PROGRAMME
L'entête du programme est de la forme
ENTITY programme_1 IS  --programme_1 est le nom de programme
PORT (
-- Description des entrées et sorties
);
END programme_1; 

1/9
II.1. Entrés et sorties à un bit
La description de toutes les entrées et sorties est obligatoire, pour une entrée on utilise
IN et pour la sortie OUT.
BIT veux dire que l'on a affaire à une seule entrée, et qu'elle peut prendre uniquement la
valeur 1 ou 0.
Exemple :
Entity exemple1 IS
PORT (D0,D1,D2,D3 : IN BIT;.
a,b,c,d,e : OUT BIT);
END exemple1;
Remarque lorsque l'on écrit des équations de récurrence, il faut obligatoirement utiliser
INOUT. C'est-à-dire à la fois une entrée et une sortie comme c'est le cas par exemple avec
l'instruction n<=n+1; ou n est à la fois une entrée est une sortie.
II.2. Entrés et sorties à n bits
Si on souhaite définir rapidement plusieurs bits (nombres à plusieurs bits pour les
données ou les adresses par exemple), on utilise les BIT_VECTOR. Il faut définir le nombre
de bits à l'intérieur du vecteur ainsi que le sens de numérotation. Afin d'éviter toute confusion
dans le sens des bits il faut commencer le bit à une valeur égal à nbits-1 et le finir à 0 en
utilisant l'instruction downto.
Entity exemple2 IS
PORT(
E : IN BIT_VECTOR (3 downto 0)
S: OUT BIT_VECTOR (4 downto 0);
END exemple2;
Ce programme déclare 4 entrées, E désignera le nombre de 4 bits (les 4 entrées a la fois),
E(0) le premier chiffre en partant de la droite (bit de poids faible), E(1) le deuxième chiffre
jusqu'à E(3) le bit de poids fort.
Remarques :
- On a également la possibilité de déclarer des nombres binaires en Entrée/Sortie grâce à
l'instruction INOUT BIT_VECTOR.
- Si on utilise l'instruction to à la place de downto, l'ordre des bits sera inversé
III. ARCHITECTURE D'UN PROGRAMME
L'architecture se met juste après la partie entité.
ARCHITECTURE nom_de_l_architecture OF nom_de_l_entité IS
BEGIN

END nom_de_l_architecture;
Le nom de l'architecture doit être le même que le nom indiqué au début.
Le nom de l'architecture et le nom de l'entité peut être identique mais pour mieux comprendre
les messages d'erreurs venant de la compilation, il est préférable de mettre des noms
différents.
Il y a plusieurs styles de programmation, les plus courants sont.
- A partir des équations
- A partir de la table de vérité
- En décrivant le schéma
III.1. Ecriture à partir des équations logiques
On imaginera une entité précédemment déclarée avec les bits a et b en entrées et y en sortie.

2/9
Equation                         correspondance VHDL
Y = a                                   y <= a;   -- se lit y reçoit a
Y = /a (complément de a)     y <= NOT a;
Y = a.b                                y <= a AND b;
Y = /(a.b)                            y <= NOT (a AND b);
Y = a+b                               y <= a OR b;
Y = /(a+b)                           y <= NOT (a OR b);
Y = a(+) b a ou exclusif b      y <= a XOR b;

Exemple On imaginera une entité précédemment déclarée avec les entrée a, b et c et en sortie
y1 et y2.
ARCHITECTURE exemple OF exempleentite IS
BEGIN --début du programme.
Y1 <=NOT(a AND b) AND (c AND (NOT b) AND (NOT a)); -- ceci est un exemple
Y2 <= (a AND b AND c);
END exemple;
Exemple d'un compteur :
ENTITY cmpt IS PORT (Clk : IN BIT; q0,q1: INOUT BIT);
END cmpt;
ARCHITECTURE acmpt OF cmpt IS
BEGIN
Cmpt1 : PROCESS (clk)
BEGIN     -- cmpt1 : peut être enlevé. (on a un seul process ici);
IF (clk'EVENT AND clk='1') THEN  -- Quand on a un événement sur clk et
que clk =1 => front montant
      q0 <= NOT q1;
      q1 <= NOT q0 xor q1;
END IF;
END PROCESS;
END acmpt;
III.2. Description du programme à partir de la Table de vérité
La principale caractéristique de cette méthode de programmation est la simplicité, en effet, à
partir d'une simple table de vérité, il est possible d'établir un programme complet pour ensuite
par exemple être programmé dans un composant. On utilise pour cela des structures
conditionnelles tels que « with select when », « when else » ou encore « case when ».
III.2.1. Méthode with select when
L'entrée 'a' est ici déclarée en tant que in bit vector 3 downto 0 et la sortie 's' est déclarée en tant
que out bit vector 3 downto 0. En plus, pour le premier exemple on déclarera deux entrées e0 et
e1.
ARCHITECTURE nom_du_prog OF nom_entity IS
BEGIN
With a SELECT                  -- 'a' étant le bit_vector d'entrée
s<= "1111" when "1010", -- s est le bit_vector de sortie.
        "1101" when "1000",   -- 's' prendre la valeur "1101" quand 'a' vaudra "1000"
        e0 when "0100",      -- 's' prendra la même valeur que e0 quand on aura
"0100" sur 'a'
        e1 when others;  -- le 'others' remplace tous les cas qui n'ont pas été étudiés.
END nom_du_prog;

3/9
Il est possible de remplacer le 'a'  dans le With a select par plusieurs entrées à la fois sans
forcement utiliser un bit_vector en utilisant l'opérateur de concaténation &. Exemple remplacer
le bit_vector 'a' par d1&d2&d3&d4 est tout à fait possible.
Ci dessous un exemple concret : La conversion code Binaire vers Code gray.
entity bingray is
port (clk : in bit; b : in bit_vector (3 downto 0), -- entrée binaire
g : out bit_vector (3 downto 0); -- sortie gray
end bingray;  -- bingray est le nom de l'entité
architecture abingray of bingray is
begin
with b select
g<= "0000" when "0000",
        "0001" when "0001",
        "0011" when "0010",
        "0010" when "0011",
        "0110" when "0100",
        "0111" when "0101",
        "0101" when "0110",
        "0100" when "0111",
        "1100" when "1000",
        "1101" when "1001",
        "1111" when "1010",
        "1110" when "1011",
        "1010" when "1100",
        "1011" when "1101",
        "1001" when "1110",
        "1000" when others;
end abingray;
Il est possible par cette méthode de décrire de nombreux systèmes très facilement,
multiplexeurs, décodeur BCD vers 7 segments pour afficheur led.
III.2.2. Méthode when else
L'entrée 'a' est ici déclarée en tant que bit vector 3 downto 0 (4 bits) et la sortie 's' est déclaré en
tant que bit vector 1 downto 0 (2 bits).
ARCHITECTURE nom_du_prog OF nom_entity IS
BEGIN
S<="11" WHEN a="1000" ELSE --si on a 1000 sur a on met 11 sur s sinon on passe,
      "01" WHEN a= "0110" ELSE    -- et ainsi de suite
      "10" WHEN a= "1101" ELSE
      "00";  -- correspond aux autres cas, si aucuns cas au dessus n'a été validé.
END nom_du_prog;
Remarque :
On doit faire attention à ce style de programmation, en effet, il faut faire attention à la priorité
des actions. Imaginons le programme suivant :
Z<= "01" when a='1' ELSE
        "00" when c='0'
        "11";
END architecture;
Explication de la remarque :
Si on a : a='1' , quelque soit la valeur de c, Z aura de toute façon la valeur 01.
C peut alors avoir la valeur 0 ou 1, cela n'a aucune importance puisque l'on ne lui demande
pas sa valeur.

4/9
III.2.3. Méthode case when
S est ici déclarée en tant que bit vector 3 downto 0 (4 bits) en entrée sortie (INOUT).
La principale utilisation de cette méthode de programmation est la simplicité, en effet, à partir
d'une simple table de vérité de récurrence (ou graphe d'état), il est possible d'établir un
programme complet pour ensuite par exemple être programmé dans un composant.
Exemple d'un compteur 4 bits gray. En majuscule les commandes, en minuscule ce qui peut
varier en fonction des programmes.
ENTITY cptgray IS
PORT (clk : IN BIT;
s : INOUT BIT_VECTOR (3 DOWNTO 0) );
END cptgray;
ARCHITECTURE acptgray OF cptgray IS
BEGIN
PROCESS (clk) BEGIN
IF clk'EVENT AND clk='1' THEN --a chaque front montant sur l'horloge on fait la
suite
CASE s IS
WHEN "0000" => s <= "0001"; -- se lit quand s est égal à '0000' Alors
s reçoit '0001'
WHEN "0001" => s <= "0011";
WHEN "0011" => s <= "0010";
WHEN "0010" => s <= "0110";
WHEN "0110" => s <= "0111";
WHEN "0111" => s <= "0101";
WHEN "0101" => s <= "0100";
WHEN "0100" => s <= "1100";
WHEN "1100" => s <= "1101";
WHEN "1101" => s <= "1111";
WHEN "1111" => s <= "1110";
WHEN "1110" => s <= "1010";
WHEN "1010" => s <= "1011";
WHEN "1011" => s <= "1001";
WHEN "1001" => s <= "1000";
WHEN OTHERS => s <= "0000";  -- tous les autres cas : 'others', pas
obligatoire mais vivement conseillé
END CASE;                         -- fin du case
END IF;                                -- fin du si du début.
END PROCESS;                 -- fin du process
END acptgray;                         --fin de l'architecture et du programme entier.
Ce programme va réaliser une boucle infinie incrémentant la sortie s à chaque front montant
de l'horloge.
III.3. Ecriture à partie du schéma

5/9
On doit décrire le programme comme si on faisait un schéma avec des portes logiques. ent1,
ent2 sont les sorties des portes logiques intermédiaires, elles ne sont pas visibles en sortie ou
entrée du composant, uniquement a l'intérieur du circuit et on les utilise donc en entrée
comme en sortie.
Afin que le compilateur sache a quoi correspond 'et', 'inverseur' et 'ou'. Il faut faire un
package. Si on a créé un package appelé 'monexemple' et que l'on souhaite inclure tous les
composants contenus dans cette librairie, le programme VHDL ressemblera a cela :
LIBRARY portes; -- si on a appelé le fichier portes
USE portes.monexemple.ALL; -- ALL signifie que l'on prend toutes les descriptions du
package
ENTITY exempleentite IS
PORT (a,b : IN BIT;
          y : OUT BIT);
END exempleentite;
ARCHITECTURE aexempleentite OF exempleentite IS
SIGNAL ent1,ent2 : BIT;
BEGIN
I1:et PORT MAP(a,b,ent1);          -- ent1=a.b
I2:inverseur PORT MAP (b,ent2); -- ent2=/b
I3:ou PORT MAP (ent2,ent1,y);      -- y=ent1+b
End aexempleentite;
Remarque :
Il est possible de ne pas avoir librairies dans le même répertoire que toutes les autres, il faut
donc spécifier au compilateur ou aller la chercher.
Il existe des types de programmation nécessitant autre chose que des bits (1 ou 0) pour les
entrées et sorties (exemple le 3 états avec la haute impédance), il faudra alors utiliser le
'standard logique' dans la librairie ieee :
LIBRARY ieee;
USE ieee.std_logic_1164.all
IV. PROGRAMMATION DE GRAFCET
Le langage VHDL peut également servir afin de programmer des composants pouvant réaliser
des fonctions décrites dans un grafcet.
En fait, nous n'allons pas programmer un grafcet mais un graphe d'état ce qui ressemble
beaucoup. En apparence du moins, mais nous ne rentrerons pas dans les details, ce que l'on
souhaite c'est une méthode simple, rapide et graphique de montrer ce que le programme doit
faire.
Nous allons prendre l'exemple d'une alarme simple:
Nous avons l'entrée 'marche' c'est la touche qui permet d'armer l'alarme.
Il y a également l'entrée 'capteur' c'est lui qui va dire si l'alarme doit sonner.
Et puis l'entrée clock qui représente l'horloge interne de l'appareil.
Il y a une seule sortie 'sonnerie'.
Traduisons en français le comportement de cette alarme.
Afin de simplifier, on va dire qu'une entrée active a un niveau haut ('1') et inversement.
Il y a 3 états possibles : 'arret', 'armee' et 'sonne' :
Si on est dans l'état 'arret' , on reste dans cet état si marche n'est pas activé et on quitte 'arret'
pour aller dans 'armee' si on a marche activé.
Si on est dans 'armee' on reste dans cet état si marche est activé et capteur inactif on quitte
'armee' pour aller dans l'état 'sonne' si on a capteur est actif. On peut également quitter
'armee' pour aller dans 'arret' si on a marche désactivé.

6/9
Si on est dans l'état 'sonne', on continue de sonner tant que marche est actif, pour arrêter de
sonner  il faut uniquement que marche devienne inactif quelque soit l'état de 'capteur'.
'Sonnerie' n'est actif que dans cet état 'sonne'.
Le schéma en graphe d'état représentant cette alarme est le suivant :

Grafcet :  Grafcet est l'acronyme de Graphe de Commande par Etape et Transitions.


Le grafcet permet de montrer le déroulement d'un programme. Ici nous ne parlerons pas de
grafcet mais de graphe d'état, la différence principale est que dans un graphe d'état, les
transitions ne sont pas bloquantes, c'est-à-dire que le grafcet reste dans la même étape si
aucune des transition n'est valide, un graphe d'état doit avoir une boucle sur lui-même pour
rester dans la même étape.
Le programme est le suivant. :
Entity alarme is
Port (Capteur,marche,clock : in bit;
Sonnerie : out bit);
ATTRIBUTE pin_number  of alarme  : ENTITY IS
"capteur : 2 , marche : 3, clock:1 , Sonnerie : 18";
End alarme;
Architecture a_alarme of alarme IS
    Type state is (armee, arret, sonne);
--on crée un type de donnée pouvant prendre 3 états.
    Signal etat : state;
 -- entre cette ligne et la précédente on peut donner le codage des états
    Begin
      Procces (clock) begin
        IF clock='1' AND clock'event then
              case etat is
       When arret => IF marche='1' then etat <= armee;
                         else etat <= arret;
                         end IF;

7/9
                         sonnerie <= '0';
      When armee => IF marche = '1'  then
                         etat <= arret;
                         elsif capteur ='1' then
                         etat <= sonne;
                         else etat <= armee;
                         End if;
                         sonnerie <='0';
      When sonne => if marche='0' then
                         Etat <= arret;
                         Else etat <= sonne
                         End if;
                         Sonnerie <= '1';
End case;
        End if;
    End process;
End a_alarme;
Ce programme peut être créer en dessinant le graphe d'état et en spécifiant les entrée, sorties,
et étapes.
V. CRÉATION D'UN PACKAGE
Quand on crée un nouvel objet, il faut faire 'new library' c'est-à-dire une nouvelle librairie de
définition de fonctions logiques. On aura à faire cela qu'une seule fois si on utilise plusieurs
fois les mêmes portes.
On écrira alors pour les portes appelées 'et', 'inverseur' et 'ou' :
PACKAGE monexemple IS
-- début de la description des entrées sorties de tous les composants de la librairie
COMPONENT et
PORT(e0,e1 : IN BIT;
        s : OUT BIT);
END COMPONENT; -- fin du composant et
COMPONENT ou  -- début du composant ou
PORT(e0,e1 : IN BIT;
        s : OUT BIT);
END COMPONENT; -- fin du composant ou
COMPONENT inverseur -- début de l'inverseur
PORT(e : IN BIT;
        s : OUT BIT);
END COMPONENT;
END monexemple;
-- Nous allons décrire le fonctionnement de ces composants maintenant.
ENTITY et IS  -- entité du et l'utilisation du mot 'et' est en relation avec les lignes ci-
dessus.
PORT (e0,e1 : IN BIT;
         s :OUT BIT);
END et;  -- fin de l'entité
ARCHITECTURE aet OF et IS BEGIN                         
s<=e0 AND e1;.
END aet;
-- on fait une entity et une architecture similaire pour les 2 autres portes :
ENTITY ou IS 

8/9
PORT (e0,e1 : IN BIT;
         s :OUT BIT);
END et; 
ARCHITECTURE aou OF ou IS
BEGIN
s<=e0 OR e1;
END aou;
-- entité de l'inverseur
ENTITY inverseur IS
PORT (e : IN BIT;
         s :OUT BIT);
END inverseur;
ARCHITECTURE ainverseur OF inverseur IS
BEGIN                         
s<= NOT e;
END ainverseur;
Il est nécessaire de préciser que les fichiers devront être stockés sur le disque à l'endroit où
tout les autres fichiers de librairie se trouvent. Dans cet exemple il a été enregistré sous le
nom portes.

9/9

Das könnte Ihnen auch gefallen