Vous êtes sur la page 1sur 43

Logique

programmable
https://drive.google.com/file/d/1xk5t2-
s7R4RtFVgsrHKFYIbiS8M7G9Zr/view?usp=sharing

Logique programmable :

- Basée sur l’emploi de circuits numériques câblés


- Temps d’éxécution rapides des tâches ( applications temps
réel / embarquées / embedded )

Logique basée sur l’emploi de µP ou PIC :

- Emploi d’une mémoire programme


- Tâches répétitives mais peu rapides ou différées .
Chapitre 1 :

introduction au langage VHDL


I Methodes de description d’un circuit numérique :

La description du fonctionnement d’un circuit numérique peut faire appel à


l’une des méthodes suivantes :

Schéma de portes : encombrants pour des circuits complexes

Chronogrammes : interprétations parfois difficiles

Diagrammes de transitions : idem

Problémes de standardisation

Le langage vhdl :

Description rigoureuse du fonctionnement d’un circuit

Des compilateurs VHDL ( MAX+PLUS II , QUARTUS , XILINX

ISE , MODELSIM .) Permettent de simuler le circuit

VHDL : Very high Hardware Design Language

~ 1980 DOD (USA)

Standardisation : VHDL’87 VHDL’93

Concurrence : le seul langage spécifiquement consacré à la prise en compte

D’une description au moyen de process concurents .

Syntaxe très rigide .

Usages :

Bases de données de circuits imprimés numériques ( matériel industriel ,

militaire , … )

Circuits FPGA ( programmation de circuits numériques câblés )


Circuits ASIC ( synthése )

II méthodologie :

Saisie d’un fichier texte ( bloc note , edit , … ) . fichier .VHD

Compilateur quartus ou max+II + fichier .VHD

Simulation

III éléments constitutifs d’une description VHDL

----- la déclaration de bibliothéque

---- la déclaration d’entité

---- la déclaration d’architecture

1- La déclaration de bibliothéque :

Library IEEE ;
Use ieee.std_logic_1164.all ;
Use ieee.std_logic_arith.all ;
Use ieee.std_logic_unsigned.all ;
( signed )
IEEE est un institut NYC qui s’est spécialisé dans la standardisation .
Spécification des états de signaux ( fils de liaisons )
Spécification des outils arithmétiques
Spécification de calculs en logique signée ou non.
NB : cette déclaration de bibliothéques est standard dans de nombreux
cas.

2- La déclaration d’entité :
Entité <====> circuit numérique
Dans la déclaration d’entité nous indiquons l’identificateur du circuit
ainsi que les signaux qui lui sont reliés :
Entity exemple1 is
Port (c : out std_logic;
a, b : in std_logic ) ;
end exemple1 ;

Exemple1 C
A

A, B Bet C : les signaux externes


3- Déclaration d’architecture :
Pour l’essentiel :
Un identificateur d’architecture
les signaux internes ( éventuellement )
Les composants internes ( éventuellement )
Begin
Le fonctionnement ( liaisons entre composants , process , instructions
concurrentes , … )

C
B

Architecture BHV of exemple1 is


Begin
C <= A and B ;
End BHV ;
4- Signaux internes :

a
e
g
b

c
f
d

Library IEEE ;
Use ieee.std_logic_1164.all ;
Use ieee.std_logic_arith.all ;
Use ieee.std_logic_unsigned.all ;
Entity ex2 is
Port ( a, b ,c,d : in std_logic ; g : out std_logic ) ;
end ex2 ;

architecture bhv of ex2 is

signal e,f : std_logic ;

begin

e <= a and b ;

f <= c and d ;

g <= e and f;

end bhv ;

5- Composants internes :

Supposons que nous avons créé un circuit appelé COD :

( nous ne donnons que sa déclaration d’entité sans la déclaration


d’architecture ou de bibliothéque pour simplifier )

a b
Entity COD is

Port (a : in std_logic ; b : out std_logic) ;

End cod ;

Nous voulons insérer COD dans le circuit ex2

e
b g
COD
s
c

f
d

Library IEEE ;
Use ieee.std_logic_1164.all ;
Use ieee.std_logic_arith.all ;
Use ieee.std_logic_unsigned.all ;
Entity ex2 is
Port ( a, b ,c,d : in std_logic ; g : out std_logic ) ;
end ex2 ;
architecture bhv of ex2 is
signal e,f,s : std_logic ;
component cod --- declaration de composant interne
Port (a : in std_logic ; b : out std_logic) ; ‫هذا حق فوق الي هو مركب الي زيدناه للجديد‬
End component ;
begin
e <= a and b ;
f <= c and d ;
s <= e and f;
c1 : cod port map ( s,g) ; --instantiation de composant interne
end bhv ;
6- Directions des signaux externes :
 Un signal entrant : IN
 Un signal sortant : OUT
 Un signal sortant mais étant rebouclé vers une entrée du circuit : BUFFER

K1,U,K2 : in
X : buffer
La broche à laquelle est relié X est une broche unidirectionnelle ( vers
l’extérieur du circuit ) , mais le signal X est rebouclé à l’intérieur même du
circuit ; aucun périphérique ne peut envoyer une donnée vers notre circuit en
utilisant le signal X.
Remarque : il est préférable d’éviter d’utiliser le mode BUFFER .
Si un signal doit être rebouclé , utiliser un signal interne .
A
ACCUM

ADDER

Library IEEE ;
Use ieee.std_logic_1164.all ;
Use ieee.std_logic_arith.all ;
Use ieee.std_logic_unsigned.all ;
Entity EX4 is
Port ( a : in std_logic_vector(7 downto 0) ; ‫اليمين هي النقاط الضعيفه واليسار القوية‬
‫لذا عكسنا‬
accum : out std_logic_vector(7 downto 0) ) ;
end ex4 ;
architecture bhv of ex4 is
signal accump : std_logic_vector(7 downto 0) ;
begin
accum <= accump ;
accump <= a + accump;
end bhv ;

 Un signal transitant par une broche bidirectionnelle : INOUT

Dans cet exemple , le circuit peut , au travers du signal DATA , envoyer et


recevoir des données vers et en provenance du boitier mémoire .

DATA  : INOUT
ADRESS : out
RW/ : out

7- Notion de process :

A l’intérieur du corps d’architecture , nous avons rencontré les 2 types


de structures suivantes :
- Des instructions d’affectations du type : a <= b and c ;
- Des instantiations de composants internes du type :
c1 : cod port map(s,f,g) ;

chacune des structures précédentes constitue un circuit qui fonctionne


en concurrence ( en même temps ) que d’autres circuits dans le cadre
d’un schéma logique global . En VHDL , la terminologie pour désigner des
structures qui fonctionnent en concurrence est : Process
Les 2 types de process précédents sont dits : process implicites .
Dans certains cas , le fonctionnement d’une unité ne peut être
représentée par une seule instruction , mais par un groupe d’instructions
s’éxécutant l’une à la suite de l’autre : process explicite. Ce groupe
d’instructions constitue un domaine séquentiel par opposition au
domaine concurrent .
Le process explicite ( ou simplement le process ) s’éxécute donc en
concurrence avec d’autres process , en particulier des instructions
concurrentes .
Dans le cas le plus simple , un process comporte :

Process ( liste de sensibilité )


Begin
--groupe d’instructions impératives
End process ;

