Sie sind auf Seite 1von 94

M. Doussot, G. Millon, S. Moutou et B.

Jacquot

TD et TP LO11

UTT 2014/2015

Prise en main de la partie schmatique


La programmation se fait toujours travers un projet. La premire chose apprendre est
donc de savoir crer et grer un projet. On rappelle qu'un projet permet de rassembler
plusieurs types de fichiers ensembles.

I. Comment dmarrer un projet


La premire chose que l'on se demande est quel est le FPGA cible que l'on utilise et
quelle sorte de botier on utilise ? En ce qui nous concerne ce sera un SPARTAN 3E 500
(xc3s500e) dans un botier FG320.
On choisit ensuite le type de langage : pour nous ce sera du schmatique... et on se
laisse guider.
Notre premier projet sera compos de deux fichiers : un fichier de schma (extension
.sch) et un fichier de contrainte (extension .ucf)

II.Saisir un schma
On va commencer par un exemple trs simple mais qui nous permettra de comprendre
comment l'environnement fonctionne.

Add wire
Icone
e1

Category : logic
Symbol : or2
s

e2
Add I/O Marker
Icone

On a deux entres que l'on va relier deux interrupteurs (sw0 et sw1 positionns
respectivement en L13 et L14) et une sortie qui va nous servir allumer une led (led0 en
F12).
Dans l'ordre, il est bon de commencer par les composants, puis par les connexions (wire)
pour terminer par les I/O Marker.

III.Saisir le fichier ucf


C'est un fichier texte dont la syntaxe est relativement simple. Il existe un outil graphique
pour faire cela mais nous utiliserons un diteur de texte simple.
net "e1" loc="L13";
net "e2" loc="L14";
1/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

net "s" loc="F12";

Seul la documentation de la carte sur laquelle est votre FPGA vous permet de trouver
comment s'appellent les broches de votre FPGA pour les mettre dans le fichier ucf
correspondant. Cette documentation vous sera toujours fournie.
Notez que pour ouvrir un fichier ucf, il ne faut pas double-cliquer dessus : cliquer
simplement et aller chercher (sur la gauche) dans la fentre process :
User Constraints
|__ Edit constraints (text).

IV.Compilation
La compilation a comme objectif de raliser un fichier binaire (d'extension .bit) qui sera
tlcharg dans le FPGA. On clique dans la fentre projet sur le fichier le plus haut dans
la hirarchie (pour le moment ce sera notre schma) puis dans la fentre process on
choisit "Generate Programming File" (double clic)

V.Tlchargement
Le tlchargement dans la carte se fait avec Impact (trouv dans la fentre process) :
Configure Target Device
|__ Manage Configuration Project (Impact)

VI.Convention de noms pour les portes


Pour s'y retrouver parmi les nombreuses portes logiques disponibles, nous donnons les
indications suivantes. Les noms des portes sont de la forme pNbM

p est un nom de porte comme and, or, nor, nand, xor et xnor reprsentant le ET, le
OU, le OU-NON le ET-NON, le OU-Exclusif, et l'identit.

N est le nombre d'entres de la porte, typiquement de 2 9 et mme parfois 16.

b est une lettre suivie d'un chiffre M variant de 1 typiquement 5 dsignant le


nombre d'entres complmentes. Certains composants n'ont pas cette extension,
par exemple le ou exclusif va de xor2 xor9.

La suite est importante pour les projets un peu plus consquents et peut tre passe en
premire lecture.

VII.Renommer un fil (net)


Renommer un fil est utile pour relier un fil une entre sans dessiner cette liaison.
Pour renommer un fil, ne pas passer par un click droit sur le fil en essayant de trouver
"Object Property", mais plutt :

edit -> Rename -> rename Selected net puis donner le nom puis OK.

2/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

VIII.Cration de plusieurs feuilles


Quand votre dessin devient complexe il faut le rpartir sur plusieurs feuilles. Pour se
faire :

click droit dans la feuille -> object properties New

Pendant que vous y tes, il est possible de changer la taille de la feuille ou des feuilles.

IX.Cration d'un symbole


Il pourra nous arriver de rassembler un schma complexe dans un symbole. Ceci peut
tre fait ainsi :
Dans la fentre Design (tout en haut) : Design Utilities -> Create Schematic Symbol
Ceci peut tre ralis aussi comme ceci :

File -> New -> Symbol

Utilisation du sorcier (Wizard)

Tools -> symbol wizard

Next

Donner un nom au symbole et ajouter le nom des entres et sorties puis next.
Remarque : Le "symbol wizard" permet de transformer directement votre schma en
cours en symbole si vous cochez "using schematic" et il vous trouve alors tout seul
l'ensemble des entres/sorties.

3/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

TP1 - Transcodeur binaire 7 segments

INFO

La logique combinatoire est prsente partir de la page 8 du polycopi


de cours.
On utilisera un FPGA de type SPARTAN 3E 500 (xc3s500e) dans un
botier FG320.

On va raliser un transcodeur binaire dcimal vers un afficheur 7 segments. L'objectif de


ce TP est d'utiliser toutes les techniques classiques de synthse combinatoire.

I. Prsentation du sujet
Un schma prsente de manire symbolique ce que l'on cherche faire.

J1
"D14" "B4"
S3E J5
"B16" "D5"
"L13" "C12" "C4" "A6"
"L14" "D12" "A11" "E7"
"H18" "G9" "C14" "A4"
"N17" "A8" "A16" "C5"
"E13" "B6"
(J4):"B11"(J1):"F7"

FPGA #J4

sw0
sw1
sw2
sw3

a
b
c
d
e
f
g

a
f

c
d

0/1
Sortieselpour
slectionner
afficheur

sel

sel est choisi 0 pour slectionner l'afficheur de droite.


La valeur binaire (de 0 9) choisie sur les interrupteurs est convertie pour tre affiche :

0000

0001

0010

0011

0100

0101

0110

0111

1000

II.Fichier ucf
Pour viter de chercher nous donnons quelques contenus du fichier ucf :
NET "SW<0>" LOC = "L13" | IOSTANDARD = LVTTL | PULLUP ;
NET "SW<1>" LOC = "L14" | IOSTANDARD = LVTTL | PULLUP ;
NET "SW<2>" LOC = "H18" | IOSTANDARD = LVTTL | PULLUP ;
NET "SW<3>" LOC = "N17" | IOSTANDARD = LVTTL | PULLUP ;
4/94

1001

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

# ==== 6-pin header J1 ====


# These four connections are shared with the FX2 connector
#NET "J1<0>" LOC = "B4" | IOSTANDARD = LVTTL |

SLEW = SLOW | DRIVE = 6 ;

#NET "J1<1>" LOC = "A4" | IOSTANDARD = LVTTL |

SLEW = SLOW | DRIVE = 6 ;

#NET "J1<2>" LOC = "D5" | IOSTANDARD = LVTTL |

SLEW = SLOW | DRIVE = 6 ;

#NET "J1<3>" LOC = "C5" | IOSTANDARD = LVTTL |

SLEW = SLOW | DRIVE = 6 ;

# ==== 6-pin header J2 ====


# These four connections are shared with the FX2 connector
#NET "J2<0>" LOC = "A6" | IOSTANDARD = LVTTL |

SLEW = SLOW | DRIVE = 6 ;

#NET "J2<1>" LOC = "B6" | IOSTANDARD = LVTTL |

SLEW = SLOW | DRIVE = 6 ;

#NET "J2<2>" LOC = "E7" | IOSTANDARD = LVTTL |

SLEW = SLOW | DRIVE = 6 ;

#NET "J2<3>" LOC = "F7" | IOSTANDARD = LVTTL |

SLEW = SLOW | DRIVE = 6 ;

Pour savoir comment sont connects nos afficheurs notre carte, il faut tlcharger la
documentation des afficheurs : dans google digilent pmodssd (donne un peu plus loin
dans ce document)

III.Table de vrit
Raliser la table de vrit correspondant au cahier des charges si on doit sortir un 1 pour
afficher un segment. Rflchissez sur la premire ligne avant de poursuivre.
sw3 sw2

sw1

sw0

IV.Synthse de la slection
Pour forcer des valeurs prdfinies :

Mettre 1 avec : Catgorie gnrale -> symbol Vcc

Mettre 0 avec : Catgorie gnrale -> symbol gnd

5/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

V.Synthse du segment "a"


Simplifier avec un tableau de Karnaugh et rechercher l'quation disjonctive
correspondant au segment a. Donner le schma ET/OU, puis implanter avec des portes
"et" (une and2b2 et une and2) avec une porte "ou" de type or4

VI.Synthse du segment "b"


Puisque le segment "b" possde deux zros dans sa colonne, on va le synthtiser par
son complment. crire le complment de "b" sous une forme disjonctive sans simplifier.
Implanter avec deux ET 4 entres et une NOR2 (c'est le NOR2 qui fait le complment
pourquoi?).

7.Synthse des segments "c", "d", "e", "f" et "g"


On utilisera la mthode du segment a pour ces synthses, c'est dire un tableau de
Karnaugh et une simplification pour finir par un schma compos de ETs et un OU.

6/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

TP2 - Des tables de vrits aux schmas

INFO

La logique combinatoire est prsente partir de la page 8 du polycopi


de cours.
On utilisera un FPGA de type SPARTAN 3E 500 (xc3s500e) dans un
botier FG320.

L'objectif de ce TP est d'augmenter un peu la productivit en schmatique en utilisant,


non plus les portes standards, mais des composants permettant d'implanter directement
des tables de vrit dans notre FPGA (sans les simplifier). On utilisera encore un
SPARTAN 3E 500 (xc3s500e) dans un botier FG320.

I. Des tables de vrit l'hexadcimal


Une table de vrit de trois entres peut tre reprsente par un nombre 8 bits que l'on
convertit en hexadcimal. Soit donc la table de vrit suivante (trois entres notes e0,
e1 et e2, une sortie note s) :
e2 e1

e0

b0

Vous pouvez synthtiser la table de vrit l'aide

b1

d'un seul nombre sur 8 bit (poids faible en haut) :

b2

- en binaire ce nombre vaut : 0b01010110

b3
0

- en hexadcimal ce nombre vaut : 0x56 (X"56" en


VHDL)

b4

b5

b6

b7

Aucune simplification faire ici

La valeur hexadcimale 56 est la valeur qu'il vous faudra utiliser dans la partie INIT
d'une (catgorie) LUT avec un composant lut3.
Pour initialiser une LUT, double cliquer dessus et remplir le champ INIT.

Combien de bits ncessite l'initialisation d'une lut4 4 entres ? Combien de chiffres


hexadcimaux ?

7/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

II.Transcodeur hexadcimal vers sept segments et LUTs


On va reprendre le transcodeur binaire hexadcimal vers un afficheur 7 segments.
L'objectif de ce TP est d'utiliser toutes les techniques classiques de synthse
combinatoire spcifiques aux FPGA pour raliser un composant dj ralis au TP
prcdent, et ce, mme si vous n'avez pas eu le temps de finir ce TP en question.

a
f

c
d

A partir de la table de vrit complte correspondant au dcodage ci-dessus, raliser la


synthse complte du dcodeur sept segments (en moins d'une heure). Il s'agit de
dessiner et configurer 7 lut4.

III.Les multiplexeurs

INFO

Le multiplexeur est prsente en pages 8 et 9 du


polycopi de cours.

Les multiplexeurs reprsentent une autre technique pour viter de simplifier et faire une
synthse. Encore une fois, la table de vrit suffit.
Soit donc la table de vrit suivante :
S2 S1

S0

D0

On a renomm les entres pour qu'elles

D1

correspondent aux entres de slection du MUX

D2

La dernire colonne a t renomme

D3

Dernire colonne + avant dernire dit quoi

D4

relier les entres du MUX

D5

D6

Aucune simplification faire ici

8/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

D7

Le principe de synthse est le suivant :

les entres de la table de vrit iront sur les entres de slections du multiplexeur
(S0,S1,S2)

les entres D0..D7 sont relies des un ou des zros.

Le problme est que la taille d'un multiplexeur augmente trs rapidement avec le
nombre d'entres.
Travail raliser : Utiliser un multiplexeur "m16_1e" en lieu et place d'une LUT
pour la synthse du segment a de la synthse prcdente. Ne pas oublier de mettre
l'entre E Vcc.

IV.Les multiplexeurs (suite)


Peut-on vraiment oublier les tableaux de Karnaugh et autres techniques
combinatoires pour autant ? Non car vous n'aurez pas toujours un multiplexeur de la
bonne taille... et il faut alors improviser.
Il nous manque une variable
Travail raliser : Utiliser un multiplexeur "m8_1e" en lieu et place d'une LUT pour
la synthse du segment b de la synthse prcdente. Ne pas oublier de mettre
l'entre E Vcc.
Il nous manque deux variables
Travail raliser : On va implanter un segment quelconque avec un MUX "m4_1e".
Il nous manque donc deux entres. Puisqu'on a deux entres de slection et quatre
entres gnrales, on choisit 2 entres gnrales que l'on amne sur les deux entres
de slection et sur les 8 entres gnrales D0,..., D7 on apporte une des 16 fonctions
des deux entres laisses pour compte.

V.Complment sur l'ucf associ l'extension.


ucf pour 8 sorties sur la nouvelle extension :
# The discrete LEDs are shared with the following 8 FX2 connections
# a segment :
NET "FX2_IO<17>" LOC = "F11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
# b segment :
NET "FX2_IO<19>" LOC = "E12" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
# c segment :
NET "FX2_IO<21>" LOC = "A13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
# d segment :
NET "FX2_IO<23>" LOC = "A14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
# e segment :
NET "FX2_IO<25>" LOC = "C14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;

9/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

# f segment :
NET "FX2_IO<27>" LOC = "A16" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
# g segment :
NET "FX2_IO<29>" LOC = "E13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
# CAT: digit selection :
NET "FX2_IO<31>" LOC = "B11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;

10/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

TP3 Arithmtique (Schmatique)

INFO

Les oprations arithmtiques sont prsentes partir de la page 35 du


polycopi de cours.
On utilisera un FPGA de type SPARTAN 3E 500 (xc3s500e) dans un
botier FG320.

L'arithmtique consiste implanter des fonctions de base de l'arithmtique, c'est dire


addition, soustraction et multiplication. L'utilisation de l'arithmtique dans un FPGA doit
suivre ses propres rgles. Nous allons commencer par examiner l'addition, d'abord sans
se proccuper du fait que l'on utilise un FPGA, puis on cherchera utiliser les
composants Xilinx. On utilisera encore un SPARTAN 3E 500 (xc3s500e) dans un botier
FG320.

I. Du demi-additionneur l'additionneur 1 bit


Les oprations d'addition sur 1 bits sont trs simples et donnent un rsultat sur 2 bits. Le
bit de poids fort est appel R (pour retenue= carry en anglais) et le poids faible est
appel S (pour somme).

a
b

DEMI
ADD

an
bn
Rn-1

ADD

S
R

Sn
R

b
0
0
1
1

a
0
1
0
1

R
0
0
0
1

S=ab
R = a.b

S
0
1
1
0

bn an
Rn-1 00 01 11 10
0
0 0
1 0
1
0 1
1 1
Rn

bn an
Rn-1 00 01 11 10
0
0 1 0
1
1
1 0 1
0
Sn

Sn = an bn Rn-1

Rn = an.bn + Rn-1.(an bn)

Remarquez que Rn n'est pas simplifi au mieux pour faire apparatre un OU exclusif.
Travail raliser

11/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Implanter un additionneur 1 bit avec deux ou-exclusifs deux entres et trois portes
NANDs. Pour les tests, les entres seront relies des interrupteurs et les sorties des
LEDs.
Copier 4 fois le schma prcdent et montrer que l'on peut raliser ainsi un additionneur
4 bits. N'oubliez pas que la somme de deux nombres de 4 bits peut donner un nombre
de 5 bits.

II.Additionneur et soustracteur sur 1 bit


On cherche maintenant raliser un circuit capable d'additionner ou de soustraire sur
un seul bit. Puisque l'on sait raliser un additionneur, on va se concentrer sur le
soustracteur. Les trois entres du soustracteurs seront aussi appeles an, bn et Rn-1. Un
soustracteur sur 1 bit ralise l'opration an-bn-Rn-1. Le rsultat est sur deux bits en
complment deux.
Prparation
On cherche reprsenter un nombre positif ou ngatif sur deux bits seulement. Avec le
complment deux seules les valeurs 1, 0, -1 et -2 sont reprsentables.
Trouver les quatre reprsentations en compltant pour les nombres ngatifs.
nombre binaire nombre binaire nombre binaire nombre binaire
1 (01)2

0 (00)2

-1

-2

Chercher la table de vrit du soustracteur 1 bit.


a

Rin

Rout

Valeur dcimale (a - b - Rin)

-1

-1

-2

-1

Travail raliser
Raliser un schma du soustracteur en modifiant celui de l'additionneur en lui ajoutant
deux inverseurs.

12/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Optionnel : sachant qu'un ou exclusif a la proprit d'inverser ou pas, remplacer les


deux inverseurs par deux ou exclusifs. Le schma obtenu possde une quatrime entre
S de slection qui permet de choisir si l'on fait une addition ou une soustraction.
Implanter ce schma en schmatique Xilinx et tester.

III.Additionneur 4 bits
Comme indiqu en introduction, si vous avez de l'arithmtique faire il faut mieux
utiliser des composants tout faits. En effet, tout FPGA moderne possde un certain
nombre de parties pr-cbles ralisant ces fonctions. On utilisera ainsi le composant

ADD4 dans la catgorie "arithmetic". Les entres de ce composant seront des interrupteurs
extrieurs mais ses sorties seront destines tre affiches sur un afficheur sept segments... et
c'est l que les choses se compliquent un peu.

Prparation

Montrer que dans le cas o la somme de deux nombres BCD sur 4 bits dpasse 9 (cette somme
n'est pas BCD mais binaire cause de ADD4), il suffit d'ajouter 6 au rsultat pour obtenir le
nombre BCD correct.

Travail raliser
On va se contenter d'utiliser le composant ADD4 de Xilinx dans le cas d'entres BCD.
Cela veut dire que chacune des entres ne peut dpasser (9)10=(1001)2.
On vous demande d'utiliser deux composants ADD4 de Xilinx pour obtenir la somme BCD (sur 5
bits) de deux nombres BCD (sur 4 bits). Le deuxime additionneur est l pour ajouter 6 en cas de
dpassement de 9. Il vous faut naturellement ajouter la logique capable de dtecter un
dpassement de 9. Un comparateur COMPM4 et un OU devraient suffire.
Les tudiants dbutants sont invits tester d'abord un additionneur ADD4 seul avec l'afficheur
7 segments, puis ajouter le comparateur COMPM4 et montrer que pour un rsultat qui
dpasse strictement 15 (autrement dit quand C0 vaut 1) le comparateur ne s'en rend pas
compte !!! d'o la prsence du OR2 qui rsout ce problme.

a
f
e

Schma complter

g
c

d
Afficheur + LED
CI

PB0 PB1 PB2 PB3 PB4

COMPM4

A0
A1
A2
A3
B0
B1
B2
B3

ADD4

S0
S1
S2
S3

A0
A1
A2
A3

dizaine

CI
GT
LT

B0
B1
B2
B3

OR2

>1

CO
13/94

A0
A1
A2
A3
B0
B1
B2
B3

ADD4

S0
S1
S2
S3

CO

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Cet ensemble est-il capable de grer correctement la retenue CI de ADD4 ( gauche) ?


Autrement dit si CI passe un, le rsultat final est-il encore correct ?
Aide pour fichier ucf
Pour prendre en compte les 4 interrupteurs supplmentaires on vous propose le fichier ucf
suivant :
# sw3b :
NET "FX2_IP<37>" LOC = "A15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
# sw2b :
NET "FX2_IP<38>" LOC = "B15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
# sw1b :
NET "FX2_IO<39>" LOC = "C3" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
# sw0b :
NET "FX2_IP<40>" LOC = "C15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;

Pour Printemps 2015 : voir dessin TP1 sachant que l'on est connect en J5 !

IV.Additionneur/soustracteur 4 bits
L'additionneur soustracteur existe comme composant tout fait ADSU4 chez Xilinx, mais
nous allons le raliser partir de ADD4. pour en comprendre le fonctionnement de
manire intime, en particulier la notion de complment deux.
Prparation
Calculer les limites d'une reprsentation en complment deux sur 4 bits notes B 4 et (B4+1) dans la suite.
Si sel = 0 on additionne et le nombre rsultat se trouve en sortie du premier
additionneur sur 5 bits (ou en sortie du deuxime additionneur mais avec comme 5 bit
CO1 et non CO2)
Si sel = 1 les complments sont raliss et on additionne 1 l'aide de CI1. On fait donc
un complment deux de B = /B+1, mais on reste sur 4 bit. Le premier additionneur fait
donc S=A+/B+1=A-B. Montrer que si B dpasse B4+1, cela ne fonctionne plus. Prendre
par exemple B= B4+2 et faire son complment deux en montrant qu'alors le bit
gauche vaut 0 et qu'ainsi ce nombre ne peut tre interprt comme ngatif.
Dans le cas de la soustraction, Sel=1, montrer l'aide de quelques exemples qu'un
rsultat positif positionne CO1 1 tandis qu'un rsultat ngatif le positionne 0 (choisir
B entre 1 et B4+1 pour la soustraction).
Pour afficher le rsultat de la soustraction correctement sur un ventuel afficheur 7
segments et une diode LED de signe, il faut refaire un complment deux pour
retrouver la valeur absolue. C'est l'objet du deuxime additionneur. Ainsi, si rsultat
positif LED teinte et valeur absolue sur afficheur et si rsultat ngatif LED allume et
valeur absolue sur afficheur. Le schma complet est prsent ci-dessous.
Travail raliser
Chercher la fonction F du schma ci-aprs.

14/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Implanter l'ensemble et tester. Donner les plages pour lesquelles l'affichage du rsultat
d'une addition fonctionne correctement si le rsultat est considr comme binaire sur 5
bits (CO1,S3,S2,S1,S0). Comme il est sur 5 bits on ne peut pas l'afficher sur un ou deux
afficheurs
Tester si l'affichage d'une soustraction fonctionne correctement pour les valeurs
prcalcules dans la prparation en restant en binaire ou en utilisant un l'afficheur 7
segments.

Sel=0:addition
Sel=1soustraction
A0
A1
A2
A3

XOR2

=1

XOR2

=1

XOR2

=1

XOR2

=1

B0
B1
B2
B3

signe

CI1

CI2

ADD4

S0
S1
S2
S3

XOR2

=1

XOR2

=1

XOR2

=1

CO1

XOR2

=1

Trouver la fonction F

Indication : F=a./b, et c'est C01 qui est complment.

15/94

A0
A1
A2
A3
B0
B1
B2
B3

ADD4

S0
S1
S2
S3

CO2

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

TP4 Introduction VHDL


On utilisera encore et toujours un SPARTAN 3E 500 (xc3s500e) dans un botier FG320.

INFO

VHDL est prsent partir de la page 75 du polycopi


de cours.

I. Au commencement tait la table de vrit...


Soit la table de vrit suivante :
a3 a2 a1 a0 s1 s0
0

libraryIEEE;
useIEEE.STD_LOGIC_1164.ALL;
ENTITYdemoISPORT(
a:inSTD_LOGIC_VECTOR(3DOWNTO0);4entres
s:outSTD_LOGIC_VECTOR(1DOWNTO0));
2sorties
ENDdemo;

Il manque 13 lignes cette table, qui sont retires, mais donnent des 0 en sortie
Notez que la partie gauche de la table de vrit appele partie SI concerne les entres,
et la partie droite (appele ALORS) concerne les sorties. La donne d'une table de vrit
permet directement de trouver l'entit. Elle permet aussi d'crire directement
l'architecture avec un "with select when" :
1
2
3
4
5
6
7
8

ARCHITECTUREmydemoOFdemoIS
BEGIN
WITHaSELECT--style with select when
s<="11"WHEN"0101",-- premiere ligne
"01"WHEN"0110",-- deuxieme ligne
"10"WHEN"1101",-- troisieme ligne
"00"WHENOTHERS;-- pour les 13 lignes retires
ENDmydemo;

Travail raliser
exo1 : Refaire le transcodeur complet d'affichage sept segments du TP1. Ce transcodeur
sera utilis trs souvent par la suite, il sera donc important d'en mettre une copie de
ct et un symbol associ.
exo2 : Modifier l'exo1 pour grer une sortie de votre choix par une quation (le reste est
gr par un with select when). Il faudra naturellement aussi modifier le "with select
when" !

