Vous êtes sur la page 1sur 64

LEFEVRE

CHALOPIN
ELEC II

Juin 2007

Rapport mini-projet VHDL


Calculateur de Harvard

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

Table des matires


1.Introduction....................................................................................................................................... 4
2. Modle de programmation du calculateur........................................................................................ 4
A. Format registre............................................................................................................................ 5
B. Format immdiat......................................................................................................................... 6
C. Format branchement....................................................................................................................6
3. Architecture de Harvard................................................................................................................... 7
A. La mmoire de donnes.............................................................................................................. 8
B. Le chemin de donnes.................................................................................................................9
B.1 Le fichier de registres......................................................................................................... 10
B.2 Lunit fonctionnelle.......................................................................................................... 10
B.3 Le bloc zero fill.................................................................................................................. 11
B.4. Description en VHDL....................................................................................................... 11
C. Lunit de contrle.................................................................................................................... 12
C.1 Le compteur ordinal........................................................................................................... 12
C.2 Le dcodeur dinstructions................................................................................................. 12
C.4 Le Bloc Branch control...................................................................................................... 13
C.5 Description en VHDL........................................................................................................ 14
D. Le calculateur complet..............................................................................................................14
4.Descriptif du travail......................................................................................................................... 16
4.A La Mmoire de donnes..........................................................................................................16
Simulations et validations :....................................................................................................... 17
4.B Le Data Path............................................................................................................................19
4.B.1. Le banc de registre.....................................................................................................19
4.B.2. Les flags (indicateurs):.............................................................................................. 21
4.B.3. Le zero fill:................................................................................................................ 21
4.B.4. Les multiplexeurs:..................................................................................................... 21
4.B.5. L'unit fonctionnelle:................................................................................................. 21
4.B.6. Simulations et validations:.........................................................................................22
4.C L'unit de Contrle..................................................................................................................23
4.C.1 La mmoire d'instructions:.............................................................................................. 24
4.C.2 Le Branch Control:.......................................................................................................... 24
4.C.3 Le Bloc d'extension:........................................................................................................ 25
4.C.4 Extraction de l'instruction:...............................................................................................25
4.C.5 Le Compteur de Programme........................................................................................... 25
4.C.6 Dcodage :....................................................................................................................... 25
4.D Le calculateur Complet........................................................................................................... 26
Simulations et validations:................................................................................................... 27
5. Conclusion:.....................................................................................................................................28
6. Annexes.......................................................................................................................................... 29
6.A Mmoire:.................................................................................................................................29
6.A.1 memoire.vhd....................................................................................................................29
6.A.1 Testmemoire.vhd.............................................................................................................32
6.A.3 program.txt...................................................................................................................... 35
6.A.4 SimuMemoire.txt............................................................................................................ 36
6.A.5 Chronogrammes.............................................................................................................. 37
6.B DataPath:................................................................................................................................. 38
6.B.1 DataPath.vhd................................................................................................................... 38
6.B.2 TestDataPath.vhd............................................................................................................ 42
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

6.B.3 initReg.txt........................................................................................................................ 45
6.B.4 SimuDataPath.txt.............................................................................................................46
6.B.5 Chronogrammes.............................................................................................................. 48
6.C Unit de Contrle:................................................................................................................... 49
6.C.1 Ctrl Unit.vhd....................................................................................................................49
6.C.2 TestCtrl_Unit.vhd............................................................................................................53
6.C.3 programRom.txt.............................................................................................................. 55
6.C.4 SimuCtrl_Unit.txt............................................................................................................ 56
6.C.5 Chronogrammes:............................................................................................................. 58
6.D Le calculateur de Harvard:......................................................................................................59
6.D.1 HarvardCalculator.vhd.................................................................................................... 59
6.D.2 testHarvardCalculator.vhd.............................................................................................. 62
6.D.3Chronogrammes............................................................................................................... 63

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

Avant-propos
Le mini-projet qui vous est propos de raliser vise comme objectif essentiel de faire la
synthse de toutes vos connaissances accumules dans le module denseignement VHDL. Il
permet galement de parfaire des connaissances dispenses dans dautres modules en
proposant une description dune architecture dont les principes ont pu tre tudis dans ces
modules. Enfin, ce mini-projet est destin vous permettre de dvelopper une premire
exprience pratique de la modlisation VHDL, dans des conditions proches de celles dun
fonctionnement en entreprise.

1. Introduction
Les circuits non programmables dterminent les oprations excuter sur la base
uniquement de ces entres de contrle et de bits dtats du chemin de donnes. Un tel circuit
nexcute donc quune seule opration dfinie (ex : multiplication par additions et dcalages,
affichage dune donne dcimale, etc). Par opposition, un microprocesseur est responsable de
lextraction dinstructions depuis la mmoire et du squencement de lexcution de ces instructions
(calcul de ladresse suivante de linstruction excuter). Dans ce type darchitecture, le
microprocesseur est compos dun chemin de donnes dont les oprations sont pilotes par une
unit de contrle. La tche de cette unit de contrle consiste extraire, dcoder et excuter les
instructions. Un calculateur btit sur le modle de harvard possde la facult de traiter lensemble
de ces oprations en un cycle dhorloge lmentaire. La sparation physique des donnes et
instructions dans deux composants distincts est une des conditions indispensable. Linterconnexion
de ces composants au travers de signaux permettant de propager les signaux de donnes ainsi que
signaux de contrle permettra de dfinir le modle interne du microprocesseur. Lobjectif du projet
est de dcrire le comportement des diffrents composants de ce modle interne, modle qui sera
vrifi par simulation VHDL sous ModelSim.

2. Modle de programmation du calculateur


Le programmeur dun calculateur doit spcifier les instructions excuter laide dun
programme. Un programme peut donc se dfinir comme une liste dinstructions spcifiant les
oprations (code opration) et leurs oprandes. Il peut galement sagir dinstructions de contrle du
droulement du programme indiquant des branchements conditionnels ou inconditionnels
effectuer. Le registre compteur ordinal (PC) permet de conserver en mmoire ladresse de la
prochaine instruction excuter.

Les instructions sont stockes dans une mmoire dinstructions tandis que les oprandes
peuvent tre stockes dans diffrents emplacements :
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

un champ de linstruction
un registre dans un fichier de registres
un emplacement mmoire de donnes

Par consquent, outre la nature de lopration excuter, le code opration doit prciser les
modalits dexcution de linstruction et prciser lemplacement des oprandes utiliser. On
parle de format dinstruction ou encore de mthode dadressage (Figure 1). Le format des
instructions qui nous intresse ici est un format fixe (toutes les instructions sont codes sur un
nombre de bits identique). Le format utilis dans le cadre de notre calculateur fait apparatre
lutilisation de 3 champs adresse/oprande. On distingue par ailleurs 3 formats
dinstruction diffrents:

A. Format registre
Dans le cas dun format registre, les 3 champs fournissent un n de registre utiliser comme
emplacement des oprandes source A,B ou comme emplacement destinataire du rsultat. Les
champs tant cods sur 3 bits, on peut dsign jusqu 8 registres (23). Un des champs source peut
savrer non significatif lorsque linstruction na besoin que dun seul oprande. Par exemple,
linstruction code
0001011 011 101 XXX code machine
NOT R3 R5 assembleur

dfinit une instruction de complment 1 (NOT) du registre n5 (Reg src A), rsultat dans le
registre n3 (destination). La valeur des bits du champ B nest pas significative. On notera que
certaines oprations utilisent le champ B au lieu du champ A. Le champ registre destinataire peut
galement ne pas savrer significatif lorsquil sagit dun transfert vers la mmoire, un des registres
stockant ladresse mmoire pour le transfert. Par exemple, linstruction code
0100000 XXX 100 101 code machine
ST R4,R5 assembleur

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

dfinit une demande de transfert de la valeur de R5 lemplacement mmoire dadresse


contenue dans R4.

B. Format immdiat
Dans le cas dun format immdiat, un des oprandes est implicitement stock dans
linstruction, dans le champ de droite en loccurrence ici. Il sagit donc dune constante dont
la valeur se situera dans lintervalle 0 7. Par exemple,
1000010 010 111 011 code machine
ADI R2 R7 3 assembleur

spcifie une opration daddition de R7 avec la constante 3, avec rsultat de lopration dans
R2.

C. Format branchement
Par opposition aux deux formats prcdents, le dernier format dinstruction nengendre
aucune modification de registre ou de mmoire de donnes. Linstruction est destine modifier
(ventuellement sous condition) lordre dextraction des instructions de la mmoire, squentiel par
dfaut On parle encore dinstructions de rupture de squence. Pour cela, le champ dadresse est
spar en deux parties , avec les 3 bits de poids forts situs dans le champ adresse(G) et les trois
bits de poids faibles situs dans le champ adresse (D). La mthode dadressage est appele
adressage relatif au PC, les 6 bits dadresses formant le dplacement ajouter au PC. Ce
dplacement est considr comme sign (reprsentation en complment
2). Cela permet de se dplacer dans le sens croissant ou dcroissant des adresses. Par exemple,
1100000 101 110 100
BRZ R6,-20

