Beruflich Dokumente
Kultur Dokumente
On note 4 états possibles en sortie, s’enchaînant inconditionnellement dans l’ordre E1, E2, E3, E4,
E1…au rythme de l’horloge H.
A partir de ce cahier des charges, on peut en déduire le diagramme (ou diagramme à bulles) suivant ;
Ce diagramme représente les différents états du système, en précisant éventuellement les niveaux
logiques correspondants en sortie, et les conditions de passage d’un état à l’autre. Dans notre cas très
simple, à chaque coup d’horloge, on passe inconditionnellement à l’état suivant.
La machine doit toujours se trouver au moins dans un état, et dans un seul état.
Avant l’apparition des langages HDL (Hardware circuits Description Language) de programmation,
la synthèse d’une machine d’état impliquait la recherche des équations des entrées des bascules de
mémorisation des états. Aujourd’hui, il est possible de retranscrire directement le diagramme d’état
en programme ; voici par exemple, un fichier VHLD associé à ce diagramme :
library ieee;
use ieee.std_logic_1164.all;
entity cde_mot_2 is
port( H : in std_logic;
Remarques :
lorsque plusieurs entrées interviennent dans un diagramme d’état, on suppose qu’une seule
est susceptible de changer à un instant donné ;
lorsque les conditions ne sont pas réalisées, l’état ne change pas (dans notre exemple, les
conditions étant complémentaires, elles sont toujours réalisées) ;
lorsque plusieurs branchements sont possibles à partir d’un état, les conditions ne doivent pas
être vraies en même temps ;
la présence de l’horloge est implicite, le passage d’un état à l’autre ne peut se faire qu’au
front actif de l’horloge.
Une description VHDL possible est alors donnée ci-après :
entity cde_mot_2Sens is
port( H,S : in std_logic;
SORTIES : out std_logic_vector (3 downto 0));
end cde_mot_2Sens;
architecture ARC_CDE OF cde_mot_2Sens is
type TYPE_ETAT is (E1, E2, E3, E4);
signal X : TYPE_ETAT;
begin
process (H)
begin
if H'event and H = '1' then
case X is
when E1 =>
if S='1' then X <= E2; else X <=E4;end if;
when E2 =>
if S='1' then X <= E3; else X <=E1; end if;
when E3 =>
if S='1' then X <= E4; else X <=E2; end if;
when others =>
if S='1' then X <= E1; else X <=E3; end if;
end case;
end if;
end process;
with X select
SORTIES <= "1001" when E1,
"1010" when E2,
"0110" when E3,
"0101" when E4;
end ARC_CDE;
Exemple 3 : diviseur de fréquence.
Le nombre d’états d’un système n’est pas lié au nombre d’états possibles des sorties. Considérons
par exemple un diviseur de fréquence fournissant une impulsion en sortie toutes les quatre
impulsions du signal d’horloge.
Pour synthétiser un tel diviseur, il ne suffit évidemment pas de prendre en compte les deux états
possibles de la sortie, mais tous les états intermédiaires du système.
On notera la déclaration de deux registre d’état, le premier « fstate » mémorisant l’état présent, le
second « reg_fstate » mémorisant l’état futur en fonction d’éventuelles entrées. L’état futur devient
l’état présent à chaque coup d’horloge dans le premier « process ».
Exemple d’utilisation
Reprenons la commande d’un moteur pas à pas, de quatre phases unipolaire décrit en annexe. Nous
allons synthétiser une machine d’état proposant ces deux modes de fonctionnement pour les deux
sens de rotation, en fonction de deux entrées :
S pour le sens ;
P pour un fonctionnement pas entier une phase ou demi-pas.
Si P est au NL1 on passe par tous les états 1, 2, 3, 4, 5, 6, 7, 8, 1… dans cet ordre ou l’inverse suivant
la valeur de S.
Si P est au NL0, seuls les états pairs seront actifs, dans l’ordre 2, 4, 6, 8, 2… ou l’inverse suivant la
valeur de S.
1001 1000 1010
0001 0010
0101(Début) 0100
0110
On pourrait imaginer aussi une entrée proposant un mode demi-pas deux phases, où seuls les états
impairs seraient actifs.
Après avoir ouvert un projet par les méthodes habituelles, ouvrir une feuille de description de
machine d’état par « file » « new » puis « States Machine File » :
Il est alors possible de décrire notre machine, soit directement sur la feuille à partir des outils
proposés, soit à l’aide de l’assistant « State Machine Wizard » de la barre d’outils, comme nous
allons le faire :
L’assistant propose, soit de créer une nouvelle machine (notre option pour l’instant), soit d’en
modifier une existante ; il sera en effet toujours possible de modifier notre description, soit à l’aide
de l’assistant, soit par les outils classiques.
Préciser ensuite que l’on souhaite une machine synchrone, avec une réinitialisation active à l’état bas
(l’appui sur les boutons poussoirs de la carte DE2 provoque un NL0) et des sorties mémorisées dans
un registre.
Dans la fenêtre suivant, commencer par déclarer tous les états possibles de E1 à E8 (pour déclarer un
nouvel état, faire un double clic dans la case correspondante) :
Déclarer ensuite les ports d’entrée (par défaut « clock » et « reset » existent déjà), puis les transitions
permettant de passer d’un état à l’autre.
Règles de syntaxes :
- un bus de N bits en entrée ou en sortie peut être déclaré par « Bus[N-1 :0] » ;
- dans les transitions les opérations logiques s’écrivent :
o ~ pour le NON (Alt Gr 2) ;
o & pour le ET ;
o | pour le OU (Alt Gr 6) ;
o ^ pour le OU EXCLUSIF ;
- la valeur d’un bus est par défaut en décimal, mais peut s’écrire en binaire par « ‘b00111001 »
par exemple ou en hexadécimal par « ‘h3A » par exemple ;
- les conditions de transition peuvent être des comparaisons :
o == pour égal ;
o != pour différent ;
o > pour supérieur ;
o < pour inférieur ;
o >= pour supérieur ou égal ;
o <= pour inférieur ou égal.
Entrer ensuite les différentes transitions pour passer d’un état à l’autre (il est conseillé, vu la syntaxe
un peu lourde, d’utiliser le « copier coller ») :
L’étape suivante consiste à déclarer les sorties et préciser leurs valeurs pour chaque état :
Nous déclarerons une sortie destinée à commander les phases du moteur « PH[3 :0] » et une
permettant éventuellement de visualiser sur la carte DE2 l’état actif (sous réserve de l’afficher via un
décodeur sur un des afficheurs 7 segments par exemples, et sous réserve que l’horloge soit
suffisamment lente pour permettre une lecture).
La dernière page récapitule les états, les entrées et les sorties.
Le diagramme d’état résultant s’affiche alors (il est parfois nécessaire d’arranger un peu
l’agencement des états et transitions pour avoir un schéma lisible) :
On peut noter une flèche pointant vers l’état E1, indiquant que la remise à 0 de la machine rendra cet
état actif par défaut, car c’est le premier que nous avons déclaré. Si cette situation ne convient pas, il
est possible de modifier par l’onglet « States » de la zone « State Table » (la faire éventuellement
apparaître avec l’outil approprié de la barre d’outils).
Une fois le résultat satisfaisant, il est ensuite nécessaire de générer le fichier HDL pour programmer
le circuit, en précisant que l’on souhaite une description VHDL (Menu « Tools » puis la commande
« Generate HDL File…. ):
Le fichier VHDL s’ouvre alors ; il est parfois nécessaire de le vérifier. Dans notre cas par exemple,
l’action du « reset » a pour effet de mettre la machine dans l’état E1 comme convenu, mais
également de mettre tous les bits des bus PH[3 :0] et ETAT[3 :0] au NL0.
Il est possible de modifier le programme à volonté, pour changer la valeur des sorties lors de
l’initialisation par exemple :
BEGIN
IF (reset='0') THEN reg_fstate <= E1; reg_PH <= "0101"; reg_ETAT <= "0001";
ELSE reg_PH <= "0101"; reg_ETAT <= "0001"; CASE fstate IS
WHEN E1 =>
Il sera maintenant nécessaire d’effectuer les opérations habituelles sur ce type de projet (vérification,
simulation, génération de symbole, compilation etc…) pour finaliser le projet.
Remarque importante :
La machine d’état est incrémentée par une horloge « clock » qui doit être de fréquence faible
(quelques kHz maximum) pour commander un moteur pas à pas.
Si on utilise la carte DE2 avec ses horloges à 27 et 50 MHz, il sera nécessaire d’implanter un
diviseur
de fréquence.
Il est impératif, pour que le système reste synchrone et ne génère pas systématiquement des états
aléatoires, d’ajouter une entrée de validation d’horloge « C_EN » par exemple. Le diviseur fera
passer C_EN au NL1 tous les N coups de l’horloge principale (si on souhaite un pas par secondes
avec l’horloge à 50 MHz, alors N vaudra 50 millions).
Il suffit alors d’ajouter « & C_EN » à toutes les conditions de transition de notre machine d’état pour
obtenir un fonctionnement correct.
Autrement…
On désire réaliser la logique d’une commande de moteur pas à pas avec la possibilité d’effectuer la
rotation en pas entier ou en demi-pas. Le moteur tournera uniquement dans le sens horaire.
Phases de commande des 4 bobines du moteur, le problème est similaire avec un moteur bipolaire.
Pas entier :
Demi-pas
Les chronogrammes ci-dessus font apparaitre les quatre phases du mode pas entier et les huit phases
du mode demi-pas.
ex :
DP : la transistion est valide pour DP = 1
~DP : la transistion est valide pour DP = 0
OPERATEURS
= = : Est égale Pour créer un bus (ex :BDT) en entrée ou en
! = : Est diffèrent sortie :
<= : Est inférieur ou égal BDT[7:0] (donc ici 8bits).
< : Est strictement inférieur
>= : Est supérieur ou égal
> : Est strictement supérieur
& : Et logique
| : Ou logique
^ : Ou exclusif
~& : NAND
~| : NOR
~^ : NON Ou exclusif Il est alors possible de créer des conditions de
~ : NON transition sur ce bus.
Ex : BDT==128 ou BDT>= ‘b010011100
ENTITY motpp_mae IS
PORT (
reset : IN STD_LOGIC := '0';
clock : IN STD_LOGIC;
DP : IN STD_LOGIC := '0';
BA1 : OUT STD_LOGIC;
BA2 : OUT STD_LOGIC;
BB1 : OUT STD_LOGIC;
BB2 : OUT STD_LOGIC
);
END motpp_mae;
WHEN P2 => reg_fstate <= P3; BA1 <= '1'; BB1 <= '0'; BB2 <= '1'; BA2 <= '0';
WHEN P3 => IF ((DP = '1')) THEN reg_fstate <= P4;
ELSIF (NOT((DP = '1'))) THEN reg_fstate <= P5;
-- Inserting 'else' block to prevent latch inference
ELSE reg_fstate <= P3;
END IF;
BA1 <= '1'; BB1 <= '0'; BB2 <= '0'; BA2 <= '0';
WHEN P4 => reg_fstate <= P5; BA1 <= '1'; BB1 <= '0'; BB2 <= '0'; BA2 <= '1';
WHEN P5 => IF ((DP = '1')) THEN reg_fstate <= P6;
ELSIF (NOT((DP = '1'))) THEN reg_fstate <= P7;
-- Inserting 'else' block to prevent latch inference
ELSE reg_fstate <= P5;
END IF;
BA1 <= '0'; BB1 <= '0'; BB2 <= '0'; BA2 <= '1';
WHEN P6 => reg_fstate <= P7; BA1 <= '0'; BB1 <= '1'; BB2 <= '0'; BA2 <= '1';
WHEN P7 => IF ((DP = '1')) THEN reg_fstate <= P8;
ELSIF (NOT((DP = '1'))) THEN reg_fstate <= P1;
-- Inserting 'else' block to prevent latch inference
ELSE reg_fstate <= P7;
END IF;
BA1 <= '0'; BB1 <= '1'; BB2 <= '0'; BA2 <= '0';
WHEN P8 => reg_fstate <= P1; BA1 <= '0'; BB1 <= '1'; BB2 <= '1'; BA2 <= '0';
WHEN OTHERS => BA1 <= 'X'; BA2 <= 'X'; BB1 <= 'X'; BB2 <= 'X';
report "Reach undefined state";
END CASE;
END IF;
END PROCESS;
END BEHAVIOR;
Un double clic sur la machine à état (fstate) permet de retrouver la description initiale.
Tools – Netlist Viewvers –Technologie Map Viewer affiche le schéma de la structure synthétisée.