Progetto in VHDL di un microprocessore a 32 bit

22
Università degli studi di Roma SAPIENZA Tesina di Architettura di Sistemi integrati Prof. Mauro Olivieri Perticaroli Stefano Patrizi Roberto Di Liberto Alessio Barbieri Stefano 1

description

Progetto in VHDL di un microprocessore con 4 porte di comunicazione indirizzabili con i primi 4 registri della memoria. Istruction set di 14 istruzione base. Architettura a blocchi espliciti implementata in VHDL, con algoritmo di simulazione per verifica dell'architettura proposta.

Transcript of Progetto in VHDL di un microprocessore a 32 bit

Page 1: Progetto in VHDL di un microprocessore a 32 bit

Università degli studi di Roma

SAPIENZA

Tesina di

Architettura di Sistemi integrati

Prof. Mauro Olivieri

Perticaroli Stefano

Patrizi Roberto

Di Liberto Alessio

Barbieri Stefano

1

Page 2: Progetto in VHDL di un microprocessore a 32 bit

2

Page 3: Progetto in VHDL di un microprocessore a 32 bit

Specifiche di base

Il processore ha una memoria interna da 32 locazioni da 32 bit ognuna numerate da 0 a 31. Le prime 4 locazioni sono particolari, sono infatti collegate a dei piedini esterni del processore e permettono la comunicazione tra più processori identici. Le locazioni di memoria per le comunicazioni sono: 0 = port N1 = port S2 = port E3 = port W

Il processore è in grado di eseguire istruzioni in virgola fissa con formati binari in complemento a due. L’instruction set del μ-transputer è dotato delle seguenti istruzioni di base:

Istruzione CampiADD MODE DEST REG MODE OP_1 MODE OP_2SUB MODE DEST REG MODE OP_1 MODE OP_2MUL MODE DEST REG MODE OP_1 MODE OP_2AND MODE DEST REG MODE R1XOR MODE DEST REG MODE R1Bit 31÷29 28 27÷23 22 21÷17 16 15÷11MOV MODE DEST REG MODE R1Bit 31÷29 28 27÷23 22 21÷17BRANCH COND CODE TARGET MODE R1Bit 31÷29 28 27÷19 18 17÷13IMOV MODE DEST REG IMMEDIATE DATABit 31÷29 28 27÷23 22÷13

In cui:

OP_1, OP_2 Rappresentano gli operandi delle istruzioni a 2 operandi, R1 nel caso di istruzioni con un solo ingresso. Sono lunghi ciascuno 5bit.

DEST REG indica in quale locazione di memoria verranno posti i risultati dell’istruzione.

MODE Rappresenta il modo di indirizzamento, diretto o indiretto. Se è posto ad 1 il processore preleva il dato da uno dei suoi 32 registri (25 = 32), in particolare dal registro indirizzato dai 5 bit OP. Se è posto a 0, i 32 bit del registro OP rappresentano l’indirizzo dell’istruzione nella memoria esterna.

Le prime 5 istruzioni a due operandi sono autoesplicative così come MOVE, che prende il contenuto del registro R1 e lo sposta in DEST_REG. Qualche parola sulle altre 2.

BRANCH aggiorna il program counter spostandosi di un numero di locazioni pari a TARGET, un intero di 9 bit con segno che permette di saltare in avanti di 255 posizioni oppure indietro di 256 se è verificata la condizione COND CODE su registro R1. Se COND CODE = 0 il salto si ha solo se il registro R1 contiene tutti bit nulli, altrimenti se COND CODE = 1 il salto si ha solo se R1 è positivo (bit 31 = 0).

IMOVE Copia un operando immediato (IMMEDIATE DATA) in un registro di destinazione (DEST REG)

3

Page 4: Progetto in VHDL di un microprocessore a 32 bit

L'instruction set è stato parzialmente modificato rispetto alle specifiche, per via dell'elevato numero di bit ancora disponibili. Sono state aggiunte altre istruzioni e per alcune istruzioni sono stati utilizzati più bit di quelli richiesti. Istruzioni come la imove o come il branch, utilizzano operandi binari a 22 bit invece dei precedenti 9 o 10. Inoltre sono state aggiunte le istruzioni di Shift, Or, Not, Bit clear, Bit set ed un codice per una No operation (NOP).

Lo shift legge il contenuto di un registro sorgente e ne trasla tutti i bit di una posizione a destra o a sinistra in base al valore di un bit di controllo, memorizzando il risultato nel registro di destinazione.

Il comando OR esegue l'or logico, bit a bit tra due registri, il NOT inverte tutti i bit di un registro.

Bit clear (BCLR) e Bit set (BSET) impostano il valore di un bit rispettivamente ad 0 ed a 1. Il bit impostabile è selezionato da un indice (5 bit) che punta ad uno tra i 32 bit del dato, numerati in ordine crescente da sinistra verso destra.

Formato istruzioni

Conservando l'impostazione data nelle specifiche il più possibile anche con l'aggiunta delle nuove istruzioni, risulta un formato regolare, sebbene talvolta un campo debba essere splittato in posizioni non adiacenti, come è avvenuto ad esempio per il codice istruzioni.

Le istruzioni in totale sono 13, per cui sono richiesti 4 bit di codice a fronte dei tre previsti inizialmente dalle specifiche. Il quarto bit è stato aggiunto perciò in decima posizione, lasciando immutati gli altri bit come da specifiche. I codici di 4 bit per ciascuna istruzione sono elencati nella seguente tabella:

Istruzione Opcode Istruzione

somma ADD 0000

differenza SUB 0010

prodotto MUL 0100

no operation NOP 0101

and logico AND 0110

mov MOV 0111

xor logico XOR 1000

