Préambule

Objectifs

VHDL est un langage typé où il est obligatoire de spécifier le type des objets utilisés. Le tableau ci dessous illustre la classification des types du langage VHDL :

type

L'objectif de ce chapitre est de vous présenter les types et les opérateurs. A l'issue de ce chapitre, vous serez en mesure de choisir le meilleur type pour l'objet que vous voulez modéliser.

Plan du chapitre.


Remarque importante

Ce chapitre, comme tous les chapitres sur la syntaxe des langages, est un peu indigeste. Il vaut mieux le voir comme une référence, une page à laquelle vous pourrez vous rapporter tout au long du cours, ou en cas de problème. Par contre, il est conseillé de l'avoir lue au moins une fois, pour garder en tête où se trouvent les pièges éventuels.

Back to Top

TYPES ENTIERS

Le type entier integer prédéfini dans le paquetage standard STD permet de définir des nombres signés sur 32 bits entre -2-31 et 231 - 1  . 

Un sous type subtype permet de déclarer un type héritant des propriétés du type père.

Il existe 2 "sous types" subtype associés à INTEGER : les entiers naturels et les entiers positifs. Leur déclaration dans le paquetage STD est la suivante :

subtype natural is integer range 0 to integer'high;
subtype positive is integer range 1 to integer'high

Notez que 
  1. range permet d'indiquer l'intervalle 
  2. 'HIGH indique la plus grande valeur du type INTEGER, c'est un attribut de type


Les types entiers servent à définir des indices de tableaux et de boucles. Pour cela il est intéressant de les restreindre de façon à contrôler les débordements.
Par exemple on peut déclarer :

subtype UN_A_DIX is natural range (1 to 10);
subtype DIX_A_UN is natural range (10 downto 1);


Il s'agit d'objets compatibles entre eux mais avec un ordre
d'indexation différent.
Il est donc possible d'effectuer des opérations entre ces objets 
En revanche si on avait déclaré :

type UN_A_DIX is natural range (1 to 10);
type DIX_A_UN is natural range (10 downto 1);

Les 2 types étant indépendants, une opération entre des objets UN_A_DIX et DIX_A_UN  aurait  causé une erreur de compilation.

   


Back to Top

Types ENUMERE

Un type énuméré est un type défini par une énumération exhaustive :

type COULEURS is (ROUGE, JAUNE, BLEU, VERT, ORANGE);


L'ordre de déclaration est important. Lors de l'initialisation d'un signal de type enuméré T, le signal prend la valeur T'LEFT.
Par exemple un signal de type COULEURS sera ROUGE en début de simulation.

Dans le paquetage STANDARD de la bibliothèque STD, plusieurs types énumérés sont définis :

type boolean is (FALSE, TRUE);
type bit is ('0', '1');
type severity_level is (NOTE, WARNING, ERROR, FAILURE);
type character is ( NUL, SOH, STX, ETX,..., '0','1', ...);

Notez
que la valeur d'un bit est équivalente à un caractère et est toujours entre quotes : '0' et  '1'  différents des entiers 0 et 1.

Dans le paquetage STD_LOGIC_1164 de la bibliothèque IEEE, le type STD_ULOGIC est défini par :

