Suggestion d`autres exercices (non exhaustif …)

publicité
ESSI1 – Spécification des circuits logiques avec AHDL (Jean-Paul Stromboni, 1999) Page - 1 -
Spécification des circuits logiques avec AHDL
Seconde partie : exercices et utilisation
V
oici un ensemble d’exercices à traiter avec AHDL. Il semble difficile de les traiter tous en
une séance unique, il est demandé d’en résoudre un ou plus … selon le temps disponible.
On peut également en proposer d’autres (la faisabilité et l’intérêt sont à discuter). Il faut
donc choisir un exercice, poser le problème, préparer une solution originale, puis la spécifier
en AHDL et valider par simulation avec l’environnement MaxPlusII d’Altera.
L’objectif est de réaliser un microprojet, chercher les informations sur AHDL nécessaires pour
résoudre le problème choisi et y apporter une solution personnelle, découvrir fonctionnalités
et limites de l’outil proposé ...
Exercices suggérés:
1. Construire un additionneur sur 16 bits (cf. subdesign addit donné en annexe):
A(16 bits)+B(16 bits)+CY(retenue) R(16bits)+ CY1(retenue suivante)
Puis, on le modifiera pour en faire un additionneur soustracteur 16 bits commandé par un
bit nommé sgnop (sgnop= 0  addition, sgnop=1  soustraction) avec le code en complément à 2. On peut utiliser la propriété : a XOR 1 = NON a et a xor 0 = a, pour
complémenter à 1 et incrémenter avec l’entrée CY pour passer uu complément à 2.
Autre amélioration, le résultat est donné dans le format valeur absolue plus signe (signe
= 1 pour négatif, 0 pour positif). Comment créer un bit de débordement OVF ?
A
A
C
B
B
B
1
Cy Cy1
C
|C|
signe
Cy Cy1
sgnop=1
sgnop=0
2. Construire le séquenceur pasapas.tdf de la commande biphase des 4 enroulements ou
phases d’un moteur pas à pas. On peut s’inspirer de stepper.tdf tiré des exemples ahdl.
On souhaite alimenter les quatre phases selon la séquence suivante : alimenter phase3
seule, puis phase3 et phase2 simultanément, ensuite phase2, puis phase2 et phase1,
etc ... pour faire tourner le moteur dans un sens en utilisant tour à tour les huit positions
d’équilibre du rotor à chaque front montant de l’horloge clk:
phases[3..0]= 1000,1100,0100,0110,0010,0011,0001,1001,1000 …
On ajoute deux entrées binaires direct et inverse fixant chacune un sens de rotation
du moteur ainsi qu’un signal reset qui ramène le rotor à la position initiale (valeur 1000).
D’autre part, on utilise un compteur/décompteur pour tenir à jour la position actuelle du
rotor en comptant les fronts de clk dans un sens de rotation et en décomptant dans
l’autre sens ; le signal reset remet ce compteur à zéro.
AB CD
A
Phase1
B
1000
1100
C
D
0110

0010
...
ESSI1 – Spécification des circuits logiques avec AHDL (Jean-Paul Stromboni, 1999) Page - 2 -
3. Détecteur de sens de rotation detect.tdf (cf. le principe utilisé pour les déplacements
des souris). On dispose de deux entrées binaires A = Xclock, B = Xdata issues d’un
codeur incrémental (disque gravé ou troué .. ouvrir sa souris) qui tourne quand on
déplace la souris. Dans le sens gauche  droite, on observe que A passe à 1, puis B passe
à 1, puis A passe à 0, puis B etc... alors que B précède A dans le sens droite  gauche.
A partir de ces deux entrées et de l’horloge clk plus rapide (4 MHz) pour échantillonner A
et B, construire un automate doté de 8 états à définir
s0 , s1 ... s7 , et la sortie binaire sens
qui donne le sens du déplacement actuel selon la séquence observée sur A et B. Ajouter
l’information de l’amplitude du déplacement en comptabilisant les impulsions sur A ou B.
disque
A et B, sens 1
A
codeur
B
instants d’échantillonnage
temps
A et B sens 2
Annexes :

Exemple d’additionneur série 8 bits : analyser et simuler cet exemple dans un premier
temps, puis modifier pour en faire un soustracteur commandé par la valeur sgnop
constant NUMBIT=8;
SUBDESIGN addit
(
a[NUMBIT..1], b[NUMBIT..1], cin : INPUT;
c[NUMBIT..1], cout
: output;
)
VARIABLE
sum[NUMBIT..1],
carryout[(NUMBIT+1)..1]: NODE;
BEGIN
carryout[1]=cin ;
FOR i IN 1 TO NUMBIT GENERATE
sum[i]= a[i] $ b[i] $ carryout[i]; % full adder %
% $ est le ou exclusif, # est le ou et & le et %
carryout[i+1]=a[i] & b[i] # carryout[i] & (a[i] $ b[i]);
end generate;
cout = carryout[NUMBIT+1];
c[]=sum[];
END;
ESSI1 – Spécification des circuits logiques avec AHDL (Jean-Paul Stromboni, 1999) Page - 3 
Lors de l’addition, on visualise les résultats transitoires sur les diagrammes temporels. Utiliser
l’opérateur + de ahdl, soit a[]+b[] au lieu de addit mène à un comportement semblable.

Exemple de création de séquenceur, machine à nombre d’états fini (voir également
simple.tdf pour une autre syntaxe)
SUBDESIGN stepper (
clk, reset
: INPUT;
ccw, cw
: INPUT;
phase[3..0] : OUTPUT;
)
VARIABLE
ss: MACHINE OF BITS (phase[3..0])
WITH STATES
(
s0 = B"0001",
s1 = B"0010",
s2 = B"0100",
s3 = B"1000");
BEGIN
ss.clk
= clk;
ss.reset = reset; % reinitialisation de la machine
TABLE
ss,
ccw,
cw
=>
ss;
s0,
1,
x
=>
s3;
s0,
x,
1
=>
s1;
s1,
1,
x
=>
s0;
s1,
x,
1
=>
s2;
s2,
1,
x
=>
s1;
s2,
x,
1
=>
s3;
s3,
1,
x
=>
s2;
s3,
x,
1
=>
s0;
END TABLE;
END;

Les instructions suivantes extraient valeur absolue et signe (1 pour <0, 0 pour >0) d’une
entrée Ca2[N..0] :
variable valabs[N..0] : node ;
signe=Ca2[N] ;
if signe then valabs[]= (Ca2[ ] $ VCC)+1 ; else valabs[ ]= Ca2[ ] ; end if ;

(a,b,c,d,e,f) définit un groupe de bits en ahdl, à partir de sous groupes a, b,c, … de même
que a[7..4] équivaut au groupe (a7, a6, a5, a4).

L’overflow OVF peut être défini ainsi à partir des de
s a , sb , s r signes des opérandes et du
résultat, et de sgnop qui indique l’opération réalisée :
OVF  sgnop(sa sb * sr *  sa * sb sr )  sgnop * (sa sb sr *  s a * sb * sr )
ESSI1 – Spécification des circuits logiques avec AHDL (Jean-Paul Stromboni, 1999) Page - 4 
comparateur 16 bits
if a[ ]== b[ ] then aeqb= VCC ;
elsif a[ ]>b[ ] then agtb = VCC ;
elsif a[ ]<b[ ] then altb = VCC ; end if ;

Quand la fonction logique synthétisée est trop importante, le compilateur ahdl demande
l’autorisation d’ajouter de la place, et de choisir des circuits logiques programmables
EPLD plus grands, cocher la case « Add extra devices as needed ».

Pour changer le format d’affichage des groupes binaires dans les diagrammes temporels,
il faut détruire le groupe « Ungroup », choisir un format Hexa, Décimal, Binaire, etc … et
refaire le groupe « Enter group »

Attention au comptage en code Gray, ou code binaire réfléchi, le code des diagrammes
de Karnaugh où le nombres successifs varient d’un bit seulement. Il donne des
comportements bizarres, tels que « 2+2=5 » ! ! !

Les subdesigns ahdl ne sont pas des programmes exécutant des instructions en
séquence, ce sont des spécifications textuelles de connexions de signaux logiques, la
plupart du temps, l’ordre des instructions n’a pas d’importance, puisqu’il ne correspond
pas à une cohérence de calcul. De plus, une instruction du type a = a +b sera refusée,
parce qu’il s’agit de relier un signal a à une valeur différente a+b (court circuit). Enfin, on
préfèrera a= VCC pour mettre a au niveau logique un.
Suggestion d’autres exercices (non exhaustif …)

Comment créer un décodeur BCD 7 segments nommé BCD.tdf dans un projet BCD ?
Utiliser ce composant pour afficher 1999.

Créer la fonction Valse.tdf qui convertit le format Valeur Absolue + signe en format
complément à deux sur 8 bits : Entrée VA+Signe , sortie Cà2, Créer la fonction inverse :
entrée Cà2, sortie VA+Signe.

Obtenir un comparateur 16 bits comp16.tdf à partir de comparateurs 4 bits à retrouver
dans les bibliothèques de MAXPLUSII : les entrées sont A(16 bits) et B(16 bits) et les 3 sorties
binaires sont notées AgtB, AltB et AeqB. Proposer une autre méthode plus simple.

Comment construire un compteur synchrone modulo 2000 dans ctr2000.tdf ? et un
compteur décompteur commandé par une variable logique updown ?

Réaliser dans distrib.tdf les équations du distributeur de boissons E , M , C , R  f ( e, m, c, p )

Réaliser une logique de décodage adressant un périphérique P1 (signal CS1=1) si R/W=1
et ALE=1 et un second périphérique P2 (signal de validation CS2=1) si ALE=1 et R/W=0.

Constituer un registre à décalage 8 bits shiftr.tdf fonctionnant en mode Parallel Input
Serial Output PISO.

Utiliser une ALU (Arithmetic and Logic Unit) pour effectuer diverses opérations sur deux
opérandes A et B contenus dans des registres 8 bits.

Peut on piloter l’Universal Asynchronous Receiver Transmitter UART inclus dans
l’environnement ? Sur l’entrée RxD, on lit successivement Startbit, B0, B1, ... B7, Stopbit. Le
circuit mémorise les Bi dans un registre à décalage, qui est lu quand il est plein. C’est la
conversion parallèle série SIPO. La conversion inverse est réalisée sur la sortie TxD ? On
prendra 19200 bauds.

Peut on réaliser multiplieur binaire par additions et décalages (ou par un autre moyen) ?

...
ESSI1 – Spécification des circuits logiques avec AHDL (Jean-Paul Stromboni, 1999) Page - 5 -
constant NUMBIT=16;
SUBDESIGN addsub (
sgnop, clk, a[NUMBIT..1], b[NUMBIT..1], cin : INPUT;
c[NUMBIT..1], cout, sgnout
: output; )
VARIABLE
sum[NUMBIT..1], carryout[(NUMBIT+1)..1]: NODE;
BEGIN
carryout[1]=cin # sgnop;
FOR i IN 1 TO NUMBIT GENERATE
sum[i]= a[i] $ (b[i] $ sgnop) $ carryout[i]; % full adder %
-- $ est le ou exclusif, # est le ou et & le et
carryout[i+1]=a[i] & (b[i] $ sgnop) # carryout[i] & (a[i] $ (b[i] $
sgnop));
end generate;
cout = carryout[NUMBIT+1];
sgnout = sum[NUMBIT];
if !sgnout then c[]=sum[]; else c[]= (sum[] $ VCC)+1; end if;
END;
-------------------------------------------------------------------------------------------------------------constant NBITS= 15;
SUBDESIGN pasapas (
clk, reset
: INPUT;
direct, inverse
: INPUT;
A,B,C,D,
: OUTPUT; )
position[NBITS..0]
VARIABLE
pos[NBITS..0]: DFF;
ss: MACHINE OF BITS (A,B,C,D)
WITH STATES
(
s0 = B"1000",
s1 = B"1100",
s2 = B"0100",
s3 = B"0101",
s4 = B"0001",
s5 = B"0011",
s6 = B"0010",
s7 = B"1010");
BEGIN
ss.clk
= clk;
ss.reset = reset;
ESSI1 – Spécification des circuits logiques avec AHDL (Jean-Paul Stromboni, 1999) Page - 6 pos[].clk=clk;
pos[].clrn = !reset;
if direct then
pos[].d=pos[] +1;
elsif inverse then
pos[].d=pos[]-1;
end if;
position[]=pos[];
TABLE
ss,
direct,
inverse
=>
ss;
%-----------------------------------------------%
s0,
1,
x
=>
s7;
s0,
x,
1
=>
s1;
s1,
1,
x
=>
s0;
s1,
x,
1
=>
s2;
s2,
1,
x
=>
s1;
s2,
x,
1
=>
s3;
s3,
1,
x
=>
s2;
s3,
x,
1
=>
s4;
s4,
1,
x
=>
s3;
s4,
x,
1
=>
s5;
s5,
1,
x
=>
s4;
s5,
x,
1
=>
s6;
s6,
1,
x
=>
s5;
s6,
x,
1
=>
s7;
s7,
1,
x
=>
s6;
s7,
x,
1
=>
s0;
END TABLE;
END;
ESSI1 – Spécification des circuits logiques avec AHDL (Jean-Paul Stromboni, 1999) Page - 7 -
subdesign detect(
clk
:
input;
reset :
input;
a,b
:
input;
s
:
output;)
variable ss: machine with states (s0,s1,s2,s3,s4,s5,s6,s7);
begin
ss.clk = clk;
ss.reset= reset;
table
ss,
a,
b
=>
s,
ss;
%------------------------------------%
s0,
0,
1
=>
0,
s1;
s0,
1,
0
=>
1,
s6;
s0,
1,
1
=>
0,
s0;
s0,
0,
0
=>
0,
s0;
s1,
1,
1
=>
0,
s3;
s1,
0,
0
=>
1,
s4;
s1,
1,
0
=>
0,
s1;
s1,
0,
0
=>
0,
s1;
s2,
1,
1
=>
1,
s7;
s2,
0,
0
=>
0,
s0;
s2,
1,
0
=>
0,
s2;
s2,
0,
1
=>
0,
s2;
s3,
1,
0
=>
0,
s2;
ESSI1 – Spécification des circuits logiques avec AHDL (Jean-Paul Stromboni, 1999) Page - 8 s3,
0,
1
=>
1,
s5;
s3,
1,
1
=>
0,
s3;
s3,
0,
0
=>
0,
s3;
s4,
0,
1
=>
0,
s1;
s4,
1,
0
=>
1,
s6;
s4,
1,
1
=>
1,
s4;
s4,
0,
0
=>
1,
s4;
s5,
1,
1
=>
0,
s3;
s5,
0,
0
=>
1,
s4;
s5,
1,
0
=>
1,
s5;
s5,
0,
1
=>
1,
s5;
s6,
1,
1
=>
1,
s7;
s6,
0,
0
=>
0,
s0;
s6,
1,
0
=>
1,
s6;
s6,
0,
1
=>
1,
s6;
s7,
0,
1
=>
1,
s5;
s7,
1,
0
=>
0,
s2;
s7,
1,
1
=>
1,
s7;
s7,
0,
0
=>
1,
s7;
end table;
end;
------------------------------------------------------------subdesign detect2 % seconde version de detect utilisant case%
(
clk
:
input;
reset :
input;
a,b
:
input;
s
:
output;)
variable
seq: machine of bits (s) with states (s0,s1,s2,s3,s4,s5,s6,s7);
begin
seq.clk = clk;
seq.reset= reset;
case seq is
when s0 =>
if !a&b then seq=s1; elsif a&!b then seq=s6; end if;
when s1 =>
if a&b then seq=s3; elsif !a&!b then seq=s4; end if;
when s2 =>
if a&b then seq=s7; elsif !a&!b then seq=s0; end if;
when s3 =>
ESSI1 – Spécification des circuits logiques avec AHDL (Jean-Paul Stromboni, 1999) Page - 9 if a&!b then seq=s2; elsif !a&b then seq=s5; end if;
when s4 =>
if !a&b then seq=s1; elsif a&!b then seq=s6; end if;
when s5 =>
if a&b then seq=s3; elsif !a&!b then seq=s4; end if;
when s6 =>
if a&b then seq=s7; elsif !a&!b then seq=s0; end if;
when s7 =>
if !a&b then seq=s5; elsif a&!b then seq=s2; end if;
end case;
end;
Téléchargement