II.Puis naquit l'horloge....


L'horloge est l'apanage du squentiel. Les fronts d'horloge sont utiliss avec un "IF"
entour forcment d'un "PROCESS".

16/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

1
2
3
4
5
6
7

TD et TP LO11

UTT 2014/2015

devantentitajouter:useIEEE.STD_LOGIC_ARITH.ALL;
devantentitajouter:useIEEE.STD_LOGIC_UNSIGNED.ALL;
PROCESS(clk)BEGIN
IFclk'eventandclk='1'THENouIFrising_edge(clk)THEN
q<=q+1;
ENDIF;
ENDPROCESS;

Ce qui se trouve aprs le "IF clk'event" est une quation de rcurrence : q se trouve
gauche de l'quation et doit par consquent tre considr comme une sortie. Mais il se
trouve aussi droite, il doit par consquent tre considr comme une entre.
Les compteurs permettent de diminuer la frquence d'horloge. Vous pouvez complter
vos connaissances sur les compteurs en VHDL sur le site
http://fr.wikibooks.org/wiki/TD3_VHDL_Compteurs_et_registres
Travail raliser
Exo3 : Vous disposez d'une horloge 50MHz en broche "C9" de votre composant FPGA
SPARTAN 3E. Raliser l'aide d'un compteur 24 bits une horloge d'environ 3 Hz. Sortie
sur une LED, le clignotement de celle-ci doit tre visible l'il.
Indications
1
2
3
4
5
6

#====Clockinputs(CLK)====
NET"clk"LOC="C9"|IOSTANDARD=LVCMOS33;
#====DiscreteLEDs(LED)====
#ThesearesharedconnectionswiththeFX2connector
NET"LED<0>"LOC="F12"|IOSTANDARD=LVTTL|SLEW=SLOW|DRIVE=8;
NET"LED<1>"LOC="E12"|IOSTANDARD=LVTTL|SLEW=SLOW|DRIVE=8;

INFO

Idem
http://fr.wikibooks.org/wiki/TD3_VHDL_Compteurs_et_registres#Exercice_
2 avec un nombre de bits diffrent.
L'horloge que l'on vient de raliser sera utilise presque
systmatiquement par la suite. Vous pouvez donc la sauver et en faire un
symbol pour une rutilisation future.

Par abus de langage on appellera compteur dans la suite un lment squentiel qui
comporte une horloge mais qui ne compte pas forcment en binaire. Dans ce dernier
cas, son quation de rcurrence ne peut donc pas s'crire simplement l'aide d'une
simple addition.

III.Les quations de rcurrences


Rappels
Avant toute chose, il nous faut nous demander comment utiliser des quations de
rcurrences boolennes

17/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Nous avons gauche un diagramme d'volution, au centre un tableau tat prsent tat
futur et droite les tableaux de Karnaugh permettant de trouver les quations de
rcurrences.
quations de rcurrence :
Q += Q Q
1

Q0+

= /Q0
Voici les extraits importants du programme VHDL correspondant :
1
2
3
4
5
6
7

PROCESS(clk)BEGIN
IFclk'eventandclk='1'THENouIFrising_edge(clk)THEN
quationsdercurrencesici
q1<=q1xorq0;
q0<=notq0;
ENDIF;
ENDPROCESS;

Le processus est prsent partir de la page 119 du polycopi de cours.

INFO

La machine tats est prsente partir de la page 136 du polycopi de


cours.

IV.Compteur dcimal sortie directe sept segments (sur un digit)


Prparation
Nous dsirons raliser ici un compteur mais qui donne sa sortie directement sur un
afficheur 7 segments. Ce compteur comporte donc 7 sorties (a, b, c, d, e, f et g). Un tel
compteur possde un nombre d'tats de 27=128 mais n'en utilise en fait que 10.
Remplir la table de transitions ci-dessous
Etat prsent

Etat Futur

b c

d e

g a+ b+ c+ d+ e+ f+ g+

zero

1 1

1 1 1

un

1 1

0 0 0

deux

1 0

1 1 0

trois

1 1

1 0 0

quatre

1 1

0 0 1

1
18/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

cinq

0 1

1 0 1

six

0 1

1 1 1

sept

1 1

0 0 0

huit

1 1

1 1 1

neuf

1 1

1 0 1

UTT 2014/2015

Travail raliser (si peu de temps aller directement l'exo 6)

clk

cmpt7seg
process

process a
b
clk_lent
c
d
e
f

cmpt7seg
clk

process

etat_present
process
process
etat_futur

Init
clk_lent

Exo4 et 6

a
b
c
d
e
f

Exo5 et 7

Exo4 :
1) crire les quations logiques a+, b+, c+, d+ ,e+, f+, g+ en fonction des entres a,
b, c, d, e, f, g.
2) Il nous reste un problme important rsoudre, c'est l'initialisation. En effet, pour bien faire, il
faudrait tudier les 127-10=117 tats restants pour voir comment ils se connectent sur notre cycle.
C'est un travail important qu'il est impossible de raliser moins d'y passer 117 soires ( raison
d'une transition par soire) soit presque 4 mois !!!
Pour viter cela on va prvoir une entre d'initialisation appele Init au cas o la mise sous tension
on se trouve dans un tat non prvu. Cette entre fonctionnera de manire synchrone, lorsqu'elle
sera 1 un front d'horloge provoquera l'affichage du 0 en sortie du compteur.
crire maintenant les quations de rcurrence trouves en 2) en ajoutant convenablement l'entre
Init.
3) Vous tes prt maintenant crire le programme VHDL complet. crire ces quations
dans le langage VHDL. Implanter en utilisant et modifiant l'horloge ralise dans la
section 2 pour pouvoir l'utiliser dans le composant : on utilisera un process pour le
diviseur de frquence et un process pour le compteur donc une seule entit.
1
2
3
4
5

ENTITYcmpt7segIS
PORT(CLK_50MHz:INSTD_LOGIC;
a,b,c,d,e,f,g:OUTSTD_LOGIC);
oualors:s7segs:outstd_logic_vector(6downto0));
ENDcmpt7seg;

Vous venez ainsi d'apprendre assembler deux blocs avec des process. Le travail
d'assemblage de blocs est une tche qui sera souvent demande dans ces TPs. Elle
sera ralise avec une technique diffrente dans le prochain TP.
Exo5 : Refaire le mme travail avec une entre d'initialisation.
19/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

1
2
3
4
5

TD et TP LO11

UTT 2014/2015

ENTITYcmpt7segIS
PORT(CLK_50MHz,Init:INSTD_LOGIC;
a,b,c,d,e,f,g:OUTSTD_LOGIC);
oualors:s7segs:outstd_logic_vector(6downto0));
END cmpt7seg;

V.Travail sans quation de rcurrence


Il existe une mthode qui vite le passage par les quations de rcurrences : on part du
graphe d'volution et on obtient le programme VHDL :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

