· 9 ADR-Bescheinigungen Schweden Slowenien (Außenseite) Slowenien (Innenseite)
5. Synthese eines Mikroprozessors fileJE Adr C Verzweigung falls ZFLG=1 - - JNE Adr D Verzweigung...
Transcript of 5. Synthese eines Mikroprozessors fileJE Adr C Verzweigung falls ZFLG=1 - - JNE Adr D Verzweigung...
1
5. Synthese eines Mikroprozessors
2
Aufgabenstellung
• 16-Bit CPU• 12 Bit Adressbus• 4 Bit Opcode• Akkumulator-Architektur• Mathematische Operationen auf vorzeichenlosen Zahlen• RAM als Verhaltenmodell in der Simulation
CPUA[11..0]
RAM
D[15..0]
R/W
CS
CLK RESET
3
OPCODEAss Mnemo Hex
KurzerläuterungFlags
CFLG ZFLGSHLA 0 CFLG <<- AKKU <<- 0 Linksschieben * *
STA Adr 1 M <- AKKU Absolut Speichern - -STA (Adr) 2 (M) <- AKKU Indirekt Speichern - -LDA (Adr) 3 AKKU <- (M) Indirekt Laden 0 *
LDA #Daten 4 AKKU <- Daten Unmittelbar Laden 0 *LDA Adr 5 AKKU <- M Absolut Laden 0 *
ADDA Adr 6 AKKU <- AKKU + M Addieren * *SUBA Adr 7 AKKU <- AKKU - M Subtrahieren * *ORA Adr 8 AKKU <- AKKU ∨ M Oder 0 *
ANDA Adr 9 AKKU <- AKKU ∧ M Und 0 *EORA Adr A AKKU <- AKKU ≠ M XOR 0 *JMP Adr B Absoluter Sprung - -JE Adr C Verzweigung falls ZFLG=1 - -
JNE Adr D Verzweigung falls ZFLG=0 - -JGE Adr E Verzweigung falls CFLG=0 - -JLT Adr F Verzweigung falls CFLG=1 - -
SHLA
STAABS
STAIND
LDAIND
LDAUNM
LDAABS
ADDA
SUBA
ORA
ANDA
EORA
JMP
JE
JNE
JGE
JLT
* Flag wird gemäß Ergebnis geändert- Flag unverändert0 Flag wird auf 0 gesetzt (Rücksetzen)
4
Befehlsformate
SHLA 0000 (leer)
LDA #Daten 0100 (leer)
Daten
Alle anderen OPCode Adresse
15 12 11 0
5
Globaler Aufbau
Steuerwerk
CLK
RESET
R/W
CS
AkkuFlags
ALUBefehlsdekodierungInstruktionsregister
PC
Adr. Mux
RAM
AC[15..0]
F[15..0]
C_FLG
Z_FLG
CFLG
ZFLG
OPCODE
OUTPC
LOADOPLOADIA
INCPC
LOADPC
D[15..0]
I[11..0]
A[11..0]
P[11..0]
LOADAF
OUTDB
6
Programmbeispiel
Euklidischer Algorithmus (Algorithmus zur Ermittlung des GGT zweier Zahlen, hier positiver Zahlen)
While A ≠B dobeginif B>A then // wenn ja, vertausche A und B
beginC := A;A := B;B := Cend;
A := A-B;end;
Wir machen daraus ein ASSEMBLER-Programm für den Musterprozessor. Dazu formulieren wir das Programm etwas um:
7
01010001000000000111000100000001111000000000101101010001000000000001000100000010010100010000000100010001000000000101000100000010000100010000000101010001000000000111000100000001000100010000000001110001000000011101000000000010
51007101E00B5100 1102510111005102 1101510071011100 7101D002
8
Sei A an Adresse 100, B an 101 und das Ergebnis wir d an 1000erwartet:
000 LDA 100001 SUBA 101 // wenn B>A ist hier das CFLG=1002 JGE 00B // springt wenn CFLG=0003 LDA 100004 STA 102005 LDA 101006 STA 100007 LDA 102008 STA 101 // jetzt ist A ≥ B009 LDA 10000A SUBA 10100B STA 100 // und A bleibt ≥ 000C SUBA 101 // wenn A=B wird ZFLG gesetzt00D JNE 00200E HALT
// am Ende ist A=B=GGT(A,B)
51007101E00B510011025101110051021101510071011100710 1D002
9
Beispiel:
Zu Beginn steht an Adresse 100 der Wert 72 und an Adresse 101 der Wert 45.Wir betrachten den Verlauf der Wertebelegungen:
100 101 102 AKKU CFLG ZFLG72 45 7227 27 0
-18 1 027 27
45 4527 27
4518 18
-9 1 018 18
27 2718 18
279 9
-9 1 09 9
18 189 9
189 9
0 0 1HALT
10
Was passiert bei welchem Befehl?
1. SHLA: Schiebt den Operanden im Akkumulator-Register um ein Bit nach links, das ausgeschobene Bit wandert ins Carry-Flag (CFLG), eine 0 wird nachgezogen.
Ausgangssituation:Der SHLA-Befehl wurde im letzten Takt vom Datenbus ins Instruktionsregister (OP-Teil) übernommen. Der PC zeigt auf den nächsten Befehl.
Aktionen:Die ALU macht die Schiebeoperation und stellt das Ergebnis sowie die neuen Flags an ihrem Ausgang zur Verfügung. Der AKKU übernimmt das Ergebnis aus der ALU. Der PC wird um 1 erhöht, sein alter Wert wird über den Adressmultiplexer am Speicher als Adresse angelegt, es wird aus dem Speicher ein Wort auf den Datenbus gelesen, dieses wird in beide Teile des Instruktionsregisters übernommen. Da eine neue Instruktion gelesen wird, kann der Datenbus nicht vom AKKU aus beschrieben werden.
Aus diesen Aktionen ergeben sich folgende Anforderungen an die Steuersignale:OUTPC =1, OUTDB=0, LOADPC=0, INCPC=1, LOADOP=1, LOADIA=1, LOADAF=1, READ=1;
11
Was passiert bei welchem Befehl? (2)
2. ADDA: Addiert den Operanden im Akkumulator-Register mit einem Wort aus dem Speicher und belässt das Ergebnis im AKKU. Erzeugt eine 1 im CFLG, wenn ein Übertrag an der höchsten Stelle entsteht, eine 1 im ZFLG, wenn das Ergebnis 0 ist.
Ausgangssituation:Der ADDA-Befehl wurde im letzten Takt vom Datenbus ins Instruktionsregister (OP-Teil) übernommen, die Adresse für den zweiten Operanden in den Adressteil. Der PC zeigt auf den nächsten Befehl.
Aktionen:Erster Takt: Die Adresse des zweiten Operanden liegt am RAM an, das RAM steht auf READ. Der zweite Operand wird auf den Datenbus gelegt und so an die ALU geführt.Die ALU macht die Additionsoperation und stellt das Ergebnis sowie die neuen Flags an ihrem Ausgang zur Verfügung. Der AKKU übernimmt das Ergebnis aus der ALU. Der PC wird nicht erhöht.
Aus diesen Aktionen ergeben sich folgende Anforderungen an die Steuersignale:OUTPC =0, OUTDB=0, LOADPC=0, INCPC=0, LOADOP=0, LOADIA=0, LOADAF=1, READ=1;
12
Zweiter Takt: Der PC wird um 1 erhöht, sein alter Wert wird über den Adressmultiplexer am Speicher als Adresse angelegt, es wird aus dem Speicher ein Wort auf den Datenbus gelesen, dieses wird in beide Teile des Instruktionsregisters übernommen. Da eine neue Instruktion gelesen wird, kann der Datenbus nicht vom AKKU aus beschrieben werden.
Aus diesen Aktionen ergeben sich folgende Anforderungen an die Steuersignale:OUTPC =1, OUTDB=0, LOADPC=0, INCPC=1, LOADOP=1, LOADIA=1, LOADAF=0, READ=1;
13
Ausführung des Befehls „ADDA 5B2“
Steuerwerk
CLK
RESET
R/W
CS
AkkuFlags
ALUBefehlsdekodierung
PC
Adr. Mux
RAM
AC[15..0]
F[15..0]
C_FLG
Z_FLG
CFLG
ZFLG
OPCODE
OUTPC
LOADOPLOADIA
INCPC
LOADPC
D[15..0]
I[11..0]
A[11..0]
P[11..0]
LOADAF
OUTDB
65B2
ADDA 5B2
1 1
14
Ausführung des Befehls „ADDA 5B2“
Steuerwerk
CLK
RESET
R/W
CS
AkkuFlags
ALUBefehlsdekodierung
PC
Adr. Mux
RAM
AC[15..0]
F[15..0]
C_FLG
Z_FLG
CFLG
ZFLG
OPCODE
OUTPC
LOADOPLOADIA
INCPC
LOADPC
D[15..0]
I[11..0]
A[11..0]
P[11..0]
LOADAF
OUTDB
ADDA 5B2
0
0
0
5B2
1
0
1
001F
0013 001F
0032
0 0
0032
15
Ausführung des Befehls „ADDA 5B2“
Steuerwerk
CLK
RESET
R/W
CS
AkkuFlags
ALUBefehlsdekodierung
PC
Adr. Mux
RAM
AC[15..0]
F[15..0]
C_FLG
Z_FLG
CFLG
ZFLG
OPCODE
OUTPC
LOADOPLOADIA
INCPC
LOADPC
D[15..0]
I[11..0]
A[11..0]
P[11..0]
LOADAF
OUTDB
1
1
0
01C
0
0
1
4002
0032 4002
4034
1 1
01C
LDAunm 002
01D
0032
16
Was passiert bei welchem Befehl? (3)
3. LDAUNM: Lädt einen Operanden ins Akkumulator-Register, der im zweiten Befehlswort des Befehls steht. Erzeugt eine 0 im CFLG, eine 1 im ZFLG, wenn das Ergebnis 0 ist.
Ausgangssituation:Das erste Wort des LDAUNM-Befehl wurde im letzten Takt vom Datenbus ins Instruktionsregister (OP-Teil) übernommen, der irrelevante Adressteil in den Adressteil. Der PC zeigt auf das zweite Wort des Befehl, das den #Daten-Operanden enthält.
Aktionen:Erster Takt: Die Adresse des Operanden ist ja der Inhalt des PC. Dieser liegt über den Adressmux am RAM an, das RAM steht auf READ. Der Operand wird auf den Datenbus gelegt und so an die ALU geführt.Die ALU leitet das Ergebnis unverändert durch, erzeugt die neuen Flags, und stellt alles an ihrem Ausgang zur Verfügung. Der AKKU übernimmt das Ergebnis aus der ALU. Der PC wird erhöht.
Aus diesen Aktionen ergeben sich folgende Anforderungen an die Steuersignale:OUTPC =1, OUTDB=0, LOADPC=0, INCPC=1, LOADOP=0, LOADIA=0, LOADAF=1, READ=1;
17
Zweiter Takt: Der PC wird um 1 erhöht, sein alter Wert wird über den Adressmultiplexer am Speicher als Adresse angelegt, es wird aus dem Speicher ein Wort auf den Datenbus gelesen, dieses wird in beide Teile des Instruktionsregisters übernommen. Da eine neue Instruktion gelesen wird, kann der Datenbus nicht vom AKKU aus beschrieben werden.
Aus diesen Aktionen ergeben sich folgende Anforderungen an die Steuersignale:OUTPC =1, OUTDB=0, LOADPC=0, INCPC=1, LOADOP=1, LOADIA=1, LOADAF=0, READ=1;
18
Was passiert bei welchem Befehl? (4)
4. LDAIND: Lädt einen indirekt adressierten Operanden ins Akkumulator-Register. Zuerst wird unter der im Befehl stehenden Adresse ein Wort aus dem Speicher gelesen, deren niederwertigen 12 Bits die Adresse des tatsächlichen Operanden sind. Dieses wird im nächsten Takt gelesen und in den AKKU geschrieben. Erzeugt eine 0 im CFLG, eine 1 im ZFLG, wenn das Ergebnis 0 ist.
Ausgangssituation:Das erste Wort des LDAIND-Befehl wurde im letzten Takt vom Datenbus ins Instruktionsregister (OP-Teil) übernommen, die indirekte Adresse in den Adressteil. Der PC zeigt auf den nächsten Befehl.
Aktionen:Erster Takt: Die indirekte Adresse des Operanden liegt über den Adressmux am RAM an, das RAM steht auf READ. Das Wort mit der absoluten Adresse wird auf den Datenbus gelegt und der Adressteil (12 Bits) werden in den Adressteil des Instruktionsregisters übernommen. Die ALU macht nichts. Der PC wird nicht erhöht.
Aus diesen Aktionen ergeben sich folgende Anforderungen an die Steuersignale:OUTPC =0, OUTDB=0, LOADPC=0, INCPC=0, LOADOP=0, LOADIA=1, LOADAF=0, READ=1;
19
Zweiter Takt: Der Adressteil des Instruktionsregisters wird über den Adressmux ans RAM angelegt, das RAM steht auf READ, der Operand wird aus dem RAM gelesen und auf den Datenbus gelegt. Von hier wird er durch die ALU durchgereicht, die dabei die Flags berechnet (CFLG = 0, ZFLG =1 gdw. Der Operand gleich 0 ist). Die Ergebnisse werden in den AKKU übernommen. Der PC wird nicht erhöht.
Aus diesen Aktionen ergeben sich folgende Anforderungen an die Steuersignale:OUTPC =0, OUTDB=0, LOADPC=0, INCPC=0, LOADOP=0, LOADIA=0, LOADAF=1, READ=1;
Dritter Takt: Der PC wird um 1 erhöht, sein alter Wert wird über den Adressmultiplexer am Speicher als Adresse angelegt, es wird aus dem Speicher ein Wort auf den Datenbus gelesen, dieses wird in beide Teile des Instruktionsregisters übernommen. Da eine neue Instruktion gelesen wird, kann der Datenbus nicht vom AKKU aus beschrieben werden.
Aus diesen Aktionen ergeben sich folgende Anforderungen an die Steuersignale:OUTPC =1, OUTDB=0, LOADPC=0, INCPC=1, LOADOP=1, LOADIA=1, LOADAF=0, READ=1;
20
Ausführung des Befehls „LDAind 0B6“
Steuerwerk
CLK
RESET
R/W
CS
AkkuFlags
ALUBefehlsdekodierung
PC
Adr. Mux
RAM
AC[15..0]
F[15..0]
C_FLG
Z_FLG
CFLG
ZFLG
OPCODE
OUTPC
LOADOPLOADIA
INCPC
LOADPC
D[15..0]
I[11..0]
A[11..0]
P[11..0]
LOADAF
OUTDB
LDAind 0B6
0
0
0
0B6
1
0
1
00FF
0032 00FF
00FF
1
0 0
00FF
21
Ausführung des Befehls „LDAind 0B6“
Steuerwerk
CLK
RESET
R/W
CS
AkkuFlags
ALUBefehlsdekodierung
PC
Adr. Mux
RAM
AC[15..0]
F[15..0]
C_FLG
Z_FLG
CFLG
ZFLG
OPCODE
OUTPC
LOADOPLOADIA
INCPC
LOADPC
D[15..0]
I[11..0]
A[11..0]
P[11..0]
LOADAF
OUTDB
LDAind 0B6
0
0
0
0B6
1
0
1
00FF
0032 00FF
00FF
1
0 0
00FF
22
Was passiert bei welchem Befehl? (5)
5.STAABS: Speichert den Inhalt des Akkumulator-Registers unter der angegebenen Adresse.
Ausgangssituation:Der STAABS-Befehl wurde im letzten Takt vom Datenbus ins Instruktionsregister (OP-Teil) übernommen, der Adressteil (12 Bit) in den Adressteil. Der PC zeigt auf den nächsten Befehl.
Aktionen:Erster Takt: Die Zieladresse liegt über den Adressmux am RAM an, das RAM steht auf WRITE. Der Operand wird vom AKKU auf den Datenbus gelegt und so ans RAM geführt. Dort wird er geschrieben. Der PC wird nicht erhöht.
Aus diesen Aktionen ergeben sich folgende Anforderungen an die Steuersignale:OUTPC =0, OUTDB=1, LOADPC=0, INCPC=0, LOADOP=0, LOADIA=0, LOADAF=0, READ=0;
23
Zweiter Takt: Der PC wird um 1 erhöht, sein alter Wert wird über den Adressmultiplexer am Speicher als Adresse angelegt, es wird aus dem Speicher ein Wort auf den Datenbus gelesen, dieses wird in beide Teile des Instruktionsregisters übernommen. Da eine neue Instruktion gelesen wird, kann der Datenbus nicht vom AKKU aus beschrieben werden.
Aus diesen Aktionen ergeben sich folgende Anforderungen an die Steuersignale:OUTPC =1, OUTDB=0, LOADPC=0, INCPC=1, LOADOP=1, LOADIA=1, LOADAF=0, READ=1;
24
Was passiert bei welchem Befehl? (6)
6. JE: Springt im Programm an die angegebene Adresse, wenn das ZFLG gesetzt ist.
Ausgangssituation:Der JE-Befehl wurde im letzten Takt vom Datenbus ins Instruktionsregister (OP-Teil) übernommen, die mögliche Zieladresse der Verzweigung (12 Bit) in den Adressteil. Der PC zeigt auf den nächsten Befehl.
Aktionen:Erster Takt: Der PC wird nicht erhöht. Stattdessen wird der PC mit dem Adressteil überschrieben, wenn das ZFLG gesetzt ist.
Aus diesen Aktionen ergeben sich folgende Anforderungen an die Steuersignale:OUTPC =X, OUTDB=0, LOADPC=ZFLG, INCPC=0, LOADOP=0, LOADIA=0, LOADAF=0, READ=X;
Besonders ist hier, dass OUTPC und READ don‘t cares sind. Würden sie auf 1 liegen, so würde zum Zeitpunkt der Bedingungsauswertung der nächste Befehl auf den Datenbus geholt werden, aber nicht dekodiert. Es würde also kein Schaden angerichtet werden. Im folgenden Takt aber wird der aktualisierte PC verwendet, um den richtigen nächsten Befehl zu holen.
25
Zweiter Takt: Der PC wird um 1 erhöht, sein alter Wert wird über den Adressmultiplexer am Speicher als Adresse angelegt, es wird aus dem Speicher ein Wort auf den Datenbus gelesen, dieses wird in beide Teile des Instruktionsregisters übernommen. Da eine neue Instruktion gelesen wird, kann der Datenbus nicht vom AKKU aus beschrieben werden.
Aus diesen Aktionen ergeben sich folgende Anforderungen an die Steuersignale:OUTPC =1, OUTDB=0, LOADPC=0, INCPC=1, LOADOP=1, LOADIA=1, LOADAF=0, READ=1;
26
Entwurf von ALU und AKKU
Aufgabe der ALU ist die ungetaktete Ausführung der jeweiligen Operation. Die ALU ist als Schaltnetz konzipiert und wird lediglich durch die Eingänge und den OP-Code gesteuert. Sie generiert außer dem Ergebnis die Flags ZFLG (Zero-Flag) und CFLG (Carry-Flag). Diese Werte werden an den AKKU weitergegeben und im Falle eines ALU-Befehls (eines Befehls, in dem die ALU im Datenpfad enthalten ist, z.B. ADDA oder LADUNM) übernommen. Bei STA-Befehlen (STAind oder STAabs) wird der Wert des AKKUs auf den Datenbus gelegt, um auf diesem in den Speicher zu gelangen. Bei allen anderen Befehlen ist der Datenbusausgang hochohmig zu schalten.
Zur Vereinfachung der einzelnen Komponenten verwenden wir ein package. Dies ist quasi eine selbst geschriebene Bibliothek aus Typen und Konstanten, die in die einzelnen VHDL-Sources eingebunden werden kann und dann überall verwendet werden kann, ohne neu explizit deklariert zu werden.
27
-- Package
library IEEE;use IEEE.STD_LOGIC_1164.all;package MP_PACK is
-- Typendeklarationtype OPTYPE is (
SHLA, STAabs, STAind, LDAind, LDAunm,LDAabs, ADDA, SUBA, ORA, ANDA, EORA,JMP, JE, JNE, JGE, JLT);
subtype D_TYPE is std_logic_vector(15 downto 0); -- 16-Bit Datensubtype A_TYPE is std_logic_vector(11 downto 0); -- 12-Bit Adressen
-- Konstantendeklarationconstant A_BREITE : integer := 12;constant D_BREITE : integer := 16;
end MP_PACK;
28
-- alu.vhd-- Synthesefähiges Verhaltensmodell für 16 Bit Alu--------------------------------------------------use WORK.MP_PACK.ALL;library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity ALU isport(
OPCODE : in OPTYPE; -- OperationsbefehlD : in D_TYPE; -- DatenbusAC : in D_TYPE; -- AkkumulatorwertF : out D_TYPE; -- OperationsergebnisC_FLG : out std_logic; -- Flag: ÜbertragZ_FLG : out std_logic); -- Flag: Ergebnis Null
end ALU;
architecture BHV of ALU isconstant ZERO : D_TYPE := ( others=>'0');begin
process (D, AC, OPCODE)variable FVAR : D_TYPE;variable DVAR, ACVAR : D_TYPE;variable RESULT : std_logic_vector(D_BREITE downto 0);
29
beginDVAR := std_logic_vector(D); -- Kopie von DACVAR := std_logic_vector(AC); -- Kopie von ACFVAR := ZERO; -- Vermeidung eines A usgangslatchesZ_FLG <= '0'; -- Vorinitialisierung der FlagsC_FLG <= '0';case OPCODE is
when LDAabs | LDAunm | LDAind => FVAR := D;when ORA => FVAR := AC or D;when ANDA => FVAR := AC and D;when EORA => FVAR := AC xor D;when SHLA => C_FLG <= AC(D_BREITE-1); --MSB
FVAR(D_BREITE-1 downto 1) := AC(D_BREITE-2 downto 0); FVAR(0) := '0'; -- Null -> LSB
when ADDA => RESULT := ('0' & ACVAR) + ('0' & DVAR);FVAR := RESULT(D_BREITE-1 downto 0);C_FLG <= RESULT(D_BREITE);
when SUBA => RESULT := ('0' & ACVAR) - ('0' & DVAR);FVAR := RESULT(D_BREITE-1 downto 0);C_FLG <= RESULT(D_BREITE);
when others => null;end case;if FVAR = ZERO then -- Null-Vergleich
Z_FLG <= '1'; -- Überschreibenend if;F <= FVAR; -- Ergebniszuweisung
end process;end BHV;
30
-- akku_flg.vhd-- Synthesefähiges Verhaltensmodell für Akkumulatorr egister--------------------------------------------------use WORK.MP_PACK.ALL;library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity AKKU_FLG isport(
CLK : in std_logic; -- SystemtaktRESET : in std_logic; -- ResetF : in D_TYPE; -- Operationsergebnis ALUAC : out D_TYPE; -- Akku(mulatorregister)D : out D_TYPE; -- DatenbusLOADAF : in std_logic; -- lade Akku und Flagregister OUTDB : in std_logic; -- schreibe D auf DatenbusC_FLG : in std_logic; -- Flag: ÜberlaufZ_FLG : in std_logic; -- Flag: Ergebnis Null CFLG : out std_logic; -- Flagregister von C_FLGZFLG : out std_logic); -- Flagregister von Z_FLG
end AKKU_FLG;
31
architecture BHV of AKKU_FLG issignal AC_INT : D_TYPE;
beginD_OUT : process(OUTDB, AC_INT) -- 16 Bit Tri State Treiberbegin
if OUTDB='1' thenD <= AC_INT;
elseD <= (others=>'Z');
end if;end process D_OUT;LOAD : process(CLK, RESET) -- 16+2 Bit Register mit Resetbegin
if RESET='1' thenAC_INT <= ( others=>'0');CFLG <= '0';ZFLG <= '0';
elsif CLK='1' and CLK'event thenif LOADAF='1' then
AC_INT <= F;CFLG <= C_FLG;ZFLG <= Z_FLG;
end if;end if;
end process LOAD;AC <= AC_INT; -- Interne Kopie des out-Signals
end BHV;
32
-- alu_akku.vhd-- Strukturmodell zum Testen von ALU, Akku und Flag- Registern--------------------------------------------------- ----------use WORK.MP_PACK.ALL;library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity ALU_AKKU is
port(CLK : in std_logic;RESET : in std_logic;OPCODE : in OPTYPE;D : inout D_TYPE;LOADAF : in std_logic;OUTDB : in std_logic;C_FLG : out std_logic;Z_FLG : out std_logic);
end ALU_AKKU;
33
architecture STR of ALU_AKKU is-- lokale Signalesignal F, AC : D_TYPE; -- interne Bussesignal C_FLG_INT, Z_FLG_INT : std_logic; -- interne Flagsig nale
-- Komponentendeklarationcomponent ALU
port(OPCODE : in OPTYPE;D : in D_TYPE;AC : in D_TYPE;F : out D_TYPE;C_FLG : out std_logic;Z_FLG : out std_logic);
end component;component AKKU_FLG
port(CLK : in std_logic;RESET : in std_logic;F : in D_TYPE;AC : out D_TYPE;D : out D_TYPE;LOADAF : in std_logic;OUTDB : in std_logic;C_FLG : in std_logic;Z_FLG : in std_logic;CFLG : out std_logic;ZFLG : out std_logic);
end component;
34
-- Komponentenkonfigurationfor all : ALU use entity WORK.ALU(BHV);for all : AKKU_FLG use entity WORK.AKKU_FLG(BHV);
beginC1 : ALU port map(
OPCODE => OPCODE,D => D,AC => AC,F => F,C_FLG => C_FLG_INT,Z_FLG => Z_FLG_INT);
C2 : AKKU_FLG port map(
CLK => CLK,RESET => RESET,F => F,AC => AC,D => D,LOADAF => LOADAF,OUTDB => OUTDB,C_FLG => C_FLG_INT,Z_FLG => Z_FLG_INT,CFLG => C_FLG,ZFLG => Z_FLG);
end STR;
35
36
Entwurf der Befehlsdekodierung, des PC und des Adre ss-Mux
OPCODE_DEC stellt einen taktflankengesteuerten Befehlsdecoder dar. In diesem wird, falls LOADOP=1 ist, das oberste Byte des aktuellen Datenbuswertes dekodiert, wobei die in der OPCODE-Tabelle angegebene hexadezimale Codierung verwendet wird. Der „when others“ Zweig in der case-Anweisung ist erforderlich, da der Typ std_logic verwendet wird. Alle nicht eindeutigen Befehlscodes werden auf SHLA abgebildet.
LD_INSTR_ADR entspricht einem taktflankengesteuerten Register mit Enable-eingang LOADIA. In diesem Register werden die drei niederwertigen Nibbles des Befehlswortes gespeichert, also der Adressteil des Befehls, was für die absolute und indirekte Adressierung erforderlich ist.
PROGCTR ist ein taktflankengesteuerter, 12 Bit breiter Zähler mit Vorladeeingang. Die Steuereingänge INCPC und LOADPC entscheiden, ob die aktuelle Adresse inkrementiert werden soll oder ob der Zähler mit dem Wert, der aktuell im Adressenregister steht, überschrieben werden soll. Wenn INCPC und LOADPC ‘0‘sind, bleibt der alte Wert im Zähler unverändert.
MUX stellt die kombinatorische Logik eines Multiplexers dar. Mit Hilfe des Auswahlsignals OUTPC wird entschieden, ob der neue Wert des Programmzählers P oder aber der Adressteil des letzten Befehlswortes auf den Adressbus gelegt werden soll.
37
-- ir_pc.vhd-- Verhaltensmodell für Instruktionsregister und Pro grammzähler--------------------------------------------------- ------------use WORK.MP_PACK.ALL;library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity IR_PC is
port(CLK : in std_logic; -- SystemtaktRESET : in std_logic; -- ResetD : in D_TYPE; -- DatenbusLOADOP : in std_logic; -- dekodiere OPcodeLOADIA : in std_logic; -- lade InstruktionsAdresseINCPC : in std_logic; -- PC = PC +1LOADPC : in std_logic; -- A(D) -> PCOUTPC : in std_logic; -- (PC xor A) -> D OPCODE : out OPTYPE; -- Instr.-CodeA : out A_TYPE); -- Adressbus am RAM
end IR_PC;
38
architecture BHV of IR_PC issignal I : A_TYPE; -- Adresse im I nstr.-Codesignal P : std_logic_vector(A_BREITE-1 downto 0); -- Programmzähler
begin -- OPCODE dekodierungOPCODE_DEC : process (CLK, RESET)begin
if RESET='1' then OPCODE <= SHLA;elsif CLK='1' and CLK'event then
if LOADOP='1' thencase D(15 downto 12) is
when "0000" => OPCODE <= SHLA;when "0001" => OPCODE <= STAabs;when "0010" => OPCODE <= STAind;when "0011" => OPCODE <= LDAind;when "0100" => OPCODE <= LDAunm;when "0101" => OPCODE <= LDAabs;when "0110" => OPCODE <= ADDA;when "0111" => OPCODE <= SUBA;when "1000" => OPCODE <= ORA;when "1001" => OPCODE <= ANDA;when "1010" => OPCODE <= EORA;when "1011" => OPCODE <= JMP;when "1100" => OPCODE <= JE;when "1101" => OPCODE <= JNE;when "1110" => OPCODE <= JGE;when "1111" => OPCODE <= JLT;when others => OPCODE <= SHLA; -- für X,Z etc
end case;end if;
end if;end process OPCODE_DEC;
39
LD_INSTR_ADR : process (CLK) -- Befehlsadresse ladenbegin
if CLK='1' and CLK'event thenif LOADIA='1' then
I <= D(A_BREITE-1 downto 0);end if;
end if;end process LD_INSTR_ADR;
PROGCTR : process (CLK, RESET) -- Programmzählerbegin
if RESET='1' thenP <= ( others=>'0');
elsif CLK='1' and CLK'event thenif LOADPC='1' then
P <= I;elsif INCPC='1' then
P <= P + 1;end if;
end if;end process PROGCTR;
MUX : process (OUTPC, I, P) -- 12 Bit MUXbegin
if OUTPC='1' then -- PC auf AdressbusA <= P;
elseA <= I;
end if;end process MUX;
end BHV;
40
Entwurf des Steuerwerks
Aufgabe des Steuerwerks ist die Generierung der Steuersignale, mit denen die anderen Einheiten (ALU, AKKU, Befehlsdekodierer, RAM usw.) gesteuert werden.
Dafür stellen wir zunächst fest, dass es (aus Sicht des Steuerwerks) vier unterschiedliche Arten von Befehlen gibt:
1-Takt-Befehle bestehend aus einem Wort: (SHLA)2-Takt-Befehle bestehend aus einem Wort (STAABS, LDAABS,…)2-Takt-Befehle bestehend aus zwei Worten (LDAUNM)3-Takt-Befehle bestehend aus einem Wort (STAIND, LDAIND)
In 1-Takt-Befehlen kann der aktuelle Befehl ausgeführt und gleichzeitig der OPCODE des nächsten Befehls geladen und dekodiert werden. Ein zweiter Takt ist erforderlich, wenn Befehle entweder einen zweiten Operanden aus dem Speicher benötigen, ein Datenwort aus dem Speicher lesen sollen oder einen Sprung bewirken sollen. Die Befehle mit indirekter Adressierung benötigen für die Berechnung der endgültigen Adresse einen eigenen Taktzyklus, wodurch sich 3-Takt-Befehle ergeben.
Wenn man den Automaten als Mealy-Typ realisiert, kann man mit drei Zuständen auskommen. Dies ist in diesem Falle sinnvoll, da wegen der großen Zahl an möglichen Ausgaben bei einem Moore-Automaten sehr viel mehr Zustände erforderlich wären.
41
Automatengraph des Steuerwerks
S0 S1
S2
2-Takt-Befehle
3-Takt-Befehle
1-Takt-Befehle
RESET
42
Ausführung des Befehls „ADDA 5B2“
Steuerwerk
CLK
RESET
R/W
CS
AkkuFlags
ALUBefehlsdekodierung
PC
Adr. Mux
RAM
AC[15..0]
F[15..0]
C_FLG
Z_FLG
CFLG
ZFLG
OPCODE
OUTPC
LOADOPLOADIA
INCPC
LOADPC
D[15..0]
I[11..0]
A[11..0]
P[11..0]
LOADAF
OUTDB
65B2
ADDA 5B2
1 1
43
Ausführung des Befehls „ADDA 5B2“
Steuerwerk
CLK
RESET
R/W
CS
AkkuFlags
ALUBefehlsdekodierung
PC
Adr. Mux
RAM
AC[15..0]
F[15..0]
C_FLG
Z_FLG
CFLG
ZFLG
OPCODE
OUTPC
LOADOPLOADIA
INCPC
LOADPC
D[15..0]
I[11..0]
A[11..0]
P[11..0]
LOADAF
OUTDB
ADDA 5B2
0
0
0
5B2
1
0
1
001F
0013 001F
0032
0 0
0032
44
Ausführung des Befehls „ADDA 5B2“
Steuerwerk
CLK
RESET
R/W
CS
AkkuFlags
ALUBefehlsdekodierung
PC
Adr. Mux
RAM
AC[15..0]
F[15..0]
C_FLG
Z_FLG
CFLG
ZFLG
OPCODE
OUTPC
LOADOPLOADIA
INCPC
LOADPC
D[15..0]
I[11..0]
A[11..0]
P[11..0]
LOADAF
OUTDB
1
1
0
01C
0
0
1
4002
0032 4002
4034
1 1
01C
LDAunm 002
01D
0032
45
Ausführung des Befehls „LDAind 100“
Steuerwerk
CLK
RESET
R/W
CS
AkkuFlags
ALUBefehlsdekodierung
PC
Adr. Mux
RAM
AC[15..0]
F[15..0]
C_FLG
Z_FLG
CFLG
ZFLG
OPCODE
OUTPC
LOADOPLOADIA
INCPC
LOADPC
D[15..0]
I[11..0]
A[11..0]
P[11..0]
LOADAF
OUTDB
3100
LDAind 100
1 1
46
Ausführung des Befehls „ADDA 5B2“
Steuerwerk
CLK
RESET
R/W
CS
AkkuFlags
ALUBefehlsdekodierung
PC
Adr. Mux
RAM
AC[15..0]
F[15..0]
C_FLG
Z_FLG
CFLG
ZFLG
OPCODE
OUTPC
LOADOPLOADIA
INCPC
LOADPC
D[15..0]
I[11..0]
A[11..0]
P[11..0]
LOADAF
OUTDB
LDAind 100
0
0
0
100
0
0
1
00B6
0032 00B6
00B6
0 1
0032
47
Ausführung des Befehls „LDAind 0B6“
Steuerwerk
CLK
RESET
R/W
CS
AkkuFlags
ALUBefehlsdekodierung
PC
Adr. Mux
RAM
AC[15..0]
F[15..0]
C_FLG
Z_FLG
CFLG
ZFLG
OPCODE
OUTPC
LOADOPLOADIA
INCPC
LOADPC
D[15..0]
I[11..0]
A[11..0]
P[11..0]
LOADAF
OUTDB
LDAind 0B6
0
0
0
0B6
1
0
1
00FF
0032 00FF
00FF
1
0 0
00FF
48
Laden des Befehls „LDAunm“
Steuerwerk
CLK
RESET
R/W
CS
AkkuFlags
ALUBefehlsdekodierung
PC
Adr. Mux
RAM
AC[15..0]
F[15..0]
C_FLG
Z_FLG
CFLG
ZFLG
OPCODE
OUTPC
LOADOPLOADIA
INCPC
LOADPC
D[15..0]
I[11..0]
A[11..0]
P[11..0]
LOADAF
OUTDB
1
1
0
01C
0
0
1
4002
00FF 4002
4002
1 1
01C
LDAunm 002
01D
00FF
49
Wertetabelle des Steuerwerkautomaten
Zustand OpCode Folg.Z OUTPC OUTDB LOADPC INCPC LOADOP LOADIA LOADAF READ
S0 SHLA S0 1 0 0 1 1 1 1 1
S0 STAABS S1 0 1 0 0 0 0 0 0
S0 STAIND S2 0 0 0 0 0 1 0 1
S0 LDAIND S2 0 0 0 0 0 1 0 1
S0 LDAUNM S1 1 0 0 0 0 0 1 1
S0 LDAABS S1 0 0 0 0 0 0 1 1
S0 ADDA S1 0 0 0 0 0 0 1 1
S0 SUBA S1 0 0 0 0 0 0 1 1
S0 ORA S1 0 0 0 0 0 0 1 1
S0 ANDA S1 0 0 0 0 0 0 1 1
S0 EORA S1 0 0 0 0 0 0 1 1
S0 JMP S1 1 0 1 0 0 0 0 1
S0 JE S1 1 0 ZFLG 0 0 0 0 1
S0 JNE S1 1 0 ¬ZFLG 0 0 0 0 1
S0 JGE S1 1 0 ¬CFLG 0 0 0 0 1
S0 JLT S1 1 0 CFLG 0 0 0 0 1
50
Wertetabelle des Steuerwerkautomaten, Fortsetzung
Zustand OpCode Folg.Z OUTPC OUTDB LOADPC INCPC LOADOP LOADIA LOADAF READ
S2 SHLA S1 - - - - - - - -
S2 STAABS S1
S2 STAIND S1 0 1 0 0 0 0 0 0
S2 LDAIND S1 0 0 0 0 0 0 1 1
S2 LDAUNM S1
S2 LDAABS S1
S2 ADDA S1
S2 SUBA S1
S2 ORA S1
S2 ANDA S1
S2 EORA S1
S2 JMP S1
S2 JE S1
S2 JNE S1
S2 JGE S1
S2 JLT S1
S1 - S0 1 0 0 1 1 1 0 1
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
51
Wieviele Takte ein Befehl benötigt, ergibt sich in der Regel aus der Nutzung des Datenbusses. Dieser muss ja im Zeitmultiplex zur Übertragung von Befehlsworten und von Datenworten genutzt werden. Wenn zum Beispiel ein LDAIND-Befehlausgeführt werden soll, muss in einem ersten Takt die absolute Adresse (aus dem RAM) auf dem Datenbus liegen, um ins Adressregister übernommen werden zu können. In einem zweiten Takt muss der Operand (aus dem RAM) gelesen und über den Datenbus an die ALU geleitet werden. Der dritte Takt ist notwendig, um den nächsten Befehl aus dem Speicher auf den Datenbus zu legen und von dort in den Operanden- und Adressteil des Instruktionsregisters zu kopieren.
Die Werte in der Tabelle auf den letzten beiden Folien ergeben sich aus den Überlegungen, die wir für die Ausführung der einzelnen Befehlstypen angestellt haben.
Die don‘t-cares bei den Steuersignalen bei Übergang von S2 nach S1 kommen daher, dass diese Kombination von Zustand und Befehl nicht vorkommt.
Vergewissern Sie sich bitte anhand des Datenpfades von der Richtigkeit der in den Tabellen eingetragenen Werte für die Steuersignale. Entsprechen dieser Einträge wird im folgenden das Steuerwerk modelliert.
52
-- st_werk.vhd-- Synthesefähiges Verhaltensmodell -- Steuerwerk--------------------------------------------------use WORK.MP_PACK.ALL;library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity ST_WERK isport(
CLK : in std_logic; -- SystemtaktRESET : in std_logic; -- ResetOPCODE : in OPTYPE; -- Instr.-CodeCFLG : in std_logic; -- Flag: Überlauf ZFLG : in std_logic; -- Flag: Ergebnis NullREADWRITE : out std_logic; LOADAF : out std_logic;OUTDB : out std_logic;LOADOP : out std_logic;LOADIA : out std_logic;INCPC : out std_logic;LOADPC : out std_logic;OUTPC : out std_logic);
end ST_WERK;
53
architecture FSM of ST_WERK istype STATE_TYPE is (S0, S1, S2);signal STATE, NEXT_STATE : STATE_TYPE;
begin-- ZustandsregisterSPEICHER : process (CLK, RESET)begin
if RESET='1' thenSTATE <= S1;
elsif CLK='1' and CLK'event thenSTATE <= NEXT_STATE; -- Zustandsübernahme
end if;end process SPEICHER;
54
-- FolgezustandsschaltnetzS_NETZE : process(STATE, OPCODE, CFLG, ZFLG)begin
OUTPC <= '0'; -- VorinitialisierungOUTDB <= '0'; -- aller AusgangssignaleLOADPC <= '0'; -- mit '0'INCPC <= '0';LOADOP <= '0';LOADIA <= '0';LOADAF <= '0';READWRITE <= '0';
case STATE iswhen S0 => -- Befehl ausfuehren
case OPCODE iswhen SHLA =>
OUTPC <='1';INCPC <='1';LOADOP <='1';LOADIA <='1';LOADAF <='1';READWRITE <='1';NEXT_STATE <= S0; --1 Tkt/1 Wort
when LDAabs | ADDA | SUBA | ORA | ANDA | EORA =>LOADAF <='1';READWRITE <='1';NEXT_STATE <= S1; --2 Tkt/1 Wort
55
when LDAunm =>OUTPC <='1';INCPC <='1';LOADAF <='1';READWRITE <='1';NEXT_STATE <= S1;-- 2 Tkt/1 Wort
when LDAind | STAind =>LOADIA <='1';READWRITE <='1';NEXT_STATE <= S2;-- 3 Tkt/1 Wort
when STAabs =>OUTDB <='1';NEXT_STATE <= S1;-- 2 Tkt/1 Wort
when JMP | JE | JNE | JGE | JLT =>OUTPC <='1';READWRITE <='1';NEXT_STATE <= S1;-- 2 Tkt/1 Wortcase OPCODE is -- LOADPC abh. v. den Flagswhen JMP =>
LOADPC <='1';when JE =>
if ZFLG ='1' thenLOADPC <='1';
end if;when JNE =>
if ZFLG ='0' thenLOADPC <='1';
end if;
56
when JGE =>if CFLG ='0' then
LOADPC <='1';end if;
when JLT =>if CFLG ='1' then
LOADPC <='1';end if;
when others => null;end case;
end case;when S1 =>
NEXT_STATE <= S0; -- Naechsten Befehl lesenOUTPC <='1'; INCPC <='1';LOADOP <='1';LOADIA <='1';READWRITE <='1';
when S2 =>NEXT_STATE <= S1;-- Endg.Adr. ermittelnif OPCODE = LDAind then
LOADAF <='1';READWRITE <='1';
elsif OPCODE = STAind thenOUTDB <='1';
end if;end case;
end process S_NETZE;end FSM;
57
VHDL-Code für den ganzen Prozessor
Um jetzt den ganzen Prozessor zu synthetisieren müssen wir nur noch die einzelnen Komponenten miteinander verbinden. Dies tun wir im letzten Schritt der VHDL-Programmierung. Es entsteht das Strukturmodell der CPU:
58
-- cpu.vhd V2.1-- Strukturmodell fuer einen Mikroprozessor--------------------------------------------------- ----- Verwendete Komponenten:-- Funktions- und Typenpackage: mp_pack.vhd-- Steuerwerk: st_werk.vhd-- Befehlsregister / Progzaehler: ir_pc.vhd-- Alu: alu.vhd-- Akkumulator und Flag-register: akku_flg.vhd--------------------------------------------------- ---
use WORK.MP_PACK.ALL;library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity CPU isport (
CLK : in std_logic; -- SystemtaktRESET : in std_logic; -- ResetD : inout D_TYPE; -- Testbench Port: Ram DatenA : out A_TYPE; -- Testbench Port: Ram AdresseREADWRITE : out std_logic ); -- Testbench Port: Ram Read/not-Write
end CPU;
59
architecture STRUKTUR of CPU is-- lokale Signale:signal AC, F : D_TYPE;signal OPCODE : OPTYPE;signal LOADOP, LOADIA, INCPC, LOADPC, OUTPC, OUTDB, LOADAF : std_logic;signal C_FLG, Z_FLG, CFLG, ZFLG : std_logic; -- Komponentendeklarationen:component ST_WERK port (
CLK : in std_logic; -- SystemtaktRESET : in std_logic; -- ResetOPCODE : in OPTYPE; -- Instr.-CodeCFLG : in std_logic; -- Flag: Überlauf ZFLG : in std_logic; -- Flag: Ergebnis NullREADWRITE : out std_logic; LOADAF : out std_logic;OUTDB : out std_logic;LOADOP : out std_logic;LOADIA : out std_logic;INCPC : out std_logic;LOADPC : out std_logic;OUTPC : out std_logic);
end component;
60
component IR_PCport (
CLK : in std_logic; -- SystemtaktRESET : in std_logic; -- ResetD : in D_TYPE; -- DatenbusLOADOP : in std_logic; -- dekodiere OPLOADIA : in std_logic; -- lade IAINCPC : in std_logic; -- PC = PC +1LOADPC : in std_logic; -- A(D) -> PCOUTPC : in std_logic; -- (PC xor A) -> D OPCODE : out OPTYPE; -- Instr.-CodeA : out A_TYPE); -- Adressbus
end component;
component ALUport (
OPCODE : in OPTYPE; -- OperationsbefehlD : in D_TYPE; -- DatenbusAC : in D_TYPE; -- AkkumulatorwertF : out D_TYPE; -- OperationsergebnisC_FLG : out std_logic; -- Flag: ÜbertragZ_FLG : out std_logic); -- Flag: Ergebnis Null
end component;
61
component AKKU_FLGport (
CLK : in std_logic; -- SystemtaktRESET : in std_logic; -- ResetF : in D_TYPE; -- Operationsergebnis ALUAC : out D_TYPE; -- Akku(mulatorregister)D : out D_TYPE; -- DatenbusLOADAF : in std_logic; -- lade Akku und Flagregister OUTDB : in std_logic; -- schreibe D auf DatenbusC_FLG : in std_logic; -- Flag: ÜberlaufZ_FLG : in std_logic; -- Flag: Ergebnis Null CFLG : out std_logic; -- Flagregister von C_FLGZFLG : out std_logic); -- Flagregister von Z_FLG
end component;
62
-- Komponentenkonfigurationen:for all: ST_WERK use entity WORK.ST_WERK(FSM);for all: IR_PC use entity WORK.IR_PC(BHV);for all: ALU use entity WORK.ALU(BHV);for all: AKKU_FLG use entity WORK.AKKU_FLG(BHV);
begin
U_ST_WERK : ST_WERKport map( CLK, RESET, OPCODE , CFLG, ZFLG, READWRITE,
LOADAF, OUTDB, LOADOP, LOADIA, INCPC, LOADPC, OUTPC );
U_IR_PC : IR_PCport map( CLK, RESET, D, LOADOP, LOADIA, INCPC, LOADPC, OUT PC, OPCODE, A);
U_ALU : ALUport map(OPCODE , D, AC, F, C_FLG, Z_FLG);
U_AKKU_FLG : AKKU_FLGport map(CLK, RESET, F, AC, D, LOADAF, OUTDB, C_FLG, Z_FLG, CFLG, ZFLG);
end STRUKTUR;
63