La liste de sensibilité :
liste des signaux dont tout changement d’état
lance automatiquement l’éxécution du process .
Ex : signal de reset.
Rque : un process s’éxécute au moins une fois !

Les instructions impératives :


sont des instructions qui s’éxécutent l’une à la suite
de l’autre comme dans les langages impératifs
(Basic,Pascal,Fortran,C,…) .
ex : instruction d’affectation <=
instruction de test IF …. Then …. Else… end if ;
instruction case

A RETENIR :
Un process démarre à chaque fois que l’état des signaux de sensibilité est
modifié.
la valeur d’un signal n’est actualisée qu’à la fin d’execution d’un process.
exemples :

*soit à implémenter un circuit réalisant l’addition de 2 octets signés a et b et


qui indique si le résultat c est nul au moyen d’un signal cnul :
a
C
8bits

b Cnul
C = 0 ? 1 bit
.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_signed.all;

entity ex4_4_12 is
port( a,b : in std_logic_vector(7 downto 0); cnul : out std_logic;
c : out std_logic_vector(7 downto 0));
end ex4_4_12;
architecture bhv of ex4_4_12 is
signal cp : std_logic_vector(7 downto 0);
begin
cp <= a + b;
c <= cp;
process ( cp)
begin
if cp = "00000000" then
cnul <= '1' ;
else
cnul <= '0' ;
end if;
end process;
end bhv;

description d’un circuit combinatoire au moyen d’un process explicite :

Soit à décrire un circuit acceptant en entrée un signal S ( 2bits) et générant


en sortie un signal Y (3bits ) conformément à la table de vérité suivante :

S Y
00 001
01 101
10 100
Autres combinaisons 111
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_signed.all;
entity ex6 is
port( s : in std_logic_vector(1 downto 0);
Y : out std_logic_vector(2 downto 0));
end ex6;
architecture bhv of ex6 is
begin
process(s)
begin
if s=”00” then
y <= “001”;
elsif s=”01” then
y <= “101”;
elsif s=”10” then
y <= “100”
else
y <= “111”;
end if;
end process;
End bhv ;

Emploi du code séquentiel pour l’implémentation de circuits


combinatoires :

Les instructions séquentielles peuvent tout aussi bien servir à implémenter des
circuits séquentiels que des circuits combinatoires. Dans le premier cas , des
bascules seront employées. Cependant , ceci ne doit pas avoir lieu dans le cas d’un
circuit combinatoire .
Ainsi , une erreur courante , consiste à utiliser une table de vérité non exhaustive ;
exemple :
Dans la figure précédente , en (b) la table de vérité n’est pas exhaustive .
Quelles valeurs affecter à y pour sel="10" ou "11" ?
Si nous choisissons la solution qui consiste à ne rien affecter à y pour sel="10" ou
"11" et utilisons le code suivant :
1 --------------------------------------
2 LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 --------------------------------------
5 ENTITY exemple IS
6 PORT (a, b, c, d: IN STD_LOGIC;
7 sel: IN INTEGER RANGE 0 TO 3; -- ou bien sel: in std_logic_vector(1 downto 0);
8 x, y: OUT STD_LOGIC);
9 END exemple;
10 --------------------------------------
11 ARCHITECTURE exemple OF exemple IS
12 BEGIN
13 PROCESS (a, b, c, d, sel)
14 BEGIN
15 IF (sel=0) THEN -- ou bien if sel=”00” then
16 x<=a;
17 y<='0';
18 ELSIF (sel=1) THEN -- ou bien if sel=”01” then
19 x<=b;
20 y<='1';
21 ELSIF (sel=2) THEN -- ou bien if sel=”10” then
22 x<=c;
23 ELSE
24 x<=d;
25 END IF;
26 END PROCESS;
27 END exemple;

Aucune erreur n’est signalée à l’issue de la compilation .Cependant , les résultats de


la simulation révèlent un mauvais fonctionnement du circuit :
puisqu’il s’agit d’un circuit combinatoire , la même valeur de sel devrait donner la
même valeur de y ; or , il n’en est rien .En fait cette simulation montre qu’il y a un
effet mémoire .Ceci est dû à l’emploi par le compilateur de l’équation :
y = (sel(0) AND sel(1)) OR (sel(0) AND y) OR (sel(1) AND y)
qui est clairement séquentielle.
Pour éviter cette erreur , nous devons compléter la table de vérité comme en (d) .
Dans le code VHDL précédent , il faudra insérer en dessous des lignes 22 et 24
l’instruction y<='X';
( ‘X’ est l’état inconnu ).
Le compilateur , choisissant de simplifier au maximum l’équation logique de y ,
utilisera y= sel(0) . Correcte dans ce cas.
8-DRIVER D’UN SIGNAL :

Le driver d’un signal est un objet donnant l’évolution dans le temps de ce


signal .Cet objet peut être assimilé à un tableau dont une colonne est celle de
différents instants ti ,alors que la seconde colonne donnent les valeurs

PREVUES pour ce signal .


Ce driver est utilisé de 2 maniéres :
- En cours de simulation , permet à partir du vecteur de stimulation
( stimulus/stimuli ) de déterminer l’évolution dans le temps de ce signal.
- Permet au compilateur d’établir le jeu d’équations logiques conforme
pour réaliser ( implémenter) une structure matérielle.
Régle : 1 seul driver par signal. Il ne peut y avoir 2 ou plusieurs affectations
à un même signal réparties sur plusieurs process

La description suivante est fausse :

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_signed.all;
entity ex5 is
port (s,r : in std_logic;
q,qbar : out std_logic);
end ex5;
Architecture bhv of EX5 is
Begin
Process (r)
Begin 
If r=’1’ then
Q <= ‘0’ ;
Qbar <= ‘1’;
End if ;
End process ;
Process(s)
Begin
If s=’1’ then
Q <= ‘1’;
Qbar <= ‘0’;
End if;
End process ;
End bhv ;
9. Signaux – constantes - variables - generiques:

Les signaux et les variables sont des objets destinés à la manipulation de


données non statiques .Une 3° catégorie d’objets est destinée aux données
statiques : les constantes et generiques .
Les constantes et les signaux peuvent être de nature globale ; i.e visible
dans n’importe quelle section du code VHDL , qu’elle soit séquentielle ou
concurrente.
A l’inverse , une variable est de nature locale , visible uniquement dans une
seule section de code séquentielle .Cette section peut être un Process , une
Fonction ou une procédure .Sa valeur ne peut être transmise directement à
l’extérieur de cette section .

CONSTANTE :
La syntaxe de la déclaration d’une constante est :
Constant identificateur : type := valeur ;
Exemple:
CONSTANT set_bit : std_logic := '1';

Une constante peut être déclarée dans un Package , Entity ou Architecture .


Sa visibilité est toujours globale .

VARIABLE :
Cette catégorie d’objet représente une information à caractére local . Une variable
ne peut être utilisée qu’à l’intérieur d’un segment de code séquentiel
( process , fonction ou procédure ) et sa valeur ne peut être transmise directement à
l’extérieur dudit segment .
D’un autre côté , l’actualisation d’une variable est immédiate et sa nouvelle
valeur est disponible immédiatement dans la ligne suivante du code VHDL.
De ce fait , il est licite d’utiliser plusieurs affectations à la même variable.
La syntaxe de la déclaration de variable est :
VARIABLE identificateur : type [intervalle] [:= valeur initiale];
Exemples:
VARIABLE control: BIT := '0';
VARIABLE count: INTEGER RANGE 0 TO 100;
VARIABLE y: STD_LOGIC_VECTOR (7 DOWNTO 0) := "10001000";