libraryIEEE;
useIEEE.STD_LOGIC_1164.ALL;
ENTITYcmptISPORT(
clk:INSTD_LOGIC;
q:INOUTSTD_LOGIC_VECTOR(1DOWNTO0));
ENDcmpt;
ARCHITECTUREacmptOFcmptIScommentviterlesequations
BEGIN
PROCESS(clk)BEGIN
IF (clk'EVENT AND clk='1') THEN
CASEqisstylecasewhen
WHEN"00"=>q<="01";premieretransition
WHEN"01"=>q<="10";deuxiemetransition
WHEN"10"=>q<="11";troisiemetransition
WHENOTHERS=>q<="00";quatriemetransition
ENDCASE;
ENDIF;
ENDPROCESS;
END acmpt;

Le style "case when" est au graphe d'volution ce que le "with select


when" est la table de vrit : un moyen d'viter les quations.
Travail raliser
Exo6 : Refaire le mme travail que l'exo5 en utilisant un case when et deux process : un
pour crer l'horloge lente et un pour le compteur set segments..
1
2
3
4

ENTITYcmpt7segIS
PORT(CLK_50MHz:INSTD_LOGIC;
s_7segs:OUTSTD_LOGIC_VECTOR(6DOWNTO0));
END cmpt7seg;

Remarquez l'utilisation du STD_LOGIC_VECTOR au lieu des sorties individuelles. Le fait


qu'il soit en OUT implique que l'on utilisera un signal interne pour les "CASE".
Il est possible d'utiliser un programme utilisant deux "process" comme indiqu dans le
cours en pages 137, ..., 140. En voici un exemple :
1
2

libraryIEEE;
useIEEE.STD_LOGIC_1164.ALL;
20/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

TD et TP LO11

UTT 2014/2015

ENTITYcmptISPORT(
clk:INSTD_LOGIC;
q:OUTSTD_LOGIC_VECTOR(1DOWNTO0));
ENDcmpt;
ARCHITECTUREacmptOFcmptIScommentviterlesequations
SIGNALetat_present,etat_futur:STD_LOGIC_VECTOR(1DOWNTO0);
BEGIN
calculdel'tatfuturenfonctiondel'etatpresent
PROCESS(etat_present)BEGIN
CASEetat_presentisstylecasewhen
WHEN"00"=>etat_futur<="01";premieretransition
WHEN"01"=>etat_futur<="10";deuxiemetransition
WHEN"10"=>etat_futur<="11";troisiemetransition
WHENOTHERS=>etat_futur<="00";
ENDCASE;
ENDPROCESS;
lefuturdevientlepresent
PROCESS(clk)BEGIN
IF rising_edge(clk) THEN
etat_present<=etat_futur;
ENDIF;
ENDPROCESS;
sansarrt
q<=etat_present
END acmpt;

Exo7 : Refaire le mme travail que l'exo6 en utilisant un style deux "process" et en
grant l'initialisation. Votre programme aura trois process en fait puisqu'il faut ajouter la
division de frquence.

21/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

TP5 Schmatique et VHDL


I. Association de composants
Dans cette section, nous allons apprendre utiliser le style de programmation
structurelle, c'est dire comprendre comment associer des composants ensemble.
Commencez par comprendre la notion de hirarchie :

e0
e1
e2

i1
e0e1

&

e2bar

i3

>1

i1
e0 e0
e0e1
s
e1 e1

&

e2 e

i2

1s

e2bar

i3
e0

>1s

i1
e0 e0
e0e1
s
e1
e1

&

e2 e

e1

i2

1s

e2bar

i3
e0

>1

e1

i2

Dans la figure de droite vous avez quatre rectangles. Il y aura donc dans votre projet
VHDL quatre entits et quatre architectures. Il y a un rectangle gris qui contient trois
rectangles bleus.
Passer du temps comprendre la figure ci-dessous : pour les "port map".
Voir aussi pour les explications :
http://fr.wikibooks.org/wiki/TD1_VHDL#Assembler_des_composants_en_VHDL

e0
e1
e2

i1
e0
e1
e

&

s e0e1

e0 e0
i3
e0

e2bar

>1

e1

e1
s S

e2

e1
e

i1

&
1

e0e1
e2bar

i3
e0

>1 s

e1

i2

i2

i1:et PORT MAP(e0=>e0,e1=>e1,s=>e0e1);


i1:et PORT MAP(e0=>e0,e1=>e1,s=>e0e1);
i3:ou PORT MAP(e0=>e0e1,e1=>e2bar,s=>S); i3:ou PORT MAP(e0=>e0e1,e1=>e2bar,s=>S);
Travail raliser
Exo1 : reprendre le problme du TP prcdent (exo4) en sparant le diviseur de
frquence et le compteur sortie directe et en regroupant le tout dans un super
composant.
Remarque : la dcomposition du problme prcdent en deux composants peut
sembler, juste titre, inutile. Il existe cependant des cas o elle ne peut absolument pas

22/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

tre vite. Un exemple important est celui des mmoires que nous allons aborder en
section 3.

II.Compteur sortie sept segments avec mmoire


Nous allons utiliser un compteur normal, c'est dire qui compte en binaire sur 4 bits
suivi d'une mmoire pour le transcodage. L'horloge de ce compteur sera ralise par le
diviseur de frquence de la section 1.
Les mmoires sont difficiles utiliser en VHDL car la faon pour les implmenter dpend
du fondeur de FPGA. Ainsi la faon de faire prsente dans cette section n'est vraie que
pour les FPGA Xilinx.
Si vous voulez que votre outil de synthse infre une RAM/ROM il vous faut crire votre
RAM/ROM avec un style spcifique. Nous prsentons ici un exemple sur lequel nous nous
appuierons dans la suite : ROM avec sortie Registered
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

ROMsUsingBlockRAMResources.
VHDLcodeforaROMwithregisteredoutput(template1)

libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entityrams_21ais
port(clk:instd_logic;
en:instd_logic;
addr:instd_logic_vector(5downto0);
data:outstd_logic_vector(19downto0));
endrams_21a;
architecturesynoframs_21ais
typerom_typeisarray(63downto0)ofstd_logic_vector(19downto0);
signalROM:rom_type:=
(X"0200A",X"00300",X"08101",X"04000",X"08601",X"0233A",
X"00300",X"08602",X"02310",X"0203B",X"08300",X"04002",
X"08201",X"00500",X"04001",X"02500",X"00340",X"00241",
X"04002",X"08300",X"08201",X"00500",X"08101",X"00602",
X"04003",X"0241E",X"00301",X"00102",X"02122",X"02021",
X"00301",X"00102",X"02222",X"04001",X"00342",X"0232B",
X"00900",X"00302",X"00102",X"04002",X"00900",X"08201",
X"02023",X"00303",X"02433",X"00301",X"04004",X"00301",
X"00102",X"02137",X"02036",X"00301",X"00102",X"02237",
X"04004",X"00304",X"04040",X"02500",X"02500",X"02500",
X"0030D",X"02341",X"08201",X"0400D");
begin
process(clk)
begin
if(clk'eventandclk='1')then
if(en='1')then
data<=ROM(conv_integer(addr));
endif;
endif;
endprocess;
endsyn;

23/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Travail raliser
Exo2 : dimensionner la ROM ncessaire votre problme. Calculer les valeurs
hexadcimales contenues dans cette ROM.
Raliser un compteur 4 bits avec initialisation asynchrone.
Reprendre le diviseur de frquence de la section 1
Assembler le tout

Init

clk_50MHz

Init

224

Compteur 4 bits
clk

Q(23)
'1' en
clk

FPGA

addr

ROM

data

a
a
b
f
g
c
d
e
e
f
d
g sel

b
c

III.Compteur sortie sept segments sur deux digits


Cette partie doit tre ralise avec les afficheurs sept segments relis la carte. Vous
tes assez avanc maintenant pour comprendre la documentation de l'afficheur.

24/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

"B4"
"D5"
"A6"
"E7"

AA
AB
AC

P1
P2
P3
P4

560

AD
AA1
AB1
AC1
AD1
AE1
AF1
AG1

GND
Vcc

"A4"
"C5"
"B6"
"F7"

P1
P2
P3
P4

UTT 2014/2015

AE
AF
AG

C1

AA2
AB2
AC2
AD2
AE2
AF2
AG2
C2

GND GND
Vcc
Vcc

Seven-Segment Display Connection Diagram

La broche de slection de l'afficheur note "sel" en tp1 est note "C" ici dans la
documentation officielle. On a reprsente en bleu la connexion de P1 (situe en broche
"B4") vers les deux segments a. C'est la mme ! Cela veut dire que si l'on veut afficher
deux valeurs diffrentes il faut les envoyer alternativement : c'est le rle du multiplexeur
qui est command par Q(19). Si un clignotement est prsent sur l'afficheur, on prendre
Q(18) voir Q(17) au lieu de Q(19). Il est important de comprendre pourquoi.

Init

lent
clk
C9

24

Init
s_Q23

horloge Q(19) Q(23)


h_sel h_lente
horl_1

Cmpt8bits

clk

sorties8

4
4
entreeFort entreeFaible
multiplexeur
sel
Affichage
4
binary

transcod7segs

FPGA

Affs7seg
sel

s7segs(6 downto 0)

25/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Travail raliser
Exo3 : Implanter l'ensemble prsent ci-dessus. Le dcodeur sept segments sera au
choix, la mmoire prcdente ou le dcodeur demand comme premier exercice de ce
TP. Le rsultat doit tre un affichage de 00 FF... Attention, le poids faible doit tre
droite !!!
Remarque :
Vous tes autoris utiliser l'outil de schmatique pour raliser cet exercice 3. Voici, par
exemple la ralisation de l'horloge lente :

vcc

s_vcc

CB16CE
CE

CB8CE
CE

Q[15:0]

CEO
TC

CLR

Q[7:0]

C
s_gnd

clk_slow(7:0)

CEO
TC

CLR

B8
clk

Sauvez ce schma quelque part

gnd

Le compteur 8 bits de l'exercice 3 peut alors tre ralis par une autre CB8CE.
Voici alors le schma de principe :

vcc

s_vcc

CB16CE
CE
C
CLR

CE

Q[15:0]
CEO
TC

clk_slow(7:0)

CB8CE

C
s_gnd

Q[7:0]
s_vcc

CEO
TC

CE
clk_slow(7)

CLR

s_gnd

clk

CB8CE

cmpt(7:0)

Q[7:0]
C CEO
TC

gnd
Mais pour le reste faites-le en VHDL.
Indication
Une aide pour implanter un multiplexeur peut tre trouve dans le polycopi de cours
p119 ou ici :

26/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

https://fr.wikiversity.org/wiki/Very_High_Speed_Integrated_Circuit_Hardware_Description_
Language/Travail_pratique/TP_1#D.C3.A9codeur_8.C2.A0bits_vers_deux_afficheurs_avec
_sa_correction

IV.Compteur BCD sur deux digits


Nous cherchons maintenant modifier le compteur du TP prcdent (exo3) pour qu'il
affiche de 00 99.
Travail raliser
Exo4 : Modifier le compteur 8 bits en le dcomposant en deux compteurs BCD (0 9 0
...) cascadables. La ralisation du compteur BCD sera obligatoirement ralise en VHDL
mais on va se servir de la schmatique pour le faire. Le compteur BCD 4 bits CD4CE
existe tout fait en schmatique. Implantez-les deux CD4CE cascads, compilez et
rcuprez le fichier d'extension vhl : il contient les compteurs BCD cascads en VHDL !
Remarque
Cette faon de faire n'est pas universelle. Par exemple il n'existe pas de
compteur/dcompteur BCD en schmatique Xilinx. Si vous en avez besoin d'un il faudra
le faire en VHDL directement.

27/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

TP6 Les compteurs BCD et applications en VHDL


I. Travail introductif
Nous allons nous intresser dans cette section la ralisation d'un compteur binaire sur
8 bits et son affichage sur deux digits.
Travail raliser
Exo1 : Raliser partir de la ressource fournie (tp5exo3.vhd) le schma de l'ensemble.
Puis raliser un projet en ajoutant le fichier ucf pour un fonctionnement correct en
hexadcimal.

II.Compteur BCD sur deux digits


Nous cherchons maintenant modifier le compteur de l'exercice prcdent pour qu'il
soit capable, l'aide d'une entre supplmentaire En, de compter en BCD. Pour vous
simplifier le travail, on vous propose le code source suivant d'un compteur BCD
cascadable :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

libraryieee;
useieee.std_logic_1164.all;
useIEEE.STD_LOGIC_ARITH.ALL;
useIEEE.STD_LOGIC_UNSIGNED.ALL;
compteurexo4TP5
entitycmptBCDisport(
clk:instd_logic;
init,en:instd_logic;
enout:outstd_logic;
s:outstd_logic_vector(3downto0)
);
endentity;

architecturebehaviorofcmptBCDis
signaln:std_logic_vector(3downto0);
begin
increment:process(clk,init)begin
ifinit='1'then
n<=(others=>'0');
elsifclk'eventandclk='1'then
ifen='1'then
ifn<9then
n<=n+1;
else
n<="0000";
endif;
endif;
endif;

endprocess;
s<=n;
process(n,en)begingestiondesortiecascadable
ifen='1'andn=9then
enout<='1';
else
28/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

35
36
37
38

TD et TP LO11

UTT 2014/2015

enout<='0';
endif;
endprocess;
endbehavior;

Travail raliser
Exo2 : Remplacer le compteur 8 bits de l'exercice 1 par un compteur BCD cascad
comme dans la figure ci-dessous :

en

en

Init

lent

clk

horloge Q(19) Q(23)


h_sel h_lente

C9

224
horl_1

CmptBCD

Init
s_Q23

enout

clk

s_en en
InitCmptBCD
s_Q23 clk

enout

4
4
entreeFort
entreeFaible
sel
multiplexeur
Affichage
4
binary

transcod7segs

FPGA

Affs7seg
sel

s7segs(6 downto 0)

Nous avons invers "entreefaible" et "entreeFort" par rapport au schma prcdent mais
cela n'a absolument aucune consquence sur le VHDL.
Je mmorise :
Apprenez par cur ou sachez retrouver cette faon de grer un "reset" et un "ena"
(parfois aussi appel "en" pour enable). D'abord avec un "reset" synchrone :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

architecturebehaviorofcompteurbcdis
signaln:std_logic_vector(3downto0);
begin
increment:process(clk)begin
ifclk'eventandclk='1'then
ifreset='1'then
n<=(others=>'0');
elsifen='1'then
ifud='1'thenup
ifn<9then
n<=n+1;
else
n<=(others=>'0');
endif;
elsedown
29/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

et maintenant avec un "reset" asynchrone :


1
2
3
4
5
6
7
8
9
10
11
12

architectureBehavioralofCounter2_VHDLis
signaltemp:std_logic_vector(3downto0);
begin
process(Clock,Reset)begin
ifReset='1'then
temp<="0000";
elsif(Clock'eventandClock='1')then
ifen='1'then
iftemp="1001"then
temp<="0000";
else
temp<=temp+1;

III.Compteur/dcompteurBCD sur deux digits


Nous cherchons maintenant modifier le compteur de l'exercice prcdent pour qu'il
soit capable, l'aide d'une entre supplmentaire DU, de compter et de dcompter en
BCD.
Travail raliser
Exo3 : Remplacer le compteur BCD de l'exercice 2 par un compteur/dcompteur BCD
cascad comme dans la figure ci-dessous :

ud
en

ud
en

ud
s_en en
CmptBCD
CmptBCD
Init
Init
enout
s_Q23
s_Q23 clk enout
clk

Init

lent

clk

horloge Q(19) Q(23)


h_sel h_lente

C9

224
horl_1

4
4
entreeFort
entreeFaible
sel multiplexeur
Affichage
4
binary

transcod7segs

FPGA

Affs7seg
sel

s7segs(6 downto 0)

30/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

La ralisation du compteur/dcompteur BCD pourra partir du morceau de code donn


dans ce lien :
http://fr.wikibooks.org/wiki/TD5_VHDL_et_CAO#El.C3.A9ments_d.27implantation_en_VHD
L

Quand tout fonctionne correctement mettre de ct pour une


utilisation dans l'exercice suivant
IV.Du graphe d'volution au graphe d'tats (pour information)
Nous avons abord les graphes d'volution pour nous intresser maintenant aux
graphes d'tats.

Key=0

Key=1

Key=1
Ring=0

Ring=0

Off
Off

Armed

Off

Off

Ring=0

Ringing

Armed
Ring=1

Armed

La transition devient rceptive, c'est dire qu'elle dcrit ce qui se passe quand la
rceptivit est vraie et quand la rceptivit est fausse (donc suppression des oreilles de
Mickey)
Prparation

INFO

Relire le cours p136 141 sur la programmation d'une machine tats pour
essayer de comprendre comment programmer un graphe d'tats.

V. Le compteur de passages
Un ensemble de deux capteurs infrarouge peroit le passage d'une personne et en fonction de son
sens de passage incrmente ou dcrmente un compteur qui dcod affiche le nombre de
personnes sur deux afficheurs 7 segments.
Il nous faudra comme composants :
deux compteurs-dcompteurs dcimaux (cascads) ainsi que la logique d'affichage. C'est ce que
l'on a fait dans l'exercice exo3 prcdent.
une logique de contrle pour dtecter le sens de passage
Seule la logique de contrle est spcifie l'aide d'un graphe d'volution que voici.

31/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

init

TD et TP LO11

sequenceur
Init='1'

S1

Gauche='0'

S3

Gauche='1'
Gauche='0''

DU<='1'
EN<='1'

S4
='1'

Gauche='1'

='1'

Droite='1'
DU<='1'
EN<='0'

S6

clk_1Hz

du

DU<='0'
EN<='0'
Droite='0'
Droite='1'
Droite='0'
DU<='0'
S5
EN<='1'

DU<='1'
EN<='0'

S2

en

DU<='0'
EN<=01'
Gauche='1'

Droite='1'

UTT 2014/2015

DU<='0'
EN<='0'

S7

Remarques :
En cours p 137, les actions sont notes dans les tats. Il n'y a aucune diffrence entre les deux
notations.
Ce graphe ne fonctionne qu'avec un compteur qui compte quand "en" est un.
On appellera ce graphe d'volution squenceur ou machine tats
clk_lente

droite
gauche
Init

clk machine_a_etat
d
g
Init
divfreq

clk_50MHz
C9

clk

compteurbcd
compteurbcd
UD
UD
endiz
En
En
enout
enout
Init
Init

UD ud
En en

222

Q(17)
Q(23)
clk_out2 clk_out1

Compteur/dcompteur BCD
clk

clk_lente

unit

mux

addr
'1'

FPGA

en
clk

e0
sel

sel

clk
s

e1

dizaine

s
4

addr

mem

data(7 downto 0)
s(7 downto 0)

selaff

Compteur de passages

32/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Prparation
Que se passe-t-il si Droite et gauche arrivent en mme temps ? Modifier le graphe
d'volution pour grer seulement le cas Droite='1'&Gauche='0' d'une part et
Gauche='1'&Droite='0' d'autre part.
(Optionnel) Chercher le graphe d'tats correspondant au problme partir du graphe
d'volution donn.
(Optionnel) crire les quations de rcurrence faisant intervenir l'entre d'initialisation "Init" si vous
dsirez les utiliser, autrement passer directement la section suivante.
Travail raliser
Exo 4 :
Programmer directement avec un style "case when" votre squenceur.
On vous demande d'implanter le graphe d'tats en lui ajoutant l'ensemble compteur dcompteur de
l'exo 1 prcdent (et le processeur pour l'horloge lente).
Vous trouverez aussi une trs grande partie du code de ce squenceur dans le lien :
http://fr.wikibooks.org/wiki/TD5_VHDL_et_CAO#El.C3.A9ments_d.27implantation_en_VHDL
Je retiens :
Voici en condens comment on programme un graphe d'volution en style deux process :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

typestateis(S1,S2,S3,S4,S5,S6,S7);
signalnext_etat,reg_etat:state;
cettepartiedpenddugraphed'tat:ellegrelestransitions
combinatoire:process(etat,d,g)begin
caseetatis
whens1=> if(d='1'andg='0')then
next_etat<=s2;
elsif(g='1'andd='0')then
next_etat<=s3;
else
next_etat<=s1;
endif;
when s2=> ....
...............
whenothers=>next_etat<=s1;
endcase;
endprocess;
cettepartienechangepastantqueresetestasynchrone
sequenceur:process(clk,reset)begin
ifreset='1'then
etat<=s1;
elsifrising_edge(clk)then
etat<=next_etat;
endif;
endprocess;
cettepartiegrelessortiesavec"whenelse"ou"withselectwhen"
en<='1'whenetat=s4else
'1'whenetat=s5else
'0';

33/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

VI.Un compteur de passages un peu plus sophistiqu


On cherche maintenant raliser ce mme squenceur mais en donnant la possibilit
aux personnes de faire demi-tour entre les deux capteurs (c'est dire de changer
d'avis).
Travail raliser
Exo5 : Montrer qu'un graphe d'tat de 9 tats est ncessaire pour grer ce problme.
crire les quations de rcurrence ou implanter avec un "case when" puis tester.

34/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

TP7 Initialisation l'assembleur AVR Tiny861

INFO

Le soft-processeur AVR Tiny861 est dtaill partir de la page 305 du


polycopi de cours... et les instructions partir de la page 310.

A partir de maintenant, nous allons utiliser un processeur dans nos FPGA. Le processeur
sera compltement fourni en VHDL : il s'agit d'un AVR compatible Tiny861 de chez
ATMEL.
Vous pouvez le trouver directement dans le fichier ressource LO11 du site "perso
moutou" dans le rpertoire TP7/Tiny861. On donnera le fichier microcontroleur.bit

I. Architecture
Architecture des registres mmoires
Il existe 3 espaces distincts en mmoire :
- Les 32 premires adresses correspondent aux 32 registres. Ces registres sont
directement relis l'ALU et tous les calculs ne peuvent tre effectus qu' partir de ces
registres (addition, soustraction, multiplication, oprations logiques, tests ).
- L'espace IO de l'adresse 0x20 0x5F. Dans cet espace se trouvent beaucoup de
registres de gestion du matriels (les ports, Timers, UART,...). Pour accder ces
registres les instructions in et out utilisent l'adresse 0 pour le premier registre et non
l'adresse 0x20. Les instructions cli et sbi permettent de mettre 0 ou 1 un bit d'un
registre
- Enfin partir de l'adresse 0x60 se trouve la mmoire proprement parler (le Tiny861
possde 512 octets de RAM). Pour accder tout l'espace mmoire (Registre et zone I/O
incluse) les instructions ST,LD et STS et LDS peuvent tre utilises. L'adressage peut
tre direct (STS ou LDS) ou indirect (ST et LD). Un adressage indirect utilise les registres
X, Y ou Z (respectivement les registres R27:R26, R29:R28 et R31:R30) pour pointer sur
une zone mmoire.
Quelques registres importants du banc de registres
Ce tableau (partiel) des registres respecte les fichiers d'inclusion du compilateur avr-gcc.
Par exemple, dans la documentation officielle, le bit b0 du PORTB s'appelle PORTB0
tandis que dans le fichier d'inclusion du GNU-C il s'appelle PB0.
Comme vous pouvez le constater, chaque registre est caractris par deux adresses.
Chacune des deux adresses est espace de 0x20=32. C'est le nombre de registres
usage gnral.
Notez que le fichier d'inclusion avr/io.h que l'on utilisera trs vite utilise les nombres qui
ne sont pas entre parenthses :
1
2
3
4

/*PortB*/
#definePINB _SFR_IO8(0x16)
#defineDDRB _SFR_IO8(0x17)
#definePORTB _SFR_IO8(0x18)
35/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

Bit 6

UTT 2014/2015

Addr

Name

Bit 7

Bit 5

Bit 4

Bit 3

Bit 2

Bit 1

0x3F(0x5F)

SREG

0x32(0x52)

TCTN0L

0x2F (0x4F)

TCCR1B

CS11

CS10

0x2E (0x4E)

TCTN1

Timer1 8 bits

0x2D (0x4D)

OCR1A

Comparaison Timer1 8 bits

0x2C (0x4C)

OCR1B

Comparaison Timer1 8 bits

0x1B(0x3B)

PORTA

PC7

PC6

PC5

PC4

PC3

PC2

PC1

PC0

0x1A(0x3A)

DDRA

DDC7

DDC6

DDC5

DDC4

DDC3

DDC2

DDC1

DDC0

0x19(0x39)

PINA

PINC7

PINC6

PINC5

PINC4

PINC3

PINC2

PINC1

PINC0

0x18(0x38)

PORTB

PB7

PB6

PB5

PB4

PB3

PB2

PB1

PB0

0x17(0x37)

DDRB

DDB7

DDB6

DDB5

DDB4

DDB3

DDB2

DDB1

DDB0

0x16(0x36)

PINB

PINB7

PINB6

PINB5

PINB4

PINB3

PINB2

PINB1

PINB0

0x14(0x34)

TCNT0H

0x05 (0x25)

ADCH

0x04 (0x24)

ADCL

0x03(0x23)

UDR

0x02(0x22)

UCSRA

RXC

TXC

UDRE

FE

DOR

PE

U2X

MPCM

0x010x21)

UCSRB

RXCIE

TXCIE

UDRIE

RXEN

TXEN

UCSZ2

RXB8

TXB8

0x00(0x20)

TCCR1E

--

--

OC1OE5 OC1OE4 OC1OE3 OC1OE2 OC1OE1 OC1OE0

Bit 0

Timer0 8 bits poids faible

CS13

CS12

Timer0 8 bits : poids fort

Registre de donnes USART I/O

Les registres marqus en rouge n'existent pas dans l'AVR Tiny861. En


gnral ils grent la liaison srie dans les autres familles. On les
implantera quand mme si besoin. Cela nous permettra d'utiliser des
routines qui fonctionnent sur un Arduino par exemple.

36/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

II.Schma de l'implantation dans le FPGA


a

Afficheurs
f
e

LEDs

g
c
d

J4"B11""D14""B16""C4""A11""C14""A16""E13"

Sel a b c d e f g

PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0

PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0

PORTB

PORTA

Tiny861
J5"A8""G9""D12""C12"

PINA

S3E"N17""H18""L14""L13"

Interrupteurs

III.Comment mettre un programme en ROM/RAM