type std_ulogic is ('U', 'X, 'O', '1', 'Z', 'W', 'L', 'H', '-');

Ce permet d'avoir 9 états significatifs de la logique. Ces états illustrent les cas où le signal est soumis à de multiples affectations. Dans ce cas chaque valeur à un niveau de priorité.
La liste suivante donne la signification de ces 9 valeurs en commençant par la valeur de plus grande priorité :

Le type énuméré est aussi très utile pour définir les états d'une machine à états d'une façon symbolique, sans avoir à définir le codage.


Back to Top

TYPES TABLEAU

Les types TABLEAU ou array sont des collections d'objets de même type, indéxés par des entiers ou des énumérés.

Exemples :

type bus is array (0 to 31) of bit;
type RAM is array (0 to 1024, 0 to 31) of bit;
type PRIX is ranger 0 to 1000;
type COULEURS is (BLANC, BLEU, VERT, ROUGE, JAUNE, NOIR, ARC_EN_CIEL);
type PRIX_PEINTURES is array (COULEUR range BLANC to NOIR) of PRIX;

Un tableau peut avoir une taille inconnue donc non contraint, par exemple le type BIT_VECTOR de la bibliothèque STD est  un tableau de dimension 1 (vecteur) de taille quelconque :

type bit_vector is array (natural range <>) of bit;

et le type STD_ULOGIC_VECTOR de la bibliothèque IEEE :

type std_ulogic_vector is array (natural range <>) of std_logic_vector;


La contrainte de taille est alors exprimée dans la déclaration de l'objet :

signal toto bit_vector(31 downto 0);
signal titi std_ulogic_vector(7 downto 0);


Il faut noter que l'indexation peut être MSB en tête (31 downto 0) , la plus courante, ou LSB en tête (0 to 31).
Attention, une affectation de signaux vectoriels ayant des indexations différente provoque une inversion des composantes du signal. 
La valeur d'un vecteur peut être représentée dans une base différente :  "001100" = 0"14" = X"0C" 

Il peut y avoir des tableaux de tableaux ou des tableaux à plusieurs dimensions; Les affectations diffèrent quelque peu comme illustré dans l'exemple suivant :

type TAB1 is array(0 to 2) of bit_vector(7 downto 0);
type TAB2 is array(0 to 3, 1 to 8) of bit;
signal A : TAB1;
signal B : TAB2;
--
begin
--tableau de tableau
A(0) <="01001111";
A(2)(5) <= '1';
-- tableau à 2 dimensions
B(3,5) <= '0';
--
end exemple;

 Notation d'agrégat

Cette notation permet d'initialiser les tableaux facilement.
Exemple :
type OPTYPE is (ADD,SUB,MUL,DIV,BRA);
type T is array ( 1 to 10) of OPTYPE;
signal A : T;
--
A <= (ADD,SUB,MUL,DIV,BRA);
A <= (ADD,SUB,5=>BRA,4=>DIV,3=>MUL);
A <= (ADD,2|4=>SUB,others => DIV);
--


Cet exemple illustre l'affectation par position et à la position par dénomination. Notez l'utilisation de la clause 'others' pour compléter automatiquement les valeurs du tableau.



Back to Top

TYPES FICHIERS 

Les types fichiers FILE permet l'échange de données entre l'extérieur et le simulateur VHDL. Il est utilisé principalement pour créer des fichiers de test ou TESTBENCH de modèles.

Le paquetage TEXTIO de la bibliothèque STD définit un type fichier texte TEXT et des procédures pour accéder aux lignes du fichier et aux chaînes dans la ligne.  
Pour l'utiliser il est nécessaire de le déclarer en début de fichier :

use STD.TEXTIO.ALL;

Un fichier peut être soit en lecture soit en écriture mais pas les 2 en même temps.
L'exemple commenté suivant illustre 2 processus permettant respectivement de lire le fichier "entrees.dat" et d'écrire les résultats dans "sorties.dat" :

LECTURE: process
variable L: line; -- le type LINE est un pointeur
file ENTREES: text open READ_MODE is "entrees.dat"; -- fichier spécifié
variable A: bit_vector(7 downto 0); -- variables à lire
variable B: natural range 0 to 11;
begin
readline(ENTREES, L); -- lecture d'une nouvelle ligne dans le fichier
read(L, A); -- lecture dans la ligne du 1er symbole => BIT
VA <= A; -- utilisation pour la simulation
read(L, B); -- lecture dans la ligne du 2ème symbole => entier
VB <= B; -- utilisation pour la simulation
wait for 20 ns; -- attente de 20 ns;
end process LECTURE;
--
ECRITURE: process(S)
variable L: line;
file SORTIES: text open WRITE_MODE is "sorties.dat";
begin
write(L, S); -- écriture de S dans la ligne
write(L, string'(" à t = ")); -- écriture de texte dans la ligne
write(L, now); -- écriture du temps de simulation dans la ligne
writeline(SORTIES, L); -- écriture de la ligne dans le fichier
end process ECRITURE;


Back to Top

 

AUTRES TYPES

Types réels

 Il existe un type réel prédéfini REAL. Il permet de représenter des nombres entre -1.0E+38 à 1.0E+38. Il n'est pas synthétisable.
Voici quelques exemples d'affectation d'un signal de type réel :
A <= 1.0;
B <= 5.9E10;
C <= -8.5E20;

Notez la présence obligatoire du point.

Types physiques

VHDL permet de définir des types physiques pour représenter une grandeur physique, comme le temps, la tension, etc... 

Un type physique est la combinaison d'un type entier et d'un système d'unité.
Le type TIME, est le seul type physique prédéfini :

type time is range $- to $+  -- l'intervalle dépend de la machine
units
fs;
ps = 1000 fs;
ns = 1000 ps;
us = 1000 ns;
Ms = 1000 us;
sec = 1000 ms;
min = 60 sec;
hr = 60 min;
end units;

Les simulateurs VHDL utilsent la fonction now, de la bibliothèque STD , qui retourne le temps physique de type TIME.

Type STRING

Ce type permet de définir les chaînes de caractères.  Il est définit comme un tableau d'éléments de type CHARACTER dans la bibliothèque STD.

type string is array (positive range <>) of character;
--
"ceci est une chaîne de caractère"

Type enregistrement RECORD

Ce type permet de définir un objet dont les composantes sont hétérogènes.

type OPTYPE is (MOV, ADD, SUB, JMP, CALL)
type INSTRUCTION is record
--
OPCODE : OPTYPE;
ADR : bit_vector(7 downto 0);
OP2 : bit_vector(7 downto 0);
--
end record;

L'affectation d'un objet de type RECORD  peut s'effectuer de différentes façons :

signal INST1 : INSTRUCTION;
signal INST2 : INSTRUCTION:
--
begin
--
INST1 <= (MOV, "00011100", X"FF");
INST2.ADR <= X"8A";
--
end;

Les RECORD sont très utiles pour les entités dont les ports peuvent être amenés à changer en nombre et en type. Les ports sont alors de type RECORD et ne changent pas. En cas de modification il suffit de modifier le contenu du type RECORD plutôt que de modifier les ports dans les entités.

Type pointeur ACCESS

Les pointeurs sont peu utilisés en VHDL car on leur préfère les tableaux indicés qui peuvent être synthétisables, à la différence des pointeurs.  Nous  ne les étudieront pas dans ce cours. 



Back to Top

ATTRIBUTS

Il s'agit de caractéristiques de types ou d'objet qu'il est possible d'utiliser dans le modèle. Ils sont représentés de cette façon :

<OBJET>'<ATTRIBUT>

Il existe des attributs sur les types, sur les objets de type tableau  et sur les signaux. 

Il est possible de créer ces propres attributs. Certains outils de synthèse en tirent profit pour passer des arguments de synthèse.

Attributs sur les types 

L'exemple suivant illustre les principaux attributs de type :

type COULEUR is (BLEU, ROUGE, VERT);
--
COULEUR'left renvoie BLEU
COULEUR'right renvoie VERT
COULEUR'pos(BLEU) renvoie 0
COULEUR'val(0) renvoie BLEU
COULEUR'succ(BLEU) renvoie ROUGE
COULEUR'pred(ROUGE) renvoie BLEU
 

Attributs sur les objets de type tableau

exemples :
type MOT is bit_vector(7 downto 0);
type TAB is array (4 downto 0) of MOT;
signal NOM : MOT;
signal TABLEAU : TAB;


MOT'LEFT renvoie 7;
MOT'LENGTH renvoie 8;
TABLEAU'RIGHT renvoie 0;
TABLEAU'RANGE renvoie 4 downto 0;

Ces attributs sont très utiles pour créer des indices ou pour écrire des sous-programmes manipulant des tableaux de taille variable.

Attributs sur les signaux

Ils servent à indiquer les caractéristiques d'évolution temporelle des signaux.
Exemples :
CLK'EVENT renvoie un BOOLEAN indiquant si le signal CLK a changé.
CLK'DELAYED(1 ns) est un signal identique à CLK décalé de 1 ns.

Attributs définis par le concepteur

Ils permettent d'associer des caractéristiques propres aux objets. Certains outils de synthèse ont leurs propres attributs pour rentrer des contraintes de synthèse dans le code.
L'exemple suivant défini le brochage de certains signaux.  
Exemple :
ATTRIBUTE NUMERO_BROCHE : POSITIVE;
ATTRIBUTE NUMERO_BROCHE of ENTREE1 is 12;
ATTRIBUTE NUMERO_BROCHE of ENTREE2 is 17;

Back to Top

OPERATEURS

Les opérateurs prédifinis en VHDL sont classiques. Ils ne portent que sur les types prédéfinis, BOOLEAN, BIT, INTEGER. Il faut donc définir une surcharge d'opérateur lorsqu'il s'agit d'effectuer des opérations sur un nouveau type. 

Il faut noter l'absence du xnor et la différence entre REM et MOD pour exprimer le reste de la division.

Type d'opérations opérateurs notes
Logiques and, or, nand, nor, xor, not
Relationnels =, /=, < , <=, > , <=
Arithmétique *, / , mod, rem  (A rem B) a le signe de A
(A mod B) a le signe de B
Divers **, abs, & ** : exponentiation
abs : valeur absolue
& : concaténation


Back to Top

En résumé

On a vu:
Prochain chapitre

le VHDL structurel.

Back to Top