spcifie un branchement ladresse PC 20(101100), si R6=0.

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

La table de la Figure 3 liste les diffrentes catgories dinstruction. Une description de type transfert
de registre explique le mode opratoire de chacune des instructions. La colonne de droite prcise si
les indicateurs N (pour ngatif) et Z (pour zro) sont affects par les instructions.

3. Architecture de Harvard
On sintresse prsent larchitecture du calculateur permettant lexcution des
instructions dfinit prcdemment, en un seul cycle dhorloge. Pour rduire la complexit du
modle, on se propose de dcomposer le calculateur en trois entits lmentaires:
lunit de contrle
le chemin de donnes
la mmoire centrale des donnes
Comme le montre la Figure 4, lunit de contrle pilote le chemin de donnes grce un
mot de contrle. Ce mot de contrle est form dun ensemble de signaux de contrle permettant de
positionner le chemin de donnes en fonction de linstruction excuter.
Dhorloge.

Une constante (Oprande immdiat) permet galement la rcupration de valeur de loprande


depuis la mmoire dinstructions dans le cas de ladressage immdiat. Le chemin de donnes
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

communique avec la mmoire de donnes grce deux bus unidirectionnels, selon le sens du
transfert raliser. Cette particularit, propre larchitecture harvard, est lune des particularits
(avec la sparation des mmoires dinstructions et de donnes) autorisant lexcution des
instructions ncessitant des accs en lecture et en criture dans le mme cycle dhorloge.

A. La mmoire de donnes
La mmoire de donnes est une mmoire de 216 lments (adresses) de 16 bits chacun.
Lopration dcriture est autorise par le signal de commande MW (pour memory write) sur niveau
haut. La valeur du mot de 16 bits correspondant ladresse est accessible en permanence sur le bus
en lecture. Ladresse du mot en lecture et en criture est donc commune et toute valeur inscrite dans
la mmoire modifie la valeur en sortie une fois celle-ci transfre.

Son comportement sera dcrit par un process manipulant une variable de type tableau,
process synchrone lhorloge clk. Le contenu devra pouvoir tre initialis pour mmoriser les
donnes initiales avant excution du programme(signal rst). Pour cela plusieurs solutions sont
possibles avec, dans lordre de flexibilit:
initialisation dans le programme VHDL au niveau de la dclaration : cette solution est la
plus simple mais elle suppose une recompilation de la description pour tout changement de contenu.
dclaration dun paramtre gnrique avec initialisation du contenu sur un signal rst. Cette
solution ne ncessite plus que la re-compilation de lentit test en cas de modification du contenu.
Mais, il vous faudra dfinir un package pour dclarer le type de ce paramtre.
Lecture des donnes initiales lues partir dun fichier : cest la solution la plus souple car
elle ne ncessite aucune recompilation. Cest galement la solution la plus proche de la ralit.Vous
pouvez dfinir une fonction load_program, fonction ralisant le chargement de la mmoire au rst.
Vous slectionnerez une des 3 mthodes, au choix. Le bus dadresse sera de type unsigned,
tandis que les bus de donnes seront de type signed (package numeric_bit de la bibliothque ieee).
La fonction de conversion to_integer vous permettra de convertir le type unsigned de ladresse sous
forme dentier, de manire pouvoir indicer correctement le tableau. On prendra 4 ns comme dlai
de propagation en lecture ou criture.

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

B. Le chemin de donnes
Diffrents composants forment la structure du chemin de donnes partag. On peut
distinguer:
un banc de registres, mmoire rapide interne au processeur compos de 8 registres de 16 bits
chacun.
une unit fonctionnelle, circuit combinatoire ralisant des oprations arithmtiques, logiques,
dcalages ou simples transferts.
quelques multiplexeurs permettant de configurer le chemin de donnes en fonction du mot de
contrle.

A titre dillustration, la table ci-dessous montre quelques exemples de micro-oprations


ralises par le chemin de donnes selon ltat du mot de contrle. Pour chaque microopration,
le multiplexeur MB est positionne en mode registre ou constante. Dans le premier
cas, loprande utilis par lunit fonctionnelle provient du fichier de registre.. Dans le second
cas, loprande provient de lextrieur (de la mmoire dinstructions de lunit de contrle) et
passe de 3 16 bits par ajout de 13 bits zro en tte. Le multiplexeur MD permet daiguiller
le rsultat dune opration ou une donne de la mmoire de donnes (data in) vers un registre
du fichier. Les 4 bits FS dfinissent la nature de lopration effectuer le cas chant.
Finalement, RW prcise si un registre doit tre modifi (1) ou non (0).

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

B.1 Le fichier de registres


Comme pour la mmoire de donnes, le banc de registre enregistre les donnes ladresse
DR sur un niveau haut de RW. La lecture des donnes seffectue sur deux bus distincts, le bus A et
le bus B. La prsence des donnes en sortie est permanente et fonction des adresses respectives DA
et DB. On notera que les critures sont synchrones lhorloge et sont effectues au dbut du cycle
dhorloge suivant la fin du traitement de linstruction courante.

B.2 Lunit fonctionnelle

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

10

Lunit fonctionnelle est capable de raliser diffrentes oprations stendant de la simple


opration de transfert pour les mouvements de donnes internes au microprocesseur ou les transferts
impliquant la mmoire externe de donnes. La table de vrit complte du composant vous est
fournie Figure 7.

B.3 Le bloc zero fill


Comme mentionn prcdemment, le microprocesseur peut utiliser une donne
implicitement contenu dans linstruction elle-mme. LUF utilisant des donnes de 16 bits, 13 bits
zros sont ajouts en tte de cette donne de 3 bits pour respecter cette contrainte. Par exemple,
110 devient 0000000000000110

B.4. Description en VHDL

La description des diffrents composants du chemin de donnes seffectuera laide


dinstructions daffectations concurrentes pour les diffrents signaux : bus D, dataout, ardout,
busB, etc. On noubliera pas de dcrire le comportement des indicateurs dtats en sortie de
lUF avec comme convention:
Z =1 si le rsultat de lopration est nul
N=1 si le rsultat de lopration est ngatif.
La description des indicateurs C(carry) et V(overflow) sera facultative. Le signal rst permettra
de positionner les registres dans un tat initial souhait. On retiendra les temps de propagation
Lecture ou criture dun registre du fichier de registre : 3 ns
Multiplexeurs (MD ou MB) et indicateurs: 1 ns
Unit fonctionnelle : 4 ns
On notera que des conversions unsigned-signed peuvent tre ncessaire lors, par exemple, de
la rcupration dune adresse partir du bus de donnes (par un simple cast ).

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

11

C. Lunit de contrle
Bien que traditionnellement considre comme ne faisant pas partie de lunit de contrle, la
mmoire dinstructions est dcrite ici par convenance. Lors de lexcution du programme,
seuls des accs en lecture vers cette mmoire sont possibles.

Outre la mmoire dinstructions (215 x 16 bits), lunit de contrle intgre les modules
suivants:

C.1 Le compteur ordinal


Le compteur ordinal PC fournit ladresse de linstruction extraire de la mmoire (16 bits).
Le compteur est mis jour chaque cycle dhorloge. Il peut sagir dune simple incrmentation,
dun chargement de la valeur en sortie du bloc extension (cas dun branchement conditionnel) ou de
ladresse (cas dun branchement inconditionnel). Un signal rst asynchrone (non reprsent sur la
figure) permet le positionnement sur la premire adresse du programme excuter (adresse 0
gnralement).

C.2 Le dcodeur dinstructions


La sortie de la mmoire est exploite par le dcodeur de linstruction, sortie que lon
dsignera par IR (IR pour instruction register, mme sil ne sagit pas dun registre proprement
parl).

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

12

16 bits des 20 bits en sortie du dcodeur permettant de contrler le fonctionnement du chemin


de donnes forment ce quon appelle le mot de contrle. La valeur de 3 bits DA, BA, AA
sobtient de manire directe partir des champs dadresse de linstruction. Il est en de mme
pour les bits de slection de lopration de lUF (FS) qui sont directement issus des bits de
poids faible du code opration de linstruction, sauf pour linstruction de branchement
conditionnel o les 4 bits de FS seront forcs zro. Cela permet lvaluation des indicateurs
Z et N par rapport au contenu du registre adress par RA. Letat des autres bits du dcodeur
est fonction de linstruction et se dfinit par la table de vrit ci-dessous (Figure 10). Cette
table de vrit montre les diffrentes catgories dinstructions.

Outre les signaux de commande du chemin de donnes, on trouve galement la valeur des
signaux de commande interne lunit de contrle et permettant la gestion du squencement
(PL, JB, BC). La table de vrit montre que PL vaut 1 lorsque le code opration spcifie une
instruction de contrle, JB valant 1 lorsque le branchement est inconditionnel, 0 sinon. Dans
le cas dun branchement conditionnel, BC prcise lindicateur servant de condition de
branchement (0 pour Z, 1 pour N).

C.4 Le Bloc Branch control


Le rle de ce bloc est de dterminer la valeur de LD (autorisation de branchement
conditionnel) en fonction des valeurs des bits BC,N, Z. Le comportement de ce bloc peut tre
spcifi par la table de vrit compacte ci-dessous.

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

13

La table de vrit montre que la valeur de LD dpend de lindicateur utilis (dtermin par
BC) et de la valeur de cet indicateur. Par exemple, si BC=0, il faut Z=1 pour que le
branchement soit effectu.

C.5 Description en VHDL

Comme pour le chemin de donnes, la description des diffrents composants seffectuera


laide dinstructions daffectation concurrentes. Les valeurs non significatives (X) lors du dcodage
seront forces 0. On retiendra les temps de propagation suivants :
Incrmentation ou chargement du PC : 1 ns
Lecture de la mmoire dinstructions : 3 ns
Dcodage : 1 ns

D. Le calculateur complet
Le calculateur complet (dont les entres/sorties se limitent aux entres clk et rst) se dcrira
en assemblant 2 entits mmoire et CPU, cette dernire entit tant elle-mme une entit forme des
composants datapath et contrle.

Le cycle dhorloge devra tre rgl par rapport au chemin critique en cumulant les temps de
propagation des composants traverss lors de lexcution dune instruction la plus longue.
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

14

Comme le montre la Figure 16, le cumul des temps de propagation aboutit un dlai de 17 ns.
La frquence dhorloge maximale est donc de 58.8 MHZ.

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

15

4.Descriptif du travail
Pour raliser ce mini-projet nous avons choisi de respecter l'ordre conseill dans les sujets.
C'est dire que nous avons commenc par la conception de la mmoire, puis celle du Data Path et
enfin l'Unit de Contrle.

4.A La Mmoire de donnes


Nous avons conu l'entit mmoire l'aide de paramtres gnriques pour pouvoir la rendre
modulable. Nanmoins nous choisissons d'imposer la mme taille pour le bus d'adresse et le bus de
donne. Le temps de propagation dans la mmoire est lui aussi gnrique.
generic(NbBits : natural ; tco : time);

Nous choisissons de dfinir notre mmoire comme tableau contenant des entiers signs. Sa
taille est donc 2^ NbBits-1, nous appelons notre type mmoire MemTableau.
type MemTableau is array (0 to 2**NbBits-1) of signed(NbBits-1 downto 0);

D'aprs la description du cahier des charges, lcriture dans la mmoire de donne se fait
uniquement sur un niveau haut du signal memory_write (mw). La valeur de datain alors crite sur
la sortie dataout ainsi que dans la mmoire ladresse adresse (adr).
En mode lecture, on transfre la donne qui se trouve dans la mmoire ladresse adresse
sur la sortie dataout.
Les critures sont synchrones mais les lectures doivent pouvoir seffectuer en permanence.
Le process qui dcrit le fonctionnement de cette mmoire est donc sensible aux paramtres clk
(lhorloge), rst (reset) et adresse. L'entre rst permet d'initialiser le contenu de la mmoire partir
d'un fichier.
mem:process(clk,rst,adr)
-- declaration de notre memoire, tabdata represente la memoire comme
-- un tableau contenant des entiers signs
variable tabdata : MemTableau;
begin
if (rst= '1') then -- rst asynchrone actif etat bas
-- premire solution : initialisation dans le programme
-- VHDL au niveau de la dclaration
-- init_zero: for i in 0 to 2**NbBits-1 loop
-- tabdata(i):= (others => std_logic'('0'));
-- end loop init_zero;
-- solution non retenue
-- deuxime solution : Lecture des donnes initiales lues
-- partir d'un fichier :
tabdata := load_program;
-- les evenements synchrones l'horloge
elsif ( clk='1' and clk'event) then

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

16

if(Mw ='1') then


--write
dataout<=datain after tco;
tabdata(to_integer(adr)):=datain ;
end if; --write
end if; -- rst/clk
--read asynchrone
dataout <= tabdata(to_integer(adr)) after tco;
end process;--mem
end behv;

Pour initialiser la mmoire nous avons opt pour une lecture de fichier. Cela permet de
pouvoir facilement changer les donnes dinitialisation sans recompiler tout le code VHDL. Nous
avons donc cr une fonction load_program (comme c'est conseill dans le sujet) qui lit le fichier
program.txt et crit ses valeurs dans la mmoire. Les donnes dans le fichier sont des entiers qui
reprsentent respectivement ladresse mmoire et la valeur inscrire. Ils sont en format entier
naturel dans le fichier et convertis lors de lcriture dans la mmoire.
function load_program return MemTableau is
file fd : text open READ_MODE is "program.txt";
variable ligne : line;
variable data : integer;
variable adr : natural;
variable mem2 : MemTableau;
begin
while not endfile(fd) loop
readline(fd,ligne);
if ligne'length > 0 and ligne(1) /='-' then
read(ligne,adr );
read(ligne,data);
mem2(adr):=to_signed(data,NbBits);
end if;
end loop;
return mem2;
end load_program;

Simulations et validations :
Pour valider le comportement de notre mmoire nous avons encore une fois fait appel
lutilisation dun fichier de simulation SimuMemoire.txt dans lequel nous avons incorpor des
driver de rst, mw, adr et datain. Cela permet une modification aise des paramtres de la simulation
sans recompiler tout le code . De plus la lisibilit est accrue par rapport une affectation classique
des signaux dans le fichier VHDL de test.
Lors de l'initialisation de la mmoire ( sur le signal rst) nous choisissons de charger partir
de l'adresse 0, le programme de test est fourni dans le sujet. Voici donc le contenu du fichier
program.txt:
0

5120

8280

49288

8352

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

17

49296

2762

49692

208

264

57400

10

200

11

272

12

49304

13

1028

14

3288

15

57400

Pour valider le comportement de la mmoire nous commenons par faire un reset avec rst
l'tat bas, puis on le maintient au niveau haut pour le reste de la simulation. Ensuite on vrifie que le
programme a bien t charg, en demandant des lecture l'adresse 0 jusqu' l'adresse 5. Les 6
premires valeurs du programme prcdemment charg doivent alors apparatre sur la sortie et
respecter les temps de propagation. On demande ensuite des critures (mw tat haut) de donnes
alatoires des adresses alatoires. Puis on demande des lectures aux adresses o l'on vient d'crire.
Dataout doit alors correspondre au prcdentes entres. Voici le contenu du fichier de test :
-- RST MW

ADR

DATAIN

00

0000000000000000 0000000000000001

10

0000000000000001 0000000000000001

10

0000000000000010 0000000000000010

10

0000000000000011 0000000000000011

10

0000000000000100 0000000000000001

10

0000000000000101 0000000000000001

10

0000000000000110 0000000110000001

10

0000000000000111 0000000110000101

10

0000000000001000 0000010000111001

10

0000000000001001 0000000000000001

10

0000000000000011 0000000000000001

10

0000000000000111 0000000000000001

10

0000000000000000 0000000000000001

10

0000000000000001 0000000000000001

10

0000000000000010 0000000000000001

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

18

10

0000000000000011 0000000000000001

10

0000000000000100 0000000000000001

10

0000000000000101 0000000000000001

11

0000001110000001 0001000100100011

11

0000001000100100 0010010101010101

11

0000000000000011 0000000000000001

10

0000001110000001 0000000000000001

10

0000001000100100 0000000000000001

Les codes VHDL de la mmoire, du test bench de la mmoire ainsi que les rsultats de la
simulation sont fournis en annexe.

4.B Le Data Path


Ce module a pour but de diriger les donnes et deffectuer des oprations en fonction dun
mot de contrle. Le cahier des charges nous impose une description comportementale de type
Dataflow ce qui nous a pos des problmes au moment de linitialisation de ces registres pour
effectuer la simulation finale. En effet elle ncessite que des valeurs particulires soient inscrites
dans certains registres pour valider le fonctionnement.
4.B.1. Le banc de registre
Le banc de registre est de type Banc_reg. Comme pour la mmoire il est reprsent par un
tableau contenant des entiers signs. La taille des registres ainsi que leur nombre sont gnriques
afin de pouvoir facilement changer les caractristiques du calculateur. Il en est de mme pour les
diffrents temps de propagation. Nous avons choisi de donner 8 registres par dfaut car bien que ce
paramtre soit gnrique son changement influencerait trop l'architecture du calculateur. Rajouter
des registres suplmentaires serait incompatible avec le mot de contrle (il faudrait rajouter un bit a
l'adressage des registres).
type Banc_reg is array (0 to Nbreg-1) of signed(NbBits-1 downto 0);
En description Dataflow on ne peut pas affecter plusieurs fois le mme signal. Or dans notre
cas nous avons besoin dinitialiser des registres lors dun reset et aussi daffecter les registres
dtermins par la valeur des bits 15 13 du mot de contrle lors des variations du bus DDATA.
Aprs validation auprs de monsieur Dekneuvel nous avons finalement dcid de raliser un
process sensible clk (lhorloge) et rst (reset) pour pouvoir initialiser et affecter des valeurs dans
les registres.
process(clk,rst)
variable initialisation : Banc_reg :=initBanc_reg;
begin
--initialisation des registres sur reset actif niveau bas
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

19

if rst='0' then
breg<=initialisation after twr_reg;
--ecriture dans les registres synchrone
elsif clk='1' and clk'event then
if ctrlword(0)='1' then
breg(to_integer(ctrlword(15 downto 13))) <= Ddata after twr_reg;
end if;
end if;
end process;
La fonction initBanc_reg permet d'initialiser les registres (sur rst l'tat bas) dans l'tat qu'on
souhaite grce au fichier initReg.txt. La premire colonne du fichier correspond au numro du
registre, la deuxime son contenu lors de l'initialisation. Voici son implementation :
function initBanc_reg return Banc_reg is
file fd :text open READ_MODE is "initReg.txt";
variable breg2: Banc_reg;
variable numli:natural:=0;
variable donnee:std_logic_vector(NbBits-1 downto 0);
variable ligne:line;
begin
while not endfile(fd) loop
readline(fd,ligne);
if ligne'length>0 and ligne(1)/='-' then
read(ligne,numli);
read(ligne,donnee);
breg2(numli):=signed(to_bitvector(donnee));
end if;
end loop;
return breg2;
end initBanc_reg;
Pour grer les entres/sorties du banc de registre, nous crons des signaux intermdiaires et nous
leur affectons les diffrents bits du mot de contrle. Voici comment nous procdons.
Adata<=breg(to_integer(ctrlword(12 downto 10))) after twr_reg;
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

20

Bdata<=breg(to_integer(ctrlword(9 downto 7))) after twr_reg;


data_out<=B;
adr_out<=unsigned(Adata);
4.B.2. Les flags (indicateurs):
Lunit de contrle a besoin de savoir si la valeur F est ngative ou nulle. Les signaux N et
Z sont des indicateurs permettent de renseigner l'unit de contrle. Ces informations sont utiles lors
de lutilisation de sauts conditionnels. Voici comment ils sont grs:
N<='1' after tuf when to_integer(F)<0 else '0' after tuf;
Z<='1' after tuf when to_integer(F)=0 else '0' after tuf;
4.B.3. Le zero fill:
On affecte les bits 0, 1 et 2 puis le reste est complt par des zros. Nous utilisons 'others'
pour ne pas tre dpendant de la taille des donnes.
Constant_in <= (2=> cste(2),1 => cste(1),0 => cste(0),others=>'0');
Attention cette desciption du zero fill gnre un warning la compilation.
4.B.4. Les multiplexeurs:
Nous avons besoins de deux multiplexeurs, un l'entre et l'autre la sortie de l'unit de
l'unit fonctionelle. Le premier gre l'entre d'un constante sur B. Et l'autre gre l'entre d'une
constante dans le banc de registre.
B<=Constant_in after tmux when ctrlword(6)='1' else Bdata after tmux;
Ddata<=data_in after tmux when ctrlword(1)='1' else F after tmux;
4.B.5. L'unit fonctionnelle:
Son rle est de raliser les oprations sur les oprandes A et B. Son fonctionnement nous est
donn par une table de vrit. Son comportement est donc combinatoire et peut donc se dfinir avec
un case. Mais comme on ne se trouve pas dan un process. Donc on utilise l'instruction with...select.
Nous utilisons others pour les combinaisons non dfinies. Et lorsque cela se produit l'unit
fonctionnelle renvoie '0'. Voici sont implmentation:
with ctrlword(5 downto 2) select
F<=A after tuf when "0000",
A+1 after tuf when "0001",
A+B after tuf when "0010",

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

21

A+B+1 after tuf when "0011",


A+(not B) after tuf when "0100",
A+(not B)+1 after tuf when "0101",
A-1 after tuf when "0110",
A after tuf when "0111",
A and B after tuf when "1000",
A or B after tuf when "1001",
A xor B after tuf when "1010",
(not A) after tuf when "1011",
B after tuf when "1100",
'0'&B(NbBits-1 downto 1) after tuf when "1101",--left shift
B(NbBits-2 downto 0)&'0' after tuf when "1110",--right shift
"0" after tuf when others; --renvoie zero quand le code FS n'est pas reconnu
4.B.6. Simulations et validations:
Pour valider le DataPath nous utilisns toujours les fichiers, pour les mmes raisons dcrites
prcdemment pour la mmoire. Nous utilisons 2 fichiers. Le premier initialise les registres, le
deuxime contient les drivers des fichiers de test.Voici le contenu du fichier qui initialise les
registres:
--ime registre

data

0000000000000001

0000000000000101 -- 5

0000000000000100

0000000011111000 -- 248

0000000000010000

0000000000000000 -- 0

0000000001000000

0000000010000000

Le deuxime fichier va dfinir le comportement des signaux de test du dataPath. Lors de ce


test nous effectuons divers micros oprations pour valider son comportement (addition, load etc).
Voici le contenu de ce deuxime fichier (des commentaires donnent des explications sur les
oprations effectues) :
--clk

rst

ctrlword

dataIn

cste

-- reset
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

22

0000000000000011 1111111111111111 001

0000000000000011 1111111111111111 001

-- R0<- Datain
0

0000000000000011 0000000100000011 001

0000000000000011 0000000100000011 001

-- R1<- Datain
0

0010000000000011 0000000000000001 001

0010000000000011 0000000000000001 001

-- R7<- Datain (oxCAFE!!!!!j'aime le caf!)


0

1110000000000011 1100101011111110 001

1110000000000011 1100101011111110 001

-- R3<-R1+R0 (resulat= 0000000000000010)


0

0110010000001001 1100101011111110 010

0110010000001001 1100101011111110 010

-- R3<-Datain signed(-1)
0

0110000000000011 1111111111111111 010

0110000000000011 1111111111111111 010

-- dataout<-R7
0

0000001110000000 0000000000000111 010

0000001110000000 0000000000000111 010

-- R6<-R7+(cte=1) (resulat = oxCAFF Caisse Allocation Familiale Franaise haha!!)


0

1101110001001001 0000000000000111 001

1101110001001001 0000000000000111 001

-- R5<-R0+2
0

1010000001001001 0000000000000111 010

1010000001001001 0000000000000111 010

-- R6<- Datain (j'aime vraiment le cafe)


0

1100000000000011 1100101011111110 001

1100000000000011 1100101011111110 001

Les codes VHDL du DataPath, son test bench ainsi que les rsultats de la simulation sont
fournis en annexe.

4.C L'unit de Contrle


Le rle de ce bloc est de fournir le mot de contrle en fonction de la donne charge dans la
mmoire dinstructions. Le cahier des charges nous spcifie une description comportementale de
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

23

type dataflow.

4.C.1 La mmoire d'instructions:


Comme pour l'entit mmoire nous choisissons pour la mmoire d'instruction d'utiliser un
tableau contenant des entiers mais cette fois-ci non signs:
type ROM is array(0 to 2**NbBits-1) of unsigned(NbBits-1 downto 0);
Cette mmoire est initialise l'aide d'un fichier qui contient le programme excuter. Voici
la fonction qui initialise la mmoire d'instruction:
function initROM return ROM is
file fd :text open READ_MODE is "programRom.txt";
variable mem2: ROM;
variable numli:natural:=0;
variable data:std_logic_vector(NbBits-1 downto 0);
variable ligne:line;
begin
while not endfile(fd) loop
readline(fd,ligne);
if ligne'length>0 and ligne(1)/='-' then
read(ligne,data);
mem2(numli):=unsigned(to_bitvector(data));
numli:=numli+1;
end if;
end loop;
return mem2;
end initROM;
Comme cette mmoire n'est accessible seulement en lecture, nous choisissons d'utliser une
constante pour reprsenter cette mmoire:
constant mem_instruc: ROM:=initRom;

4.C.2 Le Branch Control:


Le branch Control spcifie au PC s'il faut effectuer un saut d'adresse ou charger une adresse
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

24

externe dtermine par le bloc d'extension. Le comportement du Branch Control est dfinie dans le
cahier des charges.Voici comment nous l'avons dcrit en VHDL:
Ld<=Z when (BC='0') else N when (BC='1');

4.C.3 Le Bloc d'extension:


Ce bloc a pour but de dfinir le saut dadresse effectuer. Il prend en entre la concatnation
des bits 8 6 et 2 0 de la sortie IR de la mmoire dinstruction. Il faut procder une extension
des bits pour pouvoir faire laddition la valeur courante de PC. Pour cela on tend avec la valeur
du bit de poids fort, c'est--dire IR(8). Voici comment nous avons procd:
extension<=(5=>IR_sur_16_bits(8),4=>IR_sur_16_bits(7),3=>IR_sur_16_bits(6),
2=>IR_sur_16_bits(2),1=>IR_sur_16_bits(1),0=>IR_sur_16_bits(0),others=>IR_sur_16_bits(8));

4.C.4 Extraction de l'instruction:


L'instruction est charge partir de la mmoire depuis l'adresse point par PC. Les deux bits
de poids faible de l'instruction sont renvoys vers le bloc d'extension:
IR_sur_16_bits<=mem_instruc(to_integer(PC)) after t_r_mem;
IR<=signed(IR_sur_16_bits(2 downto 0));

4.C.5 Le Compteur de Programme


Il fournit en sortie la valeur de ladresse laquelle il faut aller chercher linstruction dans la
mmoire dinstructions. Son comportement est dfini dans la table donne dans le cahier des
charges. Son fonctionnement est synchrone lhorloge, on a donc sur chaque front montant une
nouvelle adresse en sortie de ce bloc.
PC<=(others=> '0') after t_inc_load when rst='0' else
PC+1 after t_inc_load when (PL='0' or (PL='1' and JB='0' and Ld='0')) and CLK'event and
CLK='1' else
adr after t_inc_load when PL='1' and JB='1' and CLK'event and CLK='1' else
PC+extension after t_inc_load when PL='1' and JB='0' and Ld='1' and CLK'event and
CLK='1';

4.C.6 Dcodage :
Il fournit le mot de contrle en sortie du dcodeur ainsi que la valeur des signaux MW, PL,
JB et BC. Lanalyse de la table de vrit fournie dans le cahier des charges nous a permis
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

25

d'effectuer quelques simplifications (de type karnaugh) et donc de modliser son comportement de
la faon suivante :
-- DA
DA<=IR_sur_16_bits(8 downto 6) after t_dec;
-- AA
AA<=IR_sur_16_bits(5 downto 3) after t_dec;
-- BA
BA<=IR_sur_16_bits(2 downto 0) after t_dec;
-- FS
FS<="0000" after t_dec when PL='1' and JB='0' else IR_sur_16_bits(5 downto 2) after t_dec;
-- MB
MB<='1' after t_dec when IR_sur_16_bits(15 downto 13)="100" else '0' after t_dec;
-- MD
MD<='1' after t_dec when IR_sur_16_bits(15 downto 13)="001" else '0' after t_dec;
-- RW
RW<='1' after t_dec when IR_sur_16_bits(14)='0' else '0' after t_dec;
-- MW
MW<='1' after t_dec when IR_sur_16_bits(15 downto 13)="010" else '0' after t_dec;
-- PL
PL<='1' after t_dec when IR_sur_16_bits(15 downto 14)="11" else '0' after t_dec;
-- JB
JB<='1' after t_dec when IR_sur_16_bits(15 downto 13)="111" else '0' after t_dec;
-- BC
BC<='1' after t_dec when IR_sur_16_bits(15 downto 13)&IR_sur_16_bits(9)="1101" else '0'
after t_dec;
Le mot de contrle est juste la concatnation dans le bon ordre des diffrents signaux du dcodeur
d'instruction:
ctrlword<=DA&AA&BA&MB&FS&MD&RW;

4.D Le calculateur Complet


Le calculateur complet est juste l'assemblage des trois composants prcdemment conus. Il
n'y a pas de relle subtilit dcrire dans son implmentation VHDL. Comme le nombre de fils
relier est lev, nous avons tent de donner des noms aux signaux, qui traduisent d'o ils partent et
o ils vont :

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

26

signal Mw_uc_to_mem : bit;


signal data_dp_to_mem : signed(NbBits-1 downto 0);
signal adr_out_dp_to_mem_and_uc: unsigned(NbBits-1 downto 0);
signal ctrlword_uc_to_dp : unsigned(NbBits-1 downto 0);
signal cste_uc_to_dp : signed(2 downto 0);
signal data_mem_to_dp: signed(NbBits-1 downto 0);
signal V_dp_to_uc, C_dp_to_uc, N_dp_to_uc, Z_dp_to_uc : bit;
Simulations et validations:
La validation de notre Calculateur de Harvard consiste en l'excution russie du programme
fourni en exemple. Les seuls signaux qui doivent tre drivs pendant la simulation sont la clk et le
rst. Nous n'avons donc pas cr de fichier spcifiques pour cette simulation. Les codes VHDL du
Calculateur de Harvard , son test bench ainsi que les rsultats de la simulation sont fournis en
annexes.

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

27

5. Conclusion:
Ce mini projet nous a permis de mettre en avant nos connaissances dans la programmation
en VHDL. Nous avons pu raliser un calculateur de Harvard fonctionnel. Ce fut un projet
intressant dans la mesure o nous avons t confronts des problmes de conceptions complexes.
Le calculateur de Hardvard que nous avons dcrit peut tre considr comme une bauche de
micro-processeur, ce qui est trs gratifiant. Il serait maintenant intressant de vrifier si le code que
nous avons crit est synthtisable, pour pouvoir l'implmenter dans un composant programmable de
type FPGA.

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

28

6. Annexes
6.A Mmoire:
6.A.1 memoire.vhd
Voici le code VHDL de la mmoire:
library IEEE;
use ieee.numeric_bit.all;
--use IEEE.numeric_std.all;
use std.textio.all;--import pour grer les fichiers
------------------------------ l'entit memoire
----------------------------entity memoire is
generic(NbBits : natural ; tco : time);
port(datain : in signed(NbBits-1 downto 0);
Mw,rst,clk : in bit;
adr : in unsigned(NbBits-1 downto 0);
dataout : out signed(NbBits-1 downto 0));
end memoire;
architecture behv of memoire is
-- defintion de la memoire comme un tableau d'entiers signs
type MemTableau is array (0 to 2**NbBits-1) of signed(NbBits-1 downto 0);
----------- FONCTION : initialise la mmoire, charge le programme
---------function load_program return MemTableau is
file inputStream : text open READ_MODE is "program.txt";
variable ligne : line;
variable data : integer;
variable adr : natural;
variable mem2 : MemTableau;

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

29

begin
while not endfile(inputStream) loop
readline(inputStream,ligne);
if ligne'length > 0 and ligne(1) /='-' then
read(ligne,adr);
read(ligne,data);
mem2(adr):=to_signed(data,NbBits);
end if;
end loop;
return mem2;
end load_program;
----------- DESCRIPTION
---------begin
mem:process(clk,rst,adr)
-- declaration de notre memoire, tabdata represente la memoire comme
-- un tableau contenant des entiers signs
variable tabdata : MemTableau;
begin
if (rst= '0') then -- rst asynchrone actif etat bas
-- premire solution : initialisation dans le programme
-- VHDL au niveau de la dclaration
-- init_zero: for i in 0 to 2**NbBits-1 loop
-- tabdata(i):= (others => std_logic'('0'));
-- end loop init_zero;
-- solution non retenue
-- deuxime solution : Lecture des donnes initiales lues
-- partir d?un fichier :
tabdata := load_program;
-- les evenements synchrones l'horloge
elsif ( clk='1' and clk'event) then
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

30

if(Mw ='1') then


--write
dataout<=datain after tco;
tabdata(to_integer(adr)):=datain ;
end if; --write
end if; -- rst/clk
--read
dataout <= tabdata(to_integer(adr)) after tco;
end process;--mem
end behv;

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

31

6.A.1 Testmemoire.vhd
Voici le TestBench de la mmoire:
library IEEE;
use ieee.std_logic_1164.all;
use IEEE.numeric_std.all;
use ieee.std_logic_textio.all;
use std.textio.all;--import pour grer les fichiers
entity testmem is
end entity;
architecture bench of testmem is
component memoire is
generic(NbBits : natural ;
tco : time);
port(datain : in signed(NbBits-1 downto 0);
Mw,rst,clk : in bit;
adr : in unsigned(NbBits-1 downto 0) ;
dataout : out signed(NbBits-1 downto 0));
end component;
--dcalration des constantes
constant NbBits : natural := 16;
constant tco : time := 4 ns;
constant cycle : time := 10 ns;
--dclaration des signaux de test
signal datain_test : signed(NbBits-1 downto 0);
signal Mw_test : bit :='0';
signal rst_test,clk_test : bit :='1';
signal adr_test : unsigned(NbBits-1 downto 0);
signal dataout_test : signed(NbBits-1 downto 0);
file fd :text open READ_MODE is "SimuMemoire.txt";
begin

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

32

mem : memoire generic map(NbBits=>NbBits,tco=>tco)port


map(datain=>datain_test,Mw=>Mw_test,rst=>rst_test,clk=>clk_test,adr=>adr_test,dataout=>datao
ut_test);
SIMU:process
--declaration des signaux
variable datainF: std_logic_vector(NbBits-1 downto 0);
variable MwF,rstF: bit;
variable adrF: std_logic_vector(NbBits-1 downto 0);
variable ligne:line;
begin
while not endfile(fd) loop
readline(fd,ligne);
if ligne'length>0 and ligne(1)/='-' then
read(ligne,rstF);
read(ligne,MwF);
read(ligne,adrF);
read(ligne,datainF);
--affectation des isugnaux lus dans le fichier
rst_test<=rstF;
Mw_test<=MwF;
adr_test<=unsigned(adrF);
datain_test<=signed(datainf);
clk_test<=not clk_test;
wait for cycle;
clk_test<=not clk_test;
wait for cycle;
end if;
end loop;
end process;
end bench;

--datain_test <= X"aaaa" after 25 ns, X"a0a0" after 35 ns, X"0a0a" after 45 ns, X"ffff" after 55 ns;
--Mw_test <='0' after 20 ns, '1' after 25 ns, '0' after 75 ns;
--rst_test <='1' after 10 ns, '0' after 12 ns;
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

33

--clk_test <=not clk_test after 10 ns;


--adr_test <=X"0000" after 20 ns,X"0001" after 30 ns,X"0002" after 40 ns,X"0001" after 100
ns,X"0000" after 130 ns;
--end bench;

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

34

6.A.3 program.txt
Voici le fichier contenant le programme charg sur le rst de la mmoire:
0

5120

8280

49288

8352

49296

2762

49692

208

264

57400

10

200

11

272

12

49304

13

1028

14

3288

15

57400

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

35

6.A.4 SimuMemoire.txt
Voici le fichier contenant les drivers des signaux de test de la mmoire:
-- RST MW

ADR

DATAIN

00

0000000000000000 0000000000000001

10

0000000000000001 0000000000000001

10

0000000000000010 0000000000000010

10

0000000000000011 0000000000000011

10

0000000000000100 0000000000000001

10

0000000000000101 0000000000000001

10

0000000000000110 0000000110000001

10

0000000000000111 0000000110000101

10

0000000000001000 0000010000111001

10

0000000000001001 0000000000000001

10

0000000000000011 0000000000000001

10

0000000000000111 0000000000000001

10

0000000000000000 0000000000000001

10

0000000000000001 0000000000000001

10

0000000000000010 0000000000000001

10

0000000000000011 0000000000000001

10

0000000000000100 0000000000000001

10

0000000000000101 0000000000000001

11

0000001110000001 0001000100100011

11

0000001000100100 0010010101010101

11

0000000000000011 0000000000000001

10

0000001110000001 0000000000000001

10

0000001000100100 0000000000000001

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

36

6.A.5 Chronogrammes
Voici le rsulat de la simualtion pour la mmoire:

Sur ce chronogramme, on peut voir en premier un


rst qui charge le programme dans la mmoire.
En suite des lectures sont demandes, et la mmoire
envoie sur la sortie les valeurs qui ont t
prcedemment charges par le rst.
Aprs quelques lectures, des critures sont
demandes. La mmoire enregistre les donnes
aux adresses demandes. Des lectures sont
effectues sur ces mme adresses. On peut voir en
sortie les donnes prcdemment entres.
Les temps de propagation sont respects.
La mmoire est donc valide.

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

37

6.B DataPath:
6.B.1 DataPath.vhd
Voici le fichier source VHDL du Datapath:
library ieee;
use ieee.numeric_bit.all;
--use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
use std.textio.all;
use ieee.std_logic_textio.all;
entity datapath is
generic(NbBits: natural;
Nbreg: natural := 8;
twr_reg : time; -- temps acces w/r du banc de registre
tmux : time; --temps multiplexeur et indicateur
tuf : time); -- temps unit fonctionnele
port(clk:in bit;
rst: in bit;
ctrlword: in unsigned(NbBits-1 downto 0);
cste: in signed(2 downto 0);
data_in: in signed(NbBits-1 downto 0);
data_out: out signed(NbBits-1 downto 0);
adr_out: out unsigned(NbBits-1 downto 0);
V,C,N,Z: out bit);
end Datapath;

architecture dflow of datapath is


--description du Banc de registre comme un tableau de
--Nbreg entier signs de NbBits bits ici 8 et 16
type Banc_reg is array (0 to Nbreg-1) of signed(NbBits-1 downto 0);
-- les signaux du datapath

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

38

signal breg: Banc_reg;


signal A,B,F,AData,Bdata,Ddata,Constant_in: signed(NbBits-1 downto 0);
-----------fonction d'initialisation des registres
--------function initBanc_reg return Banc_reg is
file fd :text open READ_MODE is "initReg.txt";
variable breg2: Banc_reg;
variable numli:natural:=0;
variable donnee:std_logic_vector(NbBits-1 downto 0);
variable ligne:line;
begin
while not endfile(fd) loop
readline(fd,ligne);
if ligne'length>0 and ligne(1)/='-' then
read(ligne,numli);
read(ligne,donnee);
breg2(numli):=signed(to_bitvector(donnee));
end if;
end loop;
return breg2;
end initBanc_reg;
--DESCRIPTION
begin
process(clk,rst)
variable initialisation : Banc_reg :=initBanc_reg;
begin
--initialisation des registres sur reset actif niveau bas
if rst='0' then
breg<=initialisation after twr_reg;
--ecriture dans les registres synchrone
--actif et MW niveau haut
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

39

elsif clk='1' and clk'event then


if ctrlword(0)='1' then
breg(to_integer(ctrlword(15 downto 13))) <= Ddata after twr_reg;
end if;
end if;
end process;
-- Banc de registre
Adata<=breg(to_integer(ctrlword(12 downto 10))) after twr_reg;
Bdata<=breg(to_integer(ctrlword(9 downto 7))) after twr_reg;
data_out<=B;
adr_out<=unsigned(Adata);
--les flags
N<='1' after tuf when to_integer(F)<0 else '0' after tuf;
Z<='1' after tuf when to_integer(F)=0 else '0' after tuf;
--"zero fill"
Constant_in <= (2=> cste(2),1 => cste(1),0 => cste(0),others=>'0');
--entre de l'unite fonctionnelle
A<=Adata;
--le mux
B<=Constant_in after tmux when ctrlword(6)='1' else Bdata after tmux;

--Unit fonctionnelle
with ctrlword(5 downto 2) select
F<=A after tuf when "0000",
A+1 after tuf when "0001",
A+B after tuf when "0010",
A+B+1 after tuf when "0011",
A+(not B) after tuf when "0100",
A+(not B)+1 after tuf when "0101",
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

40

A-1 after tuf when "0110",


A after tuf when "0111",
A and B after tuf when "1000",
A or B after tuf when "1001",
A xor B after tuf when "1010",
(not A) after tuf when "1011",
B after tuf when "1100",
'0'&B(NbBits-1 downto 1) after tuf when "1101",--left shift
B(NbBits-2 downto 0)&'0' after tuf when "1110",--right shift
"0" after tuf when others; --renvoie zero quand le code FS n'est pas reconnu

--le mux D
Ddata<=data_in after tmux when ctrlword(1)='1' else F after tmux;

end dflow;

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

41

6.B.2 TestDataPath.vhd
Voici le testBench utlis pour simuler et valider le DataPath:
--chargement des librairies
library ieee;
use ieee.numeric_bit.all;
use std.textio.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_textio.all;
entity testdatapath is
end entity;
architecture bench of testdatapath is
component datapath is
generic(NbBits: natural;
Nbreg: natural := 8;
twr_reg : time; -- temps acces w/r du banc de registre
tmux : time; --temps multiplexeur et indicateur
tuf : time); -- temps unit fonctionnele
port(clk:in bit;
rst: in bit;
ctrlword: in unsigned(NbBits-1 downto 0);
cste: in signed(2 downto 0);
data_in: in signed(NbBits-1 downto 0);
data_out: out signed(NbBits-1 downto 0);
adr_out: out unsigned(NbBits-1 downto 0);
V,C,N,Z: out bit);
end component;
--dclaration des constantes
constant NbBits : natural := 16;
constant Nbreg :natural := 8;
constant twr_reg :time := 3 ns;

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

42

constant tmux :time := 1 ns;


constant tuf :time := 4 ns;
--dclaration des signaux de test
signal rst_test,V_test,C_test,N_test,Z_test: bit;
signal clk_test: bit:='1';
signal ctrlword_test: unsigned(NbBits-1 downto 0);
signal cste_test : signed(2 downto 0);
signal data_in_test,data_out_test : signed(NbBits-1 downto 0);
signal adr_out_test: unsigned (NbBits-1 downto 0);
begin
dp: datapath generic map(NbBits=>NbBits,Nbreg=>Nbreg,
twr_reg=>twr_reg,tmux=>tmux,tuf=>tuf)
port
map(clk=>clk_test,rst=>rst_test,ctrlword=>ctrlword_test,cste=>cste_test,data_in=>data_in_test
,data_out=>data_out_test,adr_out=>adr_out_test,V=>V_test,C=>C_test,N=>N_test,Z
=>Z_test);
--affectation des drivers des sigfnauc de test
-- partir d'un fichier de simulation
SIMU:process
file fd :text open READ_MODE is "SimuDatapath.txt";
variable clkF,rstF,VF,CF,N,ZF:bit;
variable csteF:std_logic_vector(2 downto 0);
variable ctrlwordF,adrF,data_inF,data_outF:std_logic_vector(NbBits-1 downto 0);
variable ligne:line;
begin
while not endfile(fd) loop
readline(fd,ligne);
if ligne'length>0 and ligne(1)/='-' then
read(ligne,clkf);
read(ligne,rstF);
read(ligne,ctrlwordF);
read(ligne,data_inF);
read(ligne,csteF);
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

43

ctrlword_test<=unsigned(to_bitvector(ctrlwordF));
cste_test<=signed(to_bitvector(csteF));
clk_test<=clkF;
rst_test<=rstF;
data_in_test<=signed(to_bitvector(data_inF));
wait for 20 ns;
end if;
end loop;
end process;
end bench;

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

44

6.B.3 initReg.txt
Voici le fichier qui contient les initialisations des registres du datapath:
--ime registre

data

0000000000000001

0000000000000101 -- 5

0000000000000100

0000000011111000 -- 248

0000000000010000

0000000000000000 -- 0

0000000001000000

0000000010000000

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

45

6.B.4 SimuDataPath.txt
Voici le fichier qui contient les drivers des signaux de test du DataPath:
--clk

rst

ctrlword

dataIn

cste

0000000000000011 1111111111111111 001

0000000000000011 1111111111111111 001

-- reset

-- R0<- Datain
0

0000000000000011 0000000100000011 001

0000000000000011 0000000100000011 001

-- R1<- Datain
0

0010000000000011 0000000000000001 001

0010000000000011 0000000000000001 001

-- R7<- Datain (oxCAFE!!!!!j'aime le caf!)


0

1110000000000011 1100101011111110 001

1110000000000011 1100101011111110 001

-- R3<-R1+R0 (resulat= 0000000000000010)


0

0110010000001001 1100101011111110 010

0110010000001001 1100101011111110 010

-- R3<-Datain signed(-1)
0

0110000000000011 1111111111111111 010

0110000000000011 1111111111111111 010

-- dataout<-R7
0

0000001110000000 0000000000000111 010

0000001110000000 0000000000000111 010

-- R6<-R7+(cte=1) (resulat = oxCAFF Caisse Allocation Familiale Franaise)


0

1101110001001001 0000000000000111 001

1101110001001001 0000000000000111 001

-- R5<-R0+2
0

1010000001001001 0000000000000111 010

1010000001001001 0000000000000111 010

-- R6<- Datain (j'aime vraiment le cafe)


0

1100000000000011 1100101011111110 001

1100000000000011 1100101011111110 001

-- R5<-0

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

46

1010000000101001 0000000000000111 001

1010000000101001 0000000000000111 001

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

47

6.B.5 Chronogrammes
Voici le rsulat de la simulation du DataPath:
Sur cette simulation on peut
voir une bonne initialisation
des registres.
Ainsi que la bonne
excution de divers micros
oprations.( add, load ...)
Pour mieux lire le
chronogramme, on peut se
reprer avec le registre 6,
qui contient oXCAFE puis
oXCAFF!

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

48

6.C Unit de Contrle:


6.C.1 Ctrl Unit.vhd
Voici le source VHDL de l'unit de contrle:
library ieee;
use ieee.numeric_bit.all;
entity Ctrl_Unit is
generic(NbBits : natural;
t_dec : time ; -- temps temps de decodage
t_r_mem : time ; --temps de lecture mem instruction
t_inc_load : time); -- temps d'incrmentation
--et chargement du PC
port(CLK,rst,V,C,N,Z: in bit;
adr: in unsigned(NbBits-1 downto 0);
Mw: out bit;
IR: out signed(2 downto 0);
ctrlword: out unsigned(NbBits-1 downto 0));
end Ctrl_Unit;
library ieee;
use ieee.numeric_bit.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_textio.all;
use std.textio.all;
architecture dflow of Ctrl_Unit is
----------- TYPE : ROM dcrit une ROM comme un tableau de valeurs non signes
type ROM is array(0 to 2**NbBits-1) of unsigned(NbBits-1 downto 0);
-------------------- FONCTION : initialise la ROM l'aide du fichier programROM.txt
---------function initROM return ROM is
file fd :text open READ_MODE is "programRom.txt";

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

49

variable mem2: ROM;


variable numli:natural:=0;
variable data:std_logic_vector(NbBits-1 downto 0);
variable ligne:line;
begin
while not endfile(fd) loop
readline(fd,ligne);
if ligne'length>0 and ligne(1)/='-' then
read(ligne,data);
mem2(numli):=unsigned(to_bitvector(data));
numli:=numli+1;
end if;
end loop;
return mem2;
end initROM;
--mmoire d'instruction
constant mem_instruc: ROM:=initRom;
-- dfinition de tous les signaux
signal IR_sur_16_bits : unsigned(NbBits-1 downto 0);
signal BC, JB, PL, signal_MW, RW, MD, MB, Ld : bit;
signal extension,PC: unsigned(NbBits-1 downto 0);
signal DA, AA, BA : unsigned (2 downto 0);
signal FS : unsigned (3 downto 0);
--signal decalage_sur_16_bits : std_logic_vector (15 downto 0);
begin
-- Branch Control
Ld<=Z when (BC='0') else N when (BC='1');
--extension
extension <=
(5=>IR_sur_16_bits(8),4=>IR_sur_16_bits(7),3=>IR_sur_16_bits(6),2=>IR_sur_16_bits(2),

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

50

1=>IR_sur_16_bits(1),0=>IR_sur_16_bits(0),others=>IR_sur_16_bits(8));
-- Extraction d'instruction
IR_sur_16_bits<=mem_instruc(to_integer(PC)) after t_r_mem;

-- Calcul de PC rst niveau bas


PC<=(others=> '0') after t_inc_load when rst='0' else
PC+1 after t_inc_load when (PL='0' or (PL='1' and JB='0' and Ld='0')) and CLK'event and
CLK='1' else
adr after t_inc_load when PL='1' and JB='1' and CLK'event and CLK='1' else
PC+extension after t_inc_load when PL='1' and JB='0' and Ld='1' and CLK'event and
CLK='1';
-- Sortie Instruction register
IR<=signed(IR_sur_16_bits(2 downto 0));

-------------- DECODAGE
-------------- DA
DA<=IR_sur_16_bits(8 downto 6) after t_dec;
-- AA
AA<=IR_sur_16_bits(5 downto 3) after t_dec;
-- BA
BA<=IR_sur_16_bits(2 downto 0) after t_dec;
-- FS
FS<="0000" after t_dec when PL='1' and JB='0' else IR_sur_16_bits(5 downto 2) after t_dec;
-- MB
MB<='1' after t_dec when IR_sur_16_bits(15 downto 13)="100" else '0' after t_dec;
-- MD
MD<='1' after t_dec when IR_sur_16_bits(15 downto 13)="001" else '0' after t_dec;
-- RW
RW<='1' after t_dec when IR_sur_16_bits(14)='0' else '0' after t_dec;
LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

51

-- MW
MW<='1' after t_dec when IR_sur_16_bits(15 downto 13)="010" else '0' after t_dec;
-- PL
PL<='1' after t_dec when IR_sur_16_bits(15 downto 14)="11" else '0' after t_dec;
-- JB
JB<='1' after t_dec when IR_sur_16_bits(15 downto 13)="111" else '0' after t_dec;
-- BC
BC<='1' after t_dec when IR_sur_16_bits(15 downto 13)&IR_sur_16_bits(9)="1101" else '0'
after t_dec;
---------- MOT DE CONTROLE
--------ctrlword<=DA&AA&BA&MB&FS&MD&RW;
end dflow;

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

52

6.C.2 TestCtrl_Unit.vhd
Voici le source du testBench utilis pour valider l'unit de contrle:
library ieee;
use ieee.numeric_bit.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_textio.all;
use std.textio.all;
entity testUC is
end entity;
architecture bench of testUC is
component Ctrl_Unit is
-generic(NbBits : natural := 16;
generic(NbBitsAd : natural := 16;
NbBitsData : natural := 16;
t_dec : time := 1 ns; -- temps temps de decodage
t_r_mem : time := 3 ns; --temps de lecture mem instruction
t_inc_load : time := 1 ns); -- temps d'incrmentation
--et chargement du PC
port(CLK,rst,V,C,N,Z: in bit;
adr: in unsigned(NbBitsAd-1 downto 0);
Mw: out bit;
IR: out signed(2 downto 0);
-decodeur_inst_in : in std_logic_vector(15 downto 0);
ctrlword: out unsigned(NbBitsData-1 downto 0));
end component;
-- signaux de test
constant NbBitsAd : natural := 16;
constant NbBitsData : natural := 16;
signal CLK_test : bit;
signal rst_test : bit;
signal V_test : bit;
signal C_test : bit;
signal N_test : bit;
signal Z_test : bit;
signal adr_test : unsigned(NbBitsAd-1 downto 0);
signal Mw_test : bit;
signal IR_test : signed(2 downto 0);
signal ctrlword_test : unsigned(NbBitsData-1 downto 0);
signal test_decodeur_inst_in : std_logic_vector(15 downto 0);
begin
uut : Ctrl_Unit port map (CLK=>CLK_test, rst=>rst_test, V=>V_test,
C=>C_test, N=>N_test,
Z=>Z_test, adr=>adr_test, Mw=>Mw_test, IR=>IR_test,
ctrlword=>ctrlword_test );
-- Signaux de l'environnement de test
SIM :process
-- ouvre un fichier en lecture seule
file fd :text open READ_MODE is "SimuUC.txt";
variable V_adr:std_logic_vector(NbBitsData-1 downto 0);
variable V_CLK,V_rst,V_N,V_Z:bit;
variable ligne:line;

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

53

begin
while not endfile(fd) loop
readline(fd,ligne);
if ligne'length>0 and ligne(1)/='-' then
read(ligne,V_CLK);
read(ligne,V_rst);
read(ligne,V_N);
read(ligne,V_Z);
read(ligne,V_adr);
CLK_test<=( not CLK_test);
rst_test<=V_rst;
N_test<=V_N;
Z_test<=V_Z;
adr_test<=unsigned(to_bitvector(V_adr));
wait for 10 ns;
end if;
end loop;
end process;
end bench;

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

54

6.C.3 programRom.txt
Voici le fichier qui contient le programme charger dans la mmoire d'instruction et qui sera
excut:
0001010000000000
0010000001011000
0100000010001000
1000000010100000
1100000010010000
1100001011001010
1110001000011100
0000000011010000
1110000100001000
1110000000111000
0000000011001000
0000000100010000
1100000010011000
0000010000000100
0000110011011000
1110000000111000

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

55

6.C.4 SimuCtrl_Unit.txt
Voici le fichier qui contient les drivers des signaux de test de l'unit de contrle:
--CLK RST
1

ADR

0000000000000010

0000000000001000

0000000010000000

0000000000000000

0000000000000000

0000000000000001

0000000000000001

0000000000000001

0000000000000001

0000000000000010

0000000000000010

0000000000000011

0000000000000011

0000000000000100

0000000000000100

0000000000000101

0000000000000101

0000000000000110

0000000000000110

0000000000000111

0000000000000111

-- 1

-- 2

-- 3

-- 4

-- 5

-- 6

-- 7

-- 8

-- 9

-- 10

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

56

-- 11
0

0000000000001000

0000000000001000

0000000000000100

0000000000010000

0000000000000100

0000000000010000

0000000000000100

0000000000010000

0000000000000100

0000000000010000

0000000000000100

0000000000010000

0000000000000100

0000000000010000

-- 12

-- 13

-- 14

-- 15

-- 16

-- 17

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

57

6.C.5 Chronogrammes:
Voici les rsultats de la simulation de l'unit de contrle:
Sur ce chronogramme on peut
voir PC voluer de la manire
attendue.

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

58

6.D Le calculateur de Harvard:


6.D.1 HarvardCalculator.vhd
Voici le source VHDL du calculateur de Harvard:
library ieee;
use ieee.numeric_bit.all;
entity CalculateurHarvard is
generic (NbBits : natural );
port(CLK,rst:in bit);
end CalculateurHarvard;
architecture struct of CalculateurHarvard is
component memoire is
generic(NbBits : natural ; tco : time := 4 ns);
port(datain : in signed(NbBits-1 downto 0);
Mw,rst,clk : in bit;
adr : in unsigned(NbBits-1 downto 0);
dataout : out signed(NbBits-1 downto 0));
end component;
component datapath is
generic(NbBits: natural;
Nbreg: natural := 8;
twr_reg : time; -- temps acces w/r du banc de registre
tmux : time; --temps multiplexeur et indicateur
tuf : time); -- temps unit fonctionnele
port(clk:in bit;
rst: in bit;
ctrlword: in unsigned(NbBits-1 downto 0);
cste: in signed(2 downto 0);
data_in: in signed(NbBits-1 downto 0);
data_out: out signed(NbBits-1 downto 0);

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

59

adr_out: out unsigned(NbBits-1 downto 0);


V,C,N,Z: out bit);
end component;
component Ctrl_Unit is
generic(NbBits : natural;
t_dec : time; -- temps temps de decodage
t_r_mem : time; --temps de lecture mem instruction
t_inc_load : time); -- temps d'incrmentation
--et chargement du PC
port(CLK,rst,V,C,N,Z: in bit;
adr: in unsigned(NbBits-1 downto 0);
Mw: out bit;
IR: out signed(2 downto 0);
ctrlword: out unsigned(NbBits-1 downto 0));
end component;
--declaration des constantes
constant Nbreg: natural := 8;
constant tco : time := 4 ns;
constant twr_reg : time := 3 ns; -- temps acces w/r du banc de registre
constant tmux : time := 1 ns; --temps multiplexeur et indicateur
constant tuf : time := 4 ns; -- temps unit fonctionnele
constant t_dec : time := 1 ns; -- temps temps de decodage
constant t_r_mem : time := 3 ns; --temps de lecture mem instruction
constant t_inc_load : time := 1 ns; -- temps d'incrmentation
signal Mw_uc_to_mem : bit;
signal data_dp_to_mem : signed(NbBits-1 downto 0);
signal adr_out_dp_to_mem_and_uc: unsigned(NbBits-1 downto 0);
signal ctrlword_uc_to_dp : unsigned(NbBits-1 downto 0);
signal cste_uc_to_dp : signed(2 downto 0);
signal data_mem_to_dp: signed(NbBits-1 downto 0);
signal V_dp_to_uc, C_dp_to_uc, N_dp_to_uc, Z_dp_to_uc : bit;

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

60

begin
mem : memoire generic map(NbBits=>NbBits,tco=>tco)port map(clk=>clk, rst=>rst,
Mw=>Mw_uc_to_mem ,
datain=>data_dp_to_mem,adr=>adr_out_dp_to_mem_and_uc);
dp : datapath generic map(NbBits=>NbBits,Nbreg=>Nbreg,
twr_reg=>twr_reg,tmux=>tmux,tuf=>tuf)
port map (clk=>clk, rst=>rst, V=>V_dp_to_uc, C=>C_dp_to_uc,
N=>N_dp_to_uc, Z=>Z_dp_to_uc, ctrlword=>ctrlword_uc_to_dp, cste=>cste_uc_to_dp,
data_in=>data_mem_to_dp, data_out=>data_dp_to_mem,
adr_out=>adr_out_dp_to_mem_and_uc);
uc : Ctrl_Unit generic map(NbBits=>NbBits,t_dec=>t_dec,
t_r_mem=>t_r_mem,t_inc_load=>t_inc_load)
port map (CLK=>clk, rst=>rst, V=>V_dp_to_uc, C=>C_dp_to_uc,
N=>N_dp_to_uc, Z=>Z_dp_to_uc, adr=>adr_out_dp_to_mem_and_uc,
Mw=>Mw_uc_to_mem, IR=>cste_uc_to_dp, ctrlword=>ctrlword_uc_to_dp);
end struct;

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

61

6.D.2 testHarvardCalculator.vhd
Voici le source VHDL du TestBench du calculateur:
entity test_Calculateur is
end test_Calculateur;
architecture bench of test_Calculateur is
----------- COMPOSANT : Calculateur
---------component CalculateurHarvard is
generic (NbBits : natural );
port(CLK,rst:in bit);
end component;
--declaration des constantes
constant NbBits : natural := 16;
--declaration des signaux de test
signal CLK_test,rst_test:bit;
----------- DESCRIPTION
---------begin
calc: CalculateurHarvard generic map (NbBits=>NbBits)port
map(CLK=>CLK_test,rst=>rst_test);
process
begin
CLK_test<=not CLK_test;
wait for 10 ns;
end process;
rst_test<='0' after 2 ns, '1' after 13 ns;
end bench;

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

62

6.D.3Chronogrammes
Voici les rsultats de la simulation:
Sur ce chronogramme on peut
voir l'excution du programme de
test fourni dans le sujet.
On peut clairement voir
l'algorithme voluer dans les
diffrents registres du banc de
registre.
Notamment les registres 1,2 et 3.

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

63

LEFEVRE CHALOPIN

Calculateur de Harvard Juin 2007

64

Vous aimerez peut-être aussi