Commenons par nous poser la question de savoir comment on peut compiler un
programme en langage assembleur ?
Le lien suivant dcrit plus en dtail les problmes et les solutions :
https://fr.wikiversity.org/wiki/Very_High_Speed_Integrated_Circuit_Hardware_Description_
Language/Embarquer_un_Atmel_ATMega8#Annexe_I_.28transformer_un_fichier_HEX_en_
VHDL.29
L'assemblage
L'assemblage se fait en ligne de commande. Son objectif est de raliser un fichier au
format elf.
Voici un exemple de commande :

37/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

avr-gcc -mmcu=attiny861 exo1.S -o exo1.elf

Nous avons dcid d'utiliser avr-gcc pour assembler (au lieu de avr-as). Cette
dcision a des consquences que nous n'expliquerons pas ici.
Programmation de la mmoire programme
La programmation de la mmoire programme peut tre ralise de plusieurs manires.
Si la manire la plus simple reste la transformation du programme en fichier VHDL, nous
n'utiliserons pas cette mthode bien trop lente : elle ncessite une recompilation globale
du projet, ce qui peut prendre quelques minutes. Nous allons plutt utiliser un utilitaire
data2mem comme indiqu dans la figure ci-aprs.
La commande qui fait cela est :
data2mem -bm memory.bmm -bd demo.elf -bt microcontroleur.bit -o uh microcontroleur

qui construit partir du fichier microcontroleur.bit (rsultat de la compilation de l'ISE) un


ficher microcontroleur_rp.bit : c'est ce deuxime fichier que l'on va envoyer dans le
FPGA. Cette commande ncessite un fichier memory.bmm qui sera fourni et d'ajouter
quelques contraintes importantes dans le fichier ucf :
INST prgmem/Mrom_PM_Drd_mux00001 LOC = RAMB16_X1Y2;
INST prgmem/Mrom_PM_Drd_mux00002 LOC = RAMB16_X0Y3;
INST prgmem/Mrom_PM_Drd_mux00003 LOC = RAMB16_X1Y3;
INST prgmem/Mrom_PM_Drd_mux00004 LOC = RAMB16_X0Y2;

Ces contraintes sont dj prsentes dans le fichier ucf donn dans les ressources mais
sont en commentaires.
Le fichier memory.bmm ncessaire contiendra :
ADDRESS_SPACE prgmem RAMB16 [0x00000000:0x00001FFF]
BUS_BLOCK
prgmem/Mrom_PM_Drd_mux00002 [7:4] PLACED = X0Y3;
prgmem/Mrom_PM_Drd_mux00001 [3:0] PLACED = X1Y2;
prgmem/Mrom_PM_Drd_mux00004 [15:12] PLACED = X0Y2 ;
prgmem/Mrom_PM_Drd_mux00003 [11:8] PLACED
END_BUS_BLOCK;
END_ADDRESS_SPACE;

Voici donc schmatiquement comment cela se passe.

38/94

= X1Y3;

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

s3e.ucf
dm.vhd
pm.vhd
microcontroleur.vhd

ISE

attiny861.bmm

UTT 2014/2015

prog.c
prog.S

avr-gcc

data2mem Xilinx
Utility

prog.elf

microcontroleur.bit

Chane de
compilation de
programme

Impact

Chane de
compilation Xilinx
Utilisation de data2mem
Prenez un peu de temps examiner cette figure. Il est important de toujours savoir ce
que l'on fait exactement mme sans en connatre les raisons exactes. Un script peut
faire tout cela de manire automatique :
#!/bin/bash
export PATH=$PATH:/usr/bin:/opt/Xilinx/11.1/ISE/bin/lin
cp ../microcontroleur.bit .
avr-gcc -mmcu=attiny861 exo1.S -o exo1.elf
data2mem -bm attiny861.bmm -bd exo1.elf -bt microcontroleur.bit -o uh

microcontroleur

# commentez ligne suivante si pas ADEPT installe comme en TP LO11


# djtgcfg prog -d DCabUsb --index 0 --file microcontroleur_rp.bit

INFO

Ce script ralise la compilation, la transformation du fichier .bit avec le


nouveau programme. Il est sens fonctionner dans un sous-rpertoire du
projet (d'o le cp)
Votre fichier bmm s'appelle attiny861.bmm

Nous allons mettre en pratique tout ce que nous venons d'expliquer.


39/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

IV.Travail introductif
Comprendre la notion de PORT d'entre et de PORT de sorties
Voici un premier exemple de programme assembleur
#define __SFR_OFFSET 0 //obligatoire pour fonctionnement correct de "out" et "in"
.nolist
#include <avr/io.h>
.list
.section .text

; denotes code section

.global main
main:
;

LDI

R16, 255

; load R16 with 255

OUT

DDRB, R16

; set all bits of port B as output

LDI

R16, 2

; load R16 with 2

LDI

R17, 4

; load R17 with 4

ADD

R16, r17

; R16 <- R16 + R17

IN

R16, PINA

; lecture des switch

OUT

PORTA, R16

; resultat dans port A = LEDs

RJMP

main

; on recommence RJMP=GOTO

.END

Ce programme ne fait que recopier l'tat des interrupteurs (PINA) sur les LEDs (PORTA).
Un certain nombre d'instructions ont t volontairement laisses en commentaire (qui
rappelons-le, commencent par un ; ). Intressez-vous seulement ce qu'il y a entre
main : et .END
Indications
Opration

Mnemonics Operands Description

ADD

Rd, Rr

Flags

#Clocks

Additionne deux
registres

Rd Rd+Rr

Z,C,N,V,H

Charger en immdiat

Rd K

None

LDI

Rd, K

IN

Rd, Port Lecture d'un port

Rd Port

None

OUT

Port, Rr Ecriture dans un Port

Port Rr

None

RJMP

Saut relatif

PC PC + k + 1

40/94

None

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

L'entre pour un processeur du commerce comme celui qui est propos


ici se fait toujours par
IN

R16, PINA ; et non pas IN R16,PORTA

Travail raliser
Faites tourner le programme ci-dessus dans votre processeur (qui sera dans le FPGA).
Si vous avez souvenir de quelques instructions assembleur, vous pouvez essayer de
faire autre chose que la recopie sur vos LEDs

V.Travaux pratiques
Travail raliser (Exercice 1)
On ralisera un programme qui ralise une addition de 255 et de 1 et qui sort le registre
de statut (SREG) sur les Leds (PORTA). Si vous voulez savoir ce qui sort, la seule
solution est de sortir dans PORTB sur les afficheurs 7 segments.
Indication : Le registre SREG peut tre accd comme un PORT par les instructions IN
et OUT.

Travail raliser (Exercice 2)


Load R16 and R17 with two numbers and study the results and status flags (in SREG)
generated by the following operations.
COM

R16

; Complement

NEG

R16

; 2's complement

TST
AND
OR
ADD

R16

; test for zero or minus

R16, R17
R16, R17
R16, R17

; bitwise AND
; bitwise OR
; summing

Indications : Un des deux registres peut tre charg l'aide des interrupteurs.
Mnemonics Operands Description

ADD

Rd, Rr

Opration

Flags

Additionne deux
registres

Rd Rd+Rr

Z,C,N,V,H

#Clocks
1

AND

Rd, Rr

Registres du ET
logique

Rd Rd * Rr

Z,N,V

ANDI

Rd, K

Registres du ET
logique et constante

Rd Rd * K

Z,N,V

OR

Rd, Rr

Registres du OU
logique

Rd Rd v K

Z,N,V

41/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

ORI

Rd, K

Registres du OU loque Rd Rd v K
et constante

Z,N,V

EOR

Rd, Rr

Registres du OU
exclusif

Rd Rd Rr

Z,N,V

COM

Rd

Complment logique

Rd 0xFF - Rd

Z,C,N,V

NEG

Rd

Rd 0x00 - Rd

Z,C,N,V,H

TST

Rd

Rd Rd * Rd

Z,N,V

Ngation
Test du zero ou du
mini

Travail raliser (Exercice 3)


Add a number and it's 2's complement, do the same with 1's complement and compare the results
LDI

R16, 10

MOV

R17, R16

NEG

R16

ADD

; load number
; 2's complement

R17, R16

Indication :
Mnemonics Operands Description

MOV

Rd, Rr

Opration

Copier un registre
dans un autre

Rd Rr

Flags

#Clocks

None
1

Travail raliser (Exercice 4)


On vous demande de raliser un compteur binaire qui sort sur des LEDs. La seule
difficult de cet exercice est de raliser une temporisation.
Indication : essayer de comprendre et d'utiliser ce code :
delay:
ldi r24, 0xff

; load 0xffff to r24:25

ldi r25, 0xff


delayloop:
sbiw r24,1
brne delayloop

; decrement r25:r24 a cause du w


; branch if not 0

ret

Montrer qu'un tel delay est encore trop rapide. Pour avoir un temps correct il faudra le
faire environ 0x40 fois.
Indication 2 :

42/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

Mnemonics Operands Description

SUB

Rd, Rr

Opration

UTT 2014/2015

Flags

Soustraire deux
registres

RdRd - Rr

Z,C,N,V,H

#Clocks
1

SUBI

Rd, K

Soustraire les
constantes de deux
registres

RdRd - K

Z,C,N,V,H

SBIW

Rdl, K

Soustraction
immdiate du mot

Rdh:RdlRdh:Rdl - K

Z,C,N,V,S

BRNE

Brancher si non gal

if(Z=0) then PC PC None


+ k +1

INC

Rd

Incrmente

Rd Rd + 1

Z,N,V

DEC

Rd

Dcrmente

Rd Rd - 1

Z,N,V

BRNE

Brancher si non gal

RET
RCALL

if(Z=0) then PC PC None


+ k +1

Retour d'un sousprogramme

PC STACK

None

Appel du souprogramme relatif

PC PC + k + 1

None

Indication 3 :
delay:
ldi r23, 0x40 ; sur Spartan3e
delayloop_ext:
ldi r24, 0xff

; load 0xffff to r24:25

ldi r25, 0xff


delayloop:
sbiw r24,1

; decrement r25:r24 a cause du w

brne delayloop
dec

; branch if not 0

r23

brne delayloop_ext
ret

Travail raliser (Exercice 5)


On vous demande de rechercher les instructions mettre en uvre pour la ralisation
de chenillards et de raliser les programmes correspondants.
1) Raliser un chenillard simple avec l'instruction lsl en dtectant la disparition du
'1'.
43/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Indication : Si l'instruction lsl est applique dans une boucle, le '1' finit par
disparatre !!!!
Mnemonics Operands Description

Opration

Flags

#Clocks

LSL

Rd

dcalage gauche

Rd(n+1)Rd(n),Rd(0)
0

Z,C,N,V

LSR

Rd

dcalage droite

Rd(n)Rd(n+1),Rd(7) Z,C,N,V
0

BRNE

Brancher si non gal

if(Z=0) then PC PC None


+ k +1

2) Raliser ce mme chenillard en initialisant la SRAM avec un code du style :


main:
; setup : initialisation de la SRAM
LDI R16,0x01
STS 0x0060,R16 ; debut mmoire SRAM ATtiny861
LDI R16,0x02
STS 0x0061,R16

Puis aller chercher sans arrt ces valeurs dans la RAM avec l'instruction LD R16,Y+
sachant que Y=R29:R28.
Indications : La SRAM dans un ATMega8/16 va de l'adresse 0x0060 0x045F. La SRAM
d'un ATTiny26/46/86 commence partir de l'adresse 0x0060. Sa fin dpend de la srie
(128/256/512 octets) 0x0DF/0x015F/0x25F
Mnemonics Operands Description

Opration

LDI

Rd, K

Charger en immdiat

STS

K, Rr

Stockage direct de
SRAM

Flags

#Clocks

Rd K

none

(k) Rr

None

44/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Un algorithme est donn sous forme d'organigramme ci-dessous.

Initialisation RAM

LDI / STS

Initialisation Y

CLR R29
LDI R28,0x60

R16 [ Y++]

LD R16,Y+

R28 = 0x68 ?

CPI R28,0x68
BRNE suite

R28 0x60

PORTA R16

DELAY

RCALL delay

3) Ralisez les chenillards que vous dsirez (K2000 ou autre) avec la technique de votre
choix.

VI.ANNEXE : Pour information


L'espace d'adressage mmoire comprenant les registres gnraux, les SFR (Special
Function Registers) et la RAM peut rserver quelques surprises. On peut utiliser deux
instructions pour accder aux SFR : OUT et STS
Si on utilise
1
2

#define__SFR_OFFSET0
#include<avr/io.h>

alors on peut crire :


OUT PORTC, R16

mais
STS PORTC+0X20,R16

45/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Si on utilise seulement
1

#include<avr/io.h>

alors on crit :
OUT PORTC-0x20, R16

mais
STS PORTC,R16

Nous prfrons la premire solution et nous vitons du coup d'utiliser STS pour les SFRs.

46/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

TP8 Assembleur et RS232 (Transmission)

INFO

Le soft-processeur AVR Tiny861 est dtaill partir de la page 305 du


polycopi de cours... et les instructions partir de la page 310.... et les
priphriques de sortie en page 317, 318.

I. Introduction RS232 (tire d'Internet)


Les liaisons sries asynchrones sont trs utilises. La plus connue est celle qui est
utilise sur les PC. Asynchrone signifie que les donnes sont envoyes de l'metteur
vers le rcepteur sans ngociation pralable. C'est au rcepteur de se synchroniser sur
l'metteur. Pour ce faire l'metteur doit envoyer un bit de START ses donnes(de 5 8
bits) suivies ou non d'un bit de parit et de 1 ou plusieurs bits de stop. Pour qu'une
liaison srie fonctionne, il est ncessaire de configurer les 2 extrmits pour qu'elles
utilisent la mme parit, le mme nombre de bits de stop (1 1,5 ou 2) la longueur des
donnes changes (5,6,7, ou 8 bits).
La norme RSC232 dfinit les valeurs des tensions que doivent fournir et reconnatre les
interfaces sries des matrielles.

Un 0 logique est reconnu pour une tension allant de +8 +40V.


Un 1 logique est reconnu pour une tension allant de -8 -40V.

Gnralement, les signaux envoys sont compris entre -12 et + 12 V.


Sur une liaison srie au repos on doit observer un 1 logique.
Pour faire un change de donnes bidirectionnel entre 2 liaisons sries il faut au
minimum 3 fils.

Un pour les donnes qui circulent dans un sens.


Un pour les donnes qui circulent dans l'autre sens.
Un pour la masse lectrique des signaux.

Cette liaison a 3 fils est une liaison minimum. Elle ncessite une collaboration logicielle
active entre les 2 machines pour contrler le transfert des informations. Un mcanisme
souvent utilis est le protocole XON XOFF.
Notre hyperterminal sera gtkterm configur comme ci-dessous ( part peut-tre le
PORT) :
PORT :/dev/ttyS1, vitesse : 19200, Parit : none, Bits 8, Bit de stop : 1, contrle de flux :
none
N'oubliez pas de dfinir serial_out dans votre fichier ucf : un des signaux ci-dessous :
# ==== RS-232 Serial Ports (RS232) ====
NET "RS232_DCE_RXD" LOC = "R7" | IOSTANDARD = LVTTL ;
NET "RS232_DCE_TXD" LOC = "M14" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = SLOW ;
#NET "RS232_DTE_RXD" LOC = "U8" | IOSTANDARD = LVTTL ;
#NET "RS232_DTE_TXD" LOC = "M13" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = SLOW ;
47/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

II.Ralisation pratique
Ce que l'on va faire maintenant ne peut tre ralis qu'avec un processeur dans un FPGA
ou ASIC. Car :
Sur le tiny861 du commerce, il n'y a pas de liaison srie. Nous allons en
ajouter une en utilisant des registres qui ne sont pas destins cela dans
le processeur du commerce.

1) Un Logicore pour ne pas rinventer la roue


On vous donne l'ensemble matriel qui ralise la partie transmission de la liaison srie.

en_16_x_baud

uart_tx
bbfifo_16x8

data_in
write_buffer
reset_buffer

data_in
write
read
reset
clk

data_out
data_present
full
half_full

kcuart_tx
data_in
send_character
en_16_x_baud
clk

serial_out

serial_out

tx_complete
buffer_full
buffer_half_full

clk

Le schma ci-dessus fait apparatre 3 rectangles, il est donc compos de trois entits
(dont les noms sont en gras) et de trois architectures. La partie gauche est un buffer de
16 donnes de 8 bits : si vous insrez les trois fichiers dans votre projet, la connexion
indique dans le schma ci-dessus est toute faite. On peut trouver ces fichiers dans les
ressources tlchargeables dans le site perso de S.Moutou.
2) Raliser l'horloge "en_16x_baud" de la liaison srie
Ceci sera ralis comme indiqu dans le schma un peu plus loin.
Exercice de prparation
Le compteur mod_m_counter est configurer. Pour se faire, il faut savoir que l'on va
travailler 19200 bauds et que la frquence d'horloge est de 50 MHz. En dduire la
valeur mettre dans le generic de ce compteur.

INFO

Si pour une raison ou une autre, on a t oblig de mettre la frquence


du processeur 25MHz, gardez le nombre calcul et travaillez alors
9600 bauds.

48/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

Init
clk_50MHz

TD et TP LO11

clk

reset
clk

en

max_tick

q(N-1 downto 0)

uart_tx
reset_buffer
en_16_x_baud

mod_m_counter

open

UTT 2014/2015

data_in

clk
write_buffer
serial_out

buffer_full
buffer_half

open
open

serial_out
Une fois le compteur connect il faut se pencher sur l'interfaage de l'ensemble comme
un registre.
3) Comment interfacer des PORTs/Registres dans l'ATTiny861
La ralisation des PORTs PORTA et PORTB utiliss dans le TP prcdent se fait dans un
process que l'on trouve dans microcontroleur.vhd
L'ide gnrale est simple : un grand case qui slectionne les sorties en fonction des
adresses. Dans notre cas particulier on voit sur le dessin qu'il faut que l'on s'occupe de
"data_in" et de "write_buffer". Le mieux est de :
- relier "data_in" "IO_Dwr" sans condition
- relier "en" "IO_wr" quand l'adresse est celle de UDR avec une criture du type :
s_en <= IO_wr when (IO_A = UDR) else '0'; -- write UART UDR (UDR constante
-- prdfinie)
en dehors du case et des process.
4) Travail raliser (exercice 1)
Raliser la partie matrielle demande et montrer que l'on peut envoyer un caractre
constant (pas trop vite quand mme).
Indication : L'envoi d'un caractre par la liaison srie se fait par la simple instruction :
OUT UDR,R16

Mais ceci ncessite de dfinir UDR pour l'assembleur ! Voici comment on fait :
#define UCSRB

_SFR_IO8(0x01)

#define UCSRA

_SFR_IO8(0x02)

#define UDR

_SFR_IO8(0x03)

// UCSRA
#define RXC 7
#define TXC 6
#define UDRE 5
//UCSRB
#define RXEN 4
#define TXEN 3

49/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

#define __SFR_OFFSET 0 //obligatoire pour fonctionnement correct de "out" et "in"

Un moyen de faire une attente d'environ 1 seconde est :


delay:
ldi r23, 0x40

; 0x80 sur Nexys3 mais probablement 0x40

l'UTT

delayloop_ext:
ldi r24, 0xff

