rapport_projet riscvf

publicité
Projet M2 Pro CAMSI
Etude et réalisation d’un microprocesseur RISC 32 bits
Rodrigue Ndashimye, Ibrahima Djité
25/02/2013
Encadrants
F. Thiebolt.
D. Dragomirescu
Conception du chemin de données et de contrôle d’un microprocesseur RISC 32 bits à cycle
1
unique.
Table des matières
I.
Introduction .................................................................................................................................. 4
II.
Le processeur RISC R3000 ........................................................................................................... 4
III.
Présentation du Projet .................................................................................................................. 7
Cahier des charges............................................................................................................................... 7
Travail demandé : ................................................................................................................................ 8
IV.
Conception .................................................................................................................................... 8
Le pipeline ........................................................................................................................................... 8
Les aléas .............................................................................................................................................. 8
Conception des différents parties du microprocesseur ...................................................................... 9
Conception et simulation du banc de registre ......................................................................................9
Conception et simulation du banc mémoire .......................................................................................10
Définition des fonctions et procédures du microprocesseur RISC. ................................................... 11
Procédure contrôle .............................................................................................................................12
Procédure ALU : ................................................................................................................................13
Procédure envoi : ...............................................................................................................................13
Procédure aléa : ..................................................................................................................................14
Fonction plus : ....................................................................................................................................15
Définition des registres pipeline.........................................................................................................15
Conception du chemin de données ................................................................................................. 15
Les étapes de conception du chemin de données. ..............................................................................15
Analyse comportementale du processeur RISC. ................................................................................16
V.
Simulation du processeur ............................................................................................................ 19
VI.
Synthèse du microprocesseur RISC ............................................................................................ 23
VII.
Conclusion ............................................................................................................................. 26
VIII.
1- Définition du package ........................................................................................................ 28
IX.
2- Code VHDL du microprocesseur RISC ..................................................................................... 40
2
Préambule
Ce projet est réalisé dans le cadre de l’UE fondamentale Architecture avancés des machines
informatiques de la formation master professionnel conception des architecture des machines et
système informatiques (CAMSI). Le but de ce projet est concevoir un microprocesseur RISC 32bits
intégrant la technologie du pipelining. Ce projet inclue les étapes de conception en VHDL les étapes
de simulations et les étapes de synthèse du microprocesseur en circuit numériques.
3
I.
Introduction
Un processeur RISC est un microprocesseur à jeu d'instruction réduit (du mot anglais: reduced
instruction-set computer).C'est un type d'architecture matérielle de microprocesseurs, qui se caractérise
par un jeu d'instructions facile à décoder et comportant uniquement des instructions simples. Le but de
ce projet est de concevoir un microprocesseur RISC pipeliné à chemin de données et de contrôle à
cycle unique. Le déroulement du projet s'articule sur quatre étapes:
• La première étape a consistera à concevoir tous les éléments combinatoires et d'états tels
que l'unité arithmétique et logique (ALU), le banc de registre et le banc mémoire.
II.
•
La deuxième étape consistera à concevoir le chemin de données et l'unité de contrôle.
•
La troisième étape consistera en la création des fichiers de test pour la simulation et
validation des différents composants du processeur.
•
En fin la dernière étape consistera en la synthèse et à l'implémentation du processeur RISC
dans une cible de type ASIC conçu en technologie AMS 0.35µm.
Le processeur RISC R3000
Un microprocesseur RISC a les propriétés suivantes :
•
Un cycle d’instructions (nombre de cycle d’horloges) identiques à 80% des instructions.
•
Les instructions ont la même taille dans notre cas 32 bits.
•
Un jeu d’instruction réduit environ 128 instructions.
•
formats d’instructions.
•
Les accès mémoire se font avec les instructions de types load et store.
•
Toutes les opérations excepté les load et store sont de type registres à registres
•
L’unité de contrôle du microprocesseur RISC est directement câblée au niveau matériel.
•
Une large panel de registres (32 registres de 32 bits).
Taille du 6 bits
champ
Format R OP
5 bits
5 bits
5 bits
5 bits
6 bits
Commentaires
RS
RT
RD
VALDEC
fonction
Format I
OP
RS
RT
Immédiat/Adresse
Format J
OP
Adresse
Instruction
de
type
arithmétique ou logique
ou registre
Instruction
de
type
branchement ou immédiat
Instruction de type saut
Tableau 1: les types de formats du jeu d’instructions RISC
4
Le champ OP : code opération sur 6 bits représente la nature du traitement à effectuer
Le champ RS : formé de 5 bits, représente toujours un numéro du registre source
Le champ RT formé de 5 bits, représente un numéro de registre (source ou destination) ou une
condition de branchement.
Le champ RD : formé de 5 bits, représente le numéro de registre de destination.
Le champ VALDEC : formé de 5 bits représente le nombre de décalage dans les instructions de
décalage.
Le champ fonction : formé de 5 bits permet de différencier certaines instructions ayant le même code
opération.
Le champ immédiat : formé de 16 bits représente soit un déplacement signé dans le cas des
instructions de branchement, ou une constante signée immédiate dans le cas des opérations
arithmétiques signées, ou une constante non signée immédiate dans le cas des opérations logiques et
arithmétiques non signées.
Le champ adresse : représente une adresse sur 26 bits.
Le jeu d’instruction est montré dans le Tableau 2 :
Instruction
Lsl
Lsr
Jr
Add
Addu
Sub
Subu
And
Or
Xor
Nor
Slt
Sltu
Jarl
Bltz
Bgez
Bltzal
bgezal
J
Jal
Beq
Bne
Blez
Bgtz
Addi
Addiu
Slti
Sltiu
Andi
Ori
Xori
Lui
Lb
Lh
Op
000000
000000
000000
000000
000000
000000
000000
000000
000000
000000
000000
000000
000000
000000
000001
000001
000001
000001
000010
000011
000100
000101
000110
000111
001000
001001
001010
001011
001100
001101
001110
001111
100000
100001
0
0
Rs
Rs
Rs
Rs
Rs
Rs
Rs
Rs
Rs
Rs
Rs
Rs
Rs
Rs
Rs
Rs
Adresse
Adresse
Rs
Rs
Rs
Rs
Rs
Rs
Rs
Rs
Rs
Rs
Rs
0
RS**
RS**
Fonction
000000
000010
001000
100000
100001
100010
100011
100100
100101
100110
100111
101010
101011
001001
Rt
Rt
0
Rt
Rt
Rt
Rt
Rt
Rt
Rt
Rt
Rt
Rt
0
00000
00001
10000
10001
Rd
ValDec
Rd
ValDec
0
0
Rd
0
Rd
0
Rd
0
Rd
0
Rd
0
Rd
0
Rd
0
Rd
0
Rd
0
Rd
0
Rd
0
Déplacement signé
Déplacement signé
Déplacement signé
Déplacement signé
Rt
Rt
0
0
Rt*
Rt*
Rt*
Rt*
Rt*
Rt*
Rt*
Rt*
Rt*
Rt*
Déplacement signé
Déplacement signé
Déplacement signé
Déplacement signé
Constante signée (sign_extend)
Constante signée (sign_extend)
Constante signée (sign_extend)
Constante signée (sign_extend)
Constante signée (sign_extend)
Constante non signée (zero_extend)
Constante non signée (zero_extend)
Constante non signée (zero_extend)
Déplacement signé
Déplacement signé
5
Lw
100011
Rs**
Rt*
Déplacement signé
Lbu
100100
Rs**
Rt*
Déplacement signé
Lhu
100101
Rs**
Rt*
Déplacement signé
Sb
101000
Rs**
Rt
Déplacement signé
Sh
101001
Rs**
Rt
Déplacement signé
Sw
101011
Rs**
Rt
Déplacement signé
X* => Registre RT joue le rôle de registre de destination.
X** => Registre RS joue le rôle de registre de base.
sign_extend => Extension à 32 bit avec recopie du bit de signe dans les 16 bits de poids fort.
Zero_extend => Extension à 32 bit avec recopie du bit de signe dans les 16 bits de poids fort.
Tableau 2:Jeu d'instructions pris en compte dans notre RISC
Le Tableau 3 montre la signification des différentes instructions.
Catégorie
Arithmétique
Instruction
Addition
Soustraction
Add. Immédiat
Add. non signé
Soustr. Non signé
Add. Imm. Non signé
ET
OU
XOR
Non OU
ET immédiat
Logique
OU immédiat
XOR immédiat
Déc. Logic gauche
Déc. Logic droite
Chart. Poids forts
Chart. Imm.
Chart. Octet signé
Chart. Demi-mot signé
Chart. Mot
Transfert
de Chart. Octet non signé
données
Chart. Demi non signé
Rangement octet
Rangement demi-mot
Rangement mot
Branch si =
Branchement
conditionnel
Exemple
Add R1, R2, R3
Sub R1, R2, R3
Addi R1, R2, 100
Addu R1, R2, R3
Subu R1, R2, R3
Addiu R1, R2,
100
And R1, R2, R3
Or R1, R2, R3
Xor R1, R2, R3
Nor R1, R2, R3
Andi R1, R2, 100
Ori R1, R2, 100
Xori R1, R2, 100
Lsl R1, R2, 10
Lsr R1, R2, 10
Lui 100(R1)
Lb R1, 100(R2)
Lh R1, 100(R2)
Lw R1, 100(R2)
Lbu R1, 100(R2)
Lhu R1, 100(R2)
Sb R1, 100(R2)
Sh R1, 100(R2)
Sw R1, 100(R2)
Beq R1, R2, 100
Branch si ≠
Bne R1, R2, 100
Branch si ≤ 0
Branch si > 0
Branch si < 0
Branch si ≥ 0
Bt avec lien si < 0
Blez R1, 100
Bgtz R1, 100
Bltz R1, 100
Bgez R1, 100
Bltzal R1, 100
Signification
R1 = R2 + R3
R1 = R2 - R3
R1 = R2 + 100
R1 = R2 + R3
R1 = R2 - R3
R1 = R2 + 100
R1 = R2 & R3
R1 = R2 I R3
R1 = R2 xor R3
R1 = R2 nor R3
R1 = R2 & 100
R1 = R2 I 100
R1 = R2 xor 100
R1 = R2 << 10
R1 = R2 >> 10
R1 = 100 << 16
R1 = M [R2 + 100]8
R1 = M [R2 + 100]16
R1 = M [R2 + 100]
R1 = M [R2 + 100]8
R1 = M [R2 + 100]16
M [R2 + 100] =(R1)8
M [R2 + 100] =(R1)16
M [R2 + 100] = R1
if (R1 == R2) goto
CP+4+100
if
(R1 !=
R2)
goto
CP+4+100
if (R1 ≤ 0) goto CP+4+100
if (R1 > 0) goto CP+4+100
if (R1 < 0) goto CP+4+100
if (R1 ≥ 0) goto CP+4+100
if (R1 < 0) goto
CP+4+100 ; R31 <=CP+4
6
Saut
Inconditionnel
Bt avec lien si ≥ 0
Bgezal R1, 100
Positionner si <
Slt R1, R2, R3
Positionner
si
<
immédiat
Positionner si < non
signé
Positionner
si
<
immédiat non signé
Saut
Saut par registre
Saut avec lien
Saut avec lien par
registre
Slti R1, R2, 100
Sltu R1, R2, R3
Sltiu R1, R2, 100
J 1000
Jr R1
Jal 10000
Jalr R1, R3
if (R1 ≥ 0) goto CP+4+100;
R31 <=CP+4
if (R2 < R3) then R1=1 ;
else R1=0
If (R2<100) then R1=1;
else R1=0
if (R2<R3) then R1=1; else
R1=0
if (R2<100) then R1=1;
else R1=0
Jump to @10000
Jump to @(R1)
R31=CP+4 ; goto @10000
R3 <= CP+4 ; jump to
@(R1)
Tableau 3: Signification des instructions
III.
Présentation du Projet
Cahier des charges
Le processeur à concevoir sera un processeur de type RISC 32 bits et aura les caractéristiques
suivantes :
•
Un banc de registres de 32 registres R0-R31 de 32 bits chacun avec 2 ports de lecture et
port d’écriture. Le registre R0 est câblée à 0, on pourra tenter d’y écrire mais sa lecture
donnera toujours 0.
•
Une unité arithmétique et logique (ALU) avec deux entrées et une sortie de 32 bits. Elle
permet de réaliser les opérations arithmétiques et logiques sur 32bits du jeu d’instructions
donnée dans le Tableau 2
•
Une logique d’états composée de 4 bits : C(Carry), Z(zéro), V(Overflow), N(Negative)
permettant de donner une indication sur l’état des opérations réalisées et de pouvoir
effectuer les branchements conditionnels.
•
Un chemin de données pipeliné de 5 étages à : EI/DI/EX/MEM/ER :
•
o
Le premier étage EI réalise l’extraction (lecture) de l’instruction.
o
Le deuxième étage DI réalise le décodage de l’instruction et extraction des
opérandes.
o
Le troisième étage EX réalise l’exécution et le calcul de l’adresse effective.
o
Le quatrième étage MEM réalise l’accès à la mémoire.
o
Le cinquième étage ER réalise l’écriture du résultat.
Un registre : compteur de programme CP.
7
Les modes d’adressages sont de trois types : Registres à Registre, Immédiat, Indirect avec
déplacement. Toutes les instructions s’exécutent en un seul cycle. Les opérations d’accès mémoires
peuvent être réalisées au niveau de l’octet, le demi-mot (16 bits) et le mot (32bits) donc les adresses
manipulées sont des adresses octets. Toutes les opérations, arithmétiques et logiques sont effectuées
toujours sur des opérandes de 32 bits.
L’architecture interne du microprocesseur est de type Harvard avec un bus d’adresse et un bus de
données pour accéder à une mémoire d’instruction ou de données.
Dans toute l’étude on ne considéra pas l’implémentation des exceptions.
Travail demandé :
La conception et la simulation des chemins de données et de contrôle de l’ensemble du processeur
pour le jeu d’instructions d écrit dans le tableau s’effectuera en langage VHDL . On considère le
processeur muni de deux caches :
•
Un cache d’instruction
•
Un cache de données
Le problème des aléas de données sont traités par la mise en œuvre matérielle d’une unité d’envoi.
Pour les aléas de contrôle on considère une prédiction statique de branchement : Branchement non
pris.
Le processeur ainsi conçu est simulé en VHDL et sera synthétisé par l’outil de synthèse sur Synopsis à
l’AIME.
IV.
Conception
Le pipeline
Une manière d’améliorer les performances du RISC est l’utilisation de la technique du pipeline. Le
microprocesseur est divisé en différents étages. Chaque étage doit effectuer sa fonction en un cycle
horloge. Ceci rend possible l’amélioration des performances du microprocesseur en terme de débit.
Ce qui est avantageux par rapport à un microprocesseur ne disposant pas d’un pipeline. La technique
du pipeline permet aussi une optimisation de chaque étage du processeur au lieu d’une optimisation
globale. Dans le but d’améliorer les performances, la technique la plus utilisé est la subdivision des
étages du pipeline pour pouvoir augmenter le temps d’exécution des instructions. Aujourd’hui on
peut trouver des microprocesseurs RISC avec plus de 10 étages pipeline [1ci-dessous27]
Notre microprocesseur RISC va contenir un pipeline de 5 étages.
Les aléas
Dans certains cas il peut y avoir une dépendance entre deux instructions qui sont cours d’exécution.
Ces événements sont appelés aléas. Notre conception devra prendre en compte les contraintes causées
par 2 types d’aléas :
8
• Les aléas de données :. Les aléas de données surviennent lorsqu’une instruction doit utiliser
une donnée qui doit qui doit être fournit par une instruction précédente se trouvant toujours
dans le pipeline. Une première solution est l’utilisation d’une unité de détection des aléas qui
va suspendre le pipeline jusqu’à ce que l’instruction précédente est finie son exécution et
que la donnée soit disponible. Mais la mise en œuvre de cette solution va entrainer une baisse
de performance du microprocesseur. La solution que nous avons retenue ici est l’utilisation
d’une unité d’envoi cohabité avec une unité de détection d’aléas. L’unité d’envoi va
permettre de résoudre les problèmes d’aléas pour les instructions de type R et immediat. Pour
les instructions de type load, l’unité de détection des aléas va permettre de suspendre le
pipeline pendant une période d’horloge le temps de faire l’accès mémoire et de permettre à
l’unité d’envoi de transmettre la donnée à l’instruction suivante.
• Les aléas de contrôle : Les aléas de contrôle surviennent lorsqu’on doit prendre une décision
qui dépend du résultat d’une instruction. Elle s’applique dans le cas des instructions de
branchements et de saut. Nous ne pouvons pas résoudre le branchement dans l’étage de
décodage a moins de suspendre le pipeline. La solution que nous avons retenue est de faire
une prédiction de branchement. Nous allons supposer que le branchement n’est pas pris et les
instructions suivantes sont toujours exécutées. Si toutefois le branchement est pris, on vide les
étages du pipeline.
Notre microprocesseur disposant de deux caches, un cache d’instructions et un cache de données, n’est
pas assujetti aux contraintes causées par les aléas de type structurels.
Conception des différents parties du microprocesseur
La conception de notre microprocesseur a été effectuée en trois parties conception du banc de
registre, du banc mémoire et du chemin de donnée et de contrôle, chaque partie a été conçue et testée
séparément avant de regrouper tous les éléments dans une même architecture.
Conception et simulation du banc de registre
Le banc de registre est composé de 32 registres de 32 bits de R0 à R31. Le banc prend en entrée les
signaux d’horloge CLK, le signal de reset RST les signaux d’adresse ADR_A (RS) ADR_B(RT) et
ADR_W(RD) un bus de donnée D, un signal d’écriture W. Les signaux de sortie sont nommés ici QA
et QB. La lecture du registre R0 donnera toujours 0. On utilise la technique du Bypass dans le registre
dans le cas ou l’adresse d’écriture et l’adresse de lecture sont identiques c’est-à-dire que la donnée
écrire est directement mis en sortie.
Figure 1: Banc de registre
9
La simulation du banc de registre est représentée sur la Figure 2. Pour la simulation du banc de
registre, nous avons considéré un banc de 8 registres. La Figure 2 montre les résultats de simulation
effectué avec l’outil ModelSim. On voit que le banc de registre effectue les écritures que sur front
montant d’horloge et lorsque le port ADR_W présente une adresse valide. La lecture se fait de manière
immédiate lorsque nous avons une adresse valide sur le port ADR_A ou ADR_B. En cas de
correspondance entre l’adresse de lecture et l’adresse d’écriture, le banc de registre écrit la donnée
présente sur le bus de Donnée D sur la sortie QA ou QB.
Figure 2: Simulation du banc de registre
Conception et simulation du banc mémoire
Notre banc mémoire est composé 32 emplacements mémoire. La taille du mot mémoire est de 32bits.
La mémoire prend en entrée le bus de donnée D, le bus d’adresse ADR, le signal d’horloge, le signal
de reset RST, le signal de lecture écriture RW*, le signal DS qui est défini pour la sélection du type
d’accès 8/16/32 bits, le signal AS qui indique une opération valide de lecture immédiate si RW*=1 ou
d’écriture au prochain front montant d’horloge si RW*=0 et enfin le signal SIGNED qui ne concerne
que l’accès en lecture et permet l’extension de signe de la donnée lue. Le bus ADR est au format octet
et a une taille indépendante de la taille du banc mémoire. Pour la simulation du banc mémoire, nous
avons implémenté une fonction de chargement d’un fichier d’initialisation du banc. Ainsi l’activation
du signal reset RST=’0’, provoque le chargement d’un fichier passé en paramètre.
10
Figure 3: Banc mémoire à extension de signe
La Figure 4 montre les résultats de simulation du banc mémoire. Nous voyons dans cette simulation
que les écritures se font toujours sur front montant d’horloge en fonction du signal AS et du type
d’accès défini par le signal DS. La lecture se fait de manière immédiate dès que le signal RW*=’1’ et
que le signal AS est actif.
Figure 4: Simulation du banc mémoire
Définition des fonctions et procédures du microprocesseur RISC.
Nous avons défini dans un premier temps un fichier package contenant la définition de toutes les
fonctions et les procédures qui composent notre microprocesseur. L’unité de contrôle du
11
microprocesseur et l’unité de détection des aléas sont instanciées dans l’étage DI et l’unité d’envoi et
l’unité arithmétique et logiques sont instanciées dans l’étage EX. Toutes ces unités sont décrites sous
forme d’une procédure en VHDL. Le package contient aussi la définition de la plupart des
multiplexeurs qui composent le RISC ainsi que celle des registres pipeline.
Procédure contrôle
Cette procédure instanciée à l’étage DI, permet de positionner les signaux de contrôle pour chaque
étage (EX MEM ER) en fonction de l'instruction identifiée par son code opération, son code fonction,
ou son code de branchement.
Figure 5: Unité de contrôle
Le Tableau 4 représente toutes les signaux de contrôle que l’on à positionner en fonction des
instructions du RISC. Dans ce tableau on détaille les noms de chaque signal et l’opération qu’il
effectue lorsqu’il est actif ou inactif.
Signal de contrôle
SIGNED_EXT
ALU_OP
ALU_SIGNED
ALU_SRCA
ALU_SRCB
REG_DST
Saut(0)
SAUT [1,0]
Saut(1)
DC_DS
DC_RW
Effet quand signal actif
Extension de signe de la valeur
immédiate
Sélection d’une opération sur l’ALU en
fonction du code opération et du code
fonction
Opération signée sur L’ALU
Sélection d’une entrée du multiplexeur
MUX_ALU_A àvconnectée à l’entrée A
de l’ALU
Sélection d’une entrée du multiplexeur
MUX_ALU_B à connectée à l’entrée B
de l’ALU
Sélection d’une entrée du multiplexeur
MUX_REG_DST
Choix du registre de destination
Si Saut(1)=’1’
alors Saut JALR ou JR
Identifie une instruction de Saut vers
une nouvelle adresse
Sélectionne la taille d’accès au cache
8/16/32bits
Sélectionne une opération de lecture
dans le cache
Effet quand signal inactif
Pas d’extension de signe
ALU_OP<=ALU_OP’low ;
Opération non signée
ALU_SRCA<=ALU_SRCA’low ;
ALU_SRCB<=ALU_SRCB’low ;
REG_DST=< REG_DST’low ;
Si Saut(1)=’1’
alors Saut J ou JAL.
CP<=CP+1 ;
DC_DS<= DC_DS’low ;
Sélectionne une opération d’écriture
dans le cache
12
DC_AS
DC_SIGNED
BNE_BRANCH
BEQ_BRANCH
BGTZ_BRANCH
BLTZ_BRANCH
BLTZAL_BRANCH
BGEZ_BRANCH
BGEZAL_BRANCH
REGS_W
REGS_SRCD
Indique une opération valide de lecture
ou d’écriture dans le cache
Extension de signe de la donnée dans le
cache
Identifie une instruction de branchement
type BNE
Identifie une instruction de branchement
type BQE
Identifie une instruction de branchement
type BGTZ
Identifie une instruction de branchement
type BLTZ
Identifie une instruction de branchement
type BLTZAL
Identifie une instruction de branchement
type BGEZ
Identifie une instruction de branchement
type BGEZAL
Ecriture dans d’une donnée dans le banc
de registre
Sélection d’une entrée du multiplexeur
MUX_REGS_D connectée à l’entrée du
banc de registre
Cache indisponible
Pas d’extension de signe
L’instruction décodée
BNE
L’instruction décodée
BQE
L’instruction décodée
BGTZ
L’instruction décodée
BLTZ
L’instruction décodée
BLTZAL
L’instruction décodée
BGEZ
L’instruction décodée
BGEZAL
Pas d’écriture.
n’est pas un
n’est pas un
n’est pas un
n’est pas un
n’est pas un
n’est pas un
n’est pas un
REGS_SRCD<= REGS_SRCD’low;
Tableau 4: Signaux de contrôle de RISC
Procédure ALU :
Cette procédure instanciée dans l’étage EX, permet en fonction des signaux de contrôle positionnés
par la procédure de contrôle, de sélectionner les opérations à effectuer au niveau de l’ALU (addition,
soustraction, décalage, etc..).
Figure 6: Unité arithmétiques et logiques
Procédure envoi :
Cette procédure instanciée dans l’étage EX, permet en cas de présence d’aléas de données d’envoyer
une donnée présente sur un étage du pipeline vers un étage plus bas. Nous avons conçu de cette
procédure pour résoudre les aléas de données qui arrive lors de l’exécution des instructions de type R
ou immédiat.
13
Figure 7:Unité d'envoi
Le Tableau 5 montre les deux signaux de contrôle qui sont positionnés par l’unité d’envoi. Ce sont
des signaux de contrôle pour les deux multiplexeurs envoi situés dans l’étage EX.
Tableau 5:Signaux de contrôle positionnés par l'unité d'envoi
Signal de contrôle
Effet lorsque le signal est actif
Env_Mux_ALU_A1
Choix d’une parmi les entrées du Env_Mux_ALU_A1<= ALU_SRCA’low
de multiplexeur MUX_ALU_A1,
une valeur à envoyer vers le
multiplexeur MUX_ALU_A.
Choix d’une parmi les entrées du Env_Mux_ALU_B1<= ALU_SRCB’low
de multiplexeur MUX_ALU_B1,
une valeur à envoyer vers le
multiplexeur MUX_ALU_B.
Env_Mux_ALU_B1
Effet lorsque le signal est inactif
Procédure aléa :
Cette procédure est instanciée dans l’étage DI et permet de suspendre le pipeline le temps que le
donnée soit disponible. Nous avons instancié une procédure ALEA pour résoudre les aléas qui peuvent
être causés par l’instruction load. Car pour les instructions de type R, Immediat et l’instruction Store,
les aléas sont résolus grâce à notre unité d’envoi.
Figure 8: Unité de détections d'aléas
14
Signal de contrôle
Halt
Effet quand le signal est actif
Suspend le pipeline :
CP<=CP ;
Effet quand le signal est inactif
Ne suspend pas le pipeline
CP<=CP+1 ;
Tableau 6: Signaux de contrôle positionnés par la procédure ALEA
Fonction plus :
Cette fonction est instanciée dans l’étage EX elle permet de faire le calcul de l’adresse de branchement
dans le cas d’une instruction de branchement. L’architecture matérielle de cette fonction sera un
additionneur.
Le code VHDL de l’ensemble de ces procédures et fonctions est décrit en annexe 28.
Définition des registres pipeline
Nous avons défini 5 registres pipeline :
REG_PC est le registre compteur de programme qui contient l’adresse de la prochaine instruction
EI/DI est le registre situé entre l’étage EI et DI et contient l’instruction lue à partir de la mémoire
d’instruction.
DI/EX est le registre situé entre l’étage DI et l’étage EX. Il est divisé en deux parties : une partie
contient les signaux de contrôle positionnés par l’unité de contrôle pour les étages EX, MEM et ER.
Une partie contient les données lues à partir des registres, les adresses de registres de destination et les
valeurs immédiates.
EX/MEM est le registre situé entre l’étage EX et l’étage MEM. Il est aussi divisé en partie contrôle et
en partie donnée. La partie contrôle contient les signaux de contrôle des étages MEM et ER et la partie
donnée contient les données issue de l’ALU, les adresses de registres destination et les données lues à
partir des registres.
MEM/ER est registre situé entre l’étage MEM et l’étage ER. Divisé en deux parties. Une partie
contrôle qui contient les signaux de contrôle pour l’étage ER et une partie qui contient les données issu
de la mémoire, de l’ALU et des adresses de registres destinations etc…
Conception du chemin de données
Pour faciliter la synthèse de notre processeur plus tard, on emploie la librairie standard IEEE et la
librairie propre à notre conception WORK qui contient l’instanciation de tous les éléments du
microprocesseur comme le banc mémoire, les registres et l’ALU etc. La conception du chemin de
données s’appuie sur le fichier package. On définit un fichier risc.vhd dans lequel on va instancier
tous les éléments du processeur. Les étapes de conception du chemin de données sont effectuées dans
l’ordre.
Les étapes de conception du chemin de données.
•
Dans l’étage EI :
Dans un premier temps on instancie le cache d’instruction icache. Ce cache n’est accédé qu’en lecture
donc les signaux RW AS sont forcés à 1. L’entrée adresse ADR de la mémoire est connectée à la
15
sortie du registre pipeline reg_PC et la sortie mémoire est reliée au registre pipeline EI/DI. On
instancie aussi un additionneur dont le rôle est de calculer la nouvelle adresse de lecture d’une
instruction. La sortie de l’additionneur est reliée au champ pc_next du registre EI/DI et via un
multiplexeur au registre reg_PC.
•
Dans l’étage DI
On instancie le banc de registre les deux entrées adresse de lecture du banc sont reliées aux champs RS
et RT du registre pipeline EI/DI, L’entrée du bus de données du registre est reliée à la sortie du
multiplexeur REGS_SRCD. L’entrée adresse d’écriture est reliée champ REG_DST (pour registre
destination) du registre pipeline MEM/ER. Les sorties QA et QB du banc de registre sont reliés au
champ REGS_QA et REGS_QB du registre pipeline DI/EX.
•
Dans l’étage EX
On instancie l’ALU, l’additionneur de branchement, ainsi que l’unité d’envoi. On connecte à l’aide de
multiplexeurs différents champ à l’entrée de l’ALU. La sortie de l’ALU est reliée au champ UAL_S
du registre pipeline EX_MEM. Les entrés de l’additionneur de branchement sont connectées aux
champs pc_next du registre pipeline DI/EX et immédiat.
•
Dans l’étage MEM.
On instancie le cache de données. Ce cache est accédé en lecture et écriture. Les signaux de contrôle
sont alors positionnés en fonction du type d’instructions. L’entrée adresse du cache est reliée au champ
UAL_S du registre pipeline EX_MEM. L’entrée bus de donnée du cache est relié au champ RT_read
(donnée lue) du registre pipeline EX_MEM. La sortie du cache est connectée au champ mem_Q du
registre pipeline MEM_ER.
•
Dans l’étage ER
On choisit la donnée à écrire sur le banc de registre en fonction du type d’instruction à l’aide du
multiplexeur REGS_SRD.
Analyse comportementale du processeur RISC.
Figure 9:Entité RISC
Le chemin de données de notre microprocesseur risc a le comportement suivant :
16
•
Les écritures sur les registres pipelines ainsi sur le banc registre et le cache de données se font
sur front montant d’horloge.
•
Toutes les opérations de lecture se font de manière immédiate.
•
Toutes les opérations qui s’exécutent dans chaque étage du pipeline se font de manière
totalement combinatoire.
Une fois que nous avons défini tous les signaux de contrôle de notre microprocesseur, la conception de
notre chemin de données consiste à la création de process sensibles aux signaux de reset et d’horloge,
dans lesquels on fait la mise à jour des données et des signaux de contrôle de chaque étage du pipeline.
Etant donné que certains signaux de contrôle comme les signaux de contrôle pour le branchement
dépendent du résultat calculé dans le chemin de données du pipeline, nous avons défini d’autres
signaux de contrôle. Le Tableau 7 représente les effets qu’engendrent les signaux d’entrée d’horloge
CLK et de reset RST ainsi les signaux de contrôle positionnés à partir des résultats du chemin de
données.
Signal
contrôle
de Effet quand le signal est actif
RST*
CLK
MEM_BRANCH
EX_flush
MEM_flush
Effet quand le signal est
inactif
du Exécution des instructions
Initialisation
de
tous
les
éléments
microprocesseur
Ecriture sur les registres pipeline et banc de registres et cache de données sur front
montant.
Branche une nouvelle adresse
CP<=CP+1 ;
Vide le pipeline à partir de l’étage EX en Rien à faire
positionnant les signaux de contrôle à des valeurs par
défaut et vide l’instruction écrit dans le registre
EI/DI.
Vide le pipeline à partir de l’étage MEM en Rien à faire
positionnant les signaux de contrôle à des valeurs par
défaut et vide l’instruction écrit dans le registre
EI/DI.
Tableau 7: Signaux de contrôle dépendant du chemin de données
La figure suivante représente une vue globale de la conception de notre microprocesseur. Nous
n’avons pas représenté tous les éléments pour que la schéma soit lisible.
17
Figure 10: Vue Globale du microprocesseur RISC
18
V.
Simulation du processeur
Pour faire la simulation de notre microprocesseur RISC. On définit tout d’abord la partie générique
qui
contient les fichiers d’initialisation du cache instruction « IFILE » et du cache données
« DFILE ».
On a testé différents types d’instructions définies en code assembleur. On a aussi testé des
programmes écrits en code assembleur pour vérifier le bon fonctionnement de notre microprocesseur.
On utilise un crosscompilateur pour traduire les codes assembleur en code binaire exécutable sur un
microprocesseur de type RISC. Le programme du crosscompilateur est écrit en C et prend en entrée un
fichier .asm qui contient notre programme en code assembleur et fournit en sortie un fichier .text qui
contient notre programme en code binaire.
Nous avons choisi de montrer dans ce rapport l’exécution de quelques portions de codes assembleur
sur notre microprocesseur. Les simulations sont représentées sur les Figure 11, Figure 12, Figure 13.
19
Figure 11: Code assembleur 1 et son exécution sur notre RISC
20
Figure 12: Exemple code assembleur 2 et son exécution sur notre processeur RISC
21
Figure 13:Code assembleur 3 et son exécution sur notre RISC
22
VI.
Synthèse du microprocesseur RISC
Une fois que notre microprocesseur RISC a été testé et validé. La dernière concerne sa synthèse en
circuit numérique. Nous avons réalisé la synthèse de notre microprocesseur en utilisant l’outil
Synopsys qui permet la synthèse de circuits numériques à partir de code VHDL.
Notre microprocesseur va être synthétisé en utilisant la technologie AMS 0.35µm. Après avoir
spécifié la technologie de synthèse on lance l’outil . Dans le cas de notre synthèse nous avons apporté
quelques changements au code VHDL de la mémoire pour la rendre synthétisable.
L’outil Synopsys a des fonctionnalités statistiques qui permettent d’évaluer le chemin critique de notre
microprocesseur. Nous rappelons que c’est le chemin critique qui va déterminer à la fréquence
maximale de fonctionnement du microprocesseur RISC. La Figure 14 et la Figure 15 représentent
une vue schématique et une vue au niveau porte logique de notre RISC synthétisé.
Figure 14: Vue schématique du microprocesseur RISC synthétisé
Une fois que la synthèse a été effectuée nous avons effectué quelques simulations pour évaluer le
chemin critique de notre microprocesseur. Pour cela on a fait varier la période d’horloge du risc. Le
Tableau 8 montre les résultats de simulation que l’on a effectuée avec l’outil Synopsys.
Tableau 8: Simulation du temps critique et de la puissance consommée du microprocesseur
Période d’horloge Temps
(ns)
(ns)
20
19.85
15
14.85
10
9.85
8
7.85
7.85
7.65
7.4
7.25
6.7
6.55
6.6
6.63
critique Puissance
dynamique (mW)
39.62
53.04
79.95
100.21
----121.1026
122.83
Puissance de fuite Nombre
(µW)
cellules
1.22
8453
1.22
8607
1.24
9229
1.25
9288
--------1.29
9822
1.29
-----
de
23
Figure 15:Vue au niveau porte logique du microprocesseur RISC synthétisé
Au début on fixe une période d’horloge assez grande puis on diminue la période d’horloge. Tant que la
période d’horloge est supérieure au chemin critique calculé, on peut encore diminuer la période. Ainsi
comme le montre le Erreur ! Source du renvoi introuvable. à partir d’une période de l’ordre de
6.6ns notre chemin critique devient plus grand que notre période d’horloge. Le chemin trouvé par le
simulateur se trouve dans l’étage Ex de notre microprocesseur entre le champ RT_read du registre
pipeline DI/EX et le champ ual_z du registre pipeline EX/MEM le temps critique calculé est de l’ordre
6.7ns. Le fait que le chemin critique soit dans l’étage EX est réaliste car il peut avoir des unités comme
l’unité d’envoi qui entrent en jeu dans l’exécution d’une instruction par l’ALU.
Ainsi avec la technologie AMS 0.35µm, la fréquence maximale de fonctionnement de notre
processeur est de l’ordre F=150MHZ. La puissance consommée sera de l’ordre de P=123mW et le
nombre de cellule sera de l’ordre 9822 cellules logiques.
Après avoir fait la synthèse et évaluer la fréquence de fonctionnement de notre microprocesseur, on
récupère le fichier de synthèse pour réaliser le place routage de notre circuit.
Le placement du microprocesseur se fait sous cadence. La figure représente le placement
24
Figure 16: Placement routage du microprocesseur RISC
25
VII.
Conclusion
Un microprocesseur RISC (pipeline) à cycle unique présente l’avantage de l’augmentation du débit
d’exécution des instructions mais n’améliore pas le temps d’exécution. Il existe deux méthodes pour
améliorer le temps d’exécution soit par cependant soit par l’utilisation d’un processeur multicycle non
pipeliné soit par la subdivision des étages pipeline d’un RISC cycle unique.
Lors de ce projet, on a pu réaliser différents étapes de conception des circuits numériques, notamment
la spécification ; la description du microprocesseur en VHDL ; la simulation ; la synthèse; et le
placement routage.
Ce qui correspond aux étapes de description de l’architecture des circuits numériques. Dans notre
étude, la simulation du circuit a occupé une grande partie du temps et requiert plus d’attention pour la
réalisation d’un RISC répondant au cahier des charges.
En plus de connaissance théoriques, ce projet nous a permis d’acquérir des compétences pratiques en
architecture des microprocesseurs qui est le cœur des machines informatiques.
26
Bibliographie
1. Airiau, Bergé, VHDL, du langage à la modélisation, (presses polytechniques et universitaires
romandes).
2. M.Aumiaix (Masson), Initiation au langage VHDL
3. John L. Hennessy, David A. Patterson –« Architecture des ordinateurs: Une approche
quantitative » Vuibert (3e Edition).
4. « Conception des circuits en VHDL » Dominique Houzet - Cepadues
27
Annexes
VIII.
1- Définition du package
----------------------------------------- Processeur RISC/ projet /CAMSI 12-13
-- CPU Package (general definitions)
-- DJITE Ibrahima & NDASHIMYE Rodrigue
----------------------------------------- library definitions
library IEEE;
library STD;
-- library uses
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
-- ------------------------------------------------------------------------------ the package contains types, constants, and function prototypes
-- ----------------------------------------------------------------------------package cpu_package is
-- ===============================================================
-- DEFINITION DE FONCTIONS/PROCEDURES de base
-- ===============================================================
-- Fonction log2
-calcule le logarithme base2 d'un entier naturel, ou plus exactement
-renvoie le nombre de bits necessaire pour coder un entier naturel I
function log2 (I: in natural) return natural;
-- ===============================================================
-- TYPES/CONSTANT DEFINITIONS
-- ===============================================================
------------------------------------------------------------------- HARDWARE definitions
------------------------------------------------------------------- define CPU core physical sizes
constant CPU_DATA_WIDTH
: positive := 32;
-- data bus width
constant CPU_INST_WIDTH
: positive := CPU_DATA_WIDTH; -- instruction bus width
constant CPU_ADR_WIDTH
: positive := 32;
-- address bus width, byte
format
-- define MISC CPU CORE specs
constant CPU_WR_FRONT : std_logic
constant PC_WIDTH
format mot memoire
constant PCLOW
:= '1';
: positive := 26;
: positive := 2;
-- pipes write active front
-- bits pour le PC
--log2(CPU_INST_WIDTH/8);
-- define REGISTERS physical sizes
constant REG_WIDTH
: positive := 5; -- registers address bus width
constant REG_FRONT
: std_logic
:= CPU_WR_FRONT;
-- define instruction & data CACHE physical sizes
constant L1_SIZE
: positive := 32; -- taille des caches L1 en nombre de mots
constant L1_ISIZE
: positive := L1_SIZE; -- taille du cache instruction L1 en nombre de mots
28
constant L1_DSIZE
mots
constant L1_FRONT
: positive := L1_SIZE; -- taille du cache donnees L1 en nombre de
: std_logic
:= CPU_WR_FRONT;
-- define types/subtypes according to hardware specs
subtype PC
is std_logic_vector(PC_WIDTH-1+PCLOW downto PCLOW);
subtype INST
is std_logic_vector(CPU_INST_WIDTH-1 downto 0);
subtype ADDR
is std_logic_vector(CPU_ADR_WIDTH-1 downto 0);
subtype DATA
is std_logic_vector(CPU_DATA_WIDTH-1 downto 0);
subtype REGS
is std_logic_vector(REG_WIDTH-1 downto 0);
-- define default values
constant PC_DEFL : ADDR := conv_std_logic_vector(0,ADDR'length);
------------------------------------------------------------------- SOFTWARE definitions
------------------------------------------------------------------- define the basic ALU operations
-- Le fait qu'une operation soit signee ou non sera indique a l'ALU par un signal
-supplementaire, ceci dit cela n'affecte que les bits d'etat.
type
ALU_OPS
(ALU_ADD,ALU_SUB,ALU_AND,ALU_OR,ALU_NOR,ALU_XOR,ALU_SLT,ALU_LSL,ALU_LSR);
is
-- define the size of datas during memory access
type MEM_DS is (MEM_8,MEM_16,MEM_32,MEM_64);
-- definition des champs d'instructions
subtype OPCODE
is std_logic_vector(31 downto 26);
subtype RS
is std_logic_vector(25 downto 21);
subtype RT
is std_logic_vector(20 downto 16);
subtype RD
is std_logic_vector(15 downto 11);
subtype VALDEC
is std_logic_vector(10 downto 6);
subtype FCODE
is std_logic_vector(5 downto 0);
subtype BCODE
is std_logic_vector(20 downto 16);
subtype IMM
is std_logic_vector(15 downto 0);
subtype JADR
is std_logic_vector(25 downto 0);
---------------------------------------------------------------- definition des constantes de type des instructions
---------------------------------------------------------------- Instructions de type R : Registre Inst[OPCODE'range]
constant TYPE_R : std_logic_vector := "000000" ;
-- Fonctions associes au TYPE_R Inst[FCODE'range]
constant ADD
: std_logic_vector := "100000" ;
constant ADDU
: std_logic_vector := "100001" ;
constant SUB
: std_logic_vector := "100010" ;
constant SUBU
: std_logic_vector := "100011" ;
constant iAND
: std_logic_vector := "100100" ; -- i pour differencier l'operateur du meme nom
constant iOR
: std_logic_vector := "100101" ; -- i pour differencier l'operateur du meme nom
constant iNOR
: std_logic_vector := "100111" ; -- i pour differencier l'operateur du meme nom
constant iXOR
: std_logic_vector := "100110" ; -- i pour differencier l'operateur du meme nom
constant SLT
: std_logic_vector := "101010" ;
constant SLTU
: std_logic_vector := "101011" ;
constant LSL
: std_logic_vector := "000000" ;
constant LSR
: std_logic_vector := "000010" ;
constant JR
: std_logic_vector := "001000" ;
constant JALR
: std_logic_vector := "001001" ;
---------------------------------------------------------------- Instruction de Type B : Branchement
constant TYPE_B : std_logic_vector := "000001" ;
-- Branch associes au TYPE_B Inst[BCODE'range]
constant BLTZ
: std_logic_vector := "00000" ;
29
constant BGEZ
: std_logic_vector := "00001" ;
constant BLTZAL
: std_logic_vector := "10000" ;
constant BGEZAL : std_logic_vector := "10001" ;
---------------------------------------------------------------- Instructions de type J : Saut
constant J
: std_logic_vector := "000010" ;
constant JAL
: std_logic_vector := "000011" ;
---------------------------------------------------------------- Instruction de type I : Immediat
constant ADDI
: std_logic_vector := "001000" ;
constant ADDIU
: std_logic_vector := "001001" ;
constant SLTI
: std_logic_vector := "001010" ;
constant SLTIU
: std_logic_vector := "001011" ;
constant ANDI
: std_logic_vector := "001100" ;
constant ORI
: std_logic_vector := "001101" ;
constant XORI
: std_logic_vector := "001110" ;
constant LUI
: std_logic_vector := "001111" ;
constant LB
: std_logic_vector := "100000" ;
constant LH
: std_logic_vector := "100001" ;
constant LW
: std_logic_vector := "100011" ;
constant LBU
: std_logic_vector := "100100" ;
constant LHU
: std_logic_vector := "100101" ;
constant SB
: std_logic_vector := "101000" ;
constant SH
: std_logic_vector := "101001" ;
constant SW
: std_logic_vector := "101011" ;
constant BEQ
: std_logic_vector := "000100" ;
constant BNE
: std_logic_vector := "000101" ;
constant BLEZ
: std_logic_vector := "000110" ;
constant BGTZ
: std_logic_vector := "000111" ;
------------------------------------------------------------------- HARDWARE Multiplexer and Pipelines registers definitions
--------------------------------------------------------------------------------------------------------------------------------- Definition des multiplexeurs dans les etages
type MUX_ALU_A
is (REGS_QA,REGS_QB,IMMD);
type MUX_ALU_B
is (REGS_QB,IMMD,VAL_DEC,ZERO,DEC_16);
type MUX_REG_DST
is (REG_RD,REG_RT,R31);
type MUX_REGS_D
is (ALU_S,MEM_Q,NextPC);
---------------------------------------------------------------- Definitions des structures de controles des etages
-- Structure des signaux de control de l'etage DI
-- type mxDI is record
-SIGNED_EXT
: std_logic;
-- extension signee ou non donnee immediate
--end record;
-- default DI control
--constant DI_DEFL : mxDI := ( SIGNED_EXT=>'0');
-- Structure des signaux de control de l'etage EX
type mxEX is record
SIGNED_EXT
: std_logic; -- extension signee ou non donnee immediate
ALU_OP
: ALU_OPS;
-- operation sur l'ALU
ALU_SIGNED
: std_logic;
-- operation ALU signee ou non
ALU_SRCA
: MUX_ALU_A;
-- mux pour entree A de l'ALU
30
ALU_SRCB
: MUX_ALU_B;
-- mux pour entree B de l'ALU
REG_DST
: MUX_REG_DST;
-- mux pour registre destinataire
Saut
:std_logic_vector(1 downto 0);
---Signal pour selectionner le type de saut
end record;
-- default EX control
constant EX_DEFL : mxEX := ( ALU_OP=>ALU_OPS'low, ALU_SRCA=>MUX_ALU_A'low,
ALU_SRCB=>MUX_ALU_B'low, REG_DST=>MUX_REG_DST'low,
ALU_SIGNED
=>'1', Saut=>conv_std_logic_vector(0,2), others=>'0');
-- Structure des signaux de control de l'etage MEM
type mxMEM is record
DC_DS
: MEM_DS;
-- DataCache taille d'acces 8/16/32/64/...
DC_RW
: std_logic;
-- DataCache signal R/W*
DC_AS
: std_logic;
-- DataCache signal Address Strobe
DC_SIGNED
: std_logic;
-- DataCache operation signee ou non (lecture)
BNE_BRANCH
: std_logic;
BEQ_BRANCH
: std_logic;
BLEZ_BRANCH
: std_logic;
BGTZ_BRANCH
: std_logic;
BLTZ_BRANCH
: std_logic;
BLTZAL_BRANCH
: std_logic;
BGEZ_BRANCH
: std_logic;
BGEZAL_BRANCH
: std_logic;
end record;
-- default MEM control
constant MEM_DEFL : mxMEM := ( DC_DS=>MEM_DS'low, DC_RW=>'1', others=>'0' );
-- Structure des signaux de control de l'etage ER
type mxER is record
REGS_W
: std_logic;
-- signal d'ecriture W* du banc de registres
REGS_SRCD
: MUX_REGS_D;
-- mux vers bus de donnee D du banc de registres
end record;
-- default ER control
constant ER_DEFL : mxER := ( REGS_W=>'1', REGS_SRCD=>MUX_REGS_D'low );
constant ER_DEFL_1 : mxER := ( REGS_W=>'0', REGS_SRCD=>MUX_REGS_D'low );
---------------------------------------------------------------- Definition des strucures des registres pipeline
-- Structure du registre EI/DI
type EI_DI is record
-- === Data ===
pc_next
: std_logic_vector (PC'range);
-- cp incremente
inst
: std_logic_vector (INST'range);
-- instruction extraite
-- === Control ===
end record;
-- Structure du registre DI/EX
type DI_EX is record
-- === Data ===
31
pc_next
: std_logic_vector (PC'range);
-- cp incremente propage
rs
: std_logic_vector (REGS'range);
-- champ rs
rt
: std_logic_vector (REGS'range);
-- champ rt
rd
: std_logic_vector (REGS'range);
-- champ rd
r31
: std_logic_vector (REGS'range);
-- champ registre R31 pour les sauts avec lien
val_dec
: std_logic_vector (VALDEC'range);
-- valeur de decalage
IMM
: std_logic_vector (IMM'range);
-- valeur immediate etendue
jump_adr
: std_logic_vector (JADR'RANGE);
-- champ adresse de sauts
rs_read
: std_logic_vector (DATA'range);
-- donnee du registre lu rs
rt_read
: std_logic_vector (DATA'range);
-- donnee du registre lu rt
code_op
: std_logic_vector (OPCODE'length-1 downto 0);
-- code op
--code_fonction : std_logic_vector (FCODE'length-1 downto 0); -- code fonction
-- === Control ===
ex_ctrl
: mxEX;
-- signaux de control de l'etage EX
mem_ctrl
: mxMEM;
-- signaux de control de l'etage MEM
er_ctrl
: mxER;
-- signaux de control de l'etage ER
end record;
-- Structure du registre EX/MEM
type EX_MEM is record
-- === Data ===
pc_next
: std_logic_vector (PC'range);
-- cp incremente propage
ual_S
: std_logic_vector (DATA'range);
-- resultat ual
rt_read
: std_logic_vector (DATA'range);
-- resultat lue sur registre rt propage
reg_dst
: std_logic_vector (REGS'range);
-- registre destination (MUX_REG_DST)
ual_Z : std_logic;
ual_N : std_logic;
ual_V : std_logic;
ual_C : std_logic;
branch_adr :std_logic_vector (PC'range);
-- === Control ===
mem_ctrl
: mxMEM;
-- signaux de control de l'etage MEM
er_ctrl
: mxER;
-- signaux de control de l'etage ER
end record;
-- Structure du registre MEM/ER
type MEM_ER is record
-- Signaux
pc_next
: std_logic_vector (PC'range);
-- cp incremente propage
mem_Q
: std_logic_vector (DATA'range);
-- sortie memoire
ual_S
: std_logic_vector (DATA'range);
-- resultat ual propage
reg_dst
: std_logic_vector (REGS'range);
-- registre destination propage
-- Signaux de control
er_ctrl
end record;
: mxER;
-- signaux de control de l'etage ER propage
32
-- ===============================================================
-- DEFINITION DE FONCTIONS/PROCEDURES
-- ===============================================================
-- Si on ne specifie rien devant les parametres...il considere que c'est une variable
-- exemple : procedure adder_cla (A,B: in std_logic_vector;...)
-- ici A et B sont consideres comme etant des variables...
-- Sinon il faut : procedure adder_cla (signal A,B: in std_logic_vector;...)
-- Fonction "+" --> procedure adder_cla
function plus (A,B: in std_logic_vector) return std_logic_vector;
-- Procedure adder_cla
procedure adder_cla (A,B: in std_logic_vector; C_IN : in std_logic;
S : out std_logic_vector; C_OUT : out
std_logic;
V : out std_logic);
-- Procedure alu
-on notera l'utilisation d'un signal comme parametres formels de type OUT
procedure alu (A,B: in std_logic_vector; signal S: out std_logic_vector;
signal N,V,Z,C: out std_logic; SIGNED_OP: in std_logic;
CTRL_ALU: in ALU_OPS);
-- Procedure control
-permet de positionner les signaux de control pour chaque etage (EX MEM ER)
-en fonction de l'instruction identifiee soit par son code op, soit par
-son code fonction, soit par son code branchement.
procedure control ( OP : in std_logic_vector(OPCODE'length-1 downto 0);
F : in std_logic_vector(FCODE'length-1 downto 0);
B : in std_logic_vector(BCODE'length-1 downto
0);
signal EX_ctrl : out mxEX;
--
signal MEM_ctrl
--
signaux de controle de l'etage EX
: out mxMEM;
signaux de controle de l'etage MEM
signal ER_ctrl : out mxER );
-- signaux
controle de l'etage ER
-- === Procedure aleas =========================================
procedure aleas ( OP : in std_logic_vector(OPCODE'length-1 downto 0);
AleEIDI_Rs : in REGS;
AleEIDI_Rt : in REGS;
AleDIEX_RT : in REGS;
AleDIEX_EcrReg :in std_logic;
AleDIEX_RegDst :in MUX_REG_DST;
signal CP_EIDI_halt
: out std_logic);
de
-- === Procedure Envoi =========================================
procedure envoi (
EnvDIEX_RS
: in REGS;
-- champ rs: DI/EXregistrelecture1
EnvDIEX_RT
: in REGS;
-- champ rt: DI/EXregistrelecture2
EnvDIEX_RD
: in REGS;
-- champ rd: DI/EXregistreEcriture
EnvEXM_EcrReg : in std_logic;
EnvMER_EcrReg : in std_logic;
EnvEXM_RegDst :in REGS; -- champ EX/MEMregistreEcriture
EnvMER_RegDst :in REGS;
-- champ MEM/ERregistreEcriture
signal Env_ALU_SRCA1
: out std_logic_vector(1 downto 0);
-- mux pour entree A1 de l'ALU
33
signal Env_ALU_SRCB1
: out std_logic_vector(1 downto 0) );
-- mux pour
entree B1 de l'ALU
end cpu_package;
-- ------------------------------------------------------------------------------ the package contains types, constants, and function prototypes
-- ----------------------------------------------------------------------------package body cpu_package is
-- ===============================================================
-- DEFINITION DE FONCTIONS/PROCEDURES
-- ===============================================================
-- fonction log2
function log2 (I: in natural) return natural is
variable ip : natural := 1; -- valeur temporaire
variable iv : natural := 0; -- nb de bits
begin
while ip < i loop
ip := ip + ip; -- ou ip := ip * 2
iv := iv + 1;
end loop;
-- renvoie le nombre de bits
return iv;
end log2;
-- fonction "+" --> procedure adder_cla
function plus (A,B: in std_logic_vector) return std_logic_vector is
variable tmp_S : std_logic_vector(A'range);
variable tmp_COUT,tmp_V : std_logic;
begin
adder_cla(A,B,'0',tmp_S,tmp_COUT,tmp_V);
return tmp_S;
end plus;
-- Le drapeau overflow V ne sert que lors d'operations signees !!!
-- Overflow V=1 si operation signee et :
-addition de deux grands nombres positifs dont le resultat < 0
-addition de deux grands nombres negatifs dont le resultat >= 0
-soustraction d'un grand nombre positif et d'un grand nombre negatif dont le resultat < 0
-soustraction d'un grand nombre negatif et d'un grand nombre positif dont le resultat >= 0
-- Reviens a faire V = C_OUT xor <carry entrante du dernier bit>
-- procedure adder_cla
procedure adder_cla (A,B: in std_logic_vector;C_IN : in std_logic;
S : out std_logic_vector;C_OUT : out std_logic;
V : out std_logic) is
variable G_CLA,P_CLA
: std_logic_vector(A'length-1 downto 0);
variable C_CLA
: std_logic_vector(A'length downto 0);
begin
-- calcul de P et G
G_CLA:= A and B;
P_CLA:= A or B;
C_CLA(0):=C_IN;
for I in 0 to (A'length-1) loop
C_CLA(I+1):= G_CLA(I) or (P_CLA(I) and C_CLA(I));
end loop;
-- mise a jour des sorties
S:=(A Xor B) xor C_CLA(A'length-1 downto 0);
C_OUT:=C_CLA(A'length);
V:= C_CLA(A'length) xor C_CLA(A'length - 1);
end adder_cla;
34
-- procedure alu
procedure alu (A,B: in std_logic_vector;signal S: out std_logic_vector;
signal N,V,Z,C: out std_logic;SIGNED_OP: in std_logic;
CTRL_ALU: in ALU_OPS) is
variable DATA_WIDTH : positive := A'length;
variable b_in
: std_logic_vector(DATA_WIDTH-1 downto 0);
variable c_in
: std_logic;
variable tmp_S
: std_logic_vector(DATA_WIDTH-1 downto 0);
variable tmp_V
: std_logic;
variable tmp_N
: std_logic;
variable tmp_C
: std_logic;
variable tmp_CLA_C
: std_logic;
variable tmp_CLA_V
: std_logic;
begin
-- raz signaux
tmp_V := '0';
tmp_N := '0';
tmp_C := '0';
-- case sur le type d'operation
case CTRL_ALU is
when ALU_ADD | ALU_SUB | ALU_SLT =>
b_in := B;
c_in := '0';
if (CTRL_ALU /= ALU_ADD) then
b_in := not(B);
c_in := '1';
end if;
adder_cla(A,b_in,c_in,tmp_S,tmp_C,tmp_V);
if (CTRL_ALU = ALU_SLT) then
tmp_S
:=
conv_std_logic_vector(
(SIGNED_OP
and
(tmp_V
tmp_S(DATA_WIDTH-1))) or (not(SIGNED_OP) and not(tmp_C)) , S'length );
-- remize à 0 des flags selon definition
tmp_C := '0';
tmp_V := '0';
else
tmp_C := not(SIGNED_OP) and tmp_C;
tmp_N := SIGNED_OP and tmp_S(DATA_WIDTH-1);
tmp_V := SIGNED_OP and tmp_V;
end if;
when ALU_AND =>
tmp_S := A and B;
when ALU_OR =>
tmp_S := A or B;
when ALU_NOR =>
tmp_S := A nor B;
when ALU_XOR =>
tmp_S := A xor B;
when ALU_LSL =>
tmp_S := shl(A,B);
when ALU_LSR =>
tmp_S := shr(A,B);
when others =>
end case;
-- affectation de la sortie
S <= tmp_S;
-- affectation du drapeau Z (valable dans tous les cas)
if (tmp_S=conv_std_logic_vector(0,DATA_WIDTH)) then Z <= '1';
else Z <= '0';
end if;
-- affectation des autres drapeaux N,V,C
C <= tmp_C;
N <= tmp_N;
V <= tmp_V;
end alu;
xor
35
-- === Procedure control =========================================
-Permet de positionner les signaux de control pour chaque etage (EX MEM ER)
-en fonction de l'instruction identifiee soit par son code op, soit par
-son code fonction, soit par son code branchement.
procedure control ( OP : in std_logic_vector(OPCODE'length-1 downto 0);
F : in std_logic_vector(FCODE'length-1 downto 0);
B : in std_logic_vector(BCODE'length-1 downto 0);
signal EX_ctrl
: out mxEX;
--
signaux de controle de l'etage EX
signal MEM_ctrl : out mxMEM;
--
signaux
de
signal ER_ctrl
--
signaux
de
controle de l'etage MEM
: out mxER ) is
controle de l'etage ER
begin
-- Initialisation
-- DI_ctrl <= DI_DEFL;
EX_ctrl <= EX_DEFL;
MEM_ctrl <= MEM_DEFL;
ER_ctrl <= ER_DEFL;
-- Controle DI : signe-t-on ou non l'extension de la valeur immediate
if (
(OP=ADDI) or (OP=ADDIU) or (OP=LB) or (OP=LH) or (OP=LW) or (OP=LBU) or
(OP=LHU) or (OP=SB)
or (OP=SH) or (OP=SW) or (OP=SLTIU) or (OP=SLTI) or
(OP=ANDI) or (OP=ORI) or (OP=type_B) or
(OP=BEQ) or (OP=BNE) or (OP=BLEZ) or (OP=BGTZ))then
EX_ctrl.SIGNED_EXT <= '1';
else
EX_ctrl.SIGNED_EXT <= '0';
end if;
--controle EX
-----Operation sur ALU-----------Par défaut le signal de controle de l'alu ALU_OP est toujours sur (ALU_OP'low c'est à dire sur la valeur
ALU_ADD--if (
(OP=type_R and F=SUB) or (OP=type_R and F=SUBU) or (OP=type_B) or
(OP=BEQ) or (OP=BNE) or (OP=BLEZ) or (OP=BGTZ) )then
EX_ctrl.ALU_OP <=ALU_SUB;
elsif(
(OP=type_R and F=iAND) or (OP=ANDI)) then
EX_ctrl.ALU_OP <=ALU_AND;
elsif(
(OP=type_R and F=iOR) or (OP=ORI)) then
EX_ctrl.ALU_OP <=ALU_OR;
elsif(
(OP=type_R and F=iNOR)) then
EX_ctrl.ALU_OP <=ALU_NOR;
elsif(
(OP=type_R and F=iXOR) or (OP=XORI)) then
EX_ctrl.ALU_OP <=ALU_XOR;
elsif((OP=type_R and F=LSL) or (OP=LUI)) then
EX_ctrl.ALU_OP <=ALU_LSL;
elsif((OP=SLTIU) or (OP=SLTI) or (OP=type_R and F=SLT) or (OP=type_R and F=SLTU)) then
EX_ctrl.ALU_OP <=ALU_SLT;
elsif(OP=type_R and F=LSR) then
EX_ctrl.ALU_OP <=ALU_LSR;
end if;
if((OP=type_R and F=SUBU) or (OP=type_R and F=ADDU) or (OP=type_R and F=SLTU)
or (OP=ANDI)or (OP=ORI) or (OP=XORI) or (OP=LUI) or (OP=ADDIU) or ( OP=SLTIU)) then
EX_ctrl.ALU_SIGNED<='0';
end if;
-----Positionnement signaux de controles des multiplexeurs----------Signal de controle REG_DST du Multiplexeur MUX_REG_DST pour choisir le registre destination pour
certaines instructions immediates
36
-----------ou aussi le registre de base pour l'instruction de saut avec lien Jal. Par défaut le signal REG_DST toujours sur
REG_RD
if((OP=ADDI) or (OP=ADDIU) or (OP=SLTI) or (OP=SLTIU) or (OP=ANDI) or (OP=ORI) or (OP=XORI)
or (OP=LUI) or (OP=LB) or (OP=LH) or (OP=LW) or (OP=LBU) or (OP=LHU)) then
EX_ctrl.REG_DST<=REG_RT;
elsif((OP=JAL) or (OP=type_B and B=BLTZAL) or (OP=type_B and B=BGEZAL)) then
EX_ctrl.REG_DST<=R31;
else
EX_ctrl.REG_DST<=REG_RD;
end if;
--------Signal de controle ALU_SRCB, ALU_SRCA des Multiplexeurs MUX_ALU_SRCB, MUX_ALU_SRCA pour
choisir la valeur entrant dans l'entree A et B de l'ALU REGS_QB, IMMD ou VALDEC:
----------- Par défaut le signal ALU_SRCA est toujours sur REGS_QA et ALU_SRCB sur REGS_QB
if((OP=ADDI) or (OP=SLTI) or (OP=LB) or (OP=LH) or (OP=LW)
or (OP=LBU) or (OP=LHU) or (OP=SB) or (OP=SH) or (OP=SW) or (OP=ANDI)
or (OP=ORI) or (OP=XORI) or (OP=ADDIU) or (OP=SLTIU)) then
EX_ctrl.ALU_SRCB<=IMMD;
EX_ctrl.ALU_SRCA<=REGS_QA;
elsif((OP=type_R and F=LSR) or (OP=type_R and F=LSL)) then
EX_ctrl.ALU_SRCB<=VAL_DEC;
end if;
if(OP=LUI) then
EX_ctrl.ALU_SRCB<=DEC_16;
EX_ctrl.ALU_SRCA<=IMMD;
end if;
if(OP=type_R and F=LSL) or (OP=type_R and F=LSR) then
EX_ctrl.ALU_SRCB<=VAL_DEC;
EX_ctrl.ALU_SRCA<=REGS_QB;
end if;
if(OP=type_B) then
EX_ctrl.ALU_SRCB<=ZERO;
EX_ctrl.ALU_SRCA<=REGS_QA;
end if;
if ((OP=J) or (OP=JAL)) then
EX_ctrl.Saut(0)<='0';
EX_ctrl.Saut(1)<='1';
end if;
if ((OP=type_R and F=JALR) or(OP=type_R and F=JR)) then
EX_ctrl.Saut(0)<='1';
EX_ctrl.Saut(1)<='1';
end if;
--------Signal de controle ALU_SRCA du Multiplexeur MUX_ALU_SRCA pour choisir la valeur entrant dans
l'entree A de l'ALU REGS_QB, IMMD ou VALDEC:
-----------ou aussi le registre de base pour l'instruction de saut avec lien Jal. Par défaut le signal ALU_SRCA est
toujours sur REGS_QA
--controle MEM
---Branchement
if(OP=BEQ) then
MEM_CTRL.BEQ_BRANCH<='1';
elsif (OP=BLEZ) then
MEM_CTRL.BLEZ_BRANCH<='1';
elsif (OP=BGTZ) then
MEM_CTRL.BGTZ_BRANCH<='1';
elsif (OP=BNE) then
MEM_CTRL.BNE_BRANCH<='1';
end if;
if (OP=type_B) then
if(B=BLTZ) then
MEM_ctrl.BLTZ_BRANCH<='1';
elsif (B=BGEZ)then
37
MEM_ctrl.BGEZ_BRANCH<='1';
elsif (B=BLTZAL) then
MEM_ctrl.BLTZAL_BRANCH<='1';
elsif (B=BGEZAL) then
MEM_ctrl.BGEZAL_BRANCH<='1';
end if;
end if;
----Intructution de chargement------------Par défaut les signaux de controle
de l'étage MEM sont toujours sur constant MEM_DEFL
(DC_DS=>MEM_DS'low, DC_RW=>'1', others=>?0?);
if(OP=LBU) then
MEM_ctrl.DC_RW<='1';
MEM_ctrl.DC_DS<=MEM_8;
MEM_ctrl.DC_SIGNED<='0';
MEM_ctrl.DC_AS<='1';
end if;
if( (OP=LH)) then
MEM_ctrl.DC_RW<='1';
MEM_ctrl.DC_DS<=MEM_16;
MEM_ctrl.DC_SIGNED<='1';
MEM_ctrl.DC_AS<='1';
elsif((OP=LHU)) then
MEM_ctrl.DC_RW<='1';
MEM_ctrl.DC_DS<=MEM_16;
MEM_ctrl.DC_SIGNED<='0';
MEM_ctrl.DC_AS<='1';
end if;
if(OP=LW) then
MEM_ctrl.DC_RW<='1';
MEM_ctrl.DC_DS<=MEM_32;
MEM_ctrl.DC_SIGNED<='0';
MEM_ctrl.DC_AS<='1';
end if;
----Intructution de rangement--if( (OP=SB)) then
MEM_ctrl.DC_RW<='0';
MEM_ctrl.DC_DS<=MEM_8;
MEM_ctrl.DC_SIGNED<='1';
MEM_ctrl.DC_AS<='1';
end if;
if( (OP=SH)) then
MEM_ctrl.DC_RW<='0';
MEM_ctrl.DC_DS<=MEM_16;
MEM_ctrl.DC_SIGNED<='1';
MEM_ctrl.DC_AS<='1';
end if;
if((OP=SW)) then
MEM_ctrl.DC_RW<='0';
MEM_ctrl.DC_DS<=MEM_32;
MEM_ctrl.DC_SIGNED<='0';
MEM_ctrl.DC_AS<='1';
end if;
--controle ER
-------Par défaut les signaux de contrôle de l'étage ER sont toujours sur constant ER_DEFL:= (REGS_W=>'1',
REGS_SRCD=>MUX_REGS_D'low );
if((OP=SB) or (OP=SW) or (OP=SH) or (OP=SH) or (OP=BEQ) or (OP=BNE)
or (OP=type_B and B=BLTZ) or (OP=type_B and B=BGEZ) or (OP=J)
or (OP=BLEZ) or (OP=BGTZ)) then
ER_ctrl.REGS_W<='0';
end if;
38
-----Positionnement multiplexeurs étage ER Multiplexeur REG_D pour selectionner la valeur à ecrire sur le banc
de registre entre MEM_Q ALU_S et
--------NextPC. La valeur par défaut est ALU_S--if( (OP=LB)or (OP=LH) or (OP=LW) or (OP=LBU) or (OP=LHU) ) then
ER_ctrl.REGS_SRCD<=MEM_Q;
elsif( (OP=JAL) or (OP=JALR) or (OP=type_B and B=BLTZAL) or (OP=type_B and B=BGEZAL)) then
ER_ctrl.REGS_SRCD<=NextPC;
end if;
end control;
-- === Procedure aleas =========================================
-Permet de detecter les aleas pour l'etage DI
procedure aleas ( OP : in std_logic_vector(OPCODE'length-1 downto 0);
AleEIDI_Rs : in REGS;
AleEIDI_Rt : in REGS;
AleDIEX_RT : in REGS;
AleDIEX_EcrReg :in std_logic;
AleDIEX_RegDst :in MUX_REG_DST;
signal CP_EIDI_halt
: out std_logic)is
begin
CP_EIDI_halt<='0';
------aleas cohabité avec l'envoi
if((OP=LW) or (OP=LH) or (OP=LB) or (OP=LBU) or (OP=LHU)) then
if((AleDIEX_EcrReg ='1') and(AleDIEX_RegDst = REG_RT) and
((AleDIEX_RT = AleEIDI_Rs) or (AleDIEX_RT = AleEIDI_Rt))) then
CP_EIDI_halt<='1';
else
CP_EIDI_halt<='0';
end if;
end if;
end aleas;
-- === Procedure ENVOI =========================================
procedure envoi ( EnvDIEX_RS
: in REGS;
-- champ rs: DI/EXregistrelecture1
EnvDIEX_RT
: in REGS;
-- champ rt: DI/EXregistrelecture2
EnvDIEX_RD
: in REGS;
-- champ rd: DI/EXregistreEcriture
EnvEXM_EcrReg : in std_logic;
EnvMER_EcrReg : in std_logic;
EnvEXM_RegDst :in REGS; -- champ EX/MEMregistreEcriture
EnvMER_RegDst :in REGS;
-- champ MEM/ERregistreEcriture
signal Env_ALU_SRCA1
: out std_logic_vector(1 downto 0);
-- mux pour entree A1 de l'ALU
signal Env_ALU_SRCB1
: out std_logic_vector(1 downto 0) ) is
entree B1 de l'ALU
begin
--Envoi pour le multiplexeur alu A
if (EnvDIEX_RS /= conv_std_logic_vector(0,5))
and ((EnvEXM_EcrReg = '1')
and (EnvEXM_RegDst = EnvDIEX_RS))then
Env_ALU_SRCA1 <= conv_std_logic_vector(1,2);
elsif (EnvDIEX_RS /= conv_std_logic_vector(0,5))
and ((EnvMER_EcrReg ='1')
and ((EnvEXM_RegDst /= EnvDIEX_RS)
and (EnvMER_RegDst = EnvDIEX_RS)))then
Env_ALU_SRCA1 <= conv_std_logic_vector(2,2);
else
Env_ALU_SRCA1 <= conv_std_logic_vector(0,2);
end if;
-- mux pour
39
--Envoi pour le multiplexeur alu B
if (EnvDIEX_RT /= conv_std_logic_vector(0,5))
and ((EnvEXM_EcrReg ='1')
and (EnvEXM_RegDst = EnvDIEX_RT)) then
Env_ALU_SRCB1 <= conv_std_logic_vector(1,2);
elsif (EnvDIEX_RT /= conv_std_logic_vector(0,5))
and ((EnvMER_EcrReg ='1')
and ((EnvEXM_RegDst /= EnvDIEX_RT)
and (EnvMER_RegDst = EnvDIEX_RT))) then
Env_ALU_SRCB1 <= conv_std_logic_vector(2,2);
else
Env_ALU_SRCB1 <= conv_std_logic_vector(0,2);
end if;
end envoi;
end cpu_package;
IX.
2- Code VHDL du microprocesseur RISC
------------------------------------------- Processeur RISC/ projet /CAMSI 12-13
-- DJITE Ibrahima & NDASHIMYE Rodrigue
------------------------------------------------------------------------------------------------- Lors de la phase RESET, permet la lecture d'un fichier
-- instruction et un fichier donnees passe en parametre
-generique.
---------------------------------------------------------- Definition des librairies
library IEEE;
-- Definition des portee d'utilisation
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use WORK.cpu_package.all;
-- Definition de l'entite
entity risc is
-- definition des parametres generiques
generic (
-- fichier d'initialisation cache instruction
IFILE : string := "";
-- fichier d'initialisation cache donnees
DFILE : string := "" );
-- definition des entrees/sorties
port
(
-- signaux de controle du processeur
RST
: in std_logic; -- actifs a l'etat bas
CLK
: in std_logic );
end risc;
-- Definition de l'architecture du banc de registres
architecture behavior of risc is
-- definition de constantes
-- definitions de types/soustypes
40
-- definition des ressources internes
-- Registres du pipeline
signal reg_EI_DI : EI_DI;
-- registre pipeline EI/DI
signal reg_DI_EX : DI_EX;
-- registre pipeline DI/EX
signal reg_EX_MEM
: EX_MEM;
-- registre pipeline EX/MEM
signal reg_MEM_ER
: MEM_ER;
-- registre pipeline MEM/ER
-- Ressources de l'etage EI
signal reg_PC
: ADDR;
-- compteur programme format octet
signal ei_next_pc : PC;
-- pointeur sur prochaine instruction
signal ei_inst
: INST;
-- instruction en sortie du cache instruction
signal ei_halt
: std_logic;
-- suspension etage pipeline
--signal ei_flush : std_logic;
-- vidange de l'etage
-- Ressources de l'etage Dsim:/test_risc/r3k/line__212I
signal di_qa
: DATA;
-- sortie QA du banc de
signal di_qb
-- sortie QB du banc de
registres
: DATA;
registres
signal di_ctrl_ex
: mxEX;
-- signaux de controle de l'etage EX
signal di_ctrl_mem : mxMEM;
-- signaux de controle de l'etage MEM
signal di_ctrl_er
: mxER;
-- signaux de controle de l'etage ER
--signal di_halt
: std_logic;
-- suspension etage pipeline
--signal di_flush
: std_logic;
-- vidange de l'etage
-- Ressources de l'etage EX
signal EX_ALU_N : std_logic;
signal EX_ALU_C : std_logic;
signal EX_ALU_V : std_logic;
signal EX_ALU_Z : std_logic;
signal EX_ALU_S : DATA;
signal EX_imm_ext
: DATA;
signal EX_Sortie_MUX_REGDST : REGS;
signal EX_Sortie_MUX_ALU_SRCA : DATA;
signal EX_Sortie_MUX_ALU_SRCB : DATA;
--signal EX_IMMD_DECALE : DATA;
signal EX_valdec_ext : DATA;
signal EX_BRANCH
: PC;
signal EX_Saut_J_ADR : PC;
signal EX_Saut_ADR : PC;
signal EX_Env_MxALU_A1 : std_logic_vector(1 downto 0);
signal EX_Env_MxALU_B1 : std_logic_vector(1 downto 0);
signal EX_Sortie_Env_Mx_A1 : DATA;
signal EX_Sortie_Env_Mx_B1 : DATA;
signal EX_flush : std_logic;
-- Ressources de l'etage MEM
-- valeur immediate etendue
signal MEM_BR_SRC
: std_logic_vector (1 downto 0);--Signal controle multiplixeur
pour les sauts par registres et les branchements
signal ecrire_PC : PC;
signal MEM_Sortie_cache : DATA;
signal MEM_flush : std_logic;
-- Ressources de l'etage ER
signal er_regd
: DATA;
signal er_adrw
: REGS;
-- donnees a ecrire dans le banc de registre
-- adresse du registre a ecrire dans le banc de
registre
signal er_pcnext_ext : ADDR;
begin
-- ===============================================================
-- === Etage EI ==================================================
41
-- ===============================================================
------------------------------------------------------------------- instanciation et mapping du composant cache instruction
icache : entity work.memory(behavior)
generic map ( DBUS_WIDTH=>CPU_DATA_WIDTH,
ABUS_WIDTH=>CPU_ADR_WIDTH, MEM_SIZE=>L1_ISIZE,
ACTIVE_FRONT=>L1_FRONT,
FILENAME=>IFILE )
port map ( RST=>RST, CLK=>CLK, RW=>'1', DS=>MEM_32, Signed=>'0',
AS=>'1', Ready=>open,
Berr=>open, ADR=>reg_PC,
D=>(others => '0'), Q=>ei_inst );
------------------------------------------------------------------- Affectations dans le domaine combinatoire de l'etage EI
-- Incrementation du PC (format mot)
ei_next_pc <= reg_PC(PC'range)+1;
--ei_halt <= '0';
--ei_flush <= '0';
------------------------------------------------------------------- Process Etage Extraction de l'instruction et mise a jour de
l'etage EI/DI et du PC
EI: process(CLK,RST)
begin
-- test du reset
if (RST='0') then
-- reset du PC
reg_PC <= PC_DEFL;
-- test du front actif d'horloge
elsif (CLK'event and CLK=CPU_WR_FRONT) then
-- Mise a jour PC
--control d'ecriture PC avec di_ale_EcrCP activé par un alea
if (ei_halt='0') then
reg_PC(PC'range)<=ecrire_PC;
else
if(MEM_flush='1' or EX_flush='1') then
reg_PC(PC'range)<=ecrire_PC;
end if;
end if;
-- Mise a jour du registre inter-etage EI/DI
--control d'ecriture de Reg EI/DI avec di_ale_EcrEIDI activé par un alea
if (ei_halt ='0') then
reg_EI_DI.pc_next <= ei_next_pc;
reg_EI_DI.inst <= ei_inst;
end if;
if(MEM_flush='1' or EX_flush='1') then
reg_EI_DI.inst <= conv_std_logic_vector(0,CPU_INST_WIDTH);
end if;
end if;
end process EI;
-- ===============================================================
-- ============= Etage DI =========================================
-- ===============================================================
-------Appel de la Procedure aleas ------------------------------ALE_proc: aleas ( OP => reg_DI_EX.code_op,
AleEIDI_Rs =>reg_EI_DI.inst(RS'range),
AleEIDI_Rt =>reg_EI_DI.inst(RT'range),
AleDIEX_RT =>reg_DI_EX.rt,
42
AleDIEX_EcrReg =>reg_DI_EX.er_ctrl.REGS_W,
AleDIEX_RegDst =>reg_DI_EX.ex_ctrl.REG_DST, --Control de Regdst
CP_EIDI_halt =>ei_halt);
------------------------------------------------------------------- instantiation et mapping du composant registres
regf : entity work.registres(behavior)
generic map ( DBUS_WIDTH=>CPU_DATA_WIDTH,
ABUS_WIDTH=>REG_WIDTH, ACTIVE_FRONT=>REG_FRONT )
port map ( CLK=>CLK, W=>reg_MEM_ER.er_ctrl.regs_W, RST=>RST,
D=>er_regd,
ADR_A=>reg_EI_DI.inst(RS'range),
ADR_B=>reg_EI_DI.inst(RT'range),
ADR_W=>er_adrw, QA=>di_qa, QB=>di_qb
);
------------------------------------------------------------------- Affectations dans le domaine combinatoire de l'etage DI
--- Appel de la procedure contol
UC: control( reg_EI_DI.inst(OPCODE'range),
reg_EI_DI.inst(FCODE'range),
reg_EI_DI.inst(BCODE'range),
di_ctrl_ex,
di_ctrl_mem,
di_ctrl_er );
--di_halt <= '0';
--di_flush <= '0';
------------------------------------------------------------------- Process Etage Extraction de l'instruction et mise a jour de
-l'etage DI/EX
DI: process(CLK,RST)
begin
-- test du reset
if (RST='0') then
-- reset des controle du pipeline
reg_DI_EX.ex_ctrl
<= EX_DEFL;
reg_DI_EX.mem_ctrl
<= MEM_DEFL;
reg_DI_EX.er_ctrl <= ER_DEFL;
-- test du front actif d'horloge
elsif (CLK'event and CLK=CPU_WR_FRONT) then
-- Mise a jour du registre inter-etage DI/EX
reg_DI_EX.pc_next
<= reg_EI_DI.pc_next;
reg_DI_EX.code_op
<= reg_EI_DI.inst(OPCODE'range);
reg_DI_EX.rs
<= reg_EI_DI.inst(RS'range);
reg_DI_EX.rt
<= reg_EI_DI.inst(RT'range);
reg_DI_EX.rd
<= reg_EI_DI.inst(RD'range);
reg_DI_EX.val_dec
<= reg_EI_DI.inst(VALDEC'range);
reg_DI_EX.IMM
<= reg_EI_DI.inst(IMM'range);
reg_DI_EX.jump_adr
<= reg_EI_DI.inst(JADR'range);
reg_DI_EX.rs_read
<= di_qa;
reg_DI_EX.rt_read
<= di_qb;
-- Mise a jour des signaux de controle
-- Les signaux sont rendu invalide si il y'a alea ainsi ils prennent les valeur default.
-- mux de controle à l'etage DI
if (ei_halt = '0') then
reg_DI_EX.ex_ctrl
<= di_ctrl_ex;
reg_DI_EX.mem_ctrl
<= di_ctrl_mem;
reg_DI_EX.er_ctrl
<= di_ctrl_er;
end if;
43
if ((ei_halt = '1') or (MEM_flush = '1') or (EX_flush='1')) then
reg_DI_EX.ex_ctrl
<= EX_DEFL;
reg_DI_EX.mem_ctrl <= MEM_DEFL;
reg_DI_EX.er_ctrl
<= ER_DEFL_1;
end if;
end if;
end process DI;
-- ===============================================================
-- === Etage EX ==================================================
-- ===============================================================
-----Appel de le Procedure Envoi---------------------------------ENV_proc: envoi ( EnvDIEX_RS
=>reg_DI_EX.rs,
-- champ rs: DI/EXregistrelecture1
EnvDIEX_RT
=>reg_DI_EX.rt,
-- champ rt: DI/EXregistrelecture2
EnvDIEX_RD
=>reg_DI_EX.rd,
-- champ rd: DI/EXregistreEcriture
EnvEXM_EcrReg
=>reg_EX_MEM.er_ctrl.REGS_W,
EnvMER_EcrReg=>reg_MEM_ER.er_ctrl.REGS_W,
EnvEXM_RegDst =>reg_EX_MEM.reg_dst,
-- champ EX/MEMregistreEcriture
EnvMER_RegDst =>reg_MEM_ER.reg_dst,
-- champ MEM/ERregistreEcriture
Env_ALU_SRCA1 =>EX_Env_MxALU_A1,
-- mux pour entree A1 de l'ALU
Env_ALU_SRCB1 =>EX_Env_MxALU_B1);
-- mux pour entree B1 de l'ALU
-- Calcul de l'extension de la valeur immediate
EX_imm_ext(IMM'range) <= reg_DI_EX.IMM;
EX_imm_ext(DATA'high downto IMM'high+1) <= (others => '0') when reg_DI_EX.ex_ctrl.signed_ext='0' else
(others => reg_DI_EX.IMM(IMM'high));
-- Extention à 32bits de la valeur de décalage--------EX_valdec_ext(reg_DI_EX.val_dec'LENGTH -1 downto 0)<=reg_DI_EX.val_dec;
EX_valdec_ext(CPU_DATA_WIDTH-1 downto reg_DI_EX.val_dec'LENGTH)<=(others=>'0');
----Positionnement des multiplexeurs de l'étage EX---------Mux envoi de l'entree Alu A1
with EX_Env_MxALU_A1 select
EX_Sortie_Env_Mx_A1 <= reg_EX_MEM.ual_S when "01",
er_regd when "10",
reg_DI_EX.rs_read when others;
--Mux envoi de l'entree Alu B1
with EX_Env_MxALU_B1 select
EX_Sortie_Env_Mx_B1 <= reg_EX_MEM.ual_S when "01",
er_regd when "10",
reg_DI_EX.rt_read
when others;
--Mux normal de l'entree Alu A
with reg_DI_EX.ex_ctrl.ALU_SRCA select
EX_Sortie_MUX_ALU_SRCA <= EX_Sortie_Env_Mx_A1
when REGS_QA,
reg_DI_EX.rt_read when REGS_QB,
EX_imm_ext when IMMD;
--Mux normal de l'entree Alu B
with reg_DI_EX.ex_ctrl.ALU_SRCB select
EX_Sortie_MUX_ALU_SRCB <= EX_Sortie_Env_Mx_B1
when REGS_QB,
EX_valdec_ext when VAL_DEC,
EX_imm_ext when IMMD,
conv_std_logic_vector(0,CPU_DATA_WIDTH)when DEC_16,
(others=>'0') when ZERO;
---with reg_DI_EX.ex_ctrl.REG_DST select
44
EX_Sortie_MUX_REGDST <= reg_DI_EX.rd when REG_RD,
reg_DI_EX.rt when REG_RT,
conv_std_logic_vector(31,REG_WIDTH) when R31;
-- Appel de la procedure ALU ------------ALU_proc: alu (EX_Sortie_MUX_ALU_SRCA,EX_Sortie_MUX_ALU_SRCB,EX_ALU_S,
EX_ALU_N,EX_ALU_V,EX_ALU_Z,EX_ALU_C,
reg_DI_EX.ex_ctrl.ALU_SIGNED,reg_DI_EX.ex_ctrl.ALU_OP);
-----Decalage de la valeur immediate pour calcul adresse de branchement--------Calcul de l'adresse de Branchement-----------EX_BRANCH<=plus(EX_imm_ext(PC_WIDTH-1 downto 0),reg_DI_EX.pc_next);
-----Ajout d'un multiplexeur pour selection du type de saut par registre ou Saut pure ----------EX_Saut_J_ADR<=reg_DI_EX.jump_adr;
with reg_DI_EX.ex_ctrl.Saut select
EX_Saut_ADR<=EX_Saut_J_ADR when "10",
EX_ALU_S(PC_WIDTH-1+PCLOW downto PCLOW) when "11",
EX_Saut_J_ADR when others;
EX: process(CLK,RST)
begin
-- test du reset
if (RST='0') then
-- reset des controle du pipeline
reg_EX_MEM.mem_ctrl
<= MEM_DEFL;
reg_EX_MEM.er_ctrl
<= ER_DEFL;
-- test du front actif d'horloge
elsif (CLK'event and CLK=CPU_WR_FRONT) then
-- Mise a jour du registre inter-etage DI/EX
reg_EX_MEM.pc_next
<= reg_DI_EX.pc_next;
reg_EX_MEM.rt_read
<=EX_Sortie_Env_Mx_B1;
reg_EX_MEM.reg_dst
<= EX_Sortie_MUX_REGDST;
reg_EX_MEM.ual_S
<= EX_ALU_S;
reg_EX_MEM.ual_N
<= EX_ALU_N;
reg_EX_MEM.ual_V
<= EX_ALU_V;
reg_EX_MEM.ual_Z
<= EX_ALU_Z;
reg_EX_MEM.ual_C
<= EX_ALU_C;
reg_EX_MEM.branch_ADR<=EX_BRANCH;
-- Mise a jour des signaux de controle
-- Flush si branchement ou saut
if MEM_flush = '0' then
reg_EX_MEM.mem_ctrl<=reg_DI_EX.mem_ctrl;
reg_EX_MEM.er_ctrl
<= reg_DI_EX.er_ctrl;
else
reg_EX_MEM.mem_ctrl<= MEM_DEFL;
reg_EX_MEM.er_ctrl
<= ER_DEFL_1;
end if;
end if;
end process EX;
EX_flush<='1' when (reg_DI_EX.ex_ctrl.Saut(1)='1') else
'0';
------- ===============================================================
-- === Etage MEM ==================================================
-- ===============================================================
-----Fabrication du signal de controle pour le brancnement le pc next et le Saut ----------MEM_BR_SRC(0)<=((not(reg_EX_MEM.ual_Z) and reg_EX_MEM.mem_ctrl.BNE_BRANCH) or
(reg_EX_MEM.ual_Z and reg_EX_MEM.mem_ctrl.BEQ_BRANCH) or
(((reg_EX_MEM.ual_V xor reg_EX_MEM.ual_N) and not(reg_EX_MEM.ual_Z))and
reg_EX_MEM.mem_ctrl.BLTZ_BRANCH) or
45
(((reg_EX_MEM.ual_V xor reg_EX_MEM.ual_N) or reg_EX_MEM.ual_Z) and
reg_EX_MEM.mem_ctrl.BLEZ_BRANCH) or
((not(reg_EX_MEM.ual_V xor reg_EX_MEM.ual_N) and not(reg_EX_MEM.ual_Z))and
reg_EX_MEM.mem_ctrl.BGTZ_BRANCH) or
((not(reg_EX_MEM.ual_V xor reg_EX_MEM.ual_N) or reg_EX_MEM.ual_Z)and
reg_EX_MEM.mem_ctrl.BGEZ_BRANCH) or
(((reg_EX_MEM.ual_V xor reg_EX_MEM.ual_N) and not(reg_EX_MEM.ual_Z))and
reg_EX_MEM.mem_ctrl.BLTZAL_BRANCH) or
((not(reg_EX_MEM.ual_V xor reg_EX_MEM.ual_N) or reg_EX_MEM.ual_Z)and
reg_EX_MEM.mem_ctrl.BGEZAL_BRANCH));
MEM_BR_SRC(1)<=reg_DI_EX.ex_ctrl.Saut(1);
---------Ajout d'un multiplexeur pour selectionner le CP suivant soit CP+1 soit Saut ou bien Branchement-----------with MEM_BR_SRC select
ecrire_PC<=reg_EX_MEM.branch_ADR when "01",
reg_EX_MEM.branch_ADR when "11",
EX_Saut_ADR when "10",
ei_next_pc when others;
MEM_flush <= '1' when MEM_BR_SRC(0) = '1'else
'0';
dcache : entity work.memory(behavior)
generic map ( DBUS_WIDTH=>CPU_DATA_WIDTH,
ABUS_WIDTH=>CPU_ADR_WIDTH, MEM_SIZE=>L1_DSIZE,
ACTIVE_FRONT=>L1_FRONT,
FILENAME=>DFILE )
port map ( RST=>RST, CLK=>CLK, RW=>reg_EX_MEM.mem_ctrl.DC_RW,
DS=>reg_EX_MEM.mem_ctrl.DC_DS,
Signed=>reg_EX_MEM.mem_ctrl.DC_SIGNED,
AS=>reg_EX_MEM.mem_ctrl.DC_AS, Ready=>open,
Berr=>open,
ADR=>reg_EX_MEM.ual_S, D=>reg_EX_MEM.rt_read, Q=>MEM_Sortie_cache );
MEM: process(CLK,RST)
begin
-- test du reset
if (RST='0') then
-- reset des controle du pipeline
reg_MEM_ER.er_ctrl
<= ER_DEFL;
-- test du front actif d'horloge
elsif (CLK'event and CLK=CPU_WR_FRONT) then
-- Mise a jour du registre inter-etage DI/EX
reg_MEM_ER.pc_next
<= reg_EX_MEM.pc_next;
reg_MEM_ER.reg_dst <= reg_EX_MEM.reg_dst;
reg_MEM_ER.ual_S
<= reg_EX_MEM.ual_S;
reg_MEM_ER.mem_Q <=MEM_SOrtie_cache;
-- Mise a jour des signaux de controle
reg_MEM_ER.er_ctrl<=reg_EX_MEM.er_ctrl;
end if;
end process MEM;
-- ===============================================================
-- ============ Etage ER==========================================
-- ===============================================================
er_pcnext_ext(PC'RANGE)<=reg_MEM_ER.pc_next;
er_pcnext_ext(ADDR'high downto PC'HIGH+1)<=(others=>'0');
er_pcnext_ext(PC'low-1 downto 0)<=(others=>'0');
with reg_MEM_ER.er_ctrl.REGS_SRCD
select
er_regd<=reg_MEM_ER.mem_Q when MEM_Q,
reg_MEM_ER.ual_S when ALU_S,
er_pcnext_ext when NextPC;
er_adrw<=reg_MEM_ER.reg_dst;
end behavior;
46
47
Téléchargement