Cette déclaration ne peut apparaitre que dans la zone déclaration d’un process,
fonction ou procédure. La valeur initiale apparaissant éventuellement dans la
déclaration , n’est pas synthétisable , mais destinée uniquement à la
simulation .
L’opérateur d’affectation à une variable est ‘‘:=’’ (Ex.: count:=35;).

Actualisation de la valeur d’une variable/d’un signal :


Supposons que S1,S2 et S3 soient des signaux de type entier dans l’intervalle
(0,20) et que la valeur de S1 soit égale à 5 à l’instant du démarrage du process.

Process (s3) -- le process démarre dés qu’il y’a changement de valeur de s3


Variable var1 : integer range 0 to 20 := 3 ;
Variable var2 : integer range 0 to 20 ;
begin
Var2 := var1 * 2 ; -- var2 reçoit immédiatement la valeur 3 * 2 = 6
S1 <= var2 * 3 ; -- s1 recevra la valeur 6 * 3 = 18 à la suspension du process
--en cours
s2 <= s1 * 2 + var2 ; -- s2 recevra la valeur 16 à la suspension du process en
-- cours 5 * 2 + 6 = 16
end process ;

Choix entre variable ou signal :


Rappel : Quand un signal fait l’objet de plusieurs affectations , il peut en
découler soit une erreur à la compilation ,ou pire , une implémentation erronée du
circuit .
Recommandation : emploi d’une variable

Dénombrement de 1 #1 (Faux)
Soit à concevoir un circuit destiné à dénombrer le nombre de ‘1’ présents dans un
vecteur binaire . Le code suivant n’utilise que des signaux . Le signal TEMP subit
plusieurs affectations en lignes 15 ( 1 seule ) et 18 ( 8 affectations ).De plus ,
comme la valeur de TEMP n’est pas actualisée immédiatement , la ligne 15 est en
conflit avec la ligne 18 : à la suspension du process , quelle valeur est attribuée à
TEMP ? Dans ce genre de situation , il est recommandé d’utiliser une variable.
D’autre part , il peut sembler plus simple d’utiliser directement le signal ONES plutôt
que le signal interne TEMP ( ligne 11) . Pour celà , il est nécessaire de modifier le
mode de ONES : soit BUFFER soit INOUT , car ce signal subit une affectation (ligne
15) et est lu ( ligne 18).

1 ---------------------------------------
2 LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 ---------------------------------------
5 ENTITY count_ones IS
6 PORT ( din: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
7 ones: OUT INTEGER RANGE 0 TO 8);
8 END count_ones;
9 ---------------------------------------
10 ARCHITECTURE faux OF count_ones IS
11 SIGNAL temp: INTEGER RANGE 0 TO 8;
12 BEGIN
13 PROCESS (din)
14 BEGIN
15 temp <= 0;
16 FOR i IN 0 TO 7 LOOP
17 IF (din(i)='1') THEN
18 temp <= temp + 1;
19 END IF;
20 END LOOP;
21 ones <= temp;
22 END PROCESS;
23 END faux;
24 ---------------------------------------

Dénombrement de 1 #2 (juste)
Reprenons l’exemple du denombrement de ‘1’ présents dans un vecteur binaire et
considérons le code ci-dessous.La seule différence par rapport au code précédent est
que l’objet TEMP est déclaré comme variable et non plus comme signal .
Du moment qu’une variable est actualisée immédiatement à l’issue d’une affectation ,
l’initialisation de temp (ligne 15 ) n’est plus en conflit avec son incrémentation (ligne
18) ; d’autre part , les multiples affectations de la ligne 18 ne produisent plus
d’erreur en cours de compilation .

1 ---------------------------------------
2 LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 ---------------------------------------
5 ENTITY count_ones IS
6 PORT ( din: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
7 ones: OUT INTEGER RANGE 0 TO 8);
8 END count_ones;
9 ---------------------------------------
10 ARCHITECTURE juste OF count_ones IS
11 BEGIN
12 PROCESS (din)
13 VARIABLE temp: INTEGER RANGE 0 TO 8;
14 BEGIN
15 temp := 0;
16 FOR i IN 0 TO 7 LOOP
17 IF (din(i)='1') THEN
18 temp := temp + 1;
19 END IF;
20 END LOOP;
21 ones <= temp;
22 END PROCESS;
23 END juste;
24 ---------------------------------------

Le bon fonctionnement du circuit peut être vérifié grâce aux résultats de simulation
représentés ci-dessous .
Paramétre Generique  :

Un paramétre générique est un paramétre statique facilement modifiable


pour l’adapter à différentes applications. Par exemple , la taille des données à
traiter peut être fixée à 8 bits ( paramétre statique ) mais , déclarée avec generic ,
elle pourra être modifiée pour traiter des données à 16 , 32 , … bits. L’instruction
generic doit apparaitre dans la déclaration d’entité.

Exemple:

L’instruction GENERIC suivante spécifie le paramétre entier n de valeur par défaut


égale à 8 .

ENTITY my_entity IS
GENERIC (n : INTEGER := 8);
PORT (...);
END my_entity;
ARCHITECTURE my_architecture OF my_entity IS
...
END my_architecture ;

Plusieurs paramétres peuvent être spécifiés dans une instruction GENERIC.


En utilisant la spécification GENERIC MAP , il est possible de modifier les
paramétres génériques figurant dans l’instruction GENERIC.

Exemple : déclaration de 2 paramétres génériques n et v

n entier et prenant par défaut la valeur 8 et v vecteur de type bit_vector et prenant


par défaut la valeur 00001111 :

GENERIC (n: INTEGER := 8; v: BIT_VECTOR := "00001111");

Exemple : Decodeur

Ce circuit combinatoire dispose de 2 signaux d’entrée : sel (m bits) et ena (1bit). En


sortie , nous trouvons le vecteur X à n bits.
La table de vérité pour n=2 et m=4 montre que tous
les bits de X sont à ‘1’ si ena=’0’ ; sinon, seul le bit
selectioné par sel est à ‘0’.
L’idée de base pour réaliser la description est la
suivante : nous convertissons sel en son équivalent
entier. La valeur de cet entier donne la position du
bit de X qui doit être placé à ‘0’.
L’objectif est d’établir une description VHDL avec n
et m comme paramétres génériques , leurs valeurs
par défaut étant : n=8 et m=3:

1 ---------------------------------------------
2 LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 ---------------------------------------------
5 ENTITY decoder IS
Generic ( n : integer := 8 ; m : integer := 3) ;
6 PORT ( ena : IN STD_LOGIC;
7 sel : IN STD_LOGIC_VECTOR (m-1 DOWNTO 0);
8 x : OUT STD_LOGIC_VECTOR (n-1 DOWNTO 0));
9 END decoder;
10 ---------------------------------------------
11 ARCHITECTURE decoder OF decoder IS
12 BEGIN
13 PROCESS (ena, sel)
14 VARIABLE temp1 : STD_LOGIC_VECTOR (n-1 DOWNTO 0);
15 VARIABLE temp2 : INTEGER RANGE 0 TO n-1 ;
16 BEGIN
17 temp1 := (OTHERS => '1');
18 temp2 := 0;
19 IF (ena='1') THEN
20 FOR i IN 0 to m-1 LOOP -- l’intervalle de sel est 2 downto 0
21 IF (sel(i)='1') THEN -- conversion de binaire  entier
22 temp2:=2*temp2+1;
23 ELSE
24 temp2 := 2*temp2;
25 END IF;
26 END LOOP;
27 temp1(temp2):='0';
28 END IF;
29 x <= temp1;
30 END PROCESS;
31 END decoder;
32 ---------------------------------------------