; load 0xffff to r25:r24

ldi r25, 0xff


delayloop:
sbiw r24,1

; decrement r25:r24

brne delayloop
dec

; branch if not 0

r23

brne delayloop_ext
ret

On testera les communications avec gtkterm (application Linux) configur comme cidessous ( part peut-tre le PORT) :
PORT :/dev/ttyS0, vitesse : 19200, Parit : none, Bits 8, Bit de stop : 1, contrle de flux :
none
Voici en dessin ce que l'on cherche faire :

microcontroleur.vhd

iowr: process(I_CLK)
PORTA
IO_DWr[7:0]
PORTB

clk
rst
sw[7:0]
in_PINB[7:0]

leds[7:0]
Aff7segs[7:0]

IO_A[5:0]
rst
rst

mod_m_counter

reset
clk

max_tick

q(N-1 downto 0)

open

uart_tx
reset_buffer
en_16_x_baud
clk

write_buffer
serial_out
s_en
s_en <= IO_wr when (IO_A = UDR) else '0';

50/94

8
serial_out

data_in
buffer_full
buffer_half

open

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

5) Travail raliser (exercice 2)


On veut amliorer le travail de l'exercice 1 pour grer un peu mieux la liaison srie. Un
peu mieux veut dire ici que l'on cherche se rapprocher de ce qui est fait dans un AVR
du commerce (ATMega8 par exemple).
1) Raliser la partie matrielle complte en grant le bit TXEN du registre UCSRB.
L'criture dans le registre UDR devra envoyer par la liaison srie. De plus, les bits UDRE
et TXC du registre UCSRA seront relis au complment de "buffer_full". Pour simplifier,
les registres UCSRB et UDR seront en criture seulement et UCSRA sera en lecture
seulement.
Indications : On avait en exercice 1 :
- relier "en" "IO_wr" quand l'adresse est celle de UDR avec une criture du type :
s_en <= IO_wr when (IO_A = UDR) else '0'; -- write UART UDR (UDR constante
-- prdfinie)
On doit avoir maintenant :
s_en <= IO_wr and s_UCSRB(3) when (IO_A = UDR) else '0'; -- write UART UDR
car TXEN est le bit b3 du registre UCSRB.

microcontroleur.vhd

iowr: process(CLK)
PORTA
IO_DWr[7:0]
PORTB

clk
rst
sw[7:0]
in_PINB[7:0]

leds[7:0]
Aff7segs[7:0]
s_UCSRB

UCSRB
IO_A[5:0]
rst
rst

mod_m_counter

reset
clk

max_tick

q(N-1 downto 0)

open

uart_tx
reset_buffer
en_16_x_baud
clk

write_buffer
serial_out
s_en

8
serial_out

data_in
buffer_full
buffer_half

open

s_en <= IO_wr and s_UCSRB(3) when (IO_A = UDR) else '0';
Il manque le process "iord" qui est donn
- TXC et UDRE sont les bits b6 et b5 du registre UCSRA et la partie VHDL qui gre ce
registre ressemblera donc :
1

iord:process(IO_rd,IO_A,In_PINB,sw)
51/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

2
3
4
5
6
7

TD et TP LO11

UTT 2014/2015

begin
addressesfortinyX6device(useiom8.h).

ifIO_rd='1'then
caseIO_Ais
whenUCSRA=>IO_Drd<=('0'&nots_full&nots_full&"00000");

avec le dessin correspondant (laissez tomber TXC si vous voulez) :

microcontroleur.vhd
iord: process

uart_tx
data_in
write buffer buffer_full

s_full

reset
clk

open

buffer_half_full

not s_full (6)


not s_full(5) UCSRA[7:0]
PINB[7:0]

Initialisation RS232
2) Raliser un programme qui lit
sans arrt les switchs et envoie
sur la RS232 leur valeur
seulement lorsqu'ils ont chang.
Pour raliser cet exercice vous
allez procder en deux temps :

LDI R16, (1<<TXEN)


OUT UCSRB,R16

Initialisation R17

R17 contient les


anciennes valeurs
des interrupteurs

R16 PINA

R16 contient les


nouvelles valeurs
des interrupteurs

2-1) Raliser un programme qui lit


sans arrt les interrupteurs et
envoie un '1' lorsqu'ils ont chang
(et seulement dans ce cas).
L'envoi du '1' se fera par un sousprogramme. Bien faire la
distinction entre '1' et 1 !!!!
Indication : il faut rserver un
registre pour l'ancienne valeur
des interrupteurs et un pour la
nouvelle de manire pouvoir
comparer. En fin de boucle ne pas
oublier de mettre la nouvelle
valeur dans l'ancienne. Ceci est
expliqu dans l'organigramme cicontre.

IO_Drd

R16 = R17 ?

APPEL envoi_serie

CP R16,R17
BREQ suite

RCALL serial_tx

R17 R16

Retour au debut boucle RJMP loop

52/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

2-2) Modifier le sous programme serial_tx pour qu'il envoie maintenant deux
caractres correspondant la valeur hexadcimale des interrupteurs.
Indication : voici comment on procde l'envoi d'un caractre hexadcimal
correspondant la valeur des poids faibles :
;**** poids faible
MOV R18,R16 ; pour garder la valeur de R16
ANDI R18,0x0F
CPI

R18,0x0A

BRGE ss_3 ; if greater or equal


LDI R19,'0'; code ASCII de '0'
ADD R18,R19
RJMP ss_4
ss_3:
LDI R19,'A'-0x0A ; code ASCII de 'A'-A
ADD R18,R19
ss_4:
OUT UDR,R18

Faites la mme chose avec les poids forts. Le fin du fin serait d'ajouter un espace pour
sparer les futures valeurs. Essayez avec :
wait:
SBIS UCSRA,UDRE

;attente envoi prcdent termin bit UDRE

RJMP wait
LDI R18,' ' ; pour sparer la suite
OUT UDR,R18

Ou envoyer 0x0D suivi de 0x0A pour aller la ligne.


2-3) Pour simplifier la lecture par un tre humain normalement constitu, remplacer
l'affichage hexadcimal par du binaire. 0n peut faire aussi de la dco en plus :
+++++++++
|1|0|0|1|0|0|1|1|
+++++++++
Mnemonics Operands Description

Opration

Flags

BRCC

Brancher si la retenue if(C=0) then PC PC None


est 0
+ k +1

LSL

Rd

dcalage gauche

RetenueRd(n),
Rd(0) 0

53/94

#Clocks

Z,C,N,V
1

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

6) Travail raliser (exercice 3)


Raliser un compteur dcimal sur deux digits sortant par la liaison srie (avec une
temporisation bien sr).

54/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

TP9 Cration d'une rception RS232

INFO

Le soft-processeur AVR Tiny861 est dtaill partir de la page 305 du


polycopi de cours... et les priphriques d'entre en pages 317, 319.

I. Prsentation de la rception RS232


Par rapport au TP prcdent la liaison devra tre dans l'autre sens : c'est le PC qui
maintenant va fournir des valeurs au FPGA. La ralisation de cette liaison se fait
pratiquement comme dans le TP prcdent (_rx au lieu de _tx) :
uart_rx
kcuart_rx
bbfifo_16x8
serial_in serial_in
data_out
data_out
data_in
data_out
buffer_data_present
data_present
write
en_16_x_baud en_16_x_baud data_strobe
buffer_full
read
full
buffer_half_full
reset
clk
half_full
clk
read_buffer
reset_buffer
clk
On rappelle que les trois fichiers uart8_rx.vhd, kcuart8_rx.vhd et bbfifo_16x8.vhd
sont disponibles dans les ressources.
Travail raliser (exercice 1)
Modifier la partie matrielle de l'exercice 2 du TP prcdent pour raliser une rception
maintenant. Le bit RXEN du registre UCSRB autorisera la rception. Le registre UDR
sera maintenant en criture pour envoyer par la liaison srie, mais aussi en lecture pour
lire ce qui est arriv. De plus, le bit TXC du registre UCSRA sera reli au "data_present".
Indications
Le "read_buffer" est dcaler d'un front d'horloge : je lis "data_out" et j'envoie le signal
comme quoi j'ai lu l'aide de "s_buffer_read". Cela peut se raliser avec :
1
2
3
4
5
6

delay:process(clk)begin
ifrising_edge(clk)then
IO_rd_d<=IO_rd;
endif;
endprocess;
s_buffer_read<=IO_rd_dands_UCSRB(4)when(IO_A=UDR)else'0';read
UARTUDR

Une simple modification sera faite pour UCSRA (et UDR)


1

iord:process(IO_rd,IO_A,In_PINB,sw)
55/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

2
3
4
5
6
7
8

TD et TP LO11

UTT 2014/2015

begin
addressesfortinyX6device(useiom8.h).

ifIO_rd='1'then
caseIO_Ais
whenUCSRA=>IO_Drd<=(s_RXC&nots_full&nots_full&
"00000");
whenUDR=>IO_Drd<=s_in_UDR;

La partie logicielle d'essai pourra tre un simple echo :


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

#include"avr/io.h"
#undefF_CPU
#defineF_CPU50000000UL
#include"util/delay.h"

1
2
3
4
5
6
7
8
9
10

//************************************************************************
//functionuart_init()
//purpose:putcharacterinfirstrs232PORT
//arguments:
//correspondingcharacter
//return:
//note:19200,8,n,1hardcoded:transmissionandreception
//************************************************************************
voidusart_init(void){
UCSRB=(1<<TXEN)|(1<<RXEN);//transmissionetreception

#defineUCSRB _SFR_IO8(0x01)
#defineUCSRA _SFR_IO8(0x02)
#defineUDR _SFR_IO8(0x03)
//UCSRA
#defineRXC7
#defineTXC6
#defineUDRE5
//UCSRB
#defineRXEN4
#defineTXEN3
voidusart_init(void);
voidusart_send(unsignedcharch);
charusart_receive(void);
//***********************************************************************
//main
//***********************************************************************
intmain(void){
charch;
usart_init();
while(1){
//echosimple
ch=usart_receive();
usart_send(ch);
_delay_ms(500);//onverrapasserlescaractres
}
return0;
}

Les sous-programmes C donns ci-dessous devront tre vrifis pour un bon


fonctionnement.

56/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

TD et TP LO11

UTT 2014/2015

//UCSRC=(1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL);//ignorparnotrematriel
//UBBRL=0x33;//paspournouscar38400baudsSans8,2
}
//************************************************************************
//functionuart_receive()
//purpose:readcharacterinsecondrs232PORT
//arguments:
//correspondingcharacter
//return:nonblockingsubreturn1ifnodatapresentelsereturnchar
//note:19200,8,n,1hardcoded,nonblockingsubreturn0ifnodatapresent
//************************************************************************
charusart_receive(void){
while(!(UCSRA&(1<<RXC)));//attentetantquepasDataPresent
returnUDR;
}
//************************************************************************
//functionuart_send()
//purpose:putcharacterinfirstrs232PORT
//arguments:
//correspondingcharacter
//return:
//note:19200,8,n,1hardcoded
//initialisationuartprealablerequise
//************************************************************************
voidusart_send(unsignedcharch){
while(!(UCSRA&(1<<UDRE)));
UDR=ch;
}

Le schma raliser est prsent en page suivante.

57/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

microcontroleur.vhd

iowr: process(CLK)
PORTA
IO_DWr[7:0]
PORTB

clk
rst
sw[7:0]
in_PINB[7:0]
rst

UCSRB

mod_m_counter

reset
clk

max_tick

q(N-1 downto 0)

leds[7:0]
Aff7segs[7:0]
s_UCSRB
serial_out

s_en_16_x_baud
open

IO_A[5:0]

iord: process
uart_rx
serial_in serial_in
s_in_UDR UDR[7:0]
data_out
s_en_16_x_baud en_16_x_baud
s_buffer_read read_buffer buffer_data_present s_RXC(7)
IO_Drd
UCSRA[7:0]
rst
reset_buffer
buffer_full open

serial_in

buffer_half_full open

clk
IO_rd

IO_rd_d

clk
s_buffer_read <= IO_rd_d and s_UCSRB(4) when (IO_A = UDR) else '0';

La partie uart_tx du TP prcdent doit tre garde. On aura ainsi la fin


de ce TP une mission et rception srie.

II.Les chenillards et la RS232


On dsire maintenant reprendre le chenillard (exercice 5 du TP7), particulirement celui
qui utilisait une mmoire RAM pour s'excuter. Pour simplifier tout sera maintenant
ralis en C.
Travail raliser (exercice 2)
On cherche maintenant utiliser la rception RS232. L'objectif est de raliser le
chenillard normalement, sauf quand des donnes sont envoyes partir du PC. Elle sont
alors disposes dans la mmoire en lieu et place des anciennes valeurs. Pour simplifier
votre travail, on adoptera le protocole suivant : quand une donne arrive alors on sait
qu'il y en aura forcment 16 et on les attendra toutes les 16. Une fois termin on
retournera tranquillement notre chenillard.
N'oubliez pas la temporisation pour voir les chenillards.
Pour passer en mode programmation nous allons utiliser un interrupteur. En dbut de
chaque boucle la position de cet interrupteur est teste et s'il est positionn on se dirige

58/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

vers le programme de chargement. Un 'L' sera affich sur les afficheurs dans ce cas mais
un 'U' dans le cas d'un non chargement.
Raliser le programme complet : ce programme passe en mode programmation et
attend alors 16 donnes et les met dans la mmoire la place des autres.
Une fois que toute la partie matrielle est en place, il vous faut raliser un fichier binaire
de 16 valeurs pour remplir la RAM. On vous propose le fichier C++ suivant :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

/***tpmemo.cpp***/
#include<stdio.h>
#include<string.h>
charvalhex(characonv){
staticcharhex[17]="0123456789ABCDEF";
chari;
i=0;
while(aconv!=hex[i])i++;
returni;
}
main(){
FILE*sortie;
staticcharhexa[17]="0123456789ABCDEF";
chartrame[128],nomfichier[34];
unsignedcharnval,i,tab[255];
printf("****************************************************");
printf("\n*****Conversionvaleur>fichierIntelHEX*****");
printf("\n********TPprogrammationdememoires************");
printf("\n********Version0.1(S.Moutou&Cie)***********");
printf("\n****************************************************");
printf("\n\nCombiendevaleursvoulezvousentrer?");
scanf("%d",&nval);
for(i=0;i<nval;i++){
printf("%dvaleur(enhexadecimal):",i+1);
scanf("%x",&tab[i]);
}
printf("\nQuelestvotrenomdefichierdesauvegarde?(extension.bin)");
scanf("%s",nomfichier);
sortie=fopen(nomfichier,"w");
fwrite(tab,1,16,sortie);
fclose(sortie);
}

que l'on compile avec gcc tpmemo.c -o tpmemo


On le lance alors avec ./tpmemo :
[smoutou@localhost LO11]$ ./tpmemo
****************************************************
*****

Conversion valeur -> fichier Intel HEX

*****

********

TP programmation de memoires

************

********

Version 0.1 (S. Moutou & Cie)

***********

****************************************************
Combien de valeurs voulez-vous entrer ? 16
1 valeur (en hexadecimal) : 81
59/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

2 valeur (en hexadecimal) : 42


3 valeur (en hexadecimal) : 24
4 valeur (en hexadecimal) : 18
5 valeur (en hexadecimal) : FF
6 valeur (en hexadecimal) : 00
7 valeur (en hexadecimal) : FF
8 valeur (en hexadecimal) : 00
9 valeur (en hexadecimal) : 18
10 valeur (en hexadecimal) : 24
11 valeur (en hexadecimal) : 42
12 valeur (en hexadecimal) : 81
13 valeur (en hexadecimal) : 00
14 valeur (en hexadecimal) : FF
15 valeur (en hexadecimal) : 00
16 valeur (en hexadecimal) : FF
Quel est votre nom de fichier de sauvegarde ? (extension .bin) demo1.bin

Tester avec gtkterm configur comme ci-dessous :


PORT :/dev/ttyS0, vitesse : 19200, Parit : sans, Bits 8, Bit de stop : 1, contrle de flux :
none
Fichier -> envoi de fichier brut en cherchant votre fichier binaire cr.
Si tout fonctionne, vous obtiendrez un nouveau chenillard.

III.RS232 bidirectionnel pour commander les LEDs


Travail raliser (Exercice 3)
On dsire raliser un programme dans le picoBlaze qui soit capable de raliser les
oprations suivantes sur les LEDs, ordres envoys par la liaison RS232 l'aide de
GTKTerm.
clearall : teint toutes les leds
setall : allume toutes les leds
set led0 : allume la led 0
clear led1 teint la led 1
Aprs chacune de ces commandes l'tat des leds est systmatiquement envoy dans
GTKTerm avec un format de votre choix.

60/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

IV.Utiliser les afficheurs 7 segments


Travail raliser (exercice 4)
Raliser un compteur BCD sur les deux afficheurs. La commutation de l'affichage sur les
deux digits devra tre au-del de 25Hz pour viter les clignotements visibles l'il mais
le comptage proprement dit devra se faire aux envions du hertz pour tre visible l'il.
Le transcodage pourra tre fait avec un tableau.
Indications : on distinguera dans cet exercice la partie affichage de la partie comptage.
L'affichage sera ralis plusieurs fois pour prendre environ 1 seconde. Le comptage sera
fait dans une boucle infinie. Si vous voulez utiliser le sous-programme ci-dessous il faut
tout prix que celui-ci soit en BCD. En effet, l'indice du tableau nb &0x0F ne doit pas
dpasser 9 !
1
2
3
4
5
6
7

