Académique Documents
Professionnel Documents
Culture Documents
Emmanuelle Peuch
TABLE DES MATIERES
Emmanuelle Peuch
Annexes
Emmanuelle Peuch
VHDL
Entrées .. Structure
logique
.. Sorties
. .
En VHDL, une structure logique est décrite à l’aide d’une entité et d’une architecture.
architecturenom_architectureofnom_entiteis
Zone de déclaration des objets (signaux, constantes), des L’architecture décrit le fonctionnement
types. Ces déclarations sont locales au bloc considéré et
sont optionnelles.
du circuit auquel est attachée une entité.
end nom_architecture;
Création du fichier<nom>.vhd
Un fichier .vhd est donc un fichier texte constitué d'une entité et d'une architecture.
Les entrées sorties du composantsont des signaux particuliers dont il faut spécifier le sens (la
direction) d’utilisation. Ce sont les signaux d'interface de l'entité et ils sont appelés des ports.
E. Peuch 3
VHDL
Mode Sens
Extérieur
Intérieur
Mode OUT
Mode IN
Mode buffer
Mode inout
Le mode Inout (bidirectionnel) est déconseillé sur certaines architectures de FPGA (ils ne
possèdent pas de buffer trois états internes).
Donc en général pour que la description VHDL soit transportable d'un fabricant à l'autre, on
n'utilise que les ports IN et OUT (ce qui n'est pas du tout bloquant).
Conventions d’écritures :
- Il n’y a pas de différence entre majuscules et minuscules.
- La longueur d’un identificateur est limitée à celle d’une ligne.
- Un identificateur est composé de lettres (mais sans accents et ç), du symbole _ (underscore)
et de chiffres mais il doit commencer par une lettre ; il n’accepte pas deux symboles _
successifs.
- Une liste de mots est réservée à la syntaxe du langage VHDL : ces mots sont donc interdits
comme identificateurs (la liste est disponible en annexe).
Une librairie (library) comprend différents éléments qui peuvent être des composants, des sous-
programmes ou plus simplement des types de données. C’est une collection de modules
VHDLdéjà synthétisés, utilisés fréquemment et partageables par plusieurs concepteurs. Au sein
d’une librairie, ces éléments sont regroupés dans un paquetage (package).
E. Peuch 4
VHDL
Une librairie par défaut, work, est systématiquement associée à l’environnement de travail de
l’utilisateur.
Exemple
Depuis 1992, un standard a été défini et agréé par IEEE : c’est le standard IEE 1164qui comporte
neuf états de base comme, par exemple, la définition d’état haute impédance (Z), la possibilité
de disposer d’états inconnus (X). Pour ce standard il a été défini le type std_ulogic, remplaçant
le type bit et le type std_ulogic_vector remplaçant le type bit_vector.
Tous les synthétiseurs n’acceptent pas ces 9 valeurs. Il a été défini le sous type std_logic qui est
maintenant le type utilisé (à la place du type bit)ainsi que le type std_logic_vector (à la place
de bit_vector).
Ces deux types sont décrits de façon plus précise dans le chapitre suivant.
E. Peuch 5
VHDL
Une donnée appartient à une classe qui définit, avec son type, son comportement.
Des données de deux classes différentes mais de même type peuvent échanger des informations
directement.
La portée des noms est en général locale : un nom déclaré à l’intérieur d’une architecture n’est
connu que dans celle-ci.
I. Les classes
Il existe trois classes : signaux, variables et constantes.
La valeur affectée peut être le résultat d’une expression, simple ou conditionnelle, ou la valeur
renvoyée par l’appel d’une fonction.
L’affectation d’une valeur à un signal traduit une connexion « physique » (soudure par
exemple), il s’agit donc d’une opération permanente ! Il serait donc aberrant d’affecter plus
d’une fois une valeur à un signal !
L'instruction d’affectation simple pour les signaux:<=Signifie " prend la valeur de"
ou " reçoit "
E. Peuch 6
VHDL
Syntaxe de déclaration (dans la partie déclarative d’un process, d’une fonction ou procédure) :
variable nom1, nom2 : type [ := expression];
NB : tout ce qui est mis entre crochet [ ] est facultatif.
L’expression facultative (dans la déclaration de la variable) permet de donner à une variable une
valeur initiale choisie par l’utilisateur.
La valeur affectée peut être le résultat d’une expression ou la valeur renvoyée par une fonction.
Exemple
E. Peuch 7
VHDL
On déclare :
- une constantedans le domaine séquentiel comme dans le domaine concurrent,
- une variableuniquement dans le domaine séquentiel. L’affectation d’une valeur à une
variable se fait par := à l’intérieur d’un processus. La variable a alors été déclarée entre
process et begin,
- un signaluniquement dans le domaine concurrent.
Pour pouvoir utiliser les types std_logic et std_logic_vectoril faut déclarer dans le fichier .vhd
que l'on utilise le paquetage std_logic_1164:
use IEEE.STD_LOGIC_1164.ALL;
Le type actuellement le plus utilisé en remplacement du type bit est le type std_logic.
Nous utilisons donc maintenant le type std_logic et non plus le type bit !
Déclaration :
signalnom : std_logic ;
constantnom : std_logic := '0';
variablenom : std_logic ;
Info
L'IEEE définit en 1993 le standard IEEE1164 qui normalise la représentation des signaux
multi valeurs et qui étend la portée des opérateurs à ce nouveau type. C'est un complément au
standard IEEE1076 et tous les outils de développement d'aujourd'hui doivent intégrer cette
extension.
qui signifient
'U' valeur non initialisée
'X' valeurinconnue
'0' niveaulogique bas
'1' niveaulogiquehaut
'Z' état haute impédance
E. Peuch 8
VHDL
'W' valeurinconnue*
'L' niveaulogique bas*
'H' niveaulogiquehaut*
'-' valeur indifférente
*'W', 'L' et 'H' représentent respectivement un état inconnu, un niveau 0 et un niveau 1 mais ont un niveau plus
faible que 'X', '0' et '1'. Ces valeurs sont essentiellement utilisées pour la simulation.
D'un point de vue synthèse (réalisation d'un composant), il ne faut utiliser que
les valeurs '0', '1' et 'Z'.
Rappel : le type bit n’est plus utilisé et est remplacé par le type std_logic. Il en est donc de même
pour définir un bus de données : nous utiliserons le type std_logic_vector !
Affectation :
nom<= ''10001010''; -- Les bits de rang 7 , 3 et 1 sont à 1 et les autres sont à 0.
Ou alors
nom<= X"8A" -- X"valeur" indique une valeur en hexadécimale
E. Peuch 9
VHDL
Il est possible de fusionner deux vecteurs, c’est la concaténation (&), pour affecter les
valeurs correspondantes à un bus plus grand.
Concaténation :
Remarque
E. Peuch 10
VHDL
Déclaration :
signalnom : signed(3 downto 0) ;
signalnom : unsigned(3 downto 0) ;
constantnom : signed(3 downto 0) := "1101"; -- ou unsigned
Sortie <= std_logic_vector(interne);-- on peut ensuite placer le résultat dans un bus de données (un vecteur)
via la fonction de conversion de type std_logic_vector
On utilise cette technique pour réaliser des compteurs binaires, des diviseurs de fréquence,…
Il faut consulter le paquetage standard du compilateur utilisé pour connaître le format des
nombres entiers !
Déclaration :
signalnom : integer ;
variablenom : integer ;
constantnom : integer ;
Lors de l’utilisation d'un objet de type integer, il est possible de définir ses champs d’utilisation
afin de réduire son encombrement physique. Pour cela l’opérateur rangepermet de spécifier son
étendue :
E. Peuch 11
VHDL
Info
Les types std_logic_vector, unsigned et signed sont définis comme des tableaux de std_logic !
Exemple
Mem:
Déclaration Case 0
Case 1
Type exemple_tableauisarray (7 downto 0) of
Case 2 1101
std_logic_vector(3 downto 0;
Signal mem:exemple_tableau;
Case 7
Affectation
mem(2) <= "1101"; Chaque case à une longueur de
4, c’est à dire qu’on peut y
stocker des mots de 4 bits
E. Peuch 12
VHDL
heure_du_jour.heure <= 3 ;
heure_du_jour.minute <= 45 ; Utilisation de l’objet déclaré :on accède à un
heure_dujour.seconde <=55 ; élément de clock_time par son champ.
E. Peuch 13
VHDL
Le langage VHDL comporte six classes d’opérationsavec un niveau de priorité défini pour chaque
classe.
Lors de l’évaluation d’une expression, l’opération dont la classe a la plus haute priorité est
effectuée en premier. Cependant, il est conseillé d’utiliser les parenthèses ne serait ce que pour
améliorer la lisibilité de l’écriture !
Le tableau ci-dessous regroupe la liste des opérateurs classés par priorité croissante (de haut en
bas). Ainsi, les opérateurs logiques ont le niveau de priorité le plus faible, excepté l’opérateur
not!
std_logic, std_logic_vector
and, or, nand, nor, std_logic, ou
Op. logiques (pour résultat booléen)ou
xor, xnor booléen
booléen
Tous types scalaire (std_logic,
Op. relationnels = /= <<= >>= std_logic_vector, integer, booléen
unsigned, signed, booléen)
Unsigned,
+ - Unsigned, signed, integer
signed, integer
Op. d’addition
std_logic et
& (concaténation) std_logic et std_logic_vector
std_logic_vector
Unsigned,
Unsigned, signed, integer
signed, integer
* /
Op. de
multiplication(liés à la
mod (modulo)
multiplication) Unsigned,
rem(calcul du reste) Unsigned, signed, integer
signed, integer
On notera que tous les opérateurs logiques de la première ligne ont la même priorité !Il est
donc fortement conseillé de placer les parenthèses dans toute expression contenant ces
opérateurs.
Les opérateurs arithmétiques sont utilisables avec les signed et unsigned si on a déclaré au
préalable le packetagenumeric_std:use iee.numeric_std.all
E. Peuch 14
VHDL
V. Les attributs
Un attribut est une propriété associée à un type, un objet (signal, variable, constante), à une
entité: il en précise les propriétés. Cette propriété, une fois définie, peut être utilisée dans des
expressions.
Tableau_ou_type_ou_nom_de_signal' nom_attribut
Comme pour les types, il existe des attributs prédéfiniset des attributs utilisateur
(user_defined).
E. Peuch 15
VHDL
Un type scalaire est caractérisé par le fait que la valeur d’un objet de ce type est constituée d’un seul élément.
Les processus
Les instructions " generate " ;
On peut dire que « peu importe l’ordre dans lequel on soude ses composants, le résultat
sera le même ». D’un point de vue logiciel : " chacune des lignes est évaluée par le
synthétiseur, indépendamment de l’ordre dans lequel elles sont écrites ".
E. Peuch 16
VHDL
Exemple
E1 Sel S
E0 0 E0
S 1 E1
Sel
Entity aiguillage is
Port (E0, E1, Sel : in std_logic ;
S : out std_logic) ;
End aiguillage ;
E. Peuch 17
VHDL
Cette instruction est semblable à la précédente avec en plus une précision préalable du signal sur
lequel vont se porter les conditions. En d’autres termes elle permet de mettre en facteur une
condition sur un signal commun de la manière suivante :
Withsignal_conditionselect
Signal_sortie<=Expr_1whenvaleurs_1_signal_condition,
Expr_2whenvaleurs_2_signal_condition,
……
Expr when others ;
Toutes les valeurs possibles de signal_condition doivent être décrites dans l’instruction select.
Le cas par défaut est décrit par whenothers.
signal_sortie<= '0' when "11 " | "10", -- le signe | signifie ‘OU’ (agrégat)
'1' whenothers;
Exemple
Cela signifie que plusieurs process fonctionnent en parallèle et qu'ils sont permanents comme
toute instruction concurrente.
E. Peuch 18
VHDL
SYNTAXE:
Exemple
Compteur
entity compteur is
GENERIC (nb_bits : integer := 8 ) ;-- valeur par défaut = 8
PORT ( clk, en, reset : in STD_LOGIC;
CPT: out STD_LOGIC_VECTOR (nb_bit - 1downto 0));
end compteur;
E. Peuch 19
VHDL
begin
cpt<= cpt_1;
process(clk, reset)
begin
if reset = '1' then
cpt_1 <= (others => '0'); -- affectation générique
elsifclk'event and clk = '1' then
cpt_1 <= cpt_1 + 1; -- additiongénérique
end if;
end process;
end ARCHI;
Forme générale:
Etiquette :forvariable indebuttofingenerate
Instructions concurrentes
End generate [etiquette] ;
Exemple
Additionneur 8 bits
entity add_8bits is
port ( A,B : in STD_LOGIC_VECTOR (0 to 7);
CIN : in STD_LOGIC;
SUM : out STD_LOGIC_VECTOR (0 to 7);
COUT : out STD_LOGIC);
end add_8_bits;
E. Peuch 20
VHDL
endgenerate;
end ARCHI;
End arch1 ;
E. Peuch 21
VHDL
IFcondition_logique1THEN
Instructions qui s'exécutent selon l'ordre Chaque séquence d’instructions n’est exécutée
d'écriture; que si la condition logique associée est vraie
[ELSIF condition_logique2THEN] (true).
Instructions qui s'exécutent selon l'ordre
d'écriture; La condition booléenne peut se présenter sous
[else] différentes formes mais le résultat doit être
Instructions qui s'exécutent selon l'ordre vrai ou faux.
d'écriture;
end if ; […] signifie que c'est optionnel !
caseexpressionis
when choix1=> Le signe =>signifie alors.
Instructions qui s'exécutent selon l'ordre
d'écriture;
whenchoix2=>
Instructions qui s'exécutent selon l'ordre
d'écriture;
…
when others =>
Instructions qui s'exécutent selon l'ordre
d'écriture;
end case;
La condition validant l’exécution d’une séquence (choix) n’est pas limitée à une seule valeur.
Elle peut en regrouper plusieurs en utilisant l’une ou l’autre des deux écritures suivantes :
Exemple
E. Peuch 22
VHDL
case SEL is
when 0 | 1 | 2 =>
Z <= B;
when 3 to 10 =>
Z <= C;
end case;
Il est à noter que si on oublie de traiter un cas dans les instructions IF ou CASE, le logiciel va
générer un latch (une cellule mémoire) afin de mémoriser la valeur précédente du signal de
sortie (on n’est donc plus en présence d’un système combinatoire !). Pour éviter la création de
ce latch, n’oubliez pas d’expliciter toutes les branches possibles des tests !
foriin<lower_limit>to<upper_limit>loop
instructions séquentielles ; Cette instruction est basée sur un indice i
endloop; de type entier.
Exemple
for I in 1 to 10 loop
I_SQR(I) := I * I;
end loop;
E. Peuch 23
VHDL
Exemple
I := 0;
while (I < 10) loop
S <= I;
I := I + 1;
endloop;
Il existe différentes façons de décrire un composant en VHDL. Ces styles sont résumés sur le
schéma ci-après:
E. Peuch 24
VHDL
Description Description
comportementale structurelle
Interconnections
de boîtes noires
On décrit le comportement
de chaque sortie
E. Peuch 25
VHDL
I. Descriptions comportementales
entity demi_add is
Port (a,b: in std_logic;
- description avec des
S,R: out std_logic);
instructions concurrentes.
end demi_add;
- Méthode qui n’est que le reflet
architecture flot_donnees of demi_add is des équations logiques de la
begin structure combinatoire à
S <= a xor b; décrire.
R <= a and b;
end flot_donnees;
entity demi_add is
Port (a,b: in std_logic;
S, R: out std_logic);
end demi_add;
architecture instr_seq of demi_add is
begin
process (a,b)
begin
if (a='0' and b='0') then
S <= '0'; R <= '0';
end if;
if (a='0' and b='1') then
S <= '1'; R <= '0';
end if;
if (a='1' and b='0') then
S <= '1'; R <= '0';
end if;
if (a='1' and b='1') then
S <= '0'; R <= '1';
end if;
end process;
end instr_seq;
E. Peuch 26
VHDL
Cette description sera utilisée (inévitablement) lorsque notre système numérique atteint un
certain niveau de complexité. On le décomposealors en différents blocs (instances), chacun d’eux
formant un couple {entité – Architecture} qui est décrit de façon comportementale ou structurelle.
Ci-dessous est rappelé l'exemple de la description structurelle d'un additionneur 1 bit. Pour plus
de détail sur l'instanciation de composant, se reporter à la fiche "description structurelle d'un
composant".
L'additionneur 1 bit peut être réalisé à partir de deux boîtes noires "demi-additionneur":
-- description structurelle
entity add_1_bit is
port ( A1, B1, R1: in std_logic;
S1, R2: out std_logic);
end demi_add;
componentdemi_add is
port ( A, B: in std_logic;
Sd,Rd: out std_logic);
end component;
begin
U1:demi_add
PORT MAP(A => A1,
B => B1,
Sd => S2,
Rd => S3);
U2: demi_add
PORT MAP(A => S2,
B => R1,
Sd => S1,
Rd => S4);
R2 <= S4 or S3;
end structurelle;
L'instanciation d'un composant est une instruction concurrente: elle ne s'utilise donc que hors
d'un process!
E. Peuch 27
VHDL
Il est souvent utile de subdiviser en petits modules le programme à développer. Ainsi on met au
point chaque module indépendamment les uns des autres que l’on rassemble ensuite.
Les outils de base de cette organisation modulaire sont les procédures ou fonctions, les
paquetages et librairies.
Avec les sous programmes (procédures ou fonctions), e programmeur peut se constituer une
bibliothèque d’algorithmes séquentiels que l’on peut ensuite inclure dans une description.
Les fonctions et procédures diffèrent par les mécanismes d’échanges d’informations entre le
programme appelant et le sous-programme.
I. Les fonctions
Une fonction exécute une suite d’instructions séquentielles et retourne au programme
appelant une valeur unique, elle a donc un type.
Elle peut recevoir des arguments (liste de paramètres), exclusivement des signaux ou des
constantes, dont les valeurs lui sont transmises lors de l’appel.
Une fonction ne peut en aucun cas modifier les valeurs de ses arguments d’appel.
Les variables locales, déclarées dans la fonction, cessent d’exister dès que la fonction se
termine.
I.1 Syntaxe
BEGIN
….
Instructions séquentielles ;
….
RETURNnom de la variable ou valeur de retour ;
ENDnom_fonction ;
I.2 Exemple
E. Peuch 28
VHDL
entity EXAMPLE is
port (A,B : in STD_LOGIC_VECTOR (3 downto 0);
CIN : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (3 downto 0);
COUT: out STD_LOGIC );
end EXAMPLE;
begin
end ADD;
begin
S0 <= ADD (A(0), B(0), CIN); -- L'appel de la function est une instruction.
S1 <= ADD (A(1), B(1), S0(1));
S2 <= ADD (A(2), B(2), S1(1));
S3 <= ADD (A(3), B(3), S2(1));
S <= S3(0) & S2(0) & S1(0) & S0(0);
COUT <= S3(1);
end ARCHI;
Si la description de la fonction n'est pas placée dans un paquetage, elle doit être
placée avant le BEGIN de l'architecture qui l'utilise. Elle n'est donc visible que de
l'architecture dans laquelle elle est déclarée.
Une procédure, comme une fonction, peut recevoir du programme appelant des arguments :
constantes, variables ou signaux. Mais ces arguments peuvent être déclarés de modes IN, INOUT
E. Peuch 29
VHDL
ou OUT (sauf les constantes qui sont toujours de mode IN). Ce qui autorise une procédure à
renvoyer un nombre quelconque de valeurs au programme appelant.
II.1 Syntaxe
BEGIN
….
Instructions séquentielles ;
….
END nom;
II.2 Exemple
On décrit maintenant notre additionneur de deux mots de 4 bits à l’aide d’une procédure.
entity EXAMPLE is
port (A,B : in STD_LOGIC_VECTOR (3 downto 0);
CIN : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (3 downto 0);
COUT : out STD_LOGIC );
end EXAMPLE;
begin
S := A xor B xor CIN;
COUT := (A and B) or (A and CIN) or (B and CIN);
C := COUT & S;
end ADD;
begin
process (A,B,CIN)
variable S0, S1, S2, S3 : STD_LOGIC_VECTOR (1 downto 0);
begin
ADD (A(0), B(0), CIN, S0); -- L'appel de la procedure est une instruction
ADD (A(1), B(1), S0(1), S1);
ADD (A(2), B(2), S1(1), S2);
E. Peuch 30
VHDL
Une procédure peut être appelée par une instruction concurrente ou par une instruction
séquentielle (ce qui est le cas ici dans notre exemple puisque l’appel de la procédure est dans le
corps d’un process).
Mais si l’un des arguments de la procédure est une variable, elle ne peut être appelée que par
une instruction séquentielle.
Si la description de la fonction n'est pas placée dans un paquetage, elle doit être placée avant
le BEGIN de l'architecture qui l'utilise. Elle n'est donc visible que de l'architecture dans laquelle
elle est déclarée.
Pour les rendre accessibles à partir de plusieurs architectures il est nécessaire de la déclarer au
sein de packages et de déclarer en amont de l’architecture vouloir utiliser ce package.
La spécification de paquetage (package) qui est en quelque sorte la vue externe, donc
visible, du paquetage. Elle comprend donc la liste des déclarations : types, signaux,
constantes (jamais de variables), composants, sous-programmes.
Le corps du paquetage (package body) qui est la vue interne du paquetage, à savoir les
descriptions des sous-programmes s’il y en a. Cette seconde partie peut donc ne pas exister.
Packagenom_du_packageis
Déclarations de composants Les éléments d’un paquetage sont
Déclarations de fonctions accessibles dans n’importe quel fichier si le
Déclaration de types paquetage y est déclaré.
Endnom_du_package ;
Spécification de package = vue externe
Package bodynom_du_packageis
Corps d’une fonction
E. Peuch 31
VHDL
package PKG is
function ADD (A,B, CIN : STD_LOGIC ) return STD_LOGIC_VECTOR;
end PKG;
Dans notre fichier d’application il suffit de rendre visible ce paquetage par l’instruction USE. Il est à
noter que WORK est la bibliothèque de travail. L’utilisateur y stockesesproprespaquetages.
use work.PKG.all;
entity EXAMPLE is
port (A,B : in STD_LOGIC_VECTOR (3 downto 0);
CIN : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (3 downto 0);
COUT: out STD_LOGIC );
end EXAMPLE;
E. Peuch 32
VHDL
E. Peuch 33
Annexes
Pour cela il est intéressant d’utiliser : 4- L’instruction CASE avec sa clause WHEN
OTHERS et l’instruction IF avec sa clause
- la clause WHEN OTHERS de l’instruction ELSE se prêtent bien à la description d’une
CASE, machine d’état.
34
Annexes
35
Annexes
Projet
New source
VHDL package
<nom du fichier et emplacement de ce fichier>
library IEEE;
use IEEE.STD_LOGIC_1164.all;
package <Package_Name> is
type <new_type> is
record
<type_name> :std_logic_vector( 7 downto 0);
<type_name> :std_logic;
end record;
-- Declare constants
end <Package_Name>;
-- Example 1
function <function_name> (signal <signal_name> : in <type_declaration> ) return
<type_declaration> is
variable <variable_name> :<type_declaration>;
begin
36
Annexes
<variable_name> := <signal_name>xor<signal_name>);
return <variable_name>;
end <function_name>;
-- Example 2
function <function_name> (signal <signal_name> : in <type_declaration>;
signal <signal_name> : in <type_declaration> ) return <type_declaration> is
begin
if (<signal_name> = '1') then
return <signal_name>;
else
return 'Z';
end if;
end <function_name>;
-- Procedure Example
procedure <procedure_name> (<type_declaration><constant_name> : in
<type_declaration>) is
begin
end <procedure_name>;
end <Package_Name
37