A présent donnons la description d’un décodeur avec n=16 et m=4 :


---------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
---------------------------------------------
ENTITY decoder_4 IS
PORT ( ena_4 : IN STD_LOGIC;
sel_4 : IN STD_LOGIC_VECTOR (3 DOWNTO 0);
x_4 : OUT STD_LOGIC_VECTOR (15 DOWNTO 0));
END decoder_4;
architecture bhv of decoder_4 is
Component decoder
Generic ( n : integer := 8 ; m : integer := 3) ;
PORT ( ena : IN STD_LOGIC;
sel : IN STD_LOGIC_VECTOR (m-1 DOWNTO 0);
x : OUT STD_LOGIC_VECTOR (n-1 DOWNTO 0));
End component ;
Begin
C1 : decoder generic map (16,4) port map(ena_4,sel_4,x_4) ;
End bhv ;

CHAPITRE 2 :

DESCRIPTION DE CIRCUITS SEQUENTIELS SYNCHRONES

La description des circuits séquentiels synchrones est basée sur :


 Emploi d’un process incluant dans sa liste de sensibilité le signal
d’horloge CLK ainsi qu’éventuellement des signaux de set ou reset
 Emploi du mot-clé « rising_edge » pour la détection de front montant
d’horloge ( pour le front descendant , employer « falling_edge » )
Les circuits séquentiels synchrones avec toutes leurs variantes (JK , T, …) sont
basés , au niveau du synthétiseur VHDL , sur l’emploi de bascules D.

Tout signal recevant une affectation à l’intérieur d’un process séquentiel


synchrone est associé à une bascule D .

1. Bascule D : avec et sans entrée de validation

D Q D Q

en

Clk

Reset Reset

Régles de fonctionnement :
Pour une bascule D sensible au front montant d’horloge , la sortie Q reproduit
l’état de l’entrée D établie avant l’arrivée du front.Dans le cas où le signal de
validation est présent ( en ) , il doit être actif pour que la sortie suive l’entrée à
l’occurrence du front actif d’horloge.
Le signal reset est asynchrone .
L’entrée D doit être établie avant l’arrivée du front actif d’horloge ( Tsetup ) et
se maintenir constante après le passage de ce même front (Thold ) . Le non
respect de cette régle peut aboutir à des disfonctionnements (métastabilité ).

Library ieee ; Begin 


Use ieee.std_logic_1164.all ; If reset=’1’ then
Use ieee.std_logic_arith.all ; Q <= ‘0’ ;
Use ieee.std_logic_unsigned.all ; Elsif rising_edge(clk) then
Entity FFD is If en='1' then
Port ( Q <= d ;
D,clk,reset,en,raz ,ld: in std_logic ; End if;
Q,qbar : out std_logic) ; If raz='1' then
End ffd ; Q <= '0';
Architecture bhv of ffd is End if;
Begin If ld='1' then
Process (clk,reset,en,raz) Q <= '1';
End if; Qbar <= not(q);
End if ; End bhv ;
End process ;

Considérons à présent l’architecture suivante :

Architecture bhv of ffd is


Begin
Process (clk,reset)
Begin 
If reset=’1’ then
Q <= ‘0’ ;
Elsif rising_edge(clk) then
Q <= d ;
Qbar <= not(d);
End if ;
End process ;
End bhv ;

Dans ce cas , nous utiliserons 2 bascules D : l’une pour Q et la seconde pour
qbar .

2- Registre à décalage :

reset
Din Dout
3 2 1 0

Clk

Dec

Le décalage est ordonné par le signal Dec .


Library ieee ; If reset=’1’ then
Use ieee.std_logic_1164.all ; Q_int <= (others => ‘0’) ;
Use ieee.std_logic_arith.all ; Elsif rising_edge(clk) then
Use ieee.std_logic_unsigned.all ; If dec=’1’ then
Entity FFD_shift is Q_int(0) <= q_int(1) ;
Port ( Q_int(1) <= q_int(2) ;
Din,clk,reset,dec : in std_logic ; Q_int(2) <= q_int(3) ;
Dout : out std_logic) ; Q_int(3) <= Din ;
End ffd_shift ; End if ;
Architecture bhv1 of ffd_shift is End if ;
Signal q_int : std_logic_vector(3 End process ;
downto 0) ; Dout <= q_int(0) ;
Begin End bhv1 ;
Process (clk,reset)
Begin 

--dans cette seconde architecture , nous réalisons le décalage au moyen d’une


---seule instruction qui emploit l’opérateur de concaténation & .

Architecture bhv2 of ffd_shift is


Signal q_int : std_logic_vector(3
downto 0) ;
Begin
Process (clk,reset)
Begin 
If reset=’1’ then
Q_int <= (others => ‘0’) ;
Elsif rising_edge(clk) then
If dec=’1’ then
q_int <= din & q_int(3 downto 1) ;
--q_int <= q_int(2 downto 0) & din;
End if ;
End if ;
End process ;
Dout <= q_int(0) ;
End bhv2 ;
-
3- Registre 8 bits : avec validation de chargement

reset

Din Dout
8 8

Clk
En

Library ieee ;
Use ieee.std_logic_1164.all ; Process (clk,reset)
Use ieee.std_logic_arith.all ; Begin 
Use ieee.std_logic_unsigned.all ; If reset=’1’ then
Entity FFD_8 is dout <= (others =>’0’) ;
Port (Din : in std_logic_vector(7 downto Elsif rising_edge(clk) then
0) ; If en=’1’ then
clk,reset,en : in std_logic ; Dout <= din ;
dout  :out std_logic_vector(7 downto 0) ) ; End if ;
End ffd_8 ; End if ;
Architecture bhv of ffd_8 is End process ;
Begin End bhv ;
4- Compteur 8 bits :

INC

Cout
RAZ COUNT 8
CLK
reset
Ce compteur synchrone s’incrémente au moyen du signal INC .
Le signal RAZ sert à la remise à zéro du signal de sortie Cout codé sur 8 bits.

Library ieee ; coutp <= (others =>’0’) ;


Use ieee.std_logic_1164.all ; Elsif rising_edge(clk) then
Use ieee.std_logic_arith.all ; If raz=’1’ then
Use ieee.std_logic_unsigned.all ; coutp <= (others =>’0’) ;
Entity count is elsif inc=’1’ then
Port (Inc,clk,raz,reset : in std_logic ; coutp <= coutp + 1 ;
cout  : out std_logic_vector(7 downto 0) ) ; else
End count ; coutp <= coutp ;
Architecture bhv of count is End if ;
Signal coutp : std_logic_vector(7 downto End if ;
0); End process ;
Begin End bhv ;
Cout <= coutp;
Process (clk,reset)
Begin 
If reset=’1’ then
5- Bascule JK :
J k qn+1
0 0 qn
0 1 0
1 0 1
1 1 not(qn)

Library ieee ; Begin


Use ieee.std_logic_1164.all ; If reset ='1' then
Use ieee.std_logic_arith.all ; S <= '0' ;
Use ieee.std_logic_unsigned.all ; Elsif rising_edge(clk) then
Entity jkff is if jk= "00" then
Port( J,k,clk,reset : in std_logic ; s <= s ;
Q,qbar : out std_logic ); elsif jk= "01" then
End jkff ; s <= '0' ;
Architecture bhv of jkff is elsif jk= "10" then
Signal s : std_logic ; s <= '1' ;
Signal jk : std_logic_vector(1 downto 0) ; else
Begin s <= not(s) ;
Q <= s ; End if ;
Qbar <= not(s) ; End if;
Jk <= j & k ; End process;
Process (clk,reset) End bhv ;

6- Registres implémentés par une variable :

Une bascule est créée à chaque fois qu’un signal subit une affectation suite
à un front survenant sur un autre signal ; il s’agit donc de l’affectation
synchrone.
Une telle affectation ne peut avoir lieu qu’au sein d’un segment de code séquentiel
( process , fonction ou procédure ) et généralement à la suite de
‘‘IF rising_edge . . .’’ ou ‘IF falling_edge . . .’’.

Dans le cas d’une variable qui subit une affectation synchrone , il n’y a pas
nécessairement création d’une bascule :
 Si la valeur de la variable n’est utilisée qu’à l’intérieur du segment de code
séquentiel , aucune bascule n’est créée.
 Si la valeur de la variable est transmise à l’extérieur du segment de code
séquentiel ( à travers un signal par ex .) , une bascule est créée.
 Si la variable est utilisée (lue ) avant qu’elle ne subisse une affectation
synchrone ,alors dans ce cas également une bascule est créée .

Exemple:
Dans cet exemple , la variable temp subit une affectation synchrone et sa valeur est
passée au signal x .Ce dernier sera donc registré.

PROCESS (clk)
VARIABLE temp: BIT;
BEGIN
IF (clk ‘EVENT AND clk='1') THEN
temp := a; -- temp subit une affectation synchrone
END IF;
x <= temp; -- temp est transmise à x qui sera donc registré
END PROCESS;

Exemple : Registre à décalage

Considérons le registre à décalage représenté ci-dessus.La sortie Dout reproduit


l’entrée Din avec un retard de 4 clk.
Dans la solution 1 , 3 variables ( a , b et c , ligne 10 ) sont utilisées ( lues) avant
qu’une affectation synchrone n’ait lieu.Ces variables sont lues dans l’ordre inverse
( dout en ligne 13 pour finir avec din en ligne 16).Par conséquent , 4 bascules sont
créées pour sauvegarder les valeurs de ces variables issues du cycle d’éxécution
précédent du process.
Dans la solution 2 , les variables sont remplacées par des signaux (ligne 8) et les
affectations synchrones ont lieu dans l’ordre direct. Comme il s’agit d’affectations
synchrones visant des signaux , 4 bascules sont créées et le circuit est correct.
Finalement , la solution 3 utilise les mêmes variables que la solution 1 mais celles-ci
sont employées en ordre direct ( de din à dout lignes 13-16).Mais comme nous
l’avons vu , l’affectation à une variable est à effet immédiat.Comme ces variables
sont lues en ordre direct ( i.e aprés que des valeurs leur aient été affectées ) les
lignes 13-15 se réduisent à une seule ligne , équivalente à c := din. D’autre part , la
valeur de c quitte le process par le biais du signal dout ( ligne 16) et donc 1 et une
seule bascule est créée. Le circuit sera donc incorrect.

1 -------- Solution 1: -----------------


2 ENTITY reg_dec IS
3 PORT ( din, clk: IN std_logic; 1 -------- Solution 2: -----------------
4 dout: OUT std_logic); 2 ENTITY reg_dec IS
5 END reg_dec; 3 PORT ( din, clk: IN BIT;
6 -------------------------------------- 4 dout: OUT BIT);
7 ARCHITECTURE bhv OF reg_dec IS 5 END reg_dec;
8 BEGIN 6 --------------------------------------
9 PROCESS (clk) 7 ARCHITECTURE bhv OF reg_dec IS
10 VARIABLE a, b, c: std_logic; 8 SIGNAL a, b, c: std_logic;
11 BEGIN 9 BEGIN
12 IF rising_edge(clk) THEN 10 PROCESS (clk)
13 dout <= c; 11 BEGIN
14 c := b; 12 IF rising_edge(clk) THEN
15 b := a; 13 a <= din;
16 a := din; 14 b <= a;
17 END IF; 15 c <= b;
18 END PROCESS; 16 dout <= c;
19 END bhv; 17 END IF;
20 -------------------------------------- 18 END PROCESS;
19 END bhv;
1 -------- Solution 3: ----------------- 11 BEGIN
2 ENTITY reg_dec IS 12 IF rising_edge(clk) THEN
3 PORT ( din, clk: IN std_logic; 13 a := din;
4 dout: OUT BIT); 14 b := a;
5 END regf_dec; 15 c := b;
6 -------------------------------------- 16 dout <= c;
7 ARCHITECTURE bhv OF reg_dec IS 17 END IF;
8 BEGIN 18 END PROCESS;
9 PROCESS (clk) 19 END bhv;
10 VARIABLE a, b, c: BIT; 20 --------------------------------------

Les résultats de simulation sont reproduits ci-dessous.


Le premier graphe est relatif aux solutions 1 et 2 : dout est bien retardé de 4 clk par
rapport à din.
Le second graphe est relatif à la solution 3 : dout est retardé d’une seule clk par
rapport à din , confirmant que le circuit est incorrect dans ce cas .

7- Description d’un systéme d’équations sequentielles synchrones

Soit un systéme séquentiel synchrone , cadencé par une horloge clk,


comportant :
 Un ensemble d’équations dans lesquelles n’apparaissent que les
opérateurs NOT et AND . Cet ensemble est appelé : le plan ET. Les
signaux figurant aux premiers membres sont appelés les termes
produits. Dans les seconds membres , apparaissent des signaux
d’entrée ainsi que des signaux d’état.
 Un ensemble d’équations dans lesquelles n’apparait que l’opérateur
OR . Cet ensemble est appelé : le plan OU .Les signaux figurant aux
premiers membres sont les signaux d’état ainsi que les signaux de
sortie . Dans les seconds membres , figurent les signaux de termes
produits .

La description VHDL d’un tel systéme comporte :


 Chaque équation du plan ET est décrite par un process
implicite.
 L’ensemble des équations du plan OU sont regroupées au sein
d’un process explicite séquentiel et synchrone.

Exemple :

R1 = /din . /e1./e0
R2=din./e1./e0 E1 = r4 + r5
R3 = din . /e1. E0 E0 = r2 + r3
R4 = /din . /e1. E0 En= r2+r3+r4+r5
R5 = /din . e1. /e0 Raz=r6
R6 = din. E1. /e0

r1 <= not(din) and not(e1) and process(clk,reset)


not(e0); begin
r2 <= din and not(e1) and not(e0); if reset='1' then
r3 <= din and not(e1) and e0; e1 <= '0';
r4 <= not(din) and not(e1) and e0; e0 <= '0';
r5 <= not(din) and e1 and not(e0); en <= '0';
r6 <= din and e1 and not(e0); raz <= '0';
elsif rising_edge(clk) then
en <= r2 or r3 or r4 or r5;
raz <= r6;
e1 <= r4 or r5;
e0 <= r2 or r3;
end if;
end process;

Chapitre 3 : Instructions concurrentes et séquentielles


1. Instructions concurrentes :
Dans le domaine concurrent , nous trouvons :
 l'affectation <= utilisant ou non des opérateurs
 l'instantiation de composant ( déja vue)
 process (déja vu)
 When
 Generate
 Block
a. Affectation concurrente :
L'affectation concurrente peut ou non utiliser des opérateurs ; elle utilise toujours le symbole
<= ( car := ne peut concerner que les variables présentes dans du code séquentiel ).
Ex : S1 <= temp;
S2 <= S3 and S4;

<= pour l’affectation d’une valeur à un signal.


=> pour affecter des valeurs individuelles aux éléments d’un vecteur et également
pour la clause OTHERS.

Exemple: soient les déclarations de signal et variable suivantes:

SIGNAL x : STD_LOGIC;
VARIABLE y : STD_LOGIC_VECTOR(3 DOWNTO 0); -- MSB est à gauche
SIGNAL w: STD_LOGIC_VECTOR(0 TO 7); -- MSB est à droite

Les affectations suivantes sont légales:


x <= '1';
w <= "10000000"; --MSB est mis à '1', autres bits à '0'
w <= (0 =>'1', OTHERS =>'0'); -- LSB est mis à '1', autres bits à '0'

Opérateurs logiques : NOT AND OR NAND NOR XOR XNOR

Les opérandes doivent être de type BIT, STD_LOGIC ou STD_ULOGIC (ou leurs
extensions respectives BIT_VECTOR,STD_LOGIC_VECTOR ou
STD_ULOGIC_VECTOR). Ces opérateurs sont :

Remarque: l’opérateur NOT a précédence sur les autres opérateurs logiques.

Exemples:

