LE LANGAGE
VHDL
Le langage VHDL
Premier épisode
Les éléments du langage abordés au cours de cet épisode :
La vue externe du modèle est appelé entity. On peut la symboliser par un rectangle avec des " broches " d’entrées et sorties. Une entrée ou sortie est un port qui doit être défini par :
out pour une sortie
inout pour une entrée-sortie
buffer pour une sortie rebouclée en entrée.
Une architecture représente " un " contenu de ce rectangle. L’article indéfini " un " est là pour montrer qu’il y plusieurs façons de décrire le comportement du modèle. Chacune d’elles est une architecture de l’entity. Nous verrons par la suite les différents types de descriptions.
Elles jouent le même rôle que les librairies lib.h du langage C. Elles contiennent des déclarations de variables, des sous programmes, des composants génériques, etc... nécessaire à la compilation des modèles. On peut créer ses propres librairies.
Dans les exemples qui suivent on utilise la librairie IEEE.STD_LOGIC_1164 qui permet d’ajouter au type de base bit qui ne peut prendre que les valeurs 0 et 1, les valeurs x,z,u,l,h,-.
Il y a trois familles d’objets : les signaux, les constantes, les variables. Chaque objet et repéré par son nom. Ce nom doit respecter les conventions suivantes :
Les signaux représentent des équipotentielles ou, suivant l’écriture des bascules. Un signal est un noeud intermédiaire, ce n’est de ce fait ni une entrée, ni une sortie, ni une entrée-sortie. Aucun mode n’est donc a déclaré. Les signaux doivent être déclarés avant le mot clé begin.
L’affectation d’une valeur à un signal se fait par l’instruction <= et peut être faite à tout moment. Un signal peut être lié à un autre par cette instruction <=. Ainsi A <= B établit un lien permanent entre les signaux A et B, ce qui exige que ces derniers aient le même type.
Une variable se comporte comme un récipient que l’on peut remplir ou vider. L’affectation de la valeur d’une variable B à une variable A s’écrit : A := B.
La liaison entre deux variables est temporaire ce qui signifie que si la valeur de B change ensuite, celle de A est inchangée.
|
Type |
Types pré définis |
Exemple de types utilisateur |
SCALAIRE |
Enuméré |
bit boolean character severity_level |
COULEUR BIT4 |
|
entier |
integer |
INDEX |
|
flottant |
float |
COSINUS |
|
physique |
time |
CAPACITE |
COMPOSITE |
tableau (array) |
bit_vector string |
|
|
article (record) |
|
|
type bit is (‘0`, ‘1`) ;
type boolean is (false, true) ;
type character is (‘A`, ‘B`, ‘C`, ...,‘0`,‘1`,...,‘$`,...) ;
type severity_level is (note, warning, error, failure) ;
type integer is range -2 147 483 648 to 2 147 483 647 ;
type real is range -16#0.7FFFFF8#E+32 to 16#0.7FFFFF8#E+32 ;
type time is range -9_223_372_036_854_775_808 to 9_223_372_036_854_775_807 ;
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 ;
type bit_vector is array (natural range <>) of bit ;
type string is array (positive range <>) of character ;
La déclaration range
Les attributs
Un attribut est une caractéristique associée à un type ou un signal. Il est placé juste après ce type ou ce signal mais séparé de lui par une apostrophe.
Exemple :type INDEX is range 15 downto 0 ;
INDEX’high = 15 INDEX’low = 0
Nous allons détailler les six classes d’opérations de VHDL par ordre de priorité croissante.
Ce sont les opérations AND, OR, NAND, NOR, XOR. Ces cinq opérateurs ont même priorité. Les opérateurs doivent être de même type ; les opérandes doivent avoir la même longueur ; les opérations se font sur les éléments de même position.
L’opérateur NOT ne fait pas partie de cette classe.
Exemple : signal A_BUS, B_BUS, C_BUS : bit_vector (0 to 3) ;
C_BUS <= A_BUS or B_BUS ;
Ce sont les relations =, /=, <,<=,>,>=. Le résultat de la comparaison est un booléen.
Elles sont au nombre de trois : l’addition +, la soustraction - et la concaténation &. Ces opérations ne sont définies que pour les types integer, real et les types physiques. Certains compilateurs proposent des opérations agissant sur les types bit ou bit_vector.
Ce sont les signes + ou -.
Ce sont les opérations suivantes : la multiplication *, la division /, le modulo mod, le reste rem.
L’opération NOT prend le complément d’un objet de type bit, boolean, bit_vector.
L’opoération ABS prend la valeur absolue d’un objet de type integer ou real.
L’opération ** est l’élévation de l’opérande gauche à la puissance définie par l’opérande de droite.
Classe |
Opérateurs |
Types d’opérandes |
Résultat |
Opérations logiques |
AND OR NAND NOR XOR |
bit ou boolean |
bit ou boolean |
Opérations relationnelles |
= /= < <= > >= |
tous types |
boolean |
Opérations d’addition |
+ - & |
numériques tableaux |
numériques tableaux |
Signe |
+ - |
numériques |
numériques |
Opérations de multiplication |
* / mod rem |
numériques entiers |
numériques entiers |
Opérations de haute priorité |
NOT ABS ** |
bit ou boolean numériques numériques |
bit ou boolean numériques numériques |
Les instructions simultanées (concurrent) interviennent dans une architecture. Elles participent à la description du fonctionnement d’un circuit. En raison du parallélisme du langage, ces instructions peuvent être écrites dans un ordre quelconque.
Les principales instructions simultanées sont :
Les instructions simultanées sont internes aux process, aux procedures et aux functions. Elles permettent d’appliquer à la description d’un circuit une démarche algorithmique.
Les principales instructions séquentielles sont :
BEHAV1 description d’un multiplexeur 4 vers 1 utilisant les instructions with select.
BEHAV2 description d’un multiplexeur 4 vers 1 utilisant les instructions case is when.
BEHAV3 description d’un multiplexeur 4 vers 1 utilisant les instructions if then elsif else en fait on a réalisé un encodeur de priorité.
BEHAV4 description d’un multiplexeur 4 vers 1 utilisant correctement les instructions if then elsif else.
BEHAV2 totalité de la description du multiplexeur.
FLOT utilisation des signaux.
Pour le demi additionneur et l’additionneur écrire les programmes de description.
Le Multipexeur 4 :1
library IEEE ;
use IEEE.STD_LOGIC_1164.all ;
library SYNTH ;
use SYNTH.PACK1164.all ;
---------------------------------------------------------------------------------
entity MUX1 is
port (D0, D1, D2, D3 : in STD_LOGIC;
SEL :in STD_LOGIC_VECTOR(1 downto 0) ;
ZOUT :out STD_LOGIC);
end MUX1 ;
------------------------------------------------------------------------------------------
architecture BEHAV1 of MUX1 is
begin
with SEL select ZOUT <= D0 when "00",
D1 when "01",
D2 when "10",
D3 when "11",
‘-` when others ;
end BEHAV1 ;
------------------------------------------------------------------------------------------
architecture BEHAV2 of MUX1 is
begin
process (D0, D1, D2, D3 ,SEL) -- Remarquer la sensitivity list
begin
case SEL is
when "00" => ZOUT <= D0 ;
when "01" => ZOUT <= D1 ;
when "10" => ZOUT <= D2;
when "11" => ZOUT <= D3 ;
when others => ZOUT <= ‘-`;
end case ;
end process ;
end BEHAV2 ;
------------------------------------------------------------------------------------------
architecture BEHAV3 of MUX1 is
begin
process (D0, D1, D2, D3 ,SEL)
begin
if (SEL = "00") then ZOUT <= D0 ;
elsif (SEL = "01") then ZOUT <= D1 ;
elsif (SEL = "10") then ZOUT <= D2 ;
else ZOUT <= D3 ;
end if ;
end process ;
end BEHAV3 ;
------------------------------------------------------------------------------------------
architecture BEHAV4 of MUX1 is
begin
process (D0, D1, D2, D3 ,SEL)
begin
if (SEL (1)= ‘0`) then
if (SEL (0)= ‘0`) then ZOUT <= D0 ;
else ZOUT <= D1 ;
end if ;
else
if (SEL (0)= ‘0`) then ZOUT <= D2 ;
else ZOUT <= D3 ;
end if ;
end if ;
end proces ;
end BEHAV4 ;
------------------------------------------------------------------------------------------
librarie IEEE ;
use IEEE.STD_LOGIC_1164.all ;
library SYNTH ;
use SYNTH.PACK1164.all ;
entity MUX1 is
port (D0, D1, D2, D3 :in STD_LOGIC;
SEL : in STD_LOGIC_VECTOR(1 downto 0) ;
ZOUT : out STD_LOGIC);
end MUX1 ;
architecture BEHAV2 of MUX1 is
begin
process (D0, D1, D2, D3 ,SEL) -- Remarquer la sensitivity list
begin
case SEL is
when "00" => ZOUT <= D0 ;
when "01" => ZOUT <= D1 ;
when "10" => ZOUT <= D2;
when "11" => ZOUT <= D3 ;
when others => ZOUT <= ‘-`;
end case ;
end process ;
end BEHAV2 ;
------------------------------------------------------------------------------------------
architecture FLOT of MUX1 is
signal S0, S1, S2, S3 : STD_LOGIC ;
begin
S0 <= D0 and not(SEL0) and not (SEL1) ;
S1 <= D1 and SEL0 and not(SEL1);
S2 <= D2 and not(SEL0) and SEL 1;
S3 <= D3 and SEL0 and SEL1 ;
ZOUT <= S0 or S1 or S2 or S3 ;
end FLOT ;
------------------------------------------------------------------------------------------
L’additionneur
R : repport
S : somme
B |
A |
S |
R |
||||
0 |
0 |
0 |
0 |
||||
0 |
1 |
1 |
0 |
||||
1 |
0 |
1 |
0 |
||||
1 |
1 |
0 |
1 |
||||
Ri |
B |
A |
S |
R |
|||
0 |
0 |
0 |
0 |
0 |
|||
0 |
0 |
1 |
1 |
0 |
|||
0 |
1 |
0 |
1 |
0 |
|||
0 |
1 |
1 |
0 |
1 |
|||
1 |
0 |
0 |
1 |
0 |
|||
1 |
0 |
1 |
0 |
1 |
|||
1 |
1 |
0 |
0 |
1 |
|||
1 |
1 |
1 |
1 |
1 |
Ri : repport initial
Deuxième épisode
Les éléments du langage abordés au cours de cet épisode :
L’architecture décrit le fonctionnement interne d’un circuit auquel est attaché une entity. Ce fonctionnement peut être décrit de différentes façons :
Description par flot de données : le fonctionnement du circuit est décrit par un flot de données qui vont des entrées vers les sorties, en subissant, étape après étape, des transformations élémentaires successives. Ce mode de description permet de reproduire l’architecture logique, en couche successives, des opérateurs combinatoires.
Description comportementale : le comportement matériel d’un circuit est décrit par un algorithme, indépendamment de la façon dont il est réalisé au niveau structurel.
Description structurelle : le circuit est vu comme l’assemblage de composants de niveau inférieur, c’est une description " schématique ". Ce mode de description est adapté à la représentation du niveau le plus élevé d’une hiérarchie, chaque composant étant lui même défini par un programme VHDL.
Nous reprendrons l’exemple FLOT.
La description de type flot de données (data stream) est aussi appelée description temporelle parce qu’on peut lui associe un temps. En effet nous aurions pu écrire
S0 <= D0 and not(SEL0) and not(SEL1) after 10 ns ;
afin de tenir compte des temps de propagation des couches de logique. S’il y a plusieurs instructions d’affectation, elles sont exécutées en parallèle de façon asynchrone.
Nous reprendrons les exemples BEHAV1, BEHAV2, BEHAV3 et BEHAV4.
L’architecture est décrite sous forme d’un ensemble d’instructions concurrentes, elle-même constitué de process décrits par des instructions séquentielles constituant un programme informatique. Nous reviendrons sur les instructions séquentielles.
Nous prendrons comme exemple D_ADDI et ADDI.
Nous pouvons assimiler ce mode de description au schéma fonctionnels de degré 1 et 2 que nous utilisons en analyse fonctionnelle.
Notons la présence de deux blocs identiques D_ADDI. En langage VHDL, nous dirons que chaque bloc est une instance de l’entity. L’assemblage des blocs va décrire les inter connexions entre ces blocs.
Les instructions décrites ci-dessous ne peuvent se trouver que dans un process, une procedure ou une function.
Dans la forme elsif, si la condition booléenne associée au dernier elsif englobe tous les autres cas non encore envisagés, la dernière instruction elsif peut être remplacée par un else sans condition.
Dans la forme elsif sans aucun else, le cas où toutes les conditions booléennes sont fausses est envisageable, et aucune séquence d’instructions ne sera alors exécutée.
Dans la forme elsif, la première condition booléenne trouvée vraie donne lieu à l’exécution de la séquence d’instruction associées et met fin à l’exécution du if, même si une autre condition booléenne est vraie.
En conclusion, la forme elsif donne lieu à l’exécution de zéro ou une séquence d’instructions.
Si la forme if se limite à if ... then ... else il y aura toujours une instruction d’exécutée.
Si la forme if se limite à if ... then il y a mémorisation lorsque la condition booléenne est fausse.
L’instruction case exige l’exclusivité des choix, c’est à dire que l’expression ne peut avoir, à un instant donné qu’une seule des valeurs énumérées.
L’instruction case exige l’exhaustivité des choix, c’est à dire que la valeur de l’expression doit obligatoirement être l’une de celles qui sont énumérées. Le mot clé others permet de limiter la liste des choix à ceux qui sont utiles à la description.
l’indice de boucle n’a pas à être déclaré, mais elle ne peut pas être utilisée à l’extérieur de la boucle. Il n’est pas possible de spécifier un pas d’incrémentation. Si l’intervalle de variation de l’indice est nul ou négatif, la séquence est ignorée. Un label peut être affecté à la boucle.
La structure de boucle while est une variante de la boucle for.
Permet de passer à l’itération suivante dans une boucle.
Permet de provoquer une sortie de boucle.
L’additionneur
entity ADDI is
port(A,B,Ri : in STD_LOGIC ;
S,R : out STD_LOGIC );
end ADDI ;
architecture STRUCT_ADDI of ADDI is
component DEMI8ADDI
port(A,B : in STD_LOGIC ; S,R :out STD_LOGIC );
end component;
component PORTE_OU
port (E1, E2 : in STD_LOGIC ; Z :out STD_LOGIC) ;
end component;
signal S1, S2, S3 : STD_LOGIC ;
begin
INSTANCE1 : DEMI_ADDI port map (A,B, S1, S2) ;
INSTANCE2 : DEMI_ADDI port map (S1,Ri, S, S3) ;
INSTANCE : PORTE_OU port map (S3, S2,R) ;
end STRUCT_ADDI ;
------------------------------------------------------------------------------------------
Verrous et registres
Verrou 1
process (LATCH_EN, DATA_IN)
begin
if (LATCH_EN = ‘1`) then QOUT <= DATA_IN ;
endif ;
end process ;
------------------------------------------------------------------------------------------
Faux verrou
Process (LATCH_EN, DATA_IN)
begin
if (LATCH_EN = ‘1`) then QOUT <= DATA_IN ;
else QOUT <= ‘0`) ;
endif ;
end process ;
------------------------------------------------------------------------------------------
Bascule D1
Process
begin
wait until (CLOCK’EVENT and CLOCK = ‘1`) ;
QOUT <= DATA_IN ;
end process ;
------------------------------------------------------------------------------------------
Bascule D2
Process(CLOCK, DATA_IN)
begin
if (CLOCK’EVENT and CLOCK = ‘1`) then QOUT <= DATA_IN ;
endif ;
end process ;
Bascule D3
Process(CLOCK,)
begin
if (CLOCK’EVENT and CLOCK = ‘1`) then QOUT <= DATA_IN ;
endif ;
end process ;
------------------------------------------------------------------------------------------
Bascule D4
Process(RESET,CLOCK, DATA_IN)
begin
if (RESET = ‘1`) then QOUT <= ‘0`) ; -- reset asynchrone
elsif (CLOCK’EVENT and CLOCK = ‘1`) then QOUT <= DATA_IN ; -- synchrone
endif ;
end process ;
------------------------------------------------------------------------------------------
Bascule D5
Irréalisable car il est " difficile " de synthétiser une bascule dont le reset se ferait sur des " non fronts montants de CLOCK " !
Process(RESET,CLOCK, DATA_IN)
begin
if (CLOCK’EVENT and CLOCK = ‘1`) then QOUT <= DATA_IN ; -- synchrone
elsif (RESET = ‘1`) then QOUT <= ‘0`) ; -- reset asynchrone
endif ;
end process ;
------------------------------------------------------------------------------------------
Bascule D6
DATA_IN n’est pas utile dans la Sensitivity List
Process(RESET,CLOCK)
begin
if (RESET = ‘1`) then QOUT <= ‘0`) ; -- reset asynchrone
elsif (CLOCK’EVENT and CLOCK = ‘1`) then QOUT <= DATA_IN ; -- synchrone
endif ;
end process ;
------------------------------------------------------------------------------------------
Décodeur 3 vers 8
entity DECOD is
port(E : in STD_LOGIC_VECTOR (2 downto 0) ;
S : in STD_LOGIC_VECTOR (7 downto 0)) ;
end DECOD ;
architecture COMPORT1 of DECOD is
begin
process
begin
case E is
when "000" => S <= "00000001" ;
when "001" => S <= "00000010" ;
when "010" => S <= "00000100" ;
when "011" => S <= "00001000" ;
when "100" => S <= "00010000" ;
when "101" => S <= "00100000" ;
when "110" => S <= "01000000" ;
when "111" => S <= "10000000" ;
when others => S <= "00000000" ;
end case ;
wait on E ;
end process ;
end COMPORT1 ;
entity DECOD is
port(E : in STD_LOGIC_VECTOR (2 downto 0) ;
S : in STD_LOGIC_VECTOR (7 downto 0)) ;
end DECOD ;
architecture COMPORT2 of DECOD is
begin
process
variable N : integer ;
begin
N := 0 ;
if E(0) = ‘1` then N := N + 1 ; end if ;
if E(1) = ‘1` then N := N + 2 ; end if ;
if E(2) = ‘1` then N := N + 4 ; end if ;
S <= "0000 0000" ;
for I in 0 to 7 loop
if (I = N) then S(I) <= ‘1` ;
end loop ;
end process ;
end COMPORT2 ;
Troisième épisode
Les éléments du langage abordés au cours de cet épisode :
Un package est une collection de déclarations et de sous programmes utilisés fréquemment et partageables par plusieurs concepteurs. Cette collection est regroupée dans un module qui peut être compilé seul. Les informations de ce package sont rendues visibles par la clause use. Dans sa forme la plus complète un package est constitué de deux parties :
Il existe deux package pré définis qu’il n’est pas nécessaire de déclarer :
Il existe deux types de sous programmes :
L’appel d’un sous programme entraîne le passage de ses paramètres, c’est à dire que les paramètres formels sont remplacés par les paramètres réels.
Remarques :
package PACK is
function MAX(A,B : integer) return integer ;
procedure MIN_MAX(A,B,C : integer ; signal MIN,MAX : out integer) ;
end PACK ;
package body PACK is
function MAX(A,B : integer) return integer is ;
begin
if A > B then return A ;
else return B ;
end if ;
end MAX ;
procedure MIN_MAX(A,B,C : integer ; signal MIN,MAX : out integer) is;
variables AUX1,AUX2 : integer ;
begin
if A > B then
AUX1 := A ;
AUX2 := B ;
else
AUX1 := B;
AUX2 := A;
end if ;
if C > AUX1 then AUX1 := C ;
elsif C < AUX2 then AUX2 := C ;
end if ;
MIN <= AUX2 ;
MAX <= AUX1 ;
end MIN_MAX ;
end PACK ;
Exemples
1. les feux de carrefour
Les feux de la route principale sont normalement au vert et ceux de la route secondaire au rouge.
Lorsque des véhicules se présentent sur un des détecteurs de la route secondaire. Les feux entrent dans un cycle jaune vert rouge.
2. Décodeur Manchester différentiel
En codage Manchester différentiel, chaque intervalle de temps élémentaire, pendant lequel un signal binaire est transmis, est divisé en deux parties de durées égales avec les conventions suivantes :
On veut réaliser un décodeur qui fournit un sortie BIN correspondant au code émis, à partir des signaux MAN et HOR.
package
PACKAGE_FEU is-- Declarations de Type et Subtype
type COULEUR is (VERT, JAUNE, ROUGE, INCONNU);
type ETAT is ( FEU_PRIORIT_VERT,
FEU_PRIORIT_JAUNE,
FEU_SECOND_VERT,
FEU_SECOND_JAUNE);
end PACKAGE_FEU;
use WORK.PACKAGE_FEU.all;
entity CONTROLE_FEUX is
generic (
TEMPO_LONGUE: INTEGER := 6; -- Durée minimum du feu VERT
TEMPO_COURTE: INTEGER := 3); -- Durée minimum du feu JAUNE
port ( HORL_PRINCIP, RAZ_PRINCIP: in BIT;
VOIT_RTE_SECOND : in BIT;
FEU_PRIORITAIRE : out COULEUR;
FEU_SECONDAIRE : out COULEUR);
end CONTROLE_FEU;
architecture SPECIFICATION of CONTROLE_FEUXis
signal ETAT_PRESENT : ETAT:= FEU_PRIORIT_VERT; -- Signal pour le maintient de l’état présent du système
signal SORTIE_DUREE_LONGUE: BOOLEAN := FALSE; -- Signaux pour implémenter la machine à états.
signal SORTIE_DUREE_COURTE : BOOLEAN := FALSE;
signal DEBUT_TIMER, AUTRE_HORLOGE: BOOLEAN;
signal HORLOGE_PRINCIPALE, RAZ_PRINCIPAL: BOOLEAN;
signal VOITURE_ROUTE_SECONDAIRE : BOOLEAN;
procedure FRONT(signal HORLOGE, RAZ: BOOLEAN) is
begin
wait until (HORLOGE and HORLOGE'EVENT) or RAZ;
end FRONT;
procedure SET (signal CIBLE: out BOOLEAN) is
begin
CIBLE <= TRUE;
end SET;
procedure RESET (signal CIBLE: out BOOLEAN) is
begin
CIBLE <= FALSE;
end RESET;
begin -- Début de l’architecture SPECIFICATION
AUTRE_HORLOGE <= not HORLOGE_PRINCIPALE; -- Inverse l’horloge pour les autres process
-- Début machine à états
CONTROLEUR_DE_PROCESSUS: process
-- Change ETAT en NOUVEL_ETAT si CONDITION est vraie
procedure TRANSITION (constant CONDITION: BOOLEAN; NOUVEL_ETAT: STATE) is
begin
if CONDITION then
DEBUT_TIMER <= TRUE; --Relance le timer
ETAT_PRESENT <= NOUVEL_ETAT;
end if;
end TRANSITION;
-- début du process
begin
wait until RAZ_PRINCIPAL;
BCLRAZ: loop
if (RAZ_PRINCIPAL= (TRUE) then
ETAT_PRESENT <= FEU_PRIORIT_VERT;
SET(DEBUT_TIMER);
end if;
-- Attente de l’horloge.
FRONT(HORLOGE => HORLOGE_PRINCIPALE, RAZ => RAZ_PRINCIPAL);
--Ne pas remettre à zéro le timer tant qu’aucune condition de redémarage n’est vraie
RESET(DEBUT_TIMER);
-- Le changement d’état à lieu lorsque la durée de l’état précédent est écoulée .
case ETAT_PRESENT is
when FEU_PRIORIT_VERT => TRANSITION (VOITURE_ROUTE_SECONDAIRE and SORTIE_DUREE_LONGUE, FEU_PRIORIT_JAUNE);
when FEU_PRIORIT_JAUNE => TRANSITION (NOUVEL_ETAT => FEU_SECOND_VERT, CONDITION => SORTIE_DUREE_COURTE);
when FEU_SECOND_VERT => TRANSITION (not VOITURE_ROUTE_SECONDAIRE or SORTIE_DUREE_LONGUE, NOUVEL_ETAT => FEU_SECOND_JAUNE);
when FEU_SECOND_JAUNE => TRANSITION(SORTIE_DUREE_COURTE, FEU_PRIORIT_VERT);
end case;
next when RAZ_PRINCIPAL;
end loop;
end process;
-- Assignation des signaux du feu de la route prioritaire
FEU_PRIORIT_SET: with ETAT_PRESENT select
FEU_PRIORITAIRE <= VERT when FEU_PRIORIT_VERT,
JAUNE when FEU_PRIORIT_JAUNE,
ROUGE when FEU_SECOND_VERT | FEU_SECOND_JAUNE;
-- Assignation des signaux du feu de la route secondaire
FEU_SECOND_SET: with ETAT_PRESENT select
FEU_SECONDAIRE <= VERT when FEU_SECOND_VERT,
JAUNE when FEU_SECOND_JAUNE,
ROUGE when FEU_PRIORIT_VERT | FEU_PRIORIT_JAUNE;
-- Process implémentant les timers
TIMER_PROCESS: process
variable TIMER_COURT: INTEGER range 0 to 3;
variable TIMER_LONG: INTEGER range 0 to 7;
begin
wait until DEBUT_TIMER;
-- Tant que DEBUT_TIMER n’est pas mis à zéro, les siganux SORTIE_DUREE_COURTE et SORTIE_DUREE_LONGUE
-- contrôles les feux.
BCL_TIMER: loop
if DEBUT_TIMER then
RESET(SORTIE_DUREE_COURTE); -- Initialisation des sorties timer à FALSE.
RESET(SORTIE_DUREE_LONGUE);
assert TEMPO_LONGUE> TEMPO_COURTE;
TIMER_COURT := TEMPO_COURTE;
TIMER_LONG := TEMPO_LONGUE- TEMPO_COURTE;
end if;
-- Attente de l’horloge et test du reset
FRONT(AUTRE_HORLOGE, DEBUT_TIMER);
next TIMER_LOOP when DEBUT_TIMER;
-- Décomptage de TIMER_COURT
while TIMER_COURT /= 0 loop
TIMER_COURT := TIMER_COURT - 1;
FRONT(AUTRE_HORLOGE, DEBUT_TIMER);
next TIMER_LOOP when DEBUT_TIMER;
end loop;
-- Indique que TIMER_COURT=0
SET(SORTIE_DUREE_COURTE);
-- Attente de l’horloge et test du reset
FRONT(AUTRE_HORLOGE, DEBUT_TIMER);
next TIMER_LOOP when DEBUT_TIMER;
-- Décomptage de TIMER_COURT_LONGUE
while TIMER_LONG /= 0 loop
TIMER_LONG := TIMER_LONG - 1;
FRONT(AUTRE_HORLOGE, DEBUT_TIMER);
next TIMER_LOOP when DEBUT_TIMER;
end loop;
-- Indique que TIMER_LONGUE=0
SET(SORTIE_DUREE_LONGUE);
end loop TIMER_LOOP;
end process;
HORLOGE_PRINCIPALE <= FALSE when HORL_PRINCIP = '0' else TRUE;
RAZ_PRINCIPAL <= FALSE when RAZ_PRINCIP = '0' else TRUE;
VOITURE_ROUTE_SECONDAIRE <= FALSE when VOIT_RTE_SECOND = '0' else TRUE;
end SPECIFICATION;
entity MANDEC is
port ( HOR, MAN : in BIT ;
MEALY, MEALYSYNC : out BIT ;
MOORE : out BIT) ;
end MANDEC ;
architecture COMPORTE of MANDEC is
signal MOORE_ETAT : BIT_VECTOR (2 downto 0) ;
signal MEALY_ETAT : BIT_VECTOR (1 downto 0) ;
begin
MEALY <= MEALY_ETAT (1) or not(MEALY_ETAT (0) xor MAN) ;
MOORE <= MOORE_ETAT (2) ;
MACHINE_MEALY : process
begin
wait until HOR = ‘1’ ;
MEALYSYNC <= MEALY_ETAT (1) or not(MEALY_ETAT (0) xor MAN) ;
case MEALY_ETAT is
when "00" => if MAN = ‘0’ then MEALY_ETAT <= "10" ;
else MEALY_ETAT <= "01" ;
end if ;
when "01" => if MAN = ‘0’ then MEALY_ETAT <= "00" ;
else MEALY_ETAT <= "11" ;
end if ;
when "10" => if MAN = ‘1’ then MEALY_ETAT <= "01" ;
end if ;
when "11" => if MAN = ‘0’ then MEALY_ETAT <= "00" ;
end if ;
end case ;
end process MACHINE_MEALY ;
MACHINE_MOORE :process
begin
wait until HOR = ‘1’ ;
case MOORE_ETAT is
when O"0" => if MAN = ‘0’ then MOORE_ETAT <= O"6" ; -- états en octal
else MOORE_ETAT <= O"1" ;
end if ;
when O"1" => if MAN = ‘0’ then MOORE_ETAT <= O"0" ;
else MOORE_ETAT <= O"7" ;
end if ;
when O"6" => if MAN = ‘1’ then MOORE_ETAT <= O"5" ;
end if ;
when O"7" => if MAN = ‘0’ then MOORE_ETAT <= O"4" ;
end if ;
when O"4" => if MAN = ‘0’ then MOORE_ETAT <= O"6" ;
else MOORE_ETAT <= O"1" ;
end if ;
when O"5" => if MAN = ‘0’ then MOORE_ETAT <= O"0" ;
else MOORE_ETAT <= O"7" ;
end if ;
when O"2" => if MAN = ‘0’ then MOORE_ETAT <= O"6" ;
else MOORE_ETAT <= O"5" ;
end if ;
when O"3" => if MAN = ‘0’ then MOORE_ETAT <= O"4" ;
else MOORE_ETAT <= O"7" ;
end if ;
end case ;
end process MACHINE_MOORE;
end COMPORTE ;
SOMMAIRE
Premier épisode page 1
Entity Architecture page 1
Les librairies pré définies page 1
Les signaux, constantes, variables page 1
Les opérations de base sur les objets page 3
Les instuctions simultanées et séquentielles page 4
Exemples page 4
Deuxième épisode page 8
Les trois formes d’écriture page 8
Les instructions séquentielles page 9
Exemples page 10
Troisième épisode page 14
Les packages page 14
Les sous programmes page 14
Exemple page 15
Exemples page 16
Les feux de carrefour page 16
Décodeur Manchester différentiel page 17