voidaffiche(uint8_tnb){
uint8_t tab[10]={0x3F,... a complter ....}; // segment a poids faible
uint8_t i; // compteur de boucle
for (i=0;i<25;i++) {
PORTB = tab[nb & 0x0F] & 0x7F; // mettre a 0 poids fort=selection
_delay_ms(????);
//continueraveclepoidsfort(unpeuplusdifficile?)

V.ANNEXE (pour les fans d'assembleurs)


Pour ceux qui dsireraient travailler en assembleur, l'organigramme du programme
raliser est prsent maintenant .

61/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

Initialisation RAM

Initialisation Y

TD et TP LO11

serial_rx

LDI / STS
CLR R29
LDI R28,0x60

Initialisation compteur boucle

R16 PINB

Pour flag Z

R16 = 0x00 ?

UTT 2014/2015

Initialisation X

ANDI R16,0xFF

Data present ? SBIS UCSRA,RXC


RJMP rcve
BREQ not_programming_mode
RCALL serial_rx
Lecture UDR

IN r16,UDR

not_programming_mode
R16 [ Y++]

R28 = 0x70 ?

[X+] r16
CPI R28,0x70
BRNE suite

ST X+,r16

Decompte boucle
DEC R17
BRNE rcve

R28 0x60

finit ?
RET

PORTC R16

DELAY

RCALL delay

Vous pourrez peaufiner ce code pour l'affichage demand : 'L' si chargement et 'U' dans
les autres cas.
PORT :/dev/ttyS0, vitesse : 19200, Parit : none, Bits 8, Bit de stop : 1,
contrle de flux : none

INFO

62/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

TP10 Liaison PS2 (Annul)

INFO

Le processeur AVR est prsent partir de la page 305 du polycopi de


cours.
Le protocole PS/2 est prsent partir de la page 239 du polycopi de
cours.

La liaison PS2 est (ou devrait-on dire tait) utilise pour la communication entre claviers
et souris et ordinateurs PC. L'objectif de ce TP est de raliser un dcodage des
informations provenant d'un clavier.

I. Travail simple (sans processeur)


On vous demande de lire trs rapidement
http://fr.wikiversity.org/wiki/Very_High_Speed_Integrated_Circuit_Hardware_Description_L
anguage/Travail_pratique/TP_3
jusqu' la section "Mise en conformit des horloges".
Travail raliser (exercice 1)
On vous demande de prendre la correction de P. P. Chu ou celle six tats propose par
l'un d'entre nous, et de l'adapter votre carte.
Ce qu'il y a adapter c'est :
Prenez exo3 du TP5 (dans les ressources) lgrement modifier pour en faire
le composant vert ple ci-dessous.
Ajouter le registre d'affichage (rectangle jaune de la figure ci-dessous)
Raliser compltement le grand rectangle bleu (en VHDL ou en schmatique)

Reset

ps2d
ps2c
clk

Programme VHDL donn


Reset

ps2d

dout

rx_done_tick

En

clk

ps2c

Registre
affichage

Reset
sigAAfficher

clk

sel

MUX2/1

Exo3 TP5

224

Dcodeur 7 segments hexa

Q(23)

Q(19)

63/94

E13 A16 C14 A14 A13 E12 F11

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Faire constater quand cela fonctionne.

II.Rappel sur les PORTs et registres d'entre


Nous avons vu dans le TP prcdent que le processus qui gre les registres et PORTs de
sortie s'appelle "iord". Il a t prsent sous forme de programme VHDL mais nous
allons en faire un schma de principe.

avr_fpga_spartan3.vhd
io.vhd
I_CLK_50
I_CLR
I_RX
I_SWITCH[7:0]

I_CLK
I_CLR
I_ADR_IO[7:0]
I_DIN[7:0]
I_SWITCH[7:0]
I_RD_IO
I_RX
I_WE_IO

Q_INTVEC[5:0]
Q_TX
Q_7_SEGMENT[6:0]
Q_LEDS[7:0]
Q_AN[3:0]
Q_TX

iord: process(I_ADR_IO,...

I_SWITCH[7:0]

I_ADR_IO[7:0]

PINB

(0x36)

UCSRC

(0x40)

UDR

(0x2C)

Q_DOUT[7:0]

Son principe est de former le signal "Q_DOUT[7:0]" partir d'une adresse


"I_ADR_IO[7:0]" et de donnes provenant de l'extrieur ou pas. Il est possible que vous
soyez surpris par le sens de "Q_DOUT[7:0]" comme sortie du processus. Mais cette sortie
devient une entre du processeur, non ?

III.Trouver ce qui sort rellement du clavier l'aide du processeur


Votre affichage ne permet d'afficher que deux codes hexadcimaux alors que plusieurs
sont envoys la suite. Pour remdier au problme, on vous demande d'adapter une
transmission srie (comme en TP 7 pour que chaque fois qu'une valeur est affiche dans
le registre d'affichage cette mme valeur est envoye sur un octet dans le FIFO.
Comme le montre la figure ci-dessous, il nous faut dj apprendre interfacer le FIFO
notre processeur.
Commenons par expliquer le fonctionnement du bbfifo. Il fournit 3 signaux :
- "data_present"
64/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

- "full"
- "half_full"
Ces signaux doivent tre lus par le processeur et ainsi formeront un PORT d'entre. Nous
allons les relier PINC.
Les donnes "data_out" sont aussi lire par le processeur. Elles seront relies PIND.
Voyons comment tout cela est ralis pour la lecture des donnes.

io.vhd
I_CLR

+ps2d
+ps2c
I_clk

iord: process
Programme VHDL donn s_dout bbfifo_16x8
dout
data_in
Reset
s_data_present 7
data_present
rx_done_tick
write
s_buffer_full 6 PINC[7:0]
ps2d
full
read
ps2c
half_full s_half_full 5
reset
PIND_DATA
PIND[7:0]
clk
data_out
clk
s_rx_done_tick

L_RD_FIFO

Remarquez les +ps2c et + ps2d qui signifient qu'il faut ajouter ps2c et ps2d l'entit de
io.vhd et les propager dans le composant global. Le "en" de lecture du clavier ps/2 est
positionn '1'. Les signaux sont dessins en rouge et sont dclarer.
Pour la sortie des informations on se contentera du PORT qui est reli aux LEDs (TP
prcdent).
Quelques informations supplmentaires sur le VHDL correspondant :
1
2
3

utilisdansleregistrePINCenlecture
b7b6b5
signals_data_present,s_buffer_full,s_half_full:std_logic;

Les signaux ci-dessus sont utiliss dans le process de lecture :


1
2
3
4
5
6
7
8
9
10
11
12
13
14

iord:process(I_ADR_IO,I_SWITCH,
U_RX_DATA,U_RX_READY,L_RX_INT_ENABLED,
U_TX_BUSY,L_TX_INT_ENABLED)
begin
addressesformega8device(useiom8.hor#define__AVR_ATmega8__).

caseI_ADR_IOis
whenX"33"=>Q_DOUT<=PINC:
s_data_presentdatapresent?
&s_buffer_fullbufferplein?
&s_half_fullbuffermoitiplein?
&'0'nonutilis
&'0'nonutilis
&'0'nonutilis
65/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

15
16
17

TD et TP LO11

UTT 2014/2015

&'0'nonutilis
&'0';nonutilis
whenX"30"=>Q_DOUT<=PIND_DATA;PIND:

Nous n'avons pas mis l'ensemble du process ici mais seulement ce qu'il y a de nouveau
pour cet exercice.
Il y a un autre point sur lequel il nous faut revenir : la construction du signal read qui va
au FIFO. Il se fait avec le simple code :
1

L_RD_FIFO<=I_RD_IOwhen(I_ADR_IO=X"30")else'0';readPIND

Avec ce signal, toute lecture de PIND en C provoquera simultanment une vacuation de


la donne du FIFO : c'est un dcalage dans le FIFO grce ce signal qui permet de
rcuprer la donne suivante la prochaine fois qu'on viendra le lire.
N'oubliez pas d'ajouter les contraintes importantes pour la mmoire programme dans le
fichier ucf :
INST cpu/opcf/pmem/pe_1 LOC = RAMB16_X1Y2;
INST cpu/opcf/pmem/pe_0 LOC = RAMB16_X0Y3;
INST cpu/opcf/pmem/pe_3 LOC = RAMB16_X1Y3;
INST cpu/opcf/pmem/pe_2 LOC = RAMB16_X0Y2;
INST cpu/opcf/pmem/po_1 LOC = RAMB16_X1Y0;
INST cpu/opcf/pmem/po_0 LOC = RAMB16_X0Y0;
INST cpu/opcf/pmem/po_3 LOC = RAMB16_X1Y1;
INST cpu/opcf/pmem/po_2 LOC = RAMB16_X0Y1;

Travail raliser (exercice 2)


Raliser l'ensemble et sortir sur les 8 LEDs la valeur du caractre lu.
A ce point nous n'avons pas encore atteint notre objectif : rcuprer tous les codes en
provenance du clavier. C'est l'objet du prochain exercice.
Indications :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

#include"avr/io.h"
#undefF_CPU
#defineF_CPU25000000UL
#include"util/delay.h"
#defineRXDP7//RXDP:datapresentenrceptiondansFIFO
//***********************************************************************
//main
//***********************************************************************
intmain(void){
unsignedcharportc,portd;
while(1){
portc=PINC;//lectureduPORTCpourvoirsidonne?
if(portc&(1<<RXDP)){//sidatapresent
portd=PIND;
PORTB=portd;//sortiesurles8LEDs
}
_delay_ms(1000);//onverrapasserlescaractres
66/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

19
20
21

TD et TP LO11

UTT 2014/2015

}
return0;
}

IV. Amliorer l'affichage dans gtkterm


Transcodage en ASCII
On dsire vraiment connatre ce qui est envoy par le clavier pour chaque appui de
touche. Pour cela on va d'une part transcoder les octets en deux caractres ASCII ce qui
pourra ainsi tre examin dans un hyperterminal GTKTerm. On va pour cela utiliser la
RS232 toute faite de notre processeur. Elle fonctionne par dfaut 38400 bauds 8 bits
de donnes, pas de parit et 2 bits de stop.
Travail raliser (exercice 3)
On vous demande de vrifier que votre fichier ucf permette l'envoi de caractres
l'hyperterminal. Pour tester la sortie rs232, utilisez le programme complet suivant :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

#include"avr/io.h"
#undefF_CPU
#defineF_CPU25000000UL
#include"util/delay.h"
//************************************************************************
//functionuart_init()
//purpose:putcharacterinfirstrs232PORT
//arguments:
//correspondingcharacter
//return:
//note:38400,8,n,2hardcoded:transmissiononly
//************************************************************************
voidusart_init(void){
UCSRB=(1<<TXEN);//transmission
//UCSRC=(1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL);//ignorparnotrematriel
//UBBRL=0x33;//paspournouscar38400baudsSans8,2
}

//************************************************************************
//functionuart_send()
//purpose:putcharacterinfirstrs232PORT
//arguments:
//correspondingcharacter
//return:
//note:38400,8,n,2hardcoded
//************************************************************************
voidusart_send(unsignedcharch){
while(!(UCSRA&(1<<UDRE)));
UDR=ch;
}

intmain(void)
{
usart_init();//pourpouvoirdclencherinterruptionRS232
for(;;){
usart_send('A');
_delay_ms(1000);
67/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

38
39
40

TD et TP LO11

UTT 2014/2015

}
return0;
}

Travail raliser (exercice 4) : programmation de l'AVR uniquement


1) Lire sans arrt ce qui arrive du clavier et l'envoyer l'hyperterminal configur en
lecture hexadcimale.
Indications :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#defineRXDP7//RXDP:datapresentenrceptiondansFIFO
//***********************************************************************
//main
//***********************************************************************
intmain(void){
unsignedcharportc,portd;
usart_init();
while(1){
portc=PINC;
if(portc&(1<<RXDP)){//sidatapresent
portd=PIND;
usart_send(portd);
}
}
return0;
}

2) Pour prparer la question suivante, on vous demande de transcoder l'hexadcimal en


ASCII avec une ralisation de transcodage de votre choix. Un tableau est un choix
judicieux mais au cas o vous choisiriez une autre voie, nous vous avons prpar un
tableau de transcodage. Laissez tomber la parit dans ce tableau.
e(3) e(2)

e(1)

e(0)

parit

b7

b6

b5

b4

b3

b2

b1

b0

caractre

'0'

'1'

'2'

'3'

'4'

'5'

'6'

'7'

'8'

68/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

'9'

'A'

'B'

'C'

'D'

'E'

'F'

Configurez GTKTerm en ASCII pour vos tests.


3) Le document de :
http://fr.wikiversity.org/wiki/Very_High_Speed_Integrated_Circuit_Hardware_Description_L
anguage/Travail_pratique/TP_3
vous donne quelques "scan codes" de touches ainsi que vos essais de la question 2).
On vous demande d'amliorer l'affichage dans GTKTerm pour que toutes les donnes
concernant une touche se retrouvent sur une seule ligne. Autrement dit on va la ligne
pour chaque touche diffrente.
Indication : peut tre reprer le "F0" et ... vous avez remarquez que le nombre d'octet
dpend de la touche (parfois 3 parfois 5) ...

69/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

TP11 Dcouvrir CORDIC avec du logiciel

INFO

L'algorithme CORDIC est prsent partir de la page 461


du polycopi de cours et donn compltement en page
469

I. Travail thorique introductif


Nous allons commencer par un peu de travail de TD sur l'algorithme CORDIC vu en
cours.
L'algorithme nomm CORDIC est utilis notamment pour limplantation de fonctions
trigonomtriques.
Il sagit dune mthode itrative qui ncessite uniquement la multiplication par deux,
donc particulirement adapte aux composants programmables. Son symbole est le
suivant :

xn

x0
y0
z0

CORDIC

yn
zn

Figure111:Symboledel'lmentCORDIC
Les diffrentes itrations de lalgorithme sont donnes par :
x i+1=x i iy ii
yi +1= y i + x
i ii
zi +1=z i ii

{
o

i =1

1. crire les deux premires quations sous la forme matricielle en calculant la matrice
Ci :
v i +1=Civ i avec v i=( x i , y i )T et v i +1=(x i +1 , y i+1 )T
La matrice Ci peut galement s'crire : Ci = Ki . Ri.
Ki est un scalaire correspondant un facteur dchelle et Ri est une matrice de rotation
de mme dimension que Ci et pouvant scrire :
Ri=

cos( i) i sin(i )
i sin(i )
cos( i)

i =1 dtermine le sens de rotation.

2. Ci = Ki . Ri, calculer Ki et i en fonction de i.

70/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

3. Soit v0 la valeur initiale de vi, exprimer le vecteur vi en fonction de v0 et de Ci-1, Ci2, ... .
4. Exprimer vn (vecteur vi aprs n itrations) en fonction de v0, Kn-1, Kn-2, ... et Rn-1, Rn2, ... .
Nous considrons i = 2-i avec i=0,1,2,...,n.
5. Calculer i pour i=0, 1,2,...,10 (en radian) avec OpenOffice :
A

alpha_i

0,785

"=ATAN(PUISSANCE(2;-A2))"

6. Sachant que langle de rotation (aprs ni itrations) sexprime par : = ii , dans


i=0

le cas particulier o le sens de rotation est positif ( i = 1), calculer la valeur de pour
n=20. (Avec OpenOffice : "=somme(B2:B22)")
Le nombre K est appel facteur dchelle. Il a pour expression :
n

K=K 0K 1K 2...K n= K i
i=0

7. Exprimer Ki en fonction de i.
8. Nous considrons i = 2-i. Calculer K pour n=20 l'aide d'OpenOffice et comparer la
valeur 1,646760245 gnralement prise pour les calculs (d'inverse 0,60725294 arrondi
0,6073).
A

delta_i

0,500

0,25

alpha_i

K_i

<--"=PUISSANCE(2;-A2)"
>

<-- "=1/cos(C2)"

"=ATAN(B3)"--

Le produit demand est ralis avec "=produit(D2:D22)" dans une cellule en dehors du
tableau.
La troisime quation de lalgorithme de CORDIC est gale : z i+1=z i i i
9. Exprimer zn, valeur de z aprs n itrations, en fonction de z0, i , i et n.

71/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

On dfinit langle de rotation la ieme itration :

angle= k k
k=0

i +1=+1lorsque angle< z 0
i +1=1lorsque angle> z 0 (6)

10. On prolonge la partie tableur de la question 8 pour grer toute la partie angle de la
question 9 dans les colonnes E, F et G.
A

z_i

1,047

"=E2C2*G2"

angle_i

sigma_i

<--"=PI()/3"

<--"=SI(F2<$E$2;1;-1)"

"=F2+G2*C2"->

Vers quelle valeur tend zn lorsque n est trs grand ?


11. On gre enfin les itrations de l'algorithme CORDIC dans les colonnes H et I
A

z_i

1,047

"=E2C2*G2"

x_i

y_i

<--"=PI()/3"

"=H2-G2*I2*B2"-->

0
<-- "=I2+H2*G2*B2"

12. Dans quelle colonne du tableau ci-dessus obtient-on la valeur de K* sin(1.047) ?


Justifier rapidement votre rponse.
13. Quelle opration simple reste-t-il a effectuer pour obtenir la valeur correcte de
sin(1.047) ?
14. Refaire le mme calcul en initialisant x0 K=0,6073 (comme programme wikipdia
d'origine ci-dessous). Que constatez-vous ?
15. Excuter l'algorithme CORDIC en C prsent dans l'article Wikipdia l'adresse :
http://fr.wikipedia.org/wiki/CORDIC
Compiler l'algorithme sous linux : gcc -o cordic cordicWiki.c -lm
Essayer le programme : ./cordic
Veuillez entrer beta
0.785
Veuillez entrer le nombre d'iterations voulues
16
cos(beta) = 0.707431 , sin(beta) = 0.706892

72/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Remarque : pour vos essais, n'oubliez pas que l'algorithme CORDIC fonctionne entre

[ , ]
2 2

II.Travail raliser (Logiciel)


Exercice 1
1) (avec avr-gcc) Montrer que le programme de Wikipdia compil avec avr-gcc gnre
un programme qui tient tout juste dans un ATMega8 !
avr-gcc -g -mmcu=attiny861 -Wall -Os -c cordicWiki.c
avr-gcc -g -mmcu=attiny861 -o hello.elf -Wl,-Map,hello.map cordicWiki.o
avr-objdump -h -S hello.elf > hello.lss
avr-objcopy -O binary -R .eeprom

hello.elf hello.bin

La dernire ligne gnre un fichier binaire dont la taille donne la taille de la mmoire
Programme utilise (8 ko pour l'ATTiny861). Tout ajout dans le programme d'origine ne
tiendra pas dans l'ATTiny861 !!!
2) Nous dsirons modifier le programme prcdent pour qu'il fonctionne sans les
librairies de calcul en double (librairie mathmatique qu'utilisent pow(2,-i) et
atan(Pow2)) .
La technique habituelle pour faire cela est de choisir un format virgule fixe en lieu et
place des variables de type "double". Puisque les nombres sont positifs ou ngatifs on
utilisera, au choix, des "int" ou des "int16_t". Nous allons utiliser un format Q3.13 qui
veut dire que trois bits de poids forts sont la partie entire et les treize bits restants sont
la partie fractionnaire. Voici un rsum du codage utilis avec les poids correspondants :
b15 b14 b13 b12 b11 b10 b9

b8

b7

b6

b5

b4

b3

2-5

2-6

2-7

2-8

2-9

2-10 2-11 2-12 2-13

1 2-1

2-2

2-3

2-4

b2

b1

b0

S est le signe et la partie entire possde donc 2 bits, l'ensemble est cod en
complment deux.
Calculer les valeurs de 1, 0.5 et -0.25 en format Q3.13. Montrer que les multiplications
par i = 2-i se font par de simples dcalages mais qui ne sont pas identiques suivant que
les nombres sont positifs ou ngatifs.
3) (Avec gcc sous Linux) Remplacer tous les types "double" en type "float" dans le
programme de Wikipdia. La raison est que les sous programmes donns ci-dessous
manipulent des "float".
Calculer les valeurs des atan(2-i) et les convertir (pour un usage ultrieur en Q3.13)
l'aide des sous-programmes de conversion tout faits :
1
2
3
4
5
6
7

floatHexQ3_13ToFloat(intval){//conversionQ3.13versfloat
floattemp;
inti_temp;
chari;
if(val<0)i_temp=val;elsei_temp=val;
temp=((i_temp&0x6000)>>13);
for(i=0;i<13;i++)
73/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

TD et TP LO11

UTT 2014/2015

if(i_temp&(1<<i))temp+=pow(2,(i13));
if(val<0)returntemp;elsereturntemp;
}
intfloat2HexQ3_13(floatval){//conversionfloatversQ3.13
inttemp;
chari;
floatf_temp;
if(val<0)f_temp=val;elsef_temp=val;
temp=((int)floor(f_temp)<<13);
f_temp=f_tempfloor(f_temp);
for(i=0;i<13;i++){
temp|=((int)floor(2*f_temp)<<(12i));
f_temp=2*f_tempfloor(2*f_temp);
}
if(val<0)returntemp;elsereturntemp;
}

Ce travail se fait sous Linux bien sr. Expliquer alors pourquoi un tableau de 14 valeurs
suffit. Pour ce travail vous avez le droit d'utiliser la librairie mathmatique en float (ou en
double).
4) (avec gcc sous Linux) En remarquant que le calcul de atan peut tre remplac par un
tableau compos des valeurs de la question prcdente, et que les multiplications
peuvent tre remplaces par des dcalages, on vous demande d'crire le programme
complet de calcul avec le tableau et les itrations.
Indication : calcul rcursif CORDIC sans aucune multiplication !
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

for(i=0;i<nb_iter;i++){
//Sibeta<0rotationdanslesenstrigo
if(beta<0){
x_Nouveau=x+(y>>i);
y=x>>i;
beta+=atantb[i];
}
//sinondansl'autresens
else{
x_Nouveau=x(y>>i);
y+=(x>>i);
beta=atantb[i];
}
x=x_Nouveau;
}

Faire fonctionner ce programme ncessite videment d'appeler votre tableau "atantb",


puisqu'il apparat comme tel dans le morceau de programme donn !
A ce stade vous avez dj un calcul de sinus et cosinus avec CORDIC
Exercice 2
Vous allez maintenant transformer le programme de l'exercice 1 pour qu'il puisse
fonctionner dans l'AVR. Les entres et sorties ne se feront plus par les "printf" et "scanf"

74/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

puisqu'on n'a plus d'cran ni de clavier. Vous allez maintenant utiliser GTKTerm, c'est
dire que vos entres sorties seront faites par la liaison srie.
1) Dans un premier temps, on vous demande d'utiliser votre programme sans les
fonctions de conversion : vous fournirez vos donnes directement en dur dans votre
programme. Aprs calcul, vous comparerez aux valeurs pr-calcules correspondantes
sous Linux et envoyez une chaine de russite et/ou une chane d'chec l'aide des
fonctions ci-dessous GTKTerm.
Indications :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

//************************************************************************
//functionuart_init()
//purpose:putcharacterinfirstrs232PORT
//arguments:
//correspondingcharacter
//return:
//note:38400,8,n,2hardcoded:transmissionandreception
//************************************************************************
voidusart_init(void){
UCSRB=(1<<TXEN)|((1<<RXEN));//transmissionetreception
}

//************************************************************************
//functionuart_send()
//purpose:putcharacterinfirstrs232PORT
//arguments:
//correspondingcharacter
//return:
//note:38400,8,n,2hardcoded
//************************************************************************
voidusart_send(unsignedcharch){
while(!(UCSRA&(1<<UDRE)));
UDR=ch;
}
//************************************************************************
//functionuart_receive()
//purpose:readcharacterinsecondrs232PORT
//arguments:
//correspondingcharacter
//return:nonblockingsubreturn1ifnodatapresentelsereturnchar
//note:38400,8,n,2hardcoded,nonblockingsubreturn0ifnodatapresent
//************************************************************************
charusart_receive(void){
if(UCSRA&(1<<RXC))//attentetantqueDataPresentenrception
returnUDR;
elsereturn0;
}

Trouver la taille du programme C gnr. Conclusion ?


2) Ajouter la conversion ci-dessous pour rendre lisibles vos rsultats en ASCII dans
GTKTerm (sinus et cosinus) :
1
2
3
4

void HexQ3_13ToString(int valQ3_13,char str[]){


unsigned int valQ3_13b;
char digit;
if (valQ3_13 < 0) { // eviter problmes de signe !!!
75/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

TD et TP LO11

UTT 2014/2015

str[0] = '-';
valQ3_13 = -valQ3_13;
} else
str[0] = '+';
digit = valQ3_13 >> 13;
str[1]= digit + '0';
str[2]= '.';
valQ3_13 &= 0x1FFF; // on retire les 3 bits de poids fort
valQ3_13 = valQ3_13 * 5; //*5 pour tenir dans 16 bits
valQ3_13b = valQ3_13;
valQ3_13b >>= 12; // on ne garde que les 4 bits de poids fort
str[3] = valQ3_13b +'0';
valQ3_13 &= 0x0FFF; // on retire les 4 bits de poids fort
valQ3_13 = valQ3_13 * 10; //enfin le * 10
valQ3_13b = valQ3_13;
valQ3_13b >>= 12; // on ne garde que les 4 bits de poids fort
str[4] = valQ3_13b +'0';
valQ3_13 &= 0x0FFF; // on retire les 4 bits de poids fort
valQ3_13 = valQ3_13 * 10; //enfin le * 10
valQ3_13b = valQ3_13;
valQ3_13b >>= 12; // on ne garde que les 4 bits de poids fort
str[5] = valQ3_13b +'0';
valQ3_13 &= 0x0FFF; // on retire les 4 bits de poids fort
valQ3_13 = valQ3_13 * 10; //enfin le * 10
valQ3_13b = valQ3_13;
valQ3_13b >>= 12; // on ne garde que les 4 bits de poids fort
str[6] = valQ3_13b +'0';
str[7]=0;
}

Ceci rendra votre programme plus convivial. Quelle est la nouvelle taille du programme ?
3) Raliser un sous-programme de conversion d'une chane en provenance de GTKTerm
en format Q3.13. Cela permettra d'envoyer des angles pour calculer leurs cosinus et
sinus. Pour simplifier le problme, on adoptera un format fixe : un signe, un chiffre un
point et quatre chiffres. Par exemple "+0.7853" et "-1.0472" seront des chaines valides.
ATTENTION : vitez d'utiliser float2HexQ3_13 dans l'ATMega8
qui ne fonctionne pas ! Mais nous avons ajout
float2HexQ3_13_AVR dans les ressources.

III.Travail raliser (Matriel)


Notre objectif est maintenant de dplacer le calcul rcursif de CORDIC du processeur
vers un priphrique. Lorsqu'on ralise cela c'est gnralement avec un double
objectif :
- allger le travail de calcul ralis par le processeur
- amliorer le temps de calcul
Notre objectif n'est pas d'amliorer le temps de calcul mais plutt de continuer notre
apprentissage pour la ralisation de priphriques.
Vous disposez d'un cur CORDIC parmi vos ressources avec le fichier "cordic2.vhd"
76/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Exercice 3
1) Complter toutes les valeurs numriques manquantes du cur cordic fourni ( partir
des calculs de l'exercice 1).
2) Ajouter la gestion de l'entre "ena" : cette entre est dclare dans l'entit mais elle
n'est pas utilise dans le cur.
3) Interfacer le cur VHDL CORDIC pour en faire un priphrique de votre AVR en
suivant les schmas ci-dessous. Vous devez avoir l'esprit que ce cur fonctionne tant
que son entre "ena" est un. Ceci montre que ce cur n'est pas bien adapt notre
travail : il est plutt utile pour un ensemble de donnes qui lui arrive et ralise alors un
calcul pilpelin : calcul en mode flot de donnes (stream processing). Cependant, tant
que "ena est laisse 1 assez longtemps et que les valeurs en entre ne changent pas,
il est possible de l'utiliser tel quel. Pour dire les choses autrement, il serait prfrable
d'avoir un cur avec une entre "start" et une sortie "done" plutt qu'une seule entre
"ena" ! Ce serait plus l'esprit de l'interfaage avec un processeur, le "done" tant projet
en bit interne. C'est ce que l'on a utilis en TP 10 pour le clavier.
En ce qui concerne le rsultat du cur CORDIC, il sera interfac comme quatre PORTs
d'entres, deux pour le sinus et deux pour le cosinus. Notez dans le dessin qui est poids
faible (LSB) et qui est poids fort (MSB).
PORTD sera rserv faire partir de calcul l'aide de l'entre "ena" du cur CORDIC.
Cette gestion mriterait d'tre amliore.
Les (-) devant les entres/sorties veulent dire que celles-ci peuvent tre supprimes car
elles ne sont plus utilises. Ces suppressions sont optionnelles. Les (+) devant les
entres/sorties veulent dire que celles-ci doivent tre ajoutes (aucune ici).
Vous devez savoir que le processeur ATMega8 ne possde pas de PORTA que l'on a
utilis pour le poids faible du sinus. Son utilisation ncessite donc de complter le fichier
avr/io.h. Pour ne pas modifier ce fichier vous utiliserez plutt, en dbut de votre
programme :
1
2
3
4

/*PortA*/
#definePINA_SFR_IO8(0x19)
//#defineDDRA_SFR_IO8(0x1A)
//#definePORTA_SFR_IO8(0x1B)

sans vous inquiter du dcalage de 0x20 qu'il y a entre les adresses dans nos dessins et
l'adresse fournie ici.
4) Essayer ce cur matriel en utilisant la liaison srie pour visualiser vos rsultats.
Puis ralisez la question 3 de l'exercice 2 pour avoir un moyen de fournir des angles
avec GTKTerm.
5) Cette question sera ralise en lieu et place de l'exercice suivant si vous ne disposez
pas assez de temps pour le raliser (minimum 1h30). Ajouter un compteur sur 4 bits qui
se dclenche avec "ena" et ralise un signal "done" dans un bit du processeur.
Exercice 4 Transformer le cur pipeline en priphrique
Le cur pipeline du CORDIC que nous avons donn plus haut est assez mal adapt la
notion de priphrique. Il est en effet trop indpendant du processeur.
77/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Traditionnellement les priphriques sont configurables par des registres et un drapeau


indique la fin du travail. Ce bit peut d'ailleurs, en gnral, tre utilis pour dclencher
une interruption...
Un pipeline est, quant lui, destin traiter des informations au fur et mesure. D'une
certaine manire, il ne termine jamais son travail. Notre problme va donc consister le
transformer en un priphrique digne de ce nom.
1) Ajouter un fonctionnement correct de l'entre "ena"
L'entre "ena" prsente dans l'entit du cur CORDIC ne sert absolument rien. Vous
allez transformer le fichier "cordic2.vhd" pour la rendre utile : s'il elle n'est pas '1' le
cur ne calcule pas. Fonctionnement assez traditionnelle pour ce type d'entre.
L'utilisation d'un tel cur consistera alors :

positionner l'angle en crivant dans deux PORTs


positionner "ena" 1 pour lancer le calcul.
perdre un peu de temps et repositionner "ena" 0
lire les sinus et cosinus

Ce qui nous dplat dans cette faon de faire est l'attente par perte de temps. A ce
stade, peu d'amlioration par rapport au cur d'origine, sauf la possibilit de l'arrter.
Nous allons corriger cela mais avant, nous vous demandons de raliser cette tape et de
la tester.
2) Ajouter une dtection de la fin de calcul
Un bit de sortie sera prvu pour dtecter la terminaison du calcul. Ce travail n'est pas
difficile faire. Il s'agit d'ajouter un compteur dans CORDIC sur 4 bits qui s'incrmente
aussi avec "ena" (et l'horloge bien sr). Quand le compteur est une certaine valeur (14
pour nous) et bien on positionne un bit 1 (et l'on peut automatiquement positionner
"ena" 0).
L'utilisation d'un tel cur consistera alors :

positionner l'angle en crivant dans deux PORTs


positionner "ena" 1 pour lancer le calcul.
Attendre le positionnement d'un bit (de fin de calcul) et repositionner "ena" 0
lire les sinus et cosinus

Indication :
La gestion du "done" se fait en deux tapes :
1) on ajoute dans CORDIC (fichier cordic2.vhd) un compteur qui compte de 0 14
quand ena=1, qui s'arrte 14 et qui se remet 0 quand "ena" repasse 0.
Un processus combinatoire positionne la sortie "done" quand le compteur vaut 14.
2) Il faut maintenant grer le bit done dans le process iord (donc dans le fichier io.vhd)
Ceci implique que le processeur ne pourra pas changer ce bit, c'est le matriel qui le
fera.

Remarque
La faon d'organiser tout ce fonctionnement peut se faire avec quelques petites
variations (donnes juste titre indicatif) :
78/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

le repositionnement de "ena" 0 peut se faire de manire automatique quand on


lit un des registres de rsultat

le repositionnement de "ena" 0 peut se faire automatiquement par la dtection


de la fin des calculs (ce n'est pas le processeur qui le fait)

le deuxime choix peut mme amener retirer le bit fin de calcul : c'est "ena" qui
sert tout : on le positionne '1' et on attend qu'il repasse 0

Exercice 5 Ralisation matrielle de la conversion virgule fixe vers virgule flottante


Cette conversion tait l'objectif de la fonction donne et dj utilise dans l'exercice 2 :
"float HexQ3_13ToFloat(int val)"
Un coup d'il sur le code source de cette fonction montre des calculs de puissance de
deux en flottant et notre objectif ici est de les liminer en laissant le matriel les raliser.
Pour ce faire, il est possible d'utiliser un cur de calcul flottant, il en existe chez
Opencores.org. Mais on va tre plus subtil car notre conversion se fait dans un cas
suffisamment simple et nous allons tenter une ralisation sans multiplication.
1) Tester en C une conversion du type :
Exposant = 129
Recherche du premier 1 dans le nombre Q3.13 en partant des poids forts et en
dcrmentant l'exposant.
Une fois trouv supprimer ce 1, puis mettre l'exposant sa place (E dans la figure cidessous) et mettre la mantisse (dans M) aussi sa place.

31
S

23 22

Voici comment les choses se font sous Linux : on remarquera l'absence de multiplication
et de calcul flottant :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

floatHexQ3_13ToFloat2(intval){
float*temp;
inti_temp,f_temp;
unsignedcharexposant=129;
signedchari;
if(val<0)i_temp=val;elsei_temp=val;
for(i=15;i>=0;i){
if(i_temp&(1<<i)){
//oneffacele'1'trouv:
i_temp=i_temp&~(1<<i);
break;//onsortdelaboucle
}
exposant;
}
f_temp=exposant;
f_temp<<=23;
f_temp=f_temp|(i_temp<<(23i));
//cetteaffectationdepointeurprovoqueraunwarning!:
temp=&f_temp;
79/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

20
21

TD et TP LO11

UTT 2014/2015

if(val<0)return(*temp);elsereturn*temp;
}

2) On va raliser la conversion ci-dessus dans le matriel (en VHDL donc). En clair,


notre cur CORDIC va continuer travailler en virgule fixe, mais le rsultat sera converti
en flottant par le matriel puis retourn au processeur.
Pour viter de multiplier les PORTs de l'AVR, on va utiliser un FIFO dans lequel on viendra
ranger les 8 octets correspondants aux deux nombres flottant du rsultat.
Trouver une machine d'tats qui fait le calcul de conversion de la question 1 et remplit
un FIFO avec les 8 octets des deux rsultats de CORDIC.
Exercice 6 (conversion BCD du rsultat de manire matrielle)
Nous nous proposons maintenant de raliser une conversion BCD des rsultats en vue
d'un affichage dans l'hyperterminal comme dans l'exercice 2 avec HexQ3_13ToString.
Notre rsultat devra avoir le format :
signe digit1 '.' digit2 digit3 digit4
c'est dire 6 caractres (7 en ajoutant le zro de fin de chane) et ceci pour le sinus et le
cosinus. Pour viter d'avoir un nombre de PORTs trop important, vous allez utiliser un
FIFO comme dans le TP prcdent. Une autre possibilit que nous n'examinerons mme
pas, serait de projeter le rsultat directement en mmoire RAM.
1) Raliser l'interfaage du FIFO comme indiqu dans la figure ci-dessous.
Rappel : la construction du signal read qui va au FIFO. Il se fait avec le simple code :
1

L_RD_FIFO<=I_RD_IOwhen(I_ADR_IO=X"39")else'0';readPINA

avr_fpga_spartan3.vhd
io.vhd
I_CLK_50
I_CLR
I_RX
I_SWITCH[7:0]

I_CLK
I_CLR
I_ADR_IO[7:0]
I_DIN[7:0]
I_SWITCH[7:0]
I_RD_IO
I_RX
I_WE_IO

Q_INTVEC[5:0]
Q_TX
Q_7_SEGMENT[6:0]
Q_LEDS[7:0]
Q_AN[3:0]
Q_TX

iord: process(I_ADR_IO,...
PINA (0x39)
FIFO
I_ADR_IO[7:0]

80/94

Q_DOUT[7:0]

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Le FIFO devra contenir d'abord le rsultat du cosinus en chane de caractres puis le


sinus.
2) Ajouter un squenceur capable de raliser un signal "done" qui sera le dpart de la
conversion.
3) Raliser la partie matrielle pour la conversion A COMPLETER !!!!
4) Raliser ensuite le graphe d'tats de commande de l'ensemble qui ralise la
conversion et remplit correctement le FIFO.

81/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

TP12 : Priphrique de calcul sur Corps de Galois et CRC


Nous allons nous intresser dans ce TP un aspect un peu particulier du calcul dans un
corps de Galois appel GF(2) et l'appliquer au CRC (Cyclic Redundancy Code = Contrle
de redondance cyclique).
Un tutoriel en franais est prsent ici : http://dvsoft.developpez.com/Articles/CRC/

I. Notions mathmatiques
Le corps de Galois GF(2)
Le corps de Galois GF(2) comporte deux lments qui seront nots '0' et '1'. Il est muni
de deux oprations :
- addition + qui un OU exclusif que l'on notera abusivement par +
- multiplication note . qui est un ET logique
Ces deux oprateurs ont toutes les proprits de l'arithmtique : commutativit,
associativit lment neutre et, de plus, la multiplication est distributive par rapport
l'addition.
Polynmes sur GF(2)
Le Corps de Galois GF(2) permet de dfinir des polynmes coefficients dans GF(2). Par
exemple, le polynme du cinquime degr a5 . x + a4 . x + a3 . x 3+ a2 . x +a1 . x +a 0 aura tous
ses coefficients ai dans GF(2) et sera reprsent comme le contenu d'un registre ayant
des '0' et '1' la place des ai.

b5 b4 b3 b2 b1 b0
a5 a4 a3 a2 a1 a0
Avec cette convention, tout polynme peut tre reprsent par une valeur binaire ou
hexadcimale.
Le contrle de redondance cyclique
En gnral le calcul d'un code CRC se fait par division euclidienne dans le corps GF(2).
Ainsi l'opration ralise peut s'crire :
M (x)x n=Q (x)G( x )+ R ( x)
o M(x) est le message envoyer, Q(x) le quotient (qui ne nous intresse pas) G(x) est
le polynme gnrateur (forcment de degr n) connu par lmetteur et le rcepteur et
R(x) est le reste qui sera le contrle de redondance cyclique. La multiplication par xn qui
apparat dans la formule dnote qu'il faut ajouter n '0' sur les poids faibles avant de
commencer les oprations. Lors de l'envoi du message ces '0' seront remplacs par R(x).

Un CRC est donc caractris par n et par G(x)


et d'autres paramtres que l'on laisse de ct pour le moment.
82/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Les G(x) standards sont donns ici :


http://en.wikipedia.org/wiki/Polynomial_representations_of_cyclic_redundancy_checks
Si vous voulez voir comment se ralise ce calcul la main :
https://www.youtube.com/watch?v=MSAog5MEhrs (en anglais Cyclic Redundancy Check
(CRC))
Nous allons maintenant raliser de manire logicielle et matrielle le calcul d'un code
CRC. Commenons par le logiciel.

II.Ralisation logicielle du CRC16 (CCITT)


Le tutoriel en franais prsent ici : http://dvsoft.developpez.com/Articles/CRC/
donne un code en C++ pour le calcul du CRC16. On vous demande cependant de lui
prfrer le code de la ressource (Ressource2015.zip de mon site) dans le rpertoire
TP12. Pour information, il est configur par dfaut pour le calcul du tutoriel en franais
ci-dessus.
Exercice 1
1) Dcompacter la ressource crc.zip quelque part. Compilez-la avec la commande :
gcc crc.c main.c -o main
et essayez en tapant :
./main
Ajouter les 16 bits 0 dans la chane utilise pour le calcul du CRC et refaites les essais.
2) Pouvez-vous dire pourquoi on ne peut envisager qu'utiliser crcSlow() (et pas crcFast()
qui ncessite un crcInit()) avec notre architecture ATTiny861 ? (Vous devez lire le fichier
crc.c et vous rappeler de quelques unes des caractristiques de l' ATTiny861 pour
rpondre)
3) Adaptez le code ci-dessus votre compilateur C pour AVR. Cela va consister
essentiellement adapter les types... et les entres/sorties.
Ce code sera utilis avec la liaison srie et GTKTerm. Vous enverrez un message qui se
termine par un retour chariot. Le processeur recevra le message ajoutera le 0x0000 en
fin de message et calculera son CRC16. Celui-ci sera ajout en lieu et place du 0x0000
puis retourns GTKTerm. L'affichage du CRC16 sera certainement bizarre et si vous
voulez viter un passage de l'affichage en mode caractres l'affichage hexadcimal,
vous pouvez toujours raliser cette conversion affichable dans GTKTerm. Regardez ce
dont vous disposez dans les ressources.
Mettez de ct quelques chanes de caractres avec les CRC
correspondants pour l'exercice 2.
Indications :
Le programme principal pourra tre de la forme :
1
2
3
4
5

intmain(void){
unsignedcharchaine[20],i;
crccrc_chaine;
usart_init();
while(1){
83/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

TD et TP LO11

UTT 2014/2015

i=0;
do{
chaine[i]=usart_receive();
usart_send(chaine[i]);
i++;
}while(chaine[i1]!=0x0D);
//usart_send(ch);
//ajoutdes16bits0:
chaine[i1]=0x00;
chaine[i]=0x00;
crc_chaine=crcSlow(chaine,i+1);
usart_puts_hexa(crc_chaine);
_delay_ms(500);
}
return0;
}

Il vous faudra naturellement ajouter les sous-programmes ncessaires qui sont tous
disponibles dans les ressources.
La compilation pourra se faire avec un script du genre :
#!/bin/bash
export PATH=$PATH:/usr/local/avr/bin:~/XILINX/Xilinx/11.1/ISE/bin/lin/
avr-gcc -g -mmcu=attiny861 -Wall -Os -c tp12exo1.c
avr-gcc -g -mmcu=attiny861 -Wall -Os -c crc.c
avr-gcc -g -mmcu=attiny861 -o tp12exo1.elf -Wl,-Map,tp12exo1.map tp12exo1.o crc.o
cp ../microcontroleur.bit .
data2mem -bm attiny861.bmm -bd tp12exo1.elf -bt microcontroleur.bit -o uh
microcontroleur

qui vous montre comment compiler quand il y a plusieurs fichiers (tp12exo1.c + crc.c).
Pour contourner le problme de la question 2), nous allons raliser un calcul du CRC
matriel.

III.Ralisation matrielle du CRC16 (CCITT)


La division manuelle semble difficile raliser en matriel. Heureusement il existe une
proprit du CRC qui fait que l'on peut remplacer le calcul d'une division par un calcul
avec un registre dcalage LFSR (de Galois)
Exercice 2
1) On utilisera le site
http://www.sigmatone.com/utilities/crc_generator/crc_generator.htm
qui permet de gnrer automatiquement le VHDL correspondant. Notez que ce site
connat le CRC16-CCITT. On vous demande de gnrer donc correctement votre
programme VHDL pour une entre srie sur 8 bit. Il vous faudra lire ccrc.h pour connatre
l'initialisation du reste (remainder in English)
Indications :
Reset : Active High
First Serial : MSB
Data Bus : 8
Polynomial : Chercher CRT-16-CCITT
remainder : "1111111111111111"
84/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

2) Raliser la partie matrielle qui interface le CRC16 gnr en question 1 votre


processeur. Le cahier des charges est le suivant :
On utilisera les deux registres ADCL et ADCH pour tout grer.
- en lecture les deux registres ADCL et ADCH contiennent le rsultat du CRC16
- en criture : ADCL envoie les donnes dans CRC16
- en criture : ADCH gre le "reset" en poids fort (7) et "eoc" en poids (6)
Remarque 1 : on ne grera pas "soc" et sera forc 0. La sortie "crc_valid" ne sera pas
gre non plus, mais comme il s'agit d'une sortie on peut la relier open ou rien.
Indications :
Voici comment les critures dans ADCL et ADCH sont gres :

microcontroleur.vhd
clk
rst
sw[7:0]
in_PINB[7:0]

iowr: process(I_CLK)
PORTA
IO_DWr[7:0]
PORTB
ADCH
IO_A[5:0]

rst=s_ADCH(7) crc_gen
reset
soc
'0'
Q

Aff7segs[7:0]
s_ADCH

ADCL

8
data[7:0]

clk
D

leds[7:0]

crc_valid

data_valid_d data_valid
s_ADCH(6) eoc

open

clk
s_data_valid <= IO_wr when (IO_A = ADCL) else '0';

Remarque 2 : la bascule D peut tre ralise dans un process et non avec un composant.
Remarque 3 : On garde toute la gestion de la RS232 qui n'est pas prsente ici.
Voici maintenant la partie qui gre l'entre du rsultat dans les deux registres ADCL et
ADCH.

85/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

microcontroleur.vhd
clk
rst
sw[7:0]
in_PINB[7:0]

UTT 2014/2015

iord: process(CLK)
PINA

IO_Drd[7:0]

PINB
ADCH

IO_A[5:0]

rst=s_ADCH(7) crc_gen
reset
soc
'0'

data[7:0]
crc[15:0]

clk
D

ADCL

crc_valid

data_valid_d data_valid
s_ADCH(6) eoc

open

clk
s_data_valid <= IO_wr when (IO_A = ADCL) else '0';

3) Raliser le programme complet capable de tester la partie matrielle. On ajoutera


encore une fois le 0x0000 en fin de chane l'aide du programme. Testez avec les
chanes que vous avez utilises en exercice 1 pour vrifier le bon fonctionnement.
4) Raliser un programme qui calcule logiciellement le CRC, l'ajoute en bout de chane
et envoie le tout votre partie matrielle. Quel est alors le CRC correspondant ?
5) Raliser un priphrique timer capable de se mettre en marche et de s'arrter en
vue de comparer le temps utilis par les deux mthodes matrielles et logicielles.
Indication 1 :
Nous allons partiellement raliser le timer 1.
Partiellement car il est normalement sur 10 bits et nous n'en garderons que 8
Partiellement car nous nous contenterons d'une division sur 3 bits (du registre TCCR1B)
contre 4 bits dans celui du commerce. Seules les divisions par 0, 1, 2, 4, 8, 16, 32 et 64
seront implantes. Il manque donc les divisions par 128, 256, 512, 1024, 2048, 4096,
8192 et 16384.
Partiellement car nous n'implmenterons ni le dpassement de capacit ni les
comparaisons....
Partiellement car donc seuls TCNT1 (0x2E) et TCCR1B (0x2F) seront implments.
Tout ce qui est en rouge dans la figure ci-aprs ne sera pas implment.

86/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

b9 b8 b7 ........................ b0
TC1H

TCNT1

b7
b6
b5
b4
b3
CS13
b2
b1 CS12
b0 CS11

max(8 bits)

b7
b6
b5
b4
b3
b2
b1
b0

TCCR1B

UTT 2014/2015

MCU
Clock

0,1,2,4,8,16,32,64

CS10

TOV1

TIFR

Timer1 dans ATTiny861

Indication 2 :
On prendra soin de dfinir les deux constantes TCNT1 et TCCR1B. On ralisera ensuite
le clbre :
s_wr_TCNT1 <= IO_wr when IO_A = TCNT1 else '0';

Le timer pourra tre un simple process dans "microcontroleur.vhd"


process(clk) begin
if rising_edge(clk) then
if s_wr_TCNT1 = '1' then
s_s_tcnt1 <= s_tcnt1; -- s_tcnt1 vient du process iowr ( ajouter)
elsif s_en_timer1 = '1' then
s_s_tcnt1 <= s_s_tcnt1 + 1;
end if;
end if;
end process;

La prdivision peut tre faite par :


-- Timer 1
-- prescaler
process(clk) begin
if rising_edge(clk) then
s_prescaler <= s_prescaler + 1;
end if;
end process;
-- tick generation
s_div2 <= '1' when s_prescaler(0) = '1' else '0';
s_div4 <= '1' when s_prescaler(1 downto 0) = "11" else '0';
87/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

s_div8 <= '1' when s_prescaler(2 downto 0) = "111"

UTT 2014/2015

else '0';

s_div16 <= '1' when s_prescaler(3 downto 0) = "1111" else '0';


s_div32 <= '1' when s_prescaler(4 downto 0) = "11111" else '0';
s_div64 <= '1' when s_prescaler(5 downto 0) = "111111" else '0';
-- grand multiplexeur maintenant
s_en_timer1 <= '0' when s_tccr1b(2 downto 0) = "000" else -- arrt timer
'1' when s_tccr1b(2 downto 0) = "001" else -- division par 1
s_div2 when s_tccr1b(2 downto 0) = "010" else
s_div4 when s_tccr1b(2 downto 0) = "011" else
s_div8 when s_tccr1b(2 downto 0) = "100" else
s_div16 when s_tccr1b(2 downto 0) = "101" else
s_div32 when s_tccr1b(2 downto 0) = "110" else
s_div64 when s_tccr1b(2 downto 0) = "111";

Vous compltez correctement les deux process iowr et iord et c'est tout.
Indication 3 :
Le programme d'essai sera du genre :
int main (void) {
unsigned char chaine[20],i,j,ta;
unsigned int temps;
crc crc_chaine;
usart_init();
// configuration du timer 1
TCCR1B = 0x07; // demarrage avec prescaler 64
while(1) {
i = 0;
usart_puts("Entrez une chaine");
do {
chaine[i] = usart_receive();
usart_send(chaine[i]);
i++;
} while (chaine[i-1] != 0x0D);
// ajout des 16 bits 0 :
chaine[i-1] = 0x00;
chaine[i] = 0x00;
TCNT1 = 0;
crc_chaine = crcSlow(chaine, i+1);
ta=TCNT1;
usart_puts_hexa(crc_chaine); usart_puts(" temp(soft)=");usart_puts_hexa(ta);
// preparation matrielle
TCNT1 = 0;
88/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

ADCH = 0x80; // reset


ADCH = 0x00;
for (j=0;j<i+1;j++) {
ADCL = chaine[j];

// data_valid <- '1' automatiquement

}
crc_chaine = ADCH;
crc_chaine <<= 8;
crc_chaine += ADCL;
ta=TCNT1;
usart_puts(" : ");usart_puts_hexa(crc_chaine);
usart_puts(" temp(hard)=");usart_puts_hexa(temps);
usart_send(10);usart_send(13);
_delay_ms(500); // on est pas press
}
return 0;
}

o l'on voit que l'on a pris le prscaler division par 64... et qui me donne 0x40 et 0x0C
comme temps de ralisation.
Exercice 3
Nous avons examin en question 2 de l'exercice 1 les difficults qu'il y a pour implanter
logiciellement crcFast(). Nous allons chercher rsoudre ce problme de deux manires
diffrentes.
1-a) En profitant de la prsence de deux RAMB16S4 (soit 4 ko), on vous demande de
modifier dm.vhd pour rendre les 4ko disponibles pour le processeur.
1-b) Portez la primitive crcInit() pour cette nouvelle configuration et testez son bon
fonctionnement en utilisant crtFast().
Indication : L'utilisation de la mmoire RAM non prvue par le compilateur ncessite
une bonne comprhension du compilateur et en particulier des pointeurs. Ceci se fait de
la manire suivante :
- dclaration d'un pointeur : unsigned char *memoirebonus;
- initialisation de l'adresse du pointeur : memoirebonus =0x260; //1octet dispo
- affectation d'une valeur : *memoirebonus=65;
2-a) Raliser matriellement le prcalcul de crcFast() de la ressource crc.c pour une
utilisation sans pointeur.
2-b) Raliser le programme et tester.

89/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

TP13 Un priphrique CORDIC pour MSP430 (abandonn)

INFO

L'algorithme CORDIC est prsent partir de la page 461 du


polycopi de cours et donn compltement en page 469.
Voir aussi :
https://github.com/the0b/MSP430-CORDIC-sine-cosine

Dans le TP prcdant, nous avons tudi l'algorithme CORDIC avec l'AVR. Dans ce
chapitre, nous allons continuer dans deux directions :

changer d'architecture programme pour passer au MSP430 qui est une


architecture 16 bits

implanter CORDIC dans le FPGA comme un coprocesseur/priphrique et


l'interfacer avec le MSP430

Pour viter l'apprentissage d'un nouvel IDE, nous allons utiliser Energia qui est un IDE
Arduino-like donc trs facile utiliser. Le langage est du C (plus exactement C++) mais
sans main() . Celui-ci est remplacer par un void setup() et un void loop()

I. Implanter CORDIC en C dans le MSP430


L'architecture MSP430 est une architecture contenant des rudiments de cur DSP
(Digital Signal Processor). En effet, elle est commercialise par Texas Instrument qui est
le numro du DSP. Nous allons commencer par porter le programme CORDIC destin
un AVR.
1) Prise de contact avec Energia
Ralisation de quelques programmes de chenillard avec un lien direct entre le MSP430 et
les LEDs de la carte FPGA.
2) A partir du programme AVR
Aprs avoir pris contact avec Energia, le but est de porter CORDIC AVR pour le MSP430.
Une fois le travail ralis, on vous demande de mesurer le temps d'excution de
l'algorithme.

II.Aller plus loin avec le MSP430 (abandonn)


3) En utilisant le multiplieur interne du MSP430
Ce que l'on appellera MAC dans la suite, c'est l'opration de base du traitement du
signal utilise pour calculer :
N1

y= hix i

dans laquelle xi reprsente les chantillons et hi les paramtres de

i= 0

traitement (Multiplication et Accumulation).


Le MSP430 possde une unit MAC qui peut se dcliner en simple multiplieur 16x16 bits.

90/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

Travail faire
1) On vous demande d'crire une nouvelle version de CORDIC qui utilise le multiplieur
16x16 pour faire les dcalages lors du calcul CORDIC. Utilisez la documentation du
multiplieur ci-dessous. Mesurer le nouveau temps d'excution. Conclusion.

2) On cherche maintenant utiliser compltement le MAC du MSP430.


Sachant que les diffrentes itrations de lalgorithme CORDIC sont donnes par :

{
o

x i+1=x i iy ii
yi +1= y i + x
i ii
zi +1=z i ii
i =1

dcomposez-le en multiplication/accumulation pour en faire un programme


correspondant.

91/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

III.Implanter CORDIC dans le FPGA et l'interfacer avec le MSP430


On dporte maintenant la partie matrielle dans le FPGA. Si on effectue une simple
dportation, il nous faudra 16 bits d'entre pour l'angle et 32 bits de sorties pour le sinus
et cosinus. Or la carte LaunchPad dont nous disposons n'en possde pas autant (20
seulement). Il faut donc imaginer les choses autrement. Il existe des protocoles
d'changes plus ou moins rapides : le SPI et l'i2c.
1) Utilisation du SPI pour interfacer un cur CORDIC
L'interface SPI et le MSP430 est dcrite dans la page :
http://fr.wikiversity.org/wiki/Very_High_Speed_Integrated_Circuit_Hardware_Description_L
anguage/Utiliser_un_processeur_externe#Processeur_MSP_430_et_SPI

Vous trouverez dans l'image ci-dessus (disponible en


http://energia.nu/pin-maps/guide_msp430g2launchpad/ )
les ports que l'on doit utiliser pour connecter au FPGA : 7, 8, 14 et 15.

Travail faire

92/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

1) On vous demande simple ment d'interfacer l'ensemble matriel cur SPI et cur
CORDIC (tous les deux fournis) pour en faire un priphrique matriel.
2) Une fois ce travail ralis, concevoir le logiciel sur le MSP430 qui donne des angles
au priphrique matriel et rcupre les rsultats. La mesure du temps d'excution peut
tre faite titre de comparaison mais on sait d'avance qu'elle sera moins bonne que les
ralisation prcdentes cause des changes SPI.

2) Utilisation de l'i2c pour interfacer un cur CORDIC (non ralis)


L'interface i2c et l'AVR est dcrite dans la page :
http://fr.wikiversity.org/wiki/Very_High_Speed_Integrated_Circuit_Hardware_Description_L
anguage/Utiliser_un_processeur_externe#Processeur_ATMega_avec_Arduino_et_protocol
e_I2C
Travail faire
1) On vous demande simple ment d'interfacer l'ensemble matriel cur i2c et cur
CORDIC (tous les deux fournis) pour en faire un priphrique matriel.
2) Une fois ce travail ralis, concevoir le logiciel sur le MSP430 qui donne des angles
au priphrique matriel et rcupre les rsultats. La mesure du temps d'excution peut
tre faite titre de comparaison mais on sait d'avance qu'elle sera moins bonne que les
ralisation prcdentes cause des changes i2c bien lentes.

93/94

M. Doussot, G. Millon, S. Moutou et B. Jacquot

TD et TP LO11

UTT 2014/2015

TP14 Interfacer un cran VGA (Annul)

INFO

L'interface VGA est prsente partir de la page 248 du


polycopi de cours.

Il y avait seulement 12 TPs cette anne 2013/2014. Ce TP n'a donc pas t rdig. Lisez
le WIKI correspondant :
https://fr.wikiversity.org/wiki/Very_High_Speed_Integrated_Circuit_Hardware_Description_
Language/Interfaces_VGA_et_PS2
Travail raliser

AVR_FPGA
I_CLK_50
I_CLR
I_RX
I_SWITCH[9:0]

io2
I_CLK
Q_7_SEGMENT[6:0]
+ I_CLK_50
Q_DOUT[7:0]
I_CLR
Q_INTVEC[5:0]
I_ADR_IO[7:0]
Q_LEDS[7:0]
I_DIN[7:0]
Q_AN[3:0]
I_SWITCH[7:0]
Q_TX
I_RD_IO
+ hsynch
I_RX
+ vsynch
I_WE_IO VGATop
+ red
+ green
CLK_50
+ blue
x_rect[9:0]
hsynch
y_rect[9:0]
vsynch
y_raquG[7:0]
red
y_raquD[7:0]
green
scoreG[7:0]
blue
ligne1[7:0]
ligne2[7:0]

94/94

Q_7_SEGMENT[6:0]
Q_LEDS[7:0]
Q_AN[3:0]
Q_TX
+ hsynch
+ vsynch
+ red
+ green
+ blue