y <= NOT a AND b; -- (a'.b)


y <= NOT (a AND b); -- (a.b)'
y <= a NAND b; -- (a.b)'

---------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
---------------------------------------
ENTITY mux IS
PORT ( a, b, c, d, s0, s1: IN STD_LOGIC;
y: OUT STD_LOGIC);
END mux;
---------------------------------------
ARCHITECTURE pure_logic OF mux IS
BEGIN
y <= (a AND NOT s1 AND NOT s0) OR
(b AND NOT s1 AND s0) OR
(c AND s1 AND NOT s0) OR
(d AND s1 AND s0);
END pure_logic;
---------------------------------------
Opérateurs Arithmetiques :
Les opérandes peuvent être de type INTEGER,SIGNED, UNSIGNED, ou REAL (ce type
n’est pas synthétisable).De plus ,si les packages std_logic_signed ou
std_logic_unsigned de la librairie ieee sont invoqués , alors le type
STD_LOGIC_VECTOR peut également être utilisé dans les opérations
d’addition/soustraction. Ces opérateurs sont au nombre de 8 :

Opérateurs signification synthése


+ Addition oui
- Subtraction oui
* Multiplication oui
/ Division oui si diviseur est en
puissance de 2
** Exponentiation oui si la base et
l’exposant sont statiques
MOD Modulo non
REM Reste non
ABS valeur Absolue non

Opérateurs de comparaison :

Appelés également opérateurs relationnels , ils sont au nombre de 6 . Les opérandes


peuvent être de n’importe quel type cité précédemment .
= égalité
/= inégalité
< inférieur
> supérieur
<= inférieur ou égal
>= supérieur ou égal

Opérateurs de décalage :

Servent au décalage de données . Ils sont au nombre de 6 et leur syntaxe est la suivante :
<opérande gauche> <opérateur décalage> <opérande de droite>.
L’opérande gauche doit être de type BIT_VECTOR, alors que l’opérande de droite doit être de type INTEGER ( précédé du
signe + ou – éventuellement). Ces opérateurs sont :
sll décalage logique gauche ; avec insertion de ‘0’ à droite
srl décalage logique à droite ; avec insertion de ‘0’ à gauche
sla décalage arithmétique gauche ;
sra décalage arithmétique droit ;
rol rotation à gauche ;
ror rotation à droite ;

remarque : le décalage logique est à distinguer du décalage arithmétique.Ce dernier conserve le signe inchangé aprés
décalage.
Attention : ces opérateurs ne sont pas reconnus sous QUARTUS

Opérateur de concaténation : &

L’opérateur de concaténation & permet d’enchaîner des chaines de caractéres ou


de bits.

Exemple :
Soit la déclaration de signal suivante :
Signal A : std_logic_vector (3 downto 0) := "0111" ; -- A est initialisé à 0111
A <= ‘1’ & A(3 downto 1) ; -- A reçoit 1011
b. When:

Cette instruction concurrente se présente sous 2 variantes :


WHEN / ELSE:
la syntaxe est la suivante :
Affectation WHEN condition1 ELSE
Affectation WHEN condition2 ELSE
...;

Exemple :
outp <= "000" WHEN (inp='0' OR reset='1') ELSE
"001" WHEN ctl='1' ELSE
"010";
WITH / SELECT / WHEN:
la syntaxe est la suivante :
WITH identificateur SELECT
Affectation WHEN valeur,
Affectation WHEN valeur,
...;

Toutes les valeurs possibles de l’objet identificateur doivent être testées.


Aussi , le mot-clé OTHERS est pratique en permettant de regrouper plusieurs
affectations .

Exemple :
With sel SELECT
A <= B when "000",
C when "001",
D when "010",
E when "011",
F when "100",
G when others ;--- les valeurs de sel 101 , 110 , 111 ,X01,X10,… ---
--sont regroupées dans l’affectation A <= G

Un second mot-clé est pratique : UNAFFECTED , à utiliser quand aucune affectation


n’est requise .

Exemple :
WITH control SELECT
output <= "000" WHEN '0',
"111" WHEN '1',
UNAFFECTED WHEN OTHERS;

A noter que dans la syntaxe précédente , valeur peut prendre l’une des formes
suivantes :
WHEN valeur -- valeur unique
WHEN valeur1 to valeur2 -- intervalle , à utiliser pour les données de type
-- énuméré uniquement
WHEN valeur1 | valeur2 |... -- valeur1 OU valeur2 OU ...
Exemple : multiplexeur
Ce circuit dispose de 4 entrées scalaires : a , b , c et d , ainsi que d’une entrée
vectorielle Sel sur 2 bits . La sortie scalaire y est égale à l’entrée sélectionnée par
Sel . Nous donnons ci-dessous 3 descriptions de ce même circuit , équivalentes et
synthétisables.

------- Solution 1: emploi de WHEN/ELSE ----- -------------------------------------------


LIBRARY ieee; ARCHITECTURE mux1 OF mux IS
USE ieee.std_logic_1164.all; BEGIN
------------------------------------------- y <= a WHEN sel="00" ELSE
ENTITY mux IS b WHEN sel="01" ELSE
PORT ( a, b, c, d: IN STD_LOGIC; c WHEN sel="10" ELSE
7 sel: IN STD_LOGIC_VECTOR (1 DOWNTO 0); d;
8 y: OUT STD_LOGIC); END mux1;
9 END mux; -------------------------------------------

-- Solution 2: emploi de WITH/SELECT/WHEN WITH sel SELECT


LIBRARY ieee; y <= a WHEN "00", -- notez "," au lieu de ";"
USE ieee.std_logic_1164.all; b WHEN "01",
ENTITY mux IS c WHEN "10",
PORT ( a, b, c, d: IN STD_LOGIC; d WHEN OTHERS; -- et non pas "d WHEN
sel: IN STD_LOGIC_VECTOR (1 DOWNTO 0); -- "11" " car chaque bit
y: OUT STD_LOGIC); --peut prendre 9 valeurs
END mux; --possibles
ARCHITECTURE mux2 OF mux IS END mux2;
BEGIN --------------------------------------------

-------------solution 3 : sel déclaré comme entier sel: IN INTEGER RANGE 0 TO 3;


LIBRARY ieee; y: OUT STD_LOGIC);
USE ieee.std_logic_1164.all; 9 END mux;
ENTITY mux IS ---- Solution 1: with WHEN/ELSE ---------------
PORT ( a, b, c, d: IN STD_LOGIC; ARCHITECTURE mux1 OF mux IS
BEGIN y <= a WHEN 0,
y <= a WHEN sel=0 ELSE b WHEN 1,
b WHEN sel=1 ELSE c WHEN 2,
c WHEN sel=2 ELSE d WHEN 3; -- ici, 3 ou OTHERS sont
d; -- equivalents,
END mux1; -- car toutes les options ( 0 1 2 et
-- Solution 2: with WITH/SELECT/WHEN ----- -- 3 ) auront été testées de toute
ARCHITECTURE mux2 OF mux IS -- façon 
BEGIN
WITH sel SELECT END mux2;
c. Generate:

Ce type d’instruction concurrente est équivalent à une boucle : ainsi , une section de
code est répétée un certain nombre de fois. A noter que cette instruction doit être
étiquetée (label ).
La syntaxe pour FOR/GENERATE est la suivante :
label: FOR identifier IN range GENERATE
(affectations concurrentes )
END GENERATE;
Précisons que range doit être une valeur statique ; i.e immédiatement fixée lors de la
compilation.Considérons l’exemple suivant où choice constitue un paramétre d’entrée
(non statique ) . Ce type de code ne peut être synthétisé :

Pas_OK: FOR i IN 0 TO choice GENERATE


(instructions concurrentes)
END GENERATE;

D’autre part , une erreur courante survient dans l’utilisation de generate ; de


multiples drivers pour le même signal sont invoqués. Ainsi :

C_est_OK: FOR i IN 0 TO 7 GENERATE


output(i)<='1' WHEN (a(i) AND b(i))='1' ELSE '0';-- une seule affectation pour
-- chaque élément d’indice i de output
END GENERATE;

Le code précédent est correct. Par contre , les 2 codes suivants sont incorrects :

Pas_OK1: FOR i IN 0 TO 7 GENERATE


accum <="11111111" WHEN (a(i) AND b(i))='1' ELSE "00000000";
END GENERATE;

Pas_OK2: For i IN 0 to 7 GENERATE


accum <= accum + 1 WHEN x(i)='1';
END GENERATE;

En effet , dans les 2 cas précédents accum subit 8 affectations concurrentes ; donc
simultanées , donc fausses.

Exemple:
soit à réaliser un AND entre l’octet X et l’octet de poids fort du mot Y ( à placer dans
zhigh ) ensuite entre X et l’octet de poids faible du mot Y ( à placer dans zlow ).

SIGNAL x: std_logic__VECTOR (7 DOWNTO 0);


SIGNAL y: std_logic_VECTOR (15 DOWNTO 0);
SIGNAL zlow,zhigh: std_logic_VECTOR (7 DOWNTO 0);
...
G1: FOR i IN x'RANGE GENERATE
zlow(i) <= x(i) AND y(i); -- ces deux affectations
zhigh(i) <= x(i) and y(i+8) ; -- sont concurrentes
END GENERATE;

Exemple : décaleur à gauche de 4 positions

le circuit est représenté ci-contre. Le nombre de décalages


est fixé par sel. A chaque décalage , un ‘0’ est injecté à
droite.
Pour réaliser celà , nous créons un tableau 5 lignes x 8
colonnes dénommé row :

row(0): 1 1 1 1 sel=0 (aucun décalage )


row(1): 1 1 1 0 sel=1 1 décalage
row(2): 1 1 0 0 sel=2 2 décalages
row(3): 1 0 0 0 sel=3 3 décalages
row(4): 0 0 0 0 sel=4 4 décalages

ci-dessous le code VHDL  :


------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
------------------------------------------------
ENTITY shifter IS
PORT ( inp: IN STD_LOGIC_VECTOR (3 DOWNTO 0);
sel: IN INTEGER RANGE 0 TO 4;
outp: OUT STD_LOGIC_VECTOR (3 DOWNTO 0));
END shifter;
------------------------------------------------
ARCHITECTURE shifter OF shifter IS

TYPE matrix IS ARRAY (4 DOWNTO 0) OF STD_LOGIC_VECTOR (3 DOWNTO 0);


SIGNAL row: matrix;
BEGIN
row(0) <= inp;
G1: FOR i IN 1 TO 4 GENERATE
row(i) <= row(i-1)(2 DOWNTO 0) & '0'; -- notez l’emploi de l’opérateur &
END GENERATE; -- pour réaliser le décalage à gauche
outp <= row(sel);
END shifter;
------------------------------------------------
d. Block:

i. Block simple  :

Ce type de construction est juste une façon de partitionner le code pour améliorer sa lisibilité. Ce
block est étiqueté (label) ; s’ensuite une zone déclarative , le mot-clé BEGIN , des instructions
concurrentes et enfin END BLOCK. La syntaxe est  :

label: BLOCK
[déclarations]
BEGIN
(instructions concurrentes)
END BLOCK label;

Exemple:
b1: BLOCK
SIGNAL a: STD_LOGIC;
BEGIN
a <= input_sig WHEN ena='1' ELSE 'Z';
END BLOCK b1;

Un block (simple ou gardé ) peut être imbriqué dans un autre block ; la syntaxe est :
label1: BLOCK
[partie déclarative du block externe]
BEGIN
[instructions concurrentes]
label2: BLOCK
[partie déclarative du block interne]
BEGIN
(instructions concurrentes)
END BLOCK label2;
[autres instructions concurrentes du block externe]
END BLOCK label1;

ii. BLOCK gardé :

Ce type de block se distingue du précédent par la présence d’une expression dite expression de garde
. Dans le corps du block , sont placées des instructions concurrentes gardées et non gardées. Toute
instruction gardée n’est éxécutée que si l’expression de garde est vraie . Une instruction non gardée
est éxécutée quelque soit la valeur ( vrai/faux) de l’expression de garde. Une instruction gardée se
distingue par la présence en son sein du mot-clé GUARDED.

label: BLOCK (guard expression)


[declarative part]
BEGIN
(concurrent guarded and unguarded statements)
END BLOCK label;

Example : Latch

Dans cette description , clk='1' (ligne 12) est l’expresion de garde alors que q<=GUARDED d (ligne
14) est l’instruction gardée.
Donc , q<=d uniquement si clk='1'.

1 -------------------------------
2 LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 -------------------------------
5 ENTITY latch IS
6 PORT (d, clk: IN STD_LOGIC;
7 q: OUT STD_LOGIC);
8 END latch;
9 -------------------------------
10 ARCHITECTURE latch OF latch IS
11 BEGIN
12 b1: BLOCK (clk='1')
13 BEGIN
14 q <= GUARDED d;
15 END BLOCK b1;
16 END latch;
17 -------------------------------

Exemple : bascule D

Il s’agit d’une bascule D sensible au front montant et à reset synchrone.


Dans cette description , clk'EVENT AND clk='1' (ligne 12) est l’expression de garde alors que q <=
GUARDED '0' WHEN rst='1' ELSE d (ligne 14) est l’instruction gardée. Ainsi :
q <= ‘0’ si l’expression de garde est vraie et rst=’1’
q<= d si l’expression de garde est vraie et rst≠’1’

1 -------------------------------
2 LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 -------------------------------
5 ENTITY dff IS
6 PORT ( d, clk, rst: IN STD_LOGIC;
7 q: OUT STD_LOGIC);
8 END dff;
9 -------------------------------
10 ARCHITECTURE dff OF dff IS
11 BEGIN
12 b1: BLOCK (clk'EVENT AND clk='1')
13 BEGIN
14 q <= GUARDED '0' WHEN rst='1' ELSE d;
15 END BLOCK b1;
16 END dff;
17 ------------------------------

2. Instructions séquentielles :

a. IF  :

L’emploi de cette instruction est très courant vu l’analogie avec d’autres langages.
La syntaxe de l’instruction IF est la suivante :

IF conditions THEN
Instructions séquentielles;
ELSIF conditions THEN
Instructions séquentielles;
...
ELSE Instructions séquentielles ;
END IF;

Exemple:
IF (x<y) THEN temp:="11111111";
ELSIF (x=y AND w='0') THEN temp:="11110000";
ELSE temp:=(OTHERS =>'0');
End if ;

b. WAIT :

Un process dans lequel apparait l’instruction wait ne peut avoir de liste de sensibilité. Cette instruction
peut prendre 3 formes :

i. Wait until condition_signal;

Le process sera éxécuté à chaque fois que condition_signal est vérifiée.


La condition ne peut concerner qu’un seul signal.Celui-ci est le signal primaire.

Exemple :

PROCESS -- sans liste de sensibilité


BEGIN
WAIT UNTIL (clk'EVENT AND clk='1'); -- condition : front montant d’horloge
IF (rst='1') THEN
output <= "00000000";
ELSIF (clk'EVENT AND clk='1') THEN
output <= input;
END IF;
END PROCESS;

rst et input sont des signaux secondaires , clk est le signal primaire.

ii. Wait on signal1 [,signal2,…]

Dans ce cas , le process est suspendu jusqu’au prochain changement d’état de l’un des signaux
signal1,signal2,…. .

Exemple :
le process suivant est éxécuté à chaque changement portant sur clk ou rst

PROCESS
BEGIN
WAIT ON clk, rst;
IF (rst='1') THEN
output <= "00000000";
ELSIF (clk'EVENT AND clk='1') THEN
output <= input;
END IF;
END PROCESS;

Input est le signal secondaire , alors que rst et clk sont les signaux primaires.

iii. Wait for durée  ;

Cette forme est d’utilisation marginale et est réservée uniquement à la simulation fonctionnelle ( pas
de synthése ).
Exemple: WAIT FOR 5ns;

c. CASE :
La syntaxe de cette instruction est :
CASE identificateur IS
WHEN valeur => affectations;
WHEN valeur => affectations;
...
END CASE;

Exemple:
CASE control IS
WHEN "00" =>
x<=a;
y<=b;
WHEN "01" =>
x<=b;
y<=c;
WHEN OTHERS => x<="0000"; y<="ZZZZ";
END CASE;

L’instruction séquentielle CASE est très similaire à l’instruction concurrente WHEN. Ici
également , toutes les valeurs possibles de l’objet représenté par identificateur doivent
être testées ; aussi , le mot-clé OTHERS peut être d’une aide appréciable .
Cependant , l’équivalent de UNAFFECTED est NULL , à utiliser à chaque fois
qu’aucune action n’est requise. Par exemple :
WHEN OTHERS =>NULL;

D’autre part , pour chaque test , plusieurs affectations peuvent être


spécifiées , alors que WHEN n’en autorise qu’une seule.

Enfin , ici également , ‘‘WHEN valeur’’ peut prendre 3 formes :


WHEN valeur – valeur unique
WHEN valeur1 to valeur2 – intervalle de valeurs , pour types énumérés
--uniquement
WHEN valeur1 | valeur2 |... -- valeur1 ou valeur2 ou ...

d. LOOP :

Cette instruction est utilisée à chaque fois qu’un segment de code séquentiel doit
être répété. Il existe 2 variantes pour cette instruction :
FOR/LOOP et WHILE/LOOP 

i. FOR / LOOP:

La boucle est répétée un nombre fixe de fois :

[étiquette:] FOR identificateur IN intervalle LOOP


(instructions séquentielles)
END LOOP [étiquette];

Intervalle doit être statique .

Exemple:
la boucle suivante est répétée jusqu’à ce que i=5 ( donc 6 fois)

FOR i IN 0 TO 5 LOOP
x(i) <= enable AND w(i+2);
y(0, i) <= w(i);
END LOOP;

ii. WHILE / LOOP:

la boucle est répétée tant qu’une condition est vérifiée.

[étiquette:] WHILE condition LOOP


(instructions séquentielles)
END LOOP [étiquette];

Exemple :
dans cet exemple , la boucle est répétée tant que i < 10.

WHILE (i < 10) LOOP


(autres instructions séquentielles)
END LOOP;

A l’intérieur de la boucle , 2 mots-clés peuvent être utilisés :

EXIT: permet de quitter la boucle.


NEXT: permet de sauter des iterations.

Exemple :
la boucle est abandonnée dés qu’un bit different de ‘0’ est trouvé dans le vecteur
DATA :

FOR i IN data'RANGE LOOP


CASE data(i) IS
WHEN '0' => count:=count+1;
WHEN OTHERS => EXIT;
END CASE;
END LOOP;

Exemple :
dans cet exemple , avec NEXT , une iteration de la boucle est sautée quand i=skip.
FOR i IN 0 TO 15 LOOP
NEXT WHEN i=skip; -- sauter à la prochaine itération
(...)
END LOOP;
Exemple :

Soit à décrire un registre à décalage constitué de 128 registres 8 bits.


Le signal Dec valide le décalage . Celui-ci a lieu à l’arrivée d’un front montant
d’horloge.
Il est évident qu’il faut trouver une forme compacte pour décrire le décalage ,
vu le grand nombre de registres.
L’emploi d’une concaténation est impossible ; les signaux de liaison entre un
registre et le suivant étant vectoriels et non pas scalaires.
Une solution élégante consiste en l’emploi d’une instruction FOR :
reset ……
Din Dout
0 1 …… 1 1
2 2
6 7

Clk
……
Dec ……
library ieee; dout <= d(127);
use ieee.std_logic_1164.all; process (clk,reset)
entity sr is begin
port( din : in std_logic_vector(7 downto 0); if reset='1' then
dout : out std_logic_vector(7 downto 0); for i in 127 downto 0 loop
clk,reset,dec : in std_logic); ---- l’emploi de others est impossible ! car d est un
end sr; -----tableau et non un vecteur
architecture bhv of sr is d(i)<= "00000000";
type ma_table is array (0 to 127) of end loop;
std_logic_vector(7 downto 0); elsif rising_edge(clk) then
signal d : ma_table; if dec='1' then
begin d(0) <= din;
d(1 to 127)<= d(0 to 126);
end if;
end if;
end process;

end bhv;

Vous aimerez peut-être aussi