shift SHIFT 1001

or logico OR 1010

imov IMOV 1011

bit clear BCLR 1100

4

Page 5: Progetto in VHDL di un microprocessore a 32 bit

bit set BSET 1101

branch BRANCH 1110

not logico NOT 1111

Istruzioni che richiedono gli stessi campi (fino a tre operandi, una costante oppure un offset in cui saltare, un indice oppure qualche bit di controllo che specifica il comportamento delle istruzioni), utilizzano gli stessi bit dell'istruzione per lo stesso scopo: ad esempio il codice istruzione è sempre posto nei tre bit più a destra (dal 29 al 31), e nel 10 bit per ciascuna istruzione.

Campi diversi in istruzioni diverse sono sovrapposti sugli stessi bit in modo da non creare conflitti, l'utilizzo corretto dei bit dell'istruzione è affidato a segnali di controllo che stabiliscono quale parte della microarchitettura deve essere attivata coerentemente con lo scopo ed il reale utilizzo dei campi dell'istruzione. In questo modo, come risulta chiaro osservando il funzionamento dell'unità di controllo, la struttura stessa della CU risulta semplificata, rendendo più agevole l'esecuzione delle istruzioni.

Esplicitiamo quanto detto, cominciando proprio a vedere quali sono i campi delle istruzioni.

Abbiamo quattro bit di opcode, che occupano i bit dal 29 alla 31 e nel bit 10, per ciascuna istruzione. Lo schema seguente indica la loro posizione all'interno della stringa dei 32 bit di un'istruzione. I bit interessati sono evidenziato con O, il numero sopra di essi indica la posizione a partire dal bit più a destra (il bit 0) in ordine crescente man mano che ci si sposta a sinistra:

31 30 29 10 1 0

O O O O

Possono esserci fino a tre campi di registro di 5 bit ciascuno. Due campi (A, B ) indicano proprio due operandi sui quali eseguire le istruzioni, il terzo campo (D ) indica il registro di destinazione nel quale memorizzare il risultato dell'operazione. A questi si affiancano tre bit per il modo (M ) di indirizzamento che indicano se leggere il dato direttamente da uno dei 32 registri (indirizzato con 5 bit), o se utilizzare i 32 bit del registro come indirizzo per la memoria (che può raggiungere 232 = 4 G locazioni di memoria). Ciascun campo registro segue il proprio bit di modo formando tre blocchi da 6 bit posizionati a partire dal bit 28 in cui si ha l'operando in letura a, segue l'operando in scrittura b, infine l'ultimo campo è per il risultato in scrittura.

28 27 23 22 21 17 16 15 11

M A A A A A M B B B B B M D D D D D

I campi descritti sono sufficienti per scrivere istruzioni a due operandi come una somma.

Ad esempio per sommare il quinto (00101) ed il sesto (00110) registro e memorizzare il risultato nel settimo registro (00111) con tecnica di indirizzamento diretta il codice istruzione da utilizzare è il seguente:

000 100101 100110 100111 0 0000000000

Gli ultimi 10 bit sono inutilizzati e nell'istruzione sono stati posti a zero, and, or, xor, differenza e prodotto utilizzano istruzioni della stessa forma.

5

Page 6: Progetto in VHDL di un microprocessore a 32 bit

Per le operazioni che necessitano di costanti (C ) il campo utilizzato può essere di 22 bit, in tal caso copre le posizioni da 0 a 10 e da 17 a 28, oppure può essere da 15 bit, quelli compresi tra 0 e 10 e tra 17 e 21. Un opportuno controllo interno al processore determina se i bit più significativi appartengono o meno all'istruzione in base all'opcode, come mostrato nella descrizione della CU.

28 22 21 17 10 0

C C C C C C C C C C C C C C C C C C C C C C C

Ad esempio il codice per eseguire una imov che memorizza la costante 2 (...10) nel quinto (00101) registro, sempre indirizzato direttamente:

101 000000000000 1001011 0000000010 (nessun bit inutilizzato);

Se invece avessi considerato un'istruzione di branch che avanza di 3 posizioni (...011) se il sesto registro (00110) è maggiore di zero il codice corretto sarebbe stato:

111 100110 0 00000 000000 0 0000000011

In questo caso 10 bit non sono utilizzati, nell'esempio sono stati riempiti con degli zeri.

Gli ultimi due campi sono l'indice del bit da settare ad uno oppure a zero, e la direzione di shift. L'indice (I ) utilizza 5 bit, dal 22 al 18, mentre lo shift (S ) necessita di un solo bit posto in ventiduesima posizione.

28 27 23 22 21 18 17 16 15 11

S/I I I I I

Ad esempio per eseguire il bit clear del quinto (00101) registro, memorizzando il risultato nel terzo (00011) registro il codice corretto è:

100 100101 10110 0 100011 1 0000000000

con 11 bit inutilizzati evidenziati in grigio. Stessa forma per bit set. Volendo invece eseguire lo shift del quinto (00101) registro verso sinistra con risultato nel settimo (00111) registro (anche in questo caso in modo diretto), il codi corretto è:

100 100101 1 00000 100111 1 0000000000

in cui sono 15 i bit inutilizzati.

Il massimo numero di operandi facenti riferimento a registri di link sono due, uno in lettura, uno in scrittura.

Microarchitettura

Le istuzioni utilizzano un opcode con 5 bit per operando. I 5 bit sono utilizzati per indirizzare un registro tra i 32 disponibili, che fornisce una parola da 32 bit. Questa può essere un operando, oppure un registro di una memoria (che può raggiungere al massimo 4G linee) a sua volta a 32 bit per parola.

I blocchi registri e memoria sono connessi in cascata. Le tre uscite dati dei registri costituiscono altrettanti ingressi per la memoria.

Nel caso in cui il modo di indirizzamento è diretto (quindi il relativo bit di modo è posto ad 1 nell'opcode) e quindi il contenuto dei registri deve essere utilizzato come operando, la memoria

6

Page 7: Progetto in VHDL di un microprocessore a 32 bit

farà semplicemente passare il dato dall'ingresso all'uscita, proprio in base al valore dei bit di modo. Al contrario nel caso in cui il modo di indirizzamento e indiretto, nell'opcode avrò il bit di modo pari a 0, ed i 5 bit di indirizzo nei registri saranno espansi dai registri a 32 bit di indirizzo che la memoria utilizzerà per prendere un operando in uno spazio di indirizzamento di 2^32 = 4G.

La memoria prende tre ingressi a 32 bit dai registri, dei quali solamente due funzionano nel modo descritto, il terzo ingresso (c) infatti serve esclusivamente come indirizzo per la scrittura di dati provenienti dalla porta data_c. Le due uscite data_a, data_b collegate agli ingressi a, b invece sono collegate ai bus operandi dell'ALU, bus_a, bus_b. Il risultato calcolato dall'ALU (bus_c) viene riportato in ingresso nella memoria, nei registri, nell'unità di controllo e nel PC. Il risultato viene memorizzato nei registri o nella memoria in base al bit di modo, può essere utilizzato dalla CU per realizzare il branch, oppure può essere memorizzato nel PC nel caso in cui l'ultima operazione è stata svolta sul PC.

Nello schema della microarchitettura si nota inoltre l'ALU completamente combinatoria con due bus di ingresso che possono essere scritti dalla memoria oppure dai blocchi PC e Bit expander. PC è il registro utilizzato per memorizzare il program counter, mentre il bit expander serve per riportare al numero corretto di bit una costante presa dall'opcode di un'istruzione o comunque imposta dalla CU:

L'unità di controllo infine è il blocco che si occupa di coordinare le parti descritte al fine di svolgere le operazioni previste dalle specifiche del processore. Contiene il registro istruzioni (IR) nel quale viene memorizzato l'opcode dell'istruzione corrente. L'istruzione proviene da una porta apposita detta fetched pilotata in scrittura dalla memoria che vi pone il contenuto della parola indirizzato dai 32 bit presenti in ingresso su data_c.

Nello schema alla pagina seguente è riportato uno schema dell'architettura descritta. Le connessioni in blu indicano un bus di 32 bit, le linee sottili in nero indicano semplici collegamenti ad un bit, infine i collegamenti in nero più spessi indicano altri segnali a più bit.

I segnali utilizzati dal link manager sono esterni al processore e non sono riportati, così come sono assenti i segnali di clock o reset!

7

Page 8: Progetto in VHDL di un microprocessore a 32 bit

Control Unit

sel_a

sel_b

sel_c

lmng

r_ac

klm

ngr_

err

fetc

hed

ma

mb

mc

mem

_writ

em

em_o

ut_e

nfcl

kre

set

Plut

o

exp_en exp_bitnumeber

exp_constantPC_enable PC_update

data_cGovflow

ctrl_ALU indice_regshift_type

PC Bit expander

Reg_with_link

data_adata_bdata_c

sel_a

sel_b

sel_c ac

k err

write

_ena

ble m

data_in

segnali lnkmngr

ck

ALU

Memory

fetc

hed ma

mb mc w

out_

enab

le f

abc

data_adata_b

data_cck

O G IR

BUS_A BUS_B

BUS_C

CMP

Page 9: Progetto in VHDL di un microprocessore a 32 bit

ALU

L’ALU, blocco completamente combinatorio, prende gli operandi direttamente dai 2 bus in ingresso, bus_a e bus_b, ai quali sono collegati tutti i blocchi che realizzano le operazioni specifiche. Le operazioni ALU a due operandi sono add, sub, mul, and, or, xor, mentre shift, bit clear, bit set necessitano di un solo operando.

Il risultato posto in uscita sul bus_c è selezionato dal multiplexer pilotato tramite un codice di controllo binario a 4 bit. Normalmente tale codice proviene da quattro bit del codice istruzione, altrimenti può essere impostato dalla CU che può anche selezionare direttamente uno dei due operandi a, o b.

Nella seguente tabella sono elencati i codici per l'ALU e la relativa funzione svolta. Come si può notare sono tutti identici agli opcode delle istruzioni, in più compaiono due codici per passare uno dei due operandi a, b, dal bus d'ingresso al bus in uscita, che non possono essere programmati dall'esterno ma sono impostati esclusivamente dalla CU.

a 0001

b 0011

ADD 0000

SUB 0010

MUL 0100

AND 0110

XOR 1000

SHIFT 1001

OR 1010

BCR 1100

BSR 1101

9

Page 10: Progetto in VHDL di un microprocessore a 32 bit

Registri

I registri sono costituiti da un array di 32 parole da 32 bit ciascuna, i primi 4 registri sono particolari, poiché sono utilizzati come link per interfacciare altri rpocessore dello stesso tipo e saranno considerati nel paragrafo seguente.

Ogni elemento è indirizzabile con 5 bit, contenuti direttamente nell'istruzione. Poiché le istruzioni possono gestire fino a tre operandi dei quali due in lettura, due in scrittura, ci sono tre ingressi a 5 bit per tre indirizzi simultanei, cioè sel_a e sel_b e sel_c. Ad ogni fronte di salita del clock sulle uscite data_a, data_b saranno presenti i 32 bit indirizzati rispettivamente da sel_a, sel_b.

Diverso il comportamento di sel_c e rispettivo data_c per via delle differenze operative tra modo diretto ed indiretto. La lettura dai registri infatti, deve avvenire sempre e comunque allo stesso modo. Sarà poi la memoria a discriminare tra indirizzamento diretto, nel qual caso i bit in uscita dai registri sono proprio quelli richiesti dall'istruzione che pertanto saranno passati ai bus operandi, o tra indirizzamento indiretto, in cui la memoria utilizza i bit provenienti dai registri (che sono comunque necessari) come indirizzo al quale prelevare il dato richiesto dall'istruzione!

Quindi se l'operando c e indirizzato in modo diretto allora l'uscita data_c non conterrà alcun dato utile, il segnale di sel è utilizzato come indirizzo in cui memorizzare il segnale data_in. Se invece l'indirizzamento è indiretto allora si procede analogamente a quanto fatto per gli operandi a, b, passando il contenuto dei registri attraverso data_c alla memoria, che utilizzerà tale valore come indirizzo in cui scrivere. La scrittura ovviamente è abilitata solamente se viene attivato il segnale write_enable (attivo alto), inoltre il bit di modo m in ingresso indica ai registri come comportarsi.

I restanti controlli ack ed err sono utilizzati dal link manager che andiamo ora ad esaminare.

Link manager

È l’unità che gestisce le comunicazioni tra il processore e le altre cpu, funziona in modo bloccante per permettere di sincronizzare l’elaborazione, e si trova all’interno dei registri.

Utilizza due segnali di controllo in ingresso e due in uscita per ogni link. Il primo segnale è di request, viene attivato dal microtransputer quando deve eseguire un'operazione su un link. Il secondo segnale è un selettore lettura scrittura, ed è:

1 = Scrittura

0 = Lettura

L’idea di fondo è che lo scambio di dati tra processori deve essere coerente, cioè un risultato parziale di un’elaborazione viene passato ad un’altra CPU quando questo risultato è richiesto ed è stato calcolato. La comunicazione quindi, avviene solo se contemporaneamente un processore scrive un dato in uno dei registri speciali della memoria ed il processore collegato a quella porta

10

Reg_with_link

data_adata_bdata_c

sel_a

sel_b

sel_c ac

k err

write

_ena

ble m

data_in

segnali lnkmngr abc

ck

Page 11: Progetto in VHDL di un microprocessore a 32 bit

richiede la lettura del dato. Fino a quando non si verifica questa condizione (cioè un processore pronto a leggere ed un processore pronto a scrivere) il programma non prosegue!

Si distinguono fondamentalmente 2 casi, in un primo caso la scrittura precede la lettura, nel secondo caso si ha l’inverso.

Dal punto di vista fisico per ogni link il processore ha 32 linee per i dati, 2 segnali di controllo di uscita, dunque i 2 segnali simmetrici in ingresso. Saranno identificati r/w_in, ack/req_in e gli omonimi _out riferendoci ad un processore

Consideriamo per un solo link il caso in cui la scrittura preceda la lettura. In primo luogo il dato da scrivere viene memorizzato all'interno dei registri, contemporaneamente inizia la procedura per la gestione dei link. La scrittura sarà la fase finale di una qualche istruzione che adopera uno dei 4 registri di link come destinazione del risultato. L’esecuzione del programma viene arrestata e vengono alzati i segnali richiesta scrittura (req/ack = 1, r/w = 1) relativi al link attivato.

Al fronte successivo del clock il contenuto del registro viene posto sul link corrispondente se questo è disponibile per la scrittura, cioè se l'altro processore non sta già tentando di scrivere sul link. Il processore permane poi in questo stato fino a quando non legge che req/ack = 1 e r/w = 0, cioè fino a quando l'altro processore invia una richiesta di lettura sul link. Se req/ack fosse pari ad uno si avrebbe un’errore, entrambi i processori scrivono sullo stesso link.

Se il link è usato correttamente, al fronte successivo del clock l’altro processore scrive il dato, infine un ciclo dopo vengono ripristinate le impostazioni di base: il link è posto in alta impedenza e tutti i controlli sono posti a zero. Un segnale di ack interno al processore indica alla CU che l’operazione è conclusa.

Nell'immagine seguente è illustrato lo schema di principio del funzionamento

Se invece consideriamo il caso duale in cui è la lettura di un dato a precedere la scrittura, mi troverò nella fase iniziale dell'istruzione a dover inviare su uno dei due bus operandi un dato che non è ancora presente all’interno del processore. I selettori del registro indicheranno una delle prime 4 locazioni particolari.

11

Req_outRw_out

CPU1 Link (32)Rw_in

Req_in

Req_inRw_inLink (32) CPU2Rw_outReq_out

ZZZZZ

Req_out

Rw_out

Link (32)

Req_in

Rw_in

REG DATA ZZZZZ

1=lettura

<-letto!

Ciclo scrittura -> lettura

Page 12: Progetto in VHDL di un microprocessore a 32 bit

Anche in questo caso l’unità di controllo dovrà attendere che la procedura di gestione dei link completi il trasferimento, deve attendere cioè che il segnale di ack che viene inviato in concomitanza con la presenza del dato sul bus sia pari ad uno. Gli altri segnali di controllo (tipo read) vengono ignorati in questa fase, così come indifferente è il bit di modo del registro.

Anche in questo caso se si verificano errori dovuti alla simultanea lettura o scrittura di un link, viene inviato un segnale di errore (ponendo err = 1) alla CU, che invia un analogo segnale all'esterno del processore.

Il seguente diagramma temporale è stato ottenuto simulando il comportamento di due link e mostra anche altri segnali che non sono stati considerati nella precedente descrizione!

Memoria

La memoria è un array di parole da 32 bit ciascuna, implementabile in diverse capacità ma fino ad un massimo di 4G linee, corrispondenti ad indirizzi a 32 bit. Dispone di tre ingressi a 32 bit indicati con a, b e c, che possono contenere degli operandi oppure degli indirizzi, due uscite a 32 bit per i bus chiamate data_a, data_b, un'uscita utilizzata per il fetch delle istruzioni verso la CU ed un ingresso dal bus_c dei risultati.

Consideriamo in primo luogo un'operazione di lettura. La lettura può essere diretta o indiretta, nel caso in cui sia diretta la memoria riceve agli ingressi degli operandi che deve semplicemente passare sui bus istruzioni dell'ALU, altrimenti utilizza gli ingressi a, b come indirizzi, il contenuto della memoria viene posto su uno dei due bus esterni. Il tipo di accesso in

12

Memory

fetc

hed ma

mb mc w

out_

enab

le f

abc

data_adata_b

data_cck

Page 13: Progetto in VHDL di un microprocessore a 32 bit

memoria è indicato da un apposito bit nell'opcode dell'istruzione, in base a questo bit (presente sugli ingressi ma, mb, mc) la memoria discrimina tra uno dei due accessi descritti.

Entrambi gli ingressi vengono trattati simultaneamente, per cui occorre un solo ciclo di clock per leggere entrambi gli operandi di un'istruzione.

La scrittura è controllata da un apposito segnale di write attivo alto, e dal bit di modo mc. Poiché la scrittura in memoria avviene solamente se il registro di destinazione è indiretto devono essere attivi entrambi i controlli di scrittura e di modo (quest'ultimo è attivo basso per la memoria, in quanto se il bit di modo è zero allora il modo di indirizzamento dell'operando è indiretto). L'indirizzo di destinazione della memoria viene preso dal'ingresso c.

Il fetch di un'istruzione richiede di accedere in memoria alla locazione indicata dal PC. Con la microarchitettura implementata il PC viene aggiornato con lo stesso sommatore presente nell'ALU facendo la somma tra il PC ed 1, il risultato sarà presente sul bus_c che è utilizzato in questo caso dalla memoria come indirizzo al quale prelevare un'istruzione. L'istruzione è poi passata all'unità di controllo dall'uscita fetched.

In questo caso appare evidente inoltre la necessità di disporre di un controllo, out_enable attivo alto, in grado di porre la uscite in alta impedenza per poter utilizzare il bus con in PC per operazioni come il branch, o per utilizzare il bit expander come nel caso di imove.

Altri blocchi

Uno sguardo infine agli altri blocchi che compongono la microarchitettura del processore.

PC è il registro del Program Counter che ovviamente contiene l'indirizzo dell'ultima istruzione prelevata dalla memoria. Completamente asincrono, il PC reagisce immediatamente ai segnali di controllo, cioè un segnale per la memorizzazione del PC, ed un segnale PC2a attivo alto che abilità l'uscita del PC che altrimenti è posta in alta impedenza.

Il bit expander invece serve a prendere le costanti contenute nelle istruzioni di lunghezza inferiore a 32 bit, per portarle in uscita (u) in binari a 32 bit in complemento a 2 adatti per l?ALU conservandone il segno. Se en = 0 l?uscita è in alta impedenza ed il blocco è disattivato, infine il controllo exp_bitnumber indica di quandi bit è composto il binario in ingresso.

Il blocco indicato come cmp necessario per l'esecuzione del branch è indicato in figura con un ingresso connesso al bus operandi a, esso è il comparatore. Il suo scopo è di prendere in ingresso il contenuto del bus_a e di porre il bit di uscita ad uno se questo è positivo. L'uscita è passata alla CU che memorizza questo bit come flag!

Control Unit

L'unità di controllo è organizzata come macchina a stati, ad ogni stato corrisponde una fase di un'istruzione, con i corrispondenti segnali asseriti o negati per ciascuno stato. Al suo interno contiene il registro istruzioni (IR) contenente l'opcode dell'istruzione in fase di esecuzione. La maggior parte dei bit dell'IR è permanentemente collegata a dei segnali di controllo in uscita. Abbiamo ad esempio i bit di modo dei registri coinvolti nelle operazioni permanentemente collegati alle relative uscite ma, mb, mc, i tre campi da 5 bit dell'IR che indicano i registri coinvolti nell'operazione sono collegati ai segnali di selezione (sel a, b, c) dei registri. Altri, come ad esempio i 4 bit di controllo dell'ALU sono applicati presi dall'IR nella maggior parte delle operazioni, ma la CU ha la possibilità di applicare segnali differenti quando necessario, come ad esempio nelle istruzioni di branch in cui l'unità di controllo pone l'uscita ctrl_alu al valore necessario per effettuare la somma. Non tutte le istruzioni utilizzano gli stessi campi dell'IR nello

13

Page 14: Progetto in VHDL di un microprocessore a 32 bit

stesso modo! In caso di sovrapposizione i bit sono connessi ad entrambe le possibili uscite, saranno gli altri controlli a determinare quale blocco opera, quindi la correttezza delle assegnazioni!

Inoltre la CU contiene un registro FLAG formato da due bit che indicano (in ordine dal più significativo al meno significativo) se c'è stato overflow, e se il risultato è maggiore di 0.

Vediamo ora come vengono svolte alcune operazioni con l'architettura proposta:

Istruzioni con due operandi

ADD, SUB, MUL, AND, XOR, OR

Formato istruzione31 29 28 27 23 22 21 17 16 15 11 0O O O M R R R R R M R R R R R M R R R R R O

Consideriamo l’istruzione già carica nell’instruction register. Dall’unità di controllo i bit dell’opcode vengono posti sui controlli dell’ALU, i 5 bit che identificano ognuno dei 3 registri coinvolti vengono inviati ai registri (sel), ed i bit di modo degli operandi infine controlleranno i segnali read_a, b, dei registri oppure i segnali fetch_a, b, dell’EMI.

Se il modo di indirizzamento è diretto (M = 1) un ciclo dopo si sta propagando il risultato che posso memorizzare già sul secondo fronte di salita del clock, altrimenti devo attendere il prelievo del dato che sarà pronto sul bus solamente quando l’EMI attiva il segnale di ack. La logica di controllo vedrà tale segnale solamente al fronte successivo del clock, cioè quando anche il risultato si sarà propagato, quindi quando la CU legge il segnale di ack deve immediatamente memorizzare il dato.

Il risultato di un’operazione può essere scritto nei registri interni del processore oppure nella memoria esterna, sempre in base al valore del bit di modo M. Nel primo caso basterà porre ad 1 il segnale write dei registri, ricordando però che se cerco di scrivere su uno dei registri dal quale sto leggendo le uscite dei registri vanno in alta impedenza ed il dato non è memorizzato. Contemporaneamente vengono memorizzati i flag dell’istruzione eseguita negli appositi registri

In caso di indirizzamento indiretto occorre alzare il segnale store dell’EMI e negare i segnali di fetch, dopodiché basta attendere l’ack.

Nel caso in cui le operazioni facciano uso dei registri speciali, per ogni lettura o scrittura in una delle 4 locazioni si attende il segnale di ack dal link manager dei registri. In tal caso non serve una temporizzazione dei segnali di controllo per gestire prelievo da un’altro processore e poi la scrittura da un’altro processore, il link manager infatti è in grado di attendere il dato da un’altro processore, aspettare la propagazione del risultato e poi inviarlo ad un’altro processore e solamente ad operazione conclusa inviare il segnale di ack al processore, anche se i controlli sono stati impostati tutti dall’inizio.

CMPL’istruzione di comparazione è a due operandi, ma non contiene nessun registro esplicito in cui memorizzare il risultato. Infatti l’uscita di tale istruzione è il semplice bit di flag pari ad 1 se a>b. Il comparatore di per se funziona anche se in modo diverso durante l’esecuzione di una qualsiasi

14

OpcodeRegistro dest Operando 1 Operando 2

Page 15: Progetto in VHDL di un microprocessore a 32 bit

istruzione per fornire i 2 bit di flag. Anche in questo caso le operazioni per prelevare i due operandi sono standard, cambia la fase di store che deve registrare esclusivamente il flag.

Istruzioni ad un solo operando

SHIFT, BCLR, BSETLe istruzioni ad un solo operando necessitano del solo bus a. Il dato viene caricato su tale bus nel modo usuale, settati correttamente i controlli per l’ALU il risultato si ottiene in un solo ciclo, e viene memorizzato nella maniera usuale. In particolare però i flag non vengono aggiornati al termine di tali operazioni

Altre istruzioni

BRANCH

Formato istruzione31 29 28 27 19 18 17 13 12 0O O O C T T T T T T T T T M R R R R R O

Per prima cosa devo porre il registro sul bus selezionando tale operando come uscita dell’ALU. Sul bus_c ritrovo quindi lo stesso registro invariato, in più il comparatore interno all’ALU avrà stabilito se il numero è positivo o uguale a zero.

Se il bit di condizione C è zero (devo saltare se il contenuto del registro è zero) e il flag Z è uno, allora si ha il salto. Pongo quindi in alta impedenza le uscite dell’EMI e dei registri sul bus, l’operando a diviene il program counter (alzo un segnale di tipo Program counter al bus a PC2a) invio l’offset dall’unità di controllo al registro costanti indicato con l’1 sopra il bus b e richiedo una somma algebrica.

Sul bus_c ho il nuovo PC, lo salvo nel registro e lo prelevo con l’EMI asserendo store_c ed uno dei segnali di fetch. Un ciclo dopo devo riportare il bus in alta impedenza per permettere all’EMI di scrivere su di esso la successiva istruzione, che passerà attraverso l’ALU opportunamente settata per tale scopo, infine l’unità di controllo preleva l’istruzione dal bus_c.

Durante l’esecuzione di tali istruzioni vengono ignorati i flag in uscita dall’ALU.

Nel caso in cui non si abbia il salto devo semplicemente incrementare il PC in pratica la differenza sta nel valore di offset che sarà pari ad 1 invece che a quanto specificato nell’istruzione.

Nel caso di branch incondizionato o condizionato dai flag il ciclo dell’istruzione risulta semplificato. In tal caso infatti è l’unità di controllo a settare correttamente tutti i controlli già al primo ciclo, poiché non sono richieste fasi specifiche per il prelievo di un registro e la verifica del suo contenuto. Partendo dunque dal codice istruzione per prima cosa mi rendo conto che si tratta di un salto dovuto a flag, per cui confronto immediatamente il flag per sapere se saltare o meno. Se salto allora sommerò l’offset al PC, altrimenti il PC verrà incrementato di un’unità. Se il salto è incondizionato non è necessario neppure controllare i flag, sommo semplicemente l’offset al PC.

15

OpcodeTarget Registro

Page 16: Progetto in VHDL di un microprocessore a 32 bit

IMOVEIn questo caso è l’unità di controllo a porre l’operando immediato sul bus_b, passando attraverso il blocco che gestisce l’espansione a 32 bit delle costanti i nove bit del campo immediate data. Successivamente abilito la scrittura dei registri.

Il banco di registri deve consentire la scrittura, le uscite sui bus a, b sono in alta impedenza. Si può fare ponendo i controlli di lettura in modo che siano attivate le uscite per l’EMI, oppure ponendo sel_c uguale ad uno dei 2 sel a, b con write posto ad 1 che porta tutto in alta impedenza.

L’alta impedenza per l’EMI si realizza negando i segnali di fetch. In entrambi i casi occorre attendere un ciclo poiché sono unità che reagiscono ai segnali applicati, solo sul fronte di clock.

MOVEUn registro viene chiamato sul bus (ne occorre uno solo posso utilizzare il bus_a) dai registri o dall’EMI, lo faccio passare attraverso l’ALU, dopodiché si abilitano i controlli per la scrittura. Anche in questo caso può essere diretta o indiretta, nulla di nuovo

NOPEseguire una nop significa non fare nulla. Tutti i controlli sono posti a zero, per cui i registri non leggono, l’EMI non preleva dati dall’esterno, PC ed il modulo di espansione costanti presentano le uscite in alta impedenza...

Fetch istruzioneIl fetch di un’istruzione dalla memoria esterna non è un’istruzione programmabile, ma è un’operazione che deve essere comunque effettuata dall’unità di controllo tra ogni istruzione, tranne che in seguito ad istruzioni tipo branch. Il modo di procedere ricalca invece il comportamento delle istruzioni di branch, anche in questo caso infatti deve essere eseguita la somma tra il PC e 1, verranno trascurati i valori di riporto, aggiornato il PC col nuovo valore calcolato che sarà anche utilizzato dall’EMI per prelevare l’istruzione corrispondente in memoria.

Altre operazioniL’unità di controllo infine dovrà gestire il reset del processore e l’inizializzazione del processore stesso. Ciò deve avvenire non appena viene asserito dall’esterno un apposito segnale di reset (o wake up). Lo stato di riposo corrisponde ad una indefinita successione di nop, dopo il reset deve essere effettuato il fetch di un’istruzione senza utilizzare il PC. L’unità di controllo invia una costante nulla al modulo di espansione delle costanti, e seleziona l’ingresso b come uscita dell’ALU. Ottengo quindi l’indirizzo 0, che viene memorizzato nel program counter mentre l’Emi viene impostata per prelevare l’istruzione dalla memoria esterna. Caricata l’istruzione si procede al solito modo.

16

Page 17: Progetto in VHDL di un microprocessore a 32 bit

Simulazioni

Il processore è stato sottoposto a molteplici simulazioni, sia dei singoli componenti sia del processore nel suo insieme. Come ultimo test è stato creato un file ascii contenente stringhe di 1 e 0, per un totale di 32 per riga. Il file è stato caricato in memoria ed il processore ha interpretato le sequenze di bit come istruzioni, eseguendole. Di seguito riportiamo il programma utilizzato per le simulazioni con la spiegazione delle sequenze binarie.

Codice Istruzione Descrizione

0 101 111111111111 100101 1 1111111110 imove Costante #-2 in reg 5

1 101 000000000000 100110 1 0000000100 imove Costante #+6 in reg 6

2 101 000000000000 100111 1 0000100111 imove Costante #39 in reg 7

3 000 100101 100110 000111 0 0000000000 sum Somma, mem 7 = reg 5 + reg 6

4 101 000000000000 101000 1 0000101000 imove Costante #40 in reg 8

5 010 100111 100110 001000 0 0000000000 mul Moltiplica mem 8 = reg 7 * reg 6

6 011 001000 000000 111111 1 0000000000 move Muovi mem 8 in reg 31

7 110 111111 000100 111110 0 0000000000 bclr Azzera il bit 2 del reg 31 in reg 31

8 101 000000000000 101001 1 0000100000 imove Costante #32 in reg 9

9 011 111110 000000 001001 1 0000000000 move Muovi reg 31 in mem 9

10 111 100110 000000 000000 0 0000000011 branch Salta di #+3 se reg 5>0

11 000 000000 000000 000000 0 0000000000 sum Somma mem 0 = mem 0 + mem 0

12 000 000000 000000 000000 0 0000000000 sum Somma mem 0 = mem 0 + mem 0

13 101 000000000000 101001 1 0000100001 imove Costante #33 in reg 9

14 110 100111 100100 001001 1 0000000000 bset Azzera il bit 2 del reg 7 in mem 9

15 101 000000000000 101001 1 0000100010 imove Costante #34 in reg 9

16 010 100101 100110 001001 0 0000000000 mul Moltiplica mem 9 = reg 5 * reg 6

17 010 000000000000000000 1 0000000000 nop

18 011 111110 000000 100000 1 0000000000 move Muovi reg 30 in link 0

19 101 000000000000 101001 1 0000100011 imove Costante #35 in reg 9

20 000 100101 100000 001001 0 0000000000 sum Somma mem 9 = reg 5 + link 0

17

Page 18: Progetto in VHDL di un microprocessore a 32 bit

21 101 000000000000 101001 1 0000100100 imove Costante #36 in reg 9

22 111 100111 000000 001001 1 0000000000 not Mem 9 = reg 7 negato bit a bit

23 010 000000000000000000 1 0000000000 nop

24 010 000000000000000000 1 0000000000 nop

25 010 000000000000000000 1 0000000000 nop

26 010 000000000000000000 1 0000000000 nop

27 010 000000000000000000 1 0000000000 nop

28 010 000000000000000000 1 0000000000 nop

29 010 000000000000000000 1 0000000000 nop

30 010 000000000000000000 1 0000000000 nop

31 010 000000000000000000 1 0000000000 nop

32 000 000000 000000 000000 0 0010001000 sum Somma Link 0 = link 0 + link 0

33 000 000000 000001 000000 0 0000100111 sum Somma link 0 = link 0 + link 0

34 111 111111 111111 111111 1 1111110111 not Reg 31 = reg 31 negato bit a bit

35 000 000000 000000 000000 0 0010000110 sum Somma link 0 = link 0 + link 0

36 111 111111 111111 111111 1 1111011000 not Reg 31 = reg 31negato bit a bit

18

Page 19: Progetto in VHDL di un microprocessore a 32 bit

Elenco file

Il processore è stato dunque realizzato in VHDL strutturale, le varie parti precedentemente descritte sono state realizzate come entità indipendenti ciascuna scritta in un proprio file e poi connesse insieme. Vediamo quindi quali sono i file che compongono il processore con una descrizione sommaria del loro funzionamento e la loro posizione gerarchica, e la loro descrizione VHDL.

one_bit_adder.vhdIngressi abit, bbit, cinbit (1)Uscite sumbit, coutbit (1)Descrizione: Addizionatore ad un bit. Somma sumbit = abit + bbit + cinbit. In oltre ho il

riporto coutbit.

add32.vhdIngressi a,b (32), cin (1)Uscite sum (32) , cout (1)Descrizione: Calcola l'addizione con 32 bit. Sum = a+ b + cin, e genera il riporto cout. L’

L’ingresso cin è sempre essere impostato a 0.

sub32.vhdIngressi as, bs (32), cins(1)Uscite sums (32), couts (1)Descrizione: Calcola la sottrazione as – bs. Anche in questo caso il roporto è 0, sempre

badd32.vhdIngressiUsciteDescrizione: Sommatore di booth utilizzato nell'omonimo moltiplicatore

bmul32.vhdIngressi a,b (32),Uscite c (32), mul_oflow (1)Descrizione: Moltiplicatore di booth. Calcola il prodotto tra a e b, l'uscita c è a 32 bit.Il

riporto in uscita serve al solito per impostare il flag di overflow.

shifter_32bit.vhdlIngressi Input (32); shift_type (1)Uscite output (32)Descrizione: Effettua lo shift di 32 bit in ingresso a destra se shift_type = 0, a sinistra se è

1. I bit aggiunti agli estremi sono sempre pari a 0

xor32.vhdlIngressi a,b (32)Uscite outl (32)Descrizione: L'uscita c si ottiene dallo xor logico tra a, b.

Page 20: Progetto in VHDL di un microprocessore a 32 bit

and32.vhdlIngressi a, b (32)Uscite c (32)Descrizione: L'uscita c si ottiene da l'and logico tra a, b.

or32.vhdlIngressi a, b (32)Uscite c (32)Descrizione: L'uscita c si ottiene da l'or logico tra a, b.

Reg_with_link.vhdlIngressiUsciteDescrizione: Vedi documento

bit_clear.vhdlIngressi reg (32), indice_reg (5);Uscite temp (32);Descrizione: Prende in ingresso il binario a 32 bit indicato con reg (contenuto nel bus_a

della microarchitettura), ed imposta il bit indice_reg-esimo (a partire da destra) a 0.

Cmp.vhdIngressi a, b (32);uscite c (1);descrizione È un comparatore, l’uscita è 1 se a > b

bit_set.vhdlIngressi reg (32), indice_reg (5);Uscite temp (32);Descrizione: Analogo a bit clear, ma imposta il valore del bit selezionato ad 1..

ALU.vhdIngressi a, b (32);

ctrl (4), indice_reg (4), shift_type (1); Uscite y (32), ovflow (1), cmp (1);Descrizione: Mette insieme i pezzi definiti per fare operazioni aritmetico logiche, in modo

del tutto combinatorio. Oltre ai segnali ovvi quali due ingressi a, b, e l’uscita y, ci cono 4 bit per selezionare l’operazione da svolgere (ctrl), alcuni segnali per le operazioni di shift, bit clear, bit set, il segnale di overflow in uscita aggiornato all’ultima operazione che può dare overflow, è il segnale del comparatore.

Memoria.vhdIngressiUscite

Page 21: Progetto in VHDL di un microprocessore a 32 bit

Descrizione: È la memoria del processore. Vedi documento per maggiori informaz.

PC_reg.vhdIngressi i (32); PC2a, PCw (1);Uscite u (32);Descrizione: È il registro del PC. Completamente asincrono, il PC reagisce immediatamente

ai segnali di controllo. Sul fronte di salita di PCw il PC in ingresso (i) viene memorizzato. Quando il segnale PC2a è alto il PC è abilitato sul bus_a, altrimenti la sua uscita (u) è posta in alta impedenza.

bit_expander.vhdIngressi i (10), sel, en (1);Uscite u (32)Descrizione: Serve a prendere le costanti contenute nelle istruzioni (i), lunghe 9 o 10 bit,

ed a trasformarle in uscita (u) in binari a 32 bit adatti per l’ALU. Se en = 0 l’uscita è in alta impedenza, se sel = 1 si considerano tutti i 10 bit dell’ingresso.

CU.vhdDescrizione: L’unità di controllo del sistema

Microtransputer.vhdDescrizione: L’entity per eccellenza, raccoglie tutti i pezzi precedenti

clock.vhdlÉ il clock di sistema, usato per le simulazioni

Struttura

MicrotransputerEMI.vhd

reg_with_link.vhd

CU.vhd

ALU.vhd

add32.vhd

one_bit_adder.vhd

bmul32.vhd

badd32.vhd

one_bit adder

add32

Page 22: Progetto in VHDL di un microprocessore a 32 bit

one_bit adder

sub32.vhd

shifter_32bit.vhdl

xor32.vhdl

and32.vhdl

or32.vhdl

bit_clear.vhd

bit_set.vhd

cmp.vhd

bit_expander.vhd

PC_reg

memory.vhdclock.vhdl