Lattice Mico8-CPU als FSMD-Implementationpbuchegger.at/download/_BaMICO8.pdf · 5 Module der...

64

Transcript of Lattice Mico8-CPU als FSMD-Implementationpbuchegger.at/download/_BaMICO8.pdf · 5 Module der...

Lattice Mico8-CPU als

FSMD-Implementation

Peter A. Buchegger

BACHELORARBE IT

Nr. 0810306003-A

eingereicht am

Fachhochschul-Bachelorstudiengang

Hardware Software/Systems Engineering

in Hagenberg

im März 2012

Diese Arbeit entstand im Rahmen des Gegenstands

Seminar zur Bachelorarbeit

im

Sommersemester 2011

Betreuer:

Markus Pfa�, Prof. (FH) Dipl.-Ing. Dr.

ii

Erklärung

Hiermit erkläre ich an Eides statt, dass ich die vorliegende Arbeit selbst-ständig und ohne fremde Hilfe verfasst, andere als die angegebenen Quellenund Hilfsmittel nicht benutzt und die aus anderen Quellen entnommenenStellen als solche gekennzeichnet habe.

Hagenberg, am 19. März 2012

Peter A. Buchegger

iii

Inhaltsverzeichnis

Erklärung iii

Kurzfassung vii

Abstract viii

1 Einleitung 1

2 Die Mico8-CPU im Überblick 32.1 Allgemein . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32.2 Mico8 im Überblick [4] . . . . . . . . . . . . . . . . . . . . . . 32.3 Gliederung des Mico8 [4] . . . . . . . . . . . . . . . . . . . . . 4

2.3.1 ALU . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52.3.2 Programmspeicher . . . . . . . . . . . . . . . . . . . . 52.3.3 Register File . . . . . . . . . . . . . . . . . . . . . . . 52.3.4 Programm Flow und Programm Counter . . . . . . . . 52.3.5 Hardware Call Stack . . . . . . . . . . . . . . . . . . . 52.3.6 Scratchpad . . . . . . . . . . . . . . . . . . . . . . . . 52.3.7 Interrupt Vektor . . . . . . . . . . . . . . . . . . . . . 62.3.8 Interrupt-Handling . . . . . . . . . . . . . . . . . . . . 6

2.4 Instruktionen des Mico8 [4] . . . . . . . . . . . . . . . . . . . 62.5 Geprüfte Kon�gurationen der Firma Lattice . . . . . . . . . . 10

3 Testbench 123.1 Allgemein . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123.2 Aufbau der Testbench . . . . . . . . . . . . . . . . . . . . . . 12

3.2.1 Konstanten und Signale . . . . . . . . . . . . . . . . . 133.2.2 Funktionen . . . . . . . . . . . . . . . . . . . . . . . . 133.2.3 Vergleich der Signale . . . . . . . . . . . . . . . . . . . 143.2.4 Ende der Simulation . . . . . . . . . . . . . . . . . . . 143.2.5 Takt-, Reset- und Interruptgenerator . . . . . . . . . . 15

3.3 Probleme der Testbench . . . . . . . . . . . . . . . . . . . . . 16

iv

INHALTSVERZEICHNIS v

4 Portierung der Mico-CPU 174.1 Ein-/Ausgänge der Mico8-CPU . . . . . . . . . . . . . . . . . 174.2 Vorbereitung . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

4.2.1 Generisches ROM . . . . . . . . . . . . . . . . . . . . 194.2.2 Dateiauslesendes ROM . . . . . . . . . . . . . . . . . . 194.2.3 Selbst generiertes ROM . . . . . . . . . . . . . . . . . 204.2.4 RAM . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

4.3 FSMD-Implementation . . . . . . . . . . . . . . . . . . . . . . 204.3.1 Decodieren der Operationen . . . . . . . . . . . . . . . 214.3.2 ALU . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214.3.3 FSMD Prozess . . . . . . . . . . . . . . . . . . . . . . 224.3.4 Call Stack . . . . . . . . . . . . . . . . . . . . . . . . . 244.3.5 Interrupts . . . . . . . . . . . . . . . . . . . . . . . . . 25

5 Module der Mico8-CPU 265.1 GPIO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

5.1.1 Ein-/Ausgänge des Moduls . . . . . . . . . . . . . . . 265.1.2 Register . . . . . . . . . . . . . . . . . . . . . . . . . . 27

5.2 Vorteiler / Taktteiler . . . . . . . . . . . . . . . . . . . . . . . 295.2.1 Ein-/Ausgänge des Moduls . . . . . . . . . . . . . . . 29

5.3 16-Bit-Timer . . . . . . . . . . . . . . . . . . . . . . . . . . . 295.3.1 Ein-/Ausgänge des Moduls . . . . . . . . . . . . . . . 305.3.2 Register . . . . . . . . . . . . . . . . . . . . . . . . . . 31

6 Programmieren der Mico8-CPU 336.1 Assembler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336.2 C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

6.2.1 Vorbereitung . . . . . . . . . . . . . . . . . . . . . . . 336.2.2 Kompilieren . . . . . . . . . . . . . . . . . . . . . . . . 346.2.3 Zusätzliche C-Funktionen . . . . . . . . . . . . . . . . 346.2.4 Interrupt-Funktion . . . . . . . . . . . . . . . . . . . . 346.2.5 Register Tabelle für die SandboxX . . . . . . . . . . . 35

7 Mico8-CPU auf der SandboxX 367.1 Allgemein . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367.2 Ein-/Ausgänge des Top-Level-Designs . . . . . . . . . . . . . 367.3 Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

7.3.1 GPIO-Module im Design . . . . . . . . . . . . . . . . . 377.3.2 Timer-Module im Design . . . . . . . . . . . . . . . . 37

7.4 Testbench . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377.5 Testen der Mico8-CPU . . . . . . . . . . . . . . . . . . . . . . 38

7.5.1 Test 1 - Lau�icht Test . . . . . . . . . . . . . . . . . . 387.5.2 Test 2 - Tasten-Test . . . . . . . . . . . . . . . . . . . 397.5.3 Test 3 - Zähler-Test mit Timer . . . . . . . . . . . . . 40

INHALTSVERZEICHNIS vi

8 Resultate und Ausblicke 428.1 Vergleich mit der Original-CPU . . . . . . . . . . . . . . . . . 428.2 Resultat der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . 438.3 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

A VHDL Code 44A.1 Dateiauslesendes ROM . . . . . . . . . . . . . . . . . . . . . . 44A.2 RAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46A.3 SandboxX Testbench . . . . . . . . . . . . . . . . . . . . . . . 47A.4 GPIOs in der SandboxX . . . . . . . . . . . . . . . . . . . . . 47A.5 Timer in der SandboxX . . . . . . . . . . . . . . . . . . . . . 48

B Arbeitsumgebung 50B.1 Softwareumgebungen . . . . . . . . . . . . . . . . . . . . . . . 50B.2 Messgeräte . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

C Inhalt der CD-ROM 51C.1 PDF-Daten . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51C.2 Dokumente . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51C.3 Latex-Daten . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51C.4 VHDL-Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52C.5 Testbench-Daten . . . . . . . . . . . . . . . . . . . . . . . . . 52C.6 Assembler-Code . . . . . . . . . . . . . . . . . . . . . . . . . . 53C.7 C-Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53C.8 C++-Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53C.9 Synthese . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53C.10 Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54C.11 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

Literaturverzeichnis 55

Kurzfassung

Diese Bachelorarbeit befasst sich mit der Portierung einer 8-Bit-CPU derFirma Lattice in eine FSMD-Implementation. Die Mico8-CPU wurde von derFirma Lattice in Verilog-HDL entwickelt und in VHDL maschinell übersetzt.Zusätzlich soll diese CPU auf die SandboxX der FH-OÖ/Hagenberg portiertwerden.Die Mico8-CPU kann mit 50 verschiedenen Befehlen gesteuert werden undbesitzt einen Interrupt-Eingang. Es können Programme sowohl in Assemblerals auch in der Programmiersprache C erstellt werden.Zum Testen des neuen Designs wurde eine Testbench entwickelt, welche eineinfaches Testen der CPU ermöglicht. Die Test-Programme wurden über-nommen von der Firma Lattice und auch zum Abgleich zwischen dem Ori-ginal-Design mit dem neuen Design verwendet. Im Zuge der Arbeit wurdenzusätzlich verschiedene VHDL-Module erstellt (GPIO- und Timer-Modul),welche dem Design hinzugefügt werden können. Diese dienen vor zur Ein-und Ausgabe von Daten. Für diese Module wurden drei Test-Programmeentwickelt.Die neu entwickelte CPU ist circa doppelt- bis drei-fach so groÿ wie dieOriginal-CPU, verursacht durch das FSMD-Design. Auch die Taktfrequenzist nur mehr halb so hoch wie beim Original-Design.Ein groÿer Vorteil ist, dass selbst Studenten mit wenig Erfahrung die Mico8-CPU verwenden können.

vii

Abstract

This bachelor-thesis deals with the porting of a 8bit CPU to an FSMD-model.The Mico8-CPU was written by Lattice in Verilog-HDL and is automaticallyported to VHDL. The new port is supposed to run on the SandboxX boardof the University Hagenberg.The Mico8-CPU has 50 di�erent operationcodes and a single interrupt-source. The programs can be written in Assembler as well in the programlanguage C.For testing the new Design I have created a testbench, with which is easelypossible to test the new CPU. The test programs were already programmedby Lattice and I used them to test the matching between the original-CPUand the new FSMD CPU. As part of the work, some other designs weredeveloped in VHDL (GPIO and timer modules), which can easily be addedto the design. This modules target input- and output tasks. For this modulesI have created three di�erent test programs which use the GPIO and thetimer modules.The developed CPU is about twice to three times larger than the orignalCPU, because of the FSMD-Design. Also the clock frequency is only half ofthe original frequency.A big advantage is, that new students with little knowledge abouth CPUscan easely use and learn with the new Micro8-CPU.

viii

Kapitel 1

Einleitung

In dieser Bachelorarbeit soll eine Portierung der LatticeMico8-CPU in eineFSMD1-Implementation erfolgen.Die LatticeMico8 CPU ist eine einfache und kleine 8-Bit-CPU, welche inVerilog-HDL entwickelt wurde und mit maschinellen Tools in VHDL über-setzt worden ist. Durch diese maschinelle Übersetzung wird das Design inVHDL sehr unübersichtlich und schwer zu lesen.Trotz des Wissens, dass eine FSMD-Implementation meist mehr Fläche aufeinem FPGA verbraucht als eine sequenzielle Implementierung, wurde dieFSMD Version durch seine Einfachheit bevorzugt. Ein weiterer Grund fürdie FSMD-Implementation war, dass die CPU dem Studiengang HardwareSoftware Design der FH OÖ/Hagenberg zur Verfügung gestellt werden sollund als Vorlage einer einfachen CPU-Implementation in VHDL dienen soll.Mit dieser FSMD-Entwicklung können Studenten erste Erfahrungen im CPUDesign sammeln. Die neue Implementierung der CPU sollte auf der soge-nannten SandboxX der FH OÖ/Hagenberg zu testen und leicht zu erweiternsein. Somit kann man sein eigenes SoC2 erstellen und es auf seine Bedürfnisseanpassen. Zusätzlich können weitere kleine Module erstellt werden die demSoC hinzugefügt werden können (Beispiele: GPIOs, UART, Timer, usw.).Damit das Design unabhängig von den FPGA-Herstellern verwendet wer-den kann, soll die gesamte Implementierung in VHDL erfolgen und keineElemente der Hersteller verwendet werden (RAM, ROM, Addierer, usw.).

Im Kapitel 2 wird der grundlegende Aufbau der Mico8-CPU erläutert. DieTestbench wird im Kapitel 3 genau erklärt und die Vorteile eines Testverfah-rens welches das FSMD-Design mit dem original-Design vergleicht hervor-gehoben. Der Portierungsvorgang der CPU wird in Kapitel 4 beschrieben.Das Kapitel 5 beschreibt die entwickelten Module (GPIO- und Timer-Modul)die dem SoC hinzugefügt werden können. Für die Mico8-CPU können sowohlProgramme in Assembler als auch in C erstellt werden. Im Kapitel 6 wird auf

1Finite state machine with datapath2System-on-a-Chip

1

KAPITEL 1. EINLEITUNG 2

die Programmierung genauer eingegangen. Die Portierung der Mico8-CPUauf die SandboxX wird in Kapitel 7 erklärt. Im letzten Kapitel, Kapitel 8werden noch auf die Resultate und auf die Ausblicke eingegangen.

Kapitel 2

Die Mico8-CPU im Überblick

2.1 Allgemein

Die LatticeMico81, der Firma Lattice ist ein kleiner 8-Bit-CPU erstellt inVHDL oder Verilog. Derzeit bietet die Firma Lattice den Mico8 in der Ver-sion 3.15 in Verilog und in der Version 3.10 in VHDL an. Der Unterschiedvon Version 3.10 zu 3.15 besteht darin, dass einige generics andere Wertehaben. Das Design zwischen diesen beiden Versionen ist jedoch vollkommengleich.Der Mico8 unterstützt 50 Assembler-Instruktionen. Programme können inAssembler oder in C programmiert werden. Für Assembler wird ein Assem-blierer von Lattice zur Verfügung gestellt. Für C kann der gcc verwendetwerden (eine Portierung auf der Webseite von Lattice ist zum herunterladenverfügbar).

2.2 Mico8 im Überblick [4]

In Abbildung 2 ist ein Blockdiagagramm der Mico8 zu sehen. Zusätzlich isthier eine Übersicht aller Eigenschaften zu sehen:

� 8 Bit breiter Daten-Pfad

� 18 Bit breite Befehle

� Einstellbar entweder 16 oder 32 Register

� externer Speicher (bis zu 4 GB)

� Ein-/Ausgabe über Ports

� 2 oder 3 Taktzyklen pro Befehl

1http://www.latticesemi.com/mico8

3

KAPITEL 2. DIE MICO8-CPU IM ÜBERBLICK 4

Abbildung 2.1: Blockdiagagramm der Mico8 [4]

� groÿe Auswahl an Lattice-Peripherie (zum Beispiel: Timer, GPIO, UART,SPI, I2C)

2.3 Gliederung des Mico8 [4]

Der Mico8 gliedert sich in folgende Bereiche:

� ALU

� Programmspeicher

� Register File

� Programm Flow und Programm Counter

� Hardware Call Stack

� Scratchpad

� Interrupt Vektor

� Interrupt Handling

� Ein-/Ausgabe

In den folgenden Unterkapiteln werden diese Bereiche genauer erläutert.

KAPITEL 2. DIE MICO8-CPU IM ÜBERBLICK 5

2.3.1 ALU

Die ALU der Mico8-CPU kann nur Addieren und Subtrahieren. Diese beidenOperationen können mit und ohne Carry ausgeführt werden. Ein Registerkann auch mit einer Konstante addiert oder subtrahiert werden.

2.3.2 Programmspeicher

Der Programmspeicher ist ein 16 Bit breites ROM, welcher über eine 12 Bitbreite Adressleitung angesprochen werden kann. Die Gröÿe des ROMs kannüber generics bei der Synthese verändert werden.

2.3.3 Register File

Im Register File können 16 oder 32 x 8-Bit-Register (kann über generics beider Synthese ausgewählt werden) angelegt werden. Diese Register sind freibeschreib- und lesbar.

2.3.4 Programm Flow und Programm Counter

Der Programm Flow Block ist für den Ablauf des Programmes zuständig. Ersteuert alle anderen Einheiten der Mico8 und koordiniert das richtige Lesenund Schreiben der Daten.Der Programm Counter speichert die aktuelle Adresse des ROMs.

2.3.5 Hardware Call Stack

Der Call Stack speichert automatisch die nächste Adresse zum Zeitpunkteines call auf den Stack. Bei einem ret wird die letzte Adresse aus dem CallStack in den Programm Counter geladen. Zusätzlich werden auch das Zeround Carry Flag gespeichert.Bei einem Interrupt wird die nächste Adresse auf den Stack gespeichertund gleichzeitig wird in den Programm Counter die Adresse 0x00 geladen(Interrupt-Adresse). Sobald ein iret aufgerufen wird, wird die letzte Adresseaus dem Call Stack in den Programm Counter geladen und von dieser Stelleweiter gearbeitet.Der Stack ist standardmäÿig ein 16 Einträge groÿer Ringspeicher. Dieserkann jedoch über generics bei der Synthese vergröÿert bzw. verkleinert wer-den.

2.3.6 Scratchpad

Das Scratchpad ist ein externer Speicher, den man je nach belieben bei derSynthese über generics vergröÿern oder verkleinern kann. Der Mico8 kannmaximal mit 4 GB arbeiten.

KAPITEL 2. DIE MICO8-CPU IM ÜBERBLICK 6

Die ersten 32 Bytes werden direkt adressiert. Ab 32 Byte wird eine indirekteAdressierung über ein Register verwendet.

2.3.7 Interrupt Vektor

Der Mico8 hat 2 Interrupt-Adressen wie in Tabelle 2.1 zu sehen.

Adresse Funktion

0x00 Externer Interrupt0x01 Reset Interrupt

Tabelle 2.1: Interrupt-Vektoren des Mico8 [4]

Bei einem Reset springt der Mico8 auf die Adresse 0x01. Bei einem externenInterrupt springt der Mico8 auf die Adresse 0x00. Auf dieser Adresse mussentweder ein iret Befehl stehen oder ein Sprung zu einer Programmstelle,die den Interrupt abhandelt und mit einem iret Befehl beendet wird.

2.3.8 Interrupt-Handling

Der Mico8 hat nur eine externe Interrupt-Quelle. Der Interrupt kann ein-oder ausgeschaltet werden mithilfe der Instruktionen cli (= clear interrupt)und sti (= set interrupt).Wenn ein Interrupt beim Controller eintri�t, wird die Adresse des nächstenBefehls sowie Carry und Zero Flag auf den Call Stack gespeichert. Danachspringt der Mico8 auf die Adresse 0x00. Der Interrupt-Bestätigungs-Ausgangwird während der Zeit aktiviert, in welcher sich der Mico8 in der Routinefür das Abarbeiten des Interrupts be�ndet.Mit dem iret-Befehl wird das Abarbeiten des Interrupts wieder beendet. Da-für wird die nächste Adresse, sowie die Flags vom Call Stack zurück geladen,der Interrupt-Bestätigungs-Ausgang wird wieder auf inaktiv zurück gesetzt.Der Mico8 hat nur einen Interrupt-Eingang, es können deswegen keine ge-wichteten Interrupts bearbeitet werden.

2.4 Instruktionen des Mico8 [4]

Insgesamt besitzt der Mico8 50 Instruktionen.6 Befehle werden für logische Operatoren benützt (siehe Tabelle 2.2), dazuzählen und, oder und xor. Diese Befehle verändern jeweils nur das Zero Flag.

KAPITEL 2. DIE MICO8-CPU IM ÜBERBLICK 7

Operation Aktion Flags

AND Rd = Rd & Rb ZeroANDI Rd = Rd & Konstante ZeroOR Rd = Rd | Rb ZeroORI Rd = Rd | Konstante ZeroXOR Rd = Rd xor Rb ZeroXORI Rd = Rd xor Konstante Zero

Tabelle 2.2: Logische Operatoren

Für die arithmetischen Operatoren werden 8 Befehle benützt (siehe Tabelle2.3). Es kann addiert und subtrahiert mit und ohne dem Carry Flag wer-den. Die Addition oder Subtraktion kann entweder mit einer Konstante odermit den zwei Registern Rd und Rb durchgeführt werden. All diese Befehleverändern das Carry und Zero Flag.

Operation Aktion Flags

ADD Rd = Rd + Rb Carry, ZeroADDC Rd = Rd + Rb + Carry Carry, ZeroADDI Rd = Rd + Konstante Carry, ZeroADDIC Rd = Rd + Konstante + Carry Carry, ZeroSUB Rd = Rd - Rb Carry, ZeroSUBC Rd = Rd - Rb - Carry Carry, ZeroSUBI Rd = Rd - Konstante Carry, ZeroSUBIC Rd = Rd - Konstante - Carry Carry, Zero

Tabelle 2.3: Arithmetische Operatoren

Für Vergleiche stehen 4 Befehle zur Verfügung (siehe Tabelle 2.4). Bei zweiBefehlen wird subtrahiert, während bei den beiden anderen eine und -Ope-ration zum Vergleichen verwendet wird.

Operation Aktion Flags

CMP Rd - Rb Carry, ZeroCMPI Rd - Konstante Carry, ZeroTEST Rd & Rb ZeroTESTI Rd & Konstante Zero

Tabelle 2.4: Vergleichs-Operatoren

Alle drei Flags können direkt verändert werden (siehe Tabelle 2.5). Diesgeschieht durch einen Setzbefehl oder durch einen Löschbefehl.

KAPITEL 2. DIE MICO8-CPU IM ÜBERBLICK 8

Operation Aktion Flags

SETI Aktiviert InterruptCLRI Deaktiviert InterruptSETC Setzt Carry CarryCLRC Löscht Carry CarrySETZ Setzt Zero ZeroCLRZ Löscht Zero Zero

Tabelle 2.5: Befehl zum Setzen und Löschen der Flags

Alle Register können nach links oder rechts rotiert werden (siehe Tabelle2.6). Zusätzlich kann auch das Carry Flag mit eingebunden werden.

Operation Aktion Flags

ROR Rd = Rb � 1, Rd(7) = Rb(0) ZeroRORC Rd = Carry:Rb � 1, Carry = Rb(0) Carry, ZeroROL Rd = Rb � 1, Rd(0) = Rb(7) ZeroROLC Rd = Carry:Rb � 1, Rd(0) = Carry Carry, Zero

Tabelle 2.6: Rotations-Operatoren

Ein Register kann auch in ein anderes Register oder von einer Konstantenkopiert werden, dabei werden keine Flags verändert (siehe Tabelle 2.7).

Operation Aktion Flags

MOV Rd = RbMOVI Rd = Konstante

Tabelle 2.7: Verschiebe-Operatoren

Für Verzweigungen (Branches) stehen 5 Befehle zur Verfügung (siehe Ta-belle 2.8). Bei den Verzweigungen werden Programmcounter und Flags nichtgesichert.

KAPITEL 2. DIE MICO8-CPU IM ÜBERBLICK 9

Operation Aktion Flags

B Verzweigt auf eine AdresseBZ Verzweigt auf eine Adresse, wenn Zero aktivBNZ Verzweigt auf eine Adresse, wenn Zero inaktivBC Verzweigt auf eine Adresse, wenn Carry aktivBNC Verzweigt auf eine Adresse, wenn Carry inaktiv

Tabelle 2.8: Verzweigungsbefehle

Die Sprungbefehle (siehe Tabelle 2.9) speichern im Gegensatz zu den Ver-zweigungen die Flags und den Programmcounter auf den Callstack, bei einemRET -Befehl werden die Daten wieder zurück geladen. Bei einem IRET wirdzusätzlich noch das Interrupt-Flag zurückgesetzt.

Operation Aktion Flags

CALL Springt auf eine AdresseCALLZ Springt auf eine Adresse, wenn Zero aktivCALLNZ Springt auf eine Adresse, wenn Zero inaktivCALLC Springt auf eine Adresse, wenn Carry aktivCALLNC Springt auf eine Adresse, wenn Carry inaktivRET Zurück von SprungRETI Zurück von Interrupt

Tabelle 2.9: Sprung-Operationen

Die Speicher-Operationen (siehe Tabelle 2.10) und die Ein-/Ausgabe-Ope-rationen (siehe Tabelle 2.11) speichern Daten in einen externen Speicher.

Operation Aktion Flags

LSP Rd = (sp#)LSPI Rd = (Rb)SSP (sp#) = RdSSPI (Rb) = Rd

Tabelle 2.10: Speicher-Operationen

KAPITEL 2. DIE MICO8-CPU IM ÜBERBLICK 10

Operation Aktion Flags

IMPORT Rd = (Port#)IMPORTI Rd = (Rb)EXPORT (Port#) = RdEXPORTI (Rb) = Rd

Tabelle 2.11: Ein-/Ausgabe-Operationen

2.5 Geprüfte Kon�gurationen der Firma Lattice

Mit der Tabelle 2.12 legt Lattice vier verschiedene Kon�gurationen fest. Mitdiesen Kon�gurationen wurden vier verschiedene Gröÿen des Designs her-ausgefunden. Diese Gröÿenunterschiede sind in Tabelle 2.13 zu sehen.

Kon�guration Beschreibung

1 16 Register, 32-byte Ext. SP, 512 PROM, 8-bit Ext. Adresse2 32 Register, 32-byte Ext. SP, 512 PROM, 8-bit Ext. Adresse3 16 Register, 32-byte Ext. SP, 512 PROM, 16-bit Ext. Adresse4 32 Register, 32-byte Ext. SP, 512 PROM, 16-bit Ext. Adresse

Tabelle 2.12: Möglichen Kon�gurationen des Mico8 [4]

Kon�g. 2 FPGA-Chip LUTs Register SLICEs fmax(MHz)

1LCMXO2-1200HC-5MG132CES 259 62 131 53.4LFE2-50E-5484C 267 63 155 90.2

2LCMXO2-1200HC-5MG132CES 305 62 154 50.8LFE2-50E-5484C 351 65 200 88.0

3LCMXO2-1200HC-5MG132CES 262 70 132 52.3LFE2-50E-5484C 287 71 163 94.6

4LCMXO2-1200HC-5MG132CES 313 70 158 51.7LFE2-50E-5484C 342 73 195 90.5

Tabelle 2.13: FPGA-Verbrauch pro Kon�guration und FPGA [4]

Leider können die Daten aus den Tabellen 2.12 und 2.13 nicht zum Ver-gleich verwendet werden. Es ist nicht genau bekannt, welches Assembler-Programm und welche weiteren Module in dem Synthetisierten Mico8 ver-wendet wurden. Einige Synthesetools verändern sogar den PROM-Speicher,

2Siehe Tabelle 2.12

KAPITEL 2. DIE MICO8-CPU IM ÜBERBLICK 11

da sie dadurch weniger Register und LUTs benötigen. Dadurch sinkt auchdie Chip-Gröÿe des Designs.

Kapitel 3

Testbench

3.1 Allgemein

Es wurde eine Testbench entwickelt, welche das Modell automatisch auf Feh-ler testet. Der Benützer sieht auf einen Blick, ob der Test erfolgreich war oderfehlgeschlagen ist. In der Testbench werden das Original Mico8 Modell unddas neue FSMD Modell verwendet. Die einzelnen Signale werden Takt fürTakt mit dem dazugehörigen Signal des anderen Modells verglichen. SolltenAbweichungen vorkommen, erhöht die Testbench die Anzahl der Fehler umeins und gibt den Fehler aus.Die Firma Lattice stellt bereits 9 Tests zur Verfügung welche für die Test-bench zum Vergleich ein guter Ansatz sind (es werden alle Instruktionen inden 9 Tests verwendet und auf ihre Funktion geprüft). Jeder dieser Testsschreibt am Ende seiner Testreihe den Wert 0xFF in einen IO-Speicher. So-bald dieses Muster erkannt wurde, beendet die Testbench die Simulation undgibt die Fehleranzahl auf der Konsole aus.

3.2 Aufbau der Testbench

Die Testbench ist in mehrere Bereiche unterteilt:

� Einige Konstanten, mit welchen man das allgemeine Verhalten desTests verändern kann

� Mit einigen Signalen kann der Ablauf des Tests überwacht werden

� Zusätzliche Funktionen, welche zum Umwandeln in eine Zeichenkettedienen oder zum Vergleichen von std_ulogic oder std_ulogic_vector

� Instanzierung des FSMD-Modelles und der Original-CPUmit zugehöri-gem Scratchpad und IO-Speicher (Scratchpad und IO-Speicher werdenals einfaches RAM abgebildet)

12

KAPITEL 3. TESTBENCH 13

� Ein groÿer Prozess, der alle Signale vergleicht und Fehler zählt

� Prozess zum Stoppen der Simulation

� Takt-, Rest- und Interrupt-Generator

3.2.1 Konstanten und Signale

cActivateInterrupt: Wenn diese Konstante auf wahr gesetzt wird, wirdnach einer gewissen Zeit ein Interrupt ausgelöst. Der Zeitpunkt kann übercTimeInterrupt de�niert werden.

cTimeInterrupt: Zeitpunkt, zu dem ein Interrupt erfolgen soll.

cClkPeriod: Mit dieser Konstante kann die Taktperiode eingestellt wer-den.

cResetWait: Diese Konstante bestimmt die Zeitdauer des Reset-Vorganges.

cStop: Gibt die Takte an, ab wann ein automatischer Stopp von der Test-bench ausgelöst werden soll, damit bei einem Problem die Simulation auto-matisch nach einer gewissen Zeit beendet wird.

Fehler: In diesem Signal werden die Fehler die bei der Simulation aufge-treten sind gespeichert.

3.2.2 Funktionen

Funktion: to_string

Die Funktion to_string wandelt einen std_ulogic_vector in eine Zeichen-kette um. Diese Zeichenkette wird verwendet, um Fehlermeldungen auf derKonsole zu generieren.

Funktion: analysis_std_ulogic

Die Funktion analysis_std_ulogic vergleicht zwei std_ulogic-Werte mit-einander. Sind die Werte nicht identisch, wird eine Fehlerausgabe auf derKonsole erzeugt. Zusätzlich wird der Fehlerzähler um eines erhöht. Sollteeiner der beiden std_ulogic Werte gleich 'X' sein, wird kein Vergleich vorge-nommen.

KAPITEL 3. TESTBENCH 14

Funktion: analysis_std_ulogic_vector

Die Funktion analysis_std_ulogic_vector vergleicht zwei Werte des Typsstd_ulogic_vector miteinander. Sind beide Werte nicht identisch, wird eineFehlerausgabe auf der Konsole erzeugt. Zusätzlich wird der Fehlerzähler umeines erhöht. Sollte das erste std_ulogic Element einer der beiden Vekto-ren gleich 'X' sein, wird kein Vergleich vorgenommen. Die Funktion analy-sis_std_ulogic_vector verwendet die Funktion to_string um den feh-lerhaften Vektor auf der Konsole auszugeben.

3.2.3 Vergleich der Signale

Der Prozess zum Vergleich der Signale verwendet eine Eigenschaft von VHDL-2008 namens external names [1, S. 559]. Diese Eigenschaft ermöglicht einendirekten Zugri� auf Konstanten, Signale oder Variablen, welche in einer Ar-chitektur unterhalb der Testbench verwendet werden.Als Beispiel wird hier (VHDL-Code weiter unten) die Adresse des PROM-Signales auf eine Variable in einem Prozess zugewiesen. Somit kann lokalin diesem Prozess die Variable benützt werden und der Status der Variable(im Hintergrund des Signales) ausgewertet werden. Dadurch können zweiverschiedene Signale verglichen werden, welche weiter unten im Design zu�nden sind, wie im Beispiel gezeigt (Auszug aus der Testbench).

1 Compare : process(Clk)

2 variable vFehler : integer;

3 variable vCPU1PROMAddr : std_ulogic_vector((12 - 1) downto 0);

4 variable vCPU2PROMAddr : std_ulogic_vector((12 - 1) downto 0);

5 begin

6 vFehler := 0;

7

8 vCPU1PROMAddr := <<signal CPU1.prom_addr : std_ulogic_vector((12 - 1)

downto 0)>>;

9 vCPU2PROMAddr := <<signal CPU2.prom_addr : std_ulogic_vector((12 - 1)

downto 0)>>;

10

11 vFehler := analysis_std_ulogic_vector(vCPU1PROMAddr, vCPU2PROMAddr, "

vCPU1PROMAddr", vFehler);

12

13 Fehler <= Fehler + vFehler;

14 end process;

Sollten die zwei Variablen nicht übereinstimmen, wird die Variable vFehlerum eines in der Funktion analysis_std_ulogic_vector erhöht. Die Va-riable wird am Ende des Prozesses zur aktuellen Fehleranzahl hinzu addiert.

3.2.4 Ende der Simulation

Um das Ende der Simulation zu erkennen, gibt es zwei mögliche Bedingun-gen:

KAPITEL 3. TESTBENCH 15

1. Signal TimeOut (Zähler der bei jedem Takt erhöht wird) ist gröÿer alscStop(siehe Kapitel 3.2.1 auf Seite 13).

2. Signal CPU2ExtIOWrite ist aktiv und der Adressbus CPU2ExtAddr

ist gleich 0xFF.

Sobald eine der beiden Bedingungen erkannt wird, wird die Simulation sofortdurch eine Fehlermeldung [1, S. 87] gestoppt und der dazugehörige Grundauf der Konsole ausgegeben.

3.2.5 Takt-, Reset- und Interruptgenerator

Taktgenerator

Mit der Konstante cClkPeriod kann die Periodenzeit eingestellt werden.

1 Clk <= not Clk after cClkPeriod / 2;

Resetgenerator

Das Resetsignal hat eine negative Logik. Sobald die Simulation startet, wirddas Signal auf '0' gesetzt. Nach der Zeitspanne cResetWait , wird das Re-setsignal auf '1' gesetzt und wird somit inaktiv.

1 Reset : process

2 begin

3 nResetAsync <= '0';

4 wait for cResetWait;

5 nResetAsync <= '1';

6 wait;

7 end process;

Interruptgenerator

Das Interruptsignal wird am Beginn der Simulation inaktiv gesetzt. Danachwird überprüft, ob überhaupt ein Interrupt ausgelöst werden soll. Ist das derFall, wird nach der Zeit cTimeInterrupt das Interruptsignal auf aktiv ge-setzt. Sobald eines der beiden Interrupt-Bestätigungs-Signale aktiviert wird,wird das Interruptsignal wieder auf inaktiv gesetzt.

1 InterruptProc : process

2 begin

3 Interrupt <= '0';

4 if cAtivateInterrupt = true then

5 wait for cTimeInterrupt;

6 Interrupt <= '1';

7 wait on CPU1InterruptAck, CPU2InterruptAck;

8 Interrupt <= '0';

KAPITEL 3. TESTBENCH 16

9 end if;

10 wait;

11 end process;

3.3 Probleme der Testbench

Um das FSMD-Design so gut wie möglich an das Original-Design anzupas-sen, werden bei einer steigenden- und bei einer fallenden-Flanke des Taktsi-gnales alle Werte überprüft die in der Testbench zum prüfen de�niert werden.Das FSMD-Design wurde vom Timing so gut wie möglich an das Original-Design angepasst, jedoch kann dieses nicht vollkommen erfüllt werden. Esgibt vor allem Unterschiede beim Ändern der Flags in bestimmten Befehlen.

Für einen oder zwei Takte ist es möglich, dass das Zero Flag falsch angezeigtwird, obwohl es sich im nächsten Taktzyklus auf den richtigen Wert aktuali-siert. Dieses Verhalten ist jedoch vollkommen in Ordnung, da rechtzeitig vordem Abarbeiten der nächsten Operation die Flags richtig gesetzt werden.

Kapitel 4

Portierung der Mico-CPU

4.1 Ein-/Ausgänge der Mico8-CPU

Die Ein-/Ausgänge der CPU sind bereits durch das Design von Lattice de-�niert und werden nicht verändert:

1 entity isp8_core is

2 generic(

3 PORT_AW : natural := 8;

4 EXT_AW : natural := 8;

5 PROM_AW : natural := 12;

6 PROM_AD : natural := 4096;

7 REGISTERS_16 : boolean := FALSE;

8 PGM_STACK_AW : natural := 4;

9 PGM_STACK_AD : natural := 16

10 );

11 port(

12 clk : in std_ulogic;

13 rst_n : in std_ulogic;

14 ext_mem_din : in std_ulogic_vector(7 downto 0);

15 ext_mem_ready : in std_ulogic;

16

17 ext_io_din : in std_ulogic_vector(7 downto 0);

18 intr : in std_ulogic;

19 ext_addr : out std_ulogic_vector((EXT_AW - 1) downto 0);

20 ext_addr_cyc : out std_ulogic;

21 ext_dout : out std_ulogic_vector(7 downto 0);

22 ext_mem_wr : out std_ulogic;

23 ext_mem_rd : out std_ulogic;

24

25 ext_io_wr : out std_ulogic;

26 ext_io_rd : out std_ulogic;

27 intr_ack : out std_ulogic);

28 end isp8_core;

Viele der generics von Lattice werden im neuen Design nicht mehr benützt.Die Datenbreite wird �x auf 8 Bit gesetzt, zusätzlich sind keine Page Pointer

17

KAPITEL 4. PORTIERUNG DER MICO-CPU 18

verfügbar. Die PROM Gröÿe wird automatisch aus dem generierten VHDL-Code gesetzt.

clk Takteingang, es werden bei steigender Flanke Daten übernommen odergesetzt

rst_n Reseteingang (low-aktiv), setzt alle Register zurück

ext_mem_din Dateneingang des externen Speichers

ext_mem_ready ist aktiv wenn externer Speicher bereit ist (wird in demneuen Design nicht überprüft!)

ext_io_din Dateneingang des I/O-Speichers

intr Interrupt-Leitung

ext_addr Adresse für externen Speicher und I/O-Speicher

ext_addr_cyc Dient zum Stoppen der CPU bei Lese- und Schreib-Zyklen(wurde im neuen Design nicht mehr benützt)

ext_dout Datenausgang für externen Speicher und IO-Speicher

ext_mem_wr aktiv, wenn im externen Speicher gespeichert wird

ext_mem_rd aktiv, wenn vom externen Speicher gelesen wird

ext_io_wr aktiv, wenn I/O-Speicher speichern soll

ext_io_rd aktiv, wenn vom I/O-Speicher gelesen wird

intr_ack Interrupt wurde von der CPU bestätigt

4.2 Vorbereitung

Als Vorbereitung mussten alle Speicher (RAM, ROM) gegen Speicher dieselber in VHDL modelliert wurden ausgetauscht werden. Dies dient als Basis,ein exaktes Model der Speicher wie von der original Mico8-CPU zu haben.Zusätzlich sind die Modelle bei Simulationen besser auszulesen als generierteModelle von Lattice.

KAPITEL 4. PORTIERUNG DER MICO-CPU 19

Als einfache Möglichkeit wurde ein gemeinsames Dateiformat gesucht wel-ches die Daten des ROMs beinhaltet, dass von jedem Simulationstool so-wie von jedem Sythesetool verwendet werden kann. Altera verwendet dabeidas Intel-Hex-Format oder das MIF1-Format. Lattic hingegen baut auf einASCII-Hex/Binär-Format und auf ein Adressbasiertes-Hex-Format auf. So-mit sind bei den wichtigsten 2 Tools keine Überlappungen vorhanden und esmusste eine einfache eigene Lösung gefunden werden.Es wurden hierzu verschiedene Typen von ROMs entwickelt. Dabei sollte esauch möglich sein, dass sich das ROM so einfach wie möglich realisieren undbedienen lässt.

4.2.1 Generisches ROM

Das generische ROM wird über eine generic constant mit Daten versorgt.Ein Beispiel einer Entity mit generischen Daten:

1 entity Rom is

2 generic (

3 PROM_DATA: tRamData := ("111011000000000001", "010000000000000000",

"010010000000000000", "010010000100000000", others => (others =>

'0'))

4 );

5 port (

6 iClk : in std_ulogic;

7 iAddr : in std_ulogic_vector(11 downto 0);

8 oData : out std_ulogic_vector(17 downto 0)

9 );

10 end entity Rom;

Diese generischen Daten können im VHDL-Code de�niert werden, wie imBeispiel zu sehen.Questasim stellt eine Möglichkeit generics die, die Datentypen wie zumBeispiel Boolean und std_ulogic beim Kompilieren verändert können. Beistd_ulogic_vector hat Questasim jedoch Probleme und stellt dies nicht zurVerfügung. Leider wird dadurch auch der gesamte dynamische Ablauf dererho�t wurde (Programmdaten können erst später eingereicht werden) aus-geschaltet. Durch dieses Problem wurde diese Art von ROM nicht verwendet.

4.2.2 Dateiauslesendes ROM

Als eine weitere Möglichkeit wurde überlegt, ein Design zu scha�en, welcheseine ASCII-Hex Datei auslesen kann und die ausgelesenen Werte für denROM-Speicher verwendet (siehe Anhang A.1). Dieses Design kann direkt dieASCII-Hex Dateien auslesen, die von dem Assembler-Programm von Latticgeneriert werden. In der Simulation war ein Test erfolgreich und zeigte auch

1Memory Initialization File

KAPITEL 4. PORTIERUNG DER MICO-CPU 20

eine einfache Bedienbarkeit, da der Dateiname leicht über ein generic geän-dert werden kann. Jedoch stellen viele Synthesetools keine Datei-Operationenin VHDL zur Verfügung, darunter fällt auch Altera Quartus. Nachdem dasDesign jedoch mit jedem Synthesetool kompatibel werden soll, war dies auchkeine Option zur Benützung des ROMs.

4.2.3 Selbst generiertes ROM

Die einfachste Lösung, welche für alle Simulations- und Synthesetools funk-tioniert ist, für jedes neue Mico8-Programm eine eigene ROM-Datei zu ge-nerieren.Dafür wurde ein Tool in C++ entwickelt, welche Zeile für Zeile die ASCII-Hex Dateien des Assemblers ausliest und damit ein ROM in VHDL erzeugt.Diese Datei muss nur noch beim Simulieren/Kompilieren des Designs ange-geben werden.Leider ist dadurch kein dynamisches Auswechseln der Daten mehr möglich,jedoch ist diese Art des ROM-Speichers für die Simulation und die Synthesedie einfachste und für alle Tools kompatibel. Baut man die Ordnerstrukturgut auf, ist es auch möglich mit nur wenigen Befehlen eine neue Simulationoder eine Synthese mit den neu generierten ROM-Daten zu starten.

4.2.4 RAM

Es wurde ein RAM-Design erstellt (siehe Anhang A.2). Die Adressleitungwird über ein Adressregister geführt, welches bei einer steigenden Flankeaktualisiert wird. Werden die Daten im Adressregister geändert, werden auchdie Daten des RAMs auf den Ausgang gelegt. Ein Schreibvorgang wird nurbei aktiver Schreib-Leitung und einer steigenden Flanke des Taktes erfolgen.

4.3 FSMD-Implementation

Zur Übersicht wurde die Implementation aufgeteilt auf mehrere Bereiche:

� Decodieren der Operationen

� ALU

� FSMD Prozess

� Call Stack

Die Reihenfolge der Unterkapitel beschreibt auch das Vorgehen der Imple-mentation.

KAPITEL 4. PORTIERUNG DER MICO-CPU 21

4.3.1 Decodieren der Operationen

Da ein direktes Decodieren der Operationen im FSMD-Prozess sehr unüber-sichtlich ist, wurde ein eigenes Design für das Decodieren angefertigt. Eswurden dabei die verschiedenen Operationen verglichen und drei Bit-Maskenerstellt. Es gibt eine Haupt-Bit-Maske, welche zwischen allen wichtigen Ope-rationen unterscheiden kann. Bei einigen Operationen kann jedoch nicht al-leine mit dieser Maske unterschieden werden, deswegen werden noch zweiweitere Masken (Register- oder Konstanten-Maske) verwendet mit welchernun auch zwischen den restlichen Operationen unterschieden werden kann.Es wurde ein enumerated Type de�niert, welcher alle Operationen beinhal-tet, die der Mico8 beherrscht. Dieser Typ wird aus dem Decoder-Designausgegeben und im FSMD-Prozess verwendet. Zusätzlich ist dieser Typ sehrhilfreich bei der Simulation und somit auch bei der Fehlersuche, da jederzeitersichtlich ist, welche Operation gerade ausgeführt wird.

4.3.2 ALU

Da die ALU meist sehr aufwendig in der Hardware realisiert wird, wurdediese in ein eigenes Design ausgelagert. Somit kann man sicher gehen, dassnur eine ALU bei der Synthese initiiert wird.Die neue ALU kann addieren und subtrahieren sowohl mit und ohne Carry.Sie besteht aus zwei Prozessen und dem Addierwerk. Der erste Prozess er-zeugt die richtigen Daten für das Addierwerk (2er-Komplementbildung fürSubtraktion oder Datenweitergabe für Addition).

1 process (iAddSub, iRb, iCarry)

2 begin

3 if iAddSub = sub then

4 if iCarry = '1' then

5 Rb_Adder <= std_ulogic_vector(unsigned(not(iRb)));

6 carry <= not(iCarry);

7 else

8 Rb_Adder <= std_ulogic_vector(unsigned(not(iRb)) + 1);

9 carry <= iCarry;

10 end if;

11 else

12 Rb_Adder <= iRb;

13 carry <= iCarry;

14 end if;

15 end process;

16

17 sub_aktiv <= '1' when (Rb_Adder(Rb_Adder'high) = '1' and iAddSub = sub)

else '0';

Der zweite Prozess liest den Carry-Wert in Abhängigkeit davon ob subtra-hiert oder addiert wird aus und gibt diesen zurück.

1 process (adder_tmp, iAddSub)

2 begin

KAPITEL 4. PORTIERUNG DER MICO-CPU 22

3 if iAddSub = sub then

4 oCarry <= std_ulogic(adder_tmp(adder_tmp'high));

5 else

6 oCarry <= std_ulogic(adder_tmp(adder_tmp'high));

7 end if;

8 end process;

Das Addierwerk benützt die erzeugten Werte aus dem ersten Prozess, addiertdiese und schreibt die Daten auf den Ausgang oData.1 adder_tmp <= (unsigned('0' & iRd & '1')) + (unsigned(sub_aktiv &

Rb_Adder & carry));

2 oData <= std_ulogic_vector(adder_tmp(adder_tmp'high - 1 downto

adder_tmp'low + 1));

4.3.3 FSMD Prozess

Die FSMD ist wie ein typisches Register aufgebaut (Beispiel):

1 p1 : process (clk, rst_n)

2 begin

3 if rst_n = '0' then

4 R <= isp8_register_res_c;

5 elsif rising_edge(clk) then

6 R <= NextR;

7 end if;

8 end process p1;

9

10 p2 : process (R, instDec)

11 begin

12 NextR <= R;

13 if R.Cycle = Sreset then

14 NextR.Cycle <= S1;

15 else

16 case instDec is

17 when ADD_op =>

18 do_add_thing();

19 when others =>

20 null;

21 end case;

22 end if;

23 end process p2;

Die Reset-Konstante isp8_register_res_c ist im Paket isp8_pack de�niertund enthält alle wichtigen De�nitionen, die bei einem Reset gesetzt werdenmüssen.

Allgemeiner Ablauf

Zu Beginn des zweiten Prozesses (Prozess p2) werden alle typischen Wertefür die einzelnen Register gesetzt, dies verhindert ein unübersichtliches Set-zen von Registern im Ablauf des Prozesses. Standardmäÿig werden dieseRegister, wie in Tabelle 4.1 zu sehen, vorbelegt.

KAPITEL 4. PORTIERUNG DER MICO-CPU 23

Abbildung 4.1: Statusdiagramm mit allen Zyklen

Registername Registerde�nition Status

oEnablePROM Lesen des PROMs deaktiviertoWriteRD Register Rd schreiben deaktiviertoALUCarry Carry für die ALU deaktiviertoALUAddSub de�niert ob die ALU Addiert oder Subtrahiert AddierenoPop Auslesen des letzten Wertes des Stacks deaktiviertoExtMemWr Externer Speicher wird beschrieben deaktiviertoExtMemRd Externer Speicher wird gelesen deaktiviertoExtIOWr Externer IO-Speicher wird beschrieben deaktiviertoExtIORd Externer IO-Speicher wird gelesen deaktiviert

Tabelle 4.1: Registerinitialisierung im zweiten Prozess der FSMD

Wird ein Reset ausgelöst, wird noch ein Zyklus abgewartet, erst danach wirdder erste Befehl ausgeführt.Danach wird über eine groÿe case-Abfrage überprüft, welche Operation aus-geführt werden soll.Nähere Informationen zu den Operationen �ndet man im Kapitel 2.4 undden nachfolgenden Kapiteln.Ein Statusdiagramm mit allen Zyklen ist in Abbildung 4.1 zu sehen.

Operationen mit 2 Zyklen

Erster Zyklus: Der erste Zyklus dient zum Auslesen des PROMs für dienächste Operation, sowie das Setzen des Schreib-Flags zum Schreiben derDaten in das Rd-Register. Zusätzlich wird auch bei Instruktionen, in wel-chen das Carry-Flag verändert wird, der Carry-Wert der ALU ausgelesenund in das Carry-Flag gespeichert (Ausnahme sind die Vergleichsoperatio-nen, bei denen das Carry-Flag erst im zweiten Zyklus aktualisiert wird).Sollte die Instruktion eine Konstante beinhalten, wird ein Immediate-Flaggesetzt, welcher der ALU die Konstante auf den Eingang Rb legt. Bei denSubtraktionsoperationen wird im ersten Zyklus die ALU auf Subtraktionumgestellt. Bei den Verzweigungs-Operationen und den Sprung-Operatoren

KAPITEL 4. PORTIERUNG DER MICO-CPU 24

wird die neue Adresse im ersten Zyklus berechnet und um eins verkleinert inden Programmcounter gespeichert, da im zweiten Zyklus die Adresse wiederum eins erhöht wird. Werden neue Daten auf den Call Stack abgelegt oderabgerufen, werden die dazugehörigen Flags gesetzt. Auf den ersten Zyklusmuss immer der zweite folgen.

Zweiter Zyklus: Im zweiten Zyklus wird der Programmcounter um eineserhöht. Sollte die Operation das Zero-Flag verändern, geschieht das in diesemZyklus. Auch die Daten der ALU werden zum Eingang des Rd-Registersgeführt. Bei Operationen, die nicht durch die ALU berechnet werden (AND,OR, XOR, ...), werden die Daten direkt im zweiten Zyklus berechnet undzum Vergleich für das Zero-Flag und für das Register Rd verwendet. Nachdem zweiten Zyklus folgt wieder der erste Zyklus einer neuen Operation,diese kann unabhängig von der vorherigen zwei oder drei Zyklen haben.

Operationen mit 3 Zyklen

Nur die Operationen IMPORT, IMPORTI, EXPORT, EXPORTI, LSP, LSPI,SSP und SSPI dauern 3 Zyklen lang. Alle anderen Operationen verwendennur 2 Zyklen.

Erster Zyklus: Der erste Zyklus liest die Daten aus den Registern, damitsie im zweiten Zyklus aus der CPU ausgegeben werden können. Auch dasFlag zum Lesen oder Schreiben des externen Speichers wird gesetzt. Danachfolgt der zweite Zyklus.

Zweiter Zyklus: Der zweite Zyklus ähnelt dem ersten Zyklus einer Ope-ration mit zwei Zyklen. Das PROM wird gelesen, und auch das Flag zumAktivieren des Rd-Registers wird gesetzt. Zusätzlich werden die Adresslei-tungen und Datenleitungen mit den Daten aus den Registern gesetzt.

Dritter Zyklus: Im dritten Zyklus wird der Programmcounter um eins er-höht. Zusätzlich werden die Daten des externen Speichers in das Rd-Registergespeichert, sofern die Daten gespeichert werden sollen. Nach dem drittenZyklus folgt wieder der erste Zyklus einer neuen Operation.

4.3.4 Call Stack

Der Call Stack ist intern als ein Ring-Bu�er implementiert. Sollte der CallStack voll sein, werden alte Elemente überschrieben. Dadurch gehen ältereEinträge verloren und das Programm wird ein Problem beim abarbeitenbekommen. Sollte es einmal vorkommen, dass ein Programm einen gröÿerenCall Stack braucht, ist dies einfach durch Ändern eines generics möglich. Die

KAPITEL 4. PORTIERUNG DER MICO-CPU 25

CPU-Architektur wird davon nicht beein�usst, da der Call Stack gekapseltin einem Design ist.Der Call Stack speichert den Programmcounter und die aktuell berechne-ten Carry und Zero Flags. Hierbei ist zu beachten, dass nicht die Carry-und Zero-Register gespeichert werden, sondern die aktuell berechneten Flags.Dieser Unterschied kostete einige Stunden an Simulation und Durchsuchendes Original-Codes, denn normalerweise werden die aktuellen Register ge-speichert und nicht nur die aktuell berechneten Flags. Zusätzlich warenkeine Informationen von Lattice über dieses Verhalten verfügbar, obwohldie Kenntnis dieses Zusammenhangs auch für die Programmierung wichtigwäre.

4.3.5 Interrupts

Interrupts werden bei der Mico8-CPU, nicht wie zu Beginn dieser Arbeitgedacht, durch einen eigenen Befehl ausgeführt, sondern werden parallel zueinem Befehl gestartet.

Wenn zum Beispiel ein Interrupt ausgelöst wird, wobei der nächste Befehleinmovi -Befehl für die CPU ist, würde die CPU denmovi -Befehl natürlichausführen. Jedoch würde sich die CPU parallel auf den Interrupt vorbereiten.Nach dem Abhandeln des Befehles springt die CPU auf die Adresse 0x00und widmet sich dem Interrupt. Wird der Interrupt durch einen iret-Befehlbeendet, springt die CPU wieder zurück auf den Befehl, welcher nach demmovi -Befehl folgt.

Dieses Vorgehen funktioniert auch bei Befehlen die drei Zyklen haben. Jedochstartet das Abhandeln des Interrupts erst im zweiten Zyklus und nicht imersten.Bei Sprungbefehlen wird hingegen kein Interrupt ausgelöst, stattdessen wirdzunächst der Befehl ausgeführt, da der Call Stack durch den Sprungbefehlblockiert ist. Erst danach wird der Interrupt abgehandelt.

Kapitel 5

Module der Mico8-CPU

5.1 GPIO

Mit dem GPIO-Modul können GPIOs1 auf einfache Weise erstellt werden.Das Modul kann einzelne Pins zur Laufzeit als Eingang oder Ausgang de�-nieren. Für den Anschluss von Tastern können auch Pull-Ups aktiviert wer-den. Das Design des GPIO-Moduls ist sehr ähnlich zu dem der AtMegaController [2, S. 52]. GPIO-Module können auch Interrupts auslösen. Diesewerden bei steigender oder fallender Flanke am Pin aktiviert. In der aktuel-len Version des Moduls wurde jedoch keine Implementierung der Interruptsdurchgeführt.

5.1.1 Ein-/Ausgänge des Moduls

1 entity isp8_gpio is

2 generic(

3 DW : natural := 8

4 );

5 port(

6 clk : in std_ulogic;

7 rst_n : in std_ulogic;

8

9 cpu_in_data : in std_ulogic_vector((DW - 1) downto 0);

10 cpu_out_data : out std_logic_vector((DW - 1) downto 0);

11 reg_addr : in std_ulogic_vector(2 downto 0);

12 cpu_read : in std_ulogic;

13 cpu_write : in std_ulogic;

14

15 cs : in std_ulogic;

16 interrupt : out std_ulogic;

17

18 pin : inout std_logic_vector((DW - 1) downto 0)

19 );

1General Purpose Input/Output

26

KAPITEL 5. MODULE DER MICO8-CPU 27

20 end isp8_gpio;

Wie im VHDL Code zu sehen, besitzt das Modul mehrere Ein- und Ausgänge,welche verwendet werden müssen:

clk Takteingang, es werden bei steigender Flanke Daten übernommen odergesetzt

rst_n Reseteingang (low-Aktiv), Setzt alle Register zurück

cpu_in_data Dateneingang, Daten von der CPU

cpu_out_data Datenausgang, Daten für die CPU

reg_addr Registeradresse zum Lesen oder Schreiben

cpu_read Wenn aktiv, wird von dem ausgewählten Register gelesen

cpu_write Wenn aktiv, wird auf das ausgewählte Register geschrieben

cs ChipSelect, wenn aktiv, werden die Lese- und Schreib-Leitungen über-wacht und darauf reagiert

interrupt wird aktiv gesetzt wenn ein Interrupt auf einen Pin erfolgt, derals Interrupt-Pin aktiviert wurde

pin Pins als Ein-/Ausgang des Chips

5.1.2 Register

Das GPIO-Modul hat sechs Register:

0x000 - Datenrichtung

Das Register auf der Adresse 0x000 beschreibt die Datenrichtung der einzel-nen Pins. Ist ein Bit aktiviert, ist dieser Pin als Ausgang gesetzt. Sollte dasBit jedoch inaktiv sein, ist dieser Pin als Eingang de�niert.Dieses Register kann gelesen und beschrieben werden.

KAPITEL 5. MODULE DER MICO8-CPU 28

0x001 - Datenausgang

Das Register auf der Adresse 0x001 beschreibt ob die einzelnen Pins gesetztoder nicht gesetzt sind. Ist ein Pin als Ausgang de�niert, wird der Wertdes Registers direkt auf den Ausgang des Chips übertragen. Wird dieses Bitaktiv gesetzt, wird auch der Pin am Chip aktiv gesetzt, ist dieses Bit inaktiv,wird auch der Pin inaktiv gesetzt.Ist der Pin als Eingang de�niert, wird beim zugehörigem aktivem Bit desRegisters 0x001 ein Pullup aktiviert. Sollte das Bit inaktiv sein, wird derPin hochohmig geschaltet.Dieses Register kann gelesen und beschrieben werden.

0x010 - Interrupt aktivieren

Das Register auf der Adresse 0x010 beschreibt das Aktivieren eines Inter-rupts auf einzelne Pins. Wird eine Bit aktiv gesetzt, wird ein Interrupt aus-gelöst sobald die nötigen Voraussetzungen erfüllt sind (siehe Register 0x011).Dieses Register kann gelesen und beschrieben werden, wurde in der aktuellenVersion jedoch nicht implementiert.

0x011 - Interrupt�anke

Mit dem Register auf der Adresse 0x011 kann beschrieben werden, in welcherArt ein Pin sich ändern muss, damit ein Interrupt ausgelöst wird. Wird einBit aktiv gesetzt, wird ein Interrupt ausgelöst wenn eine steigende Flankeerkannt wurde. Ist das Bit inaktiv, wird ein Interrupt ausgelöst wenn einefallende Flanke erkannt wurde.Dieses Register kann gelesen und beschrieben werden. Wurde in der aktuellenVersion jedoch nicht implementiert.

0x100 - Aktuelle Werte der Pins

Mit diesem Register auf der Adresse 0x100 können die aktuellen Werte derPins ausgelesen werden. Es werden sowohl Ausgänge als auch Eingänge ge-lesen.Dieses Register kann nur gelesen werden.

0x101 - Interruptquelle

Aus dem Register auf der Adresse 0x101 kann die Interruptquelle ausgele-sen werden, welcher Pin den aktuellen Interrupt ausgelöst hat. Es könnenmehrere Pins zur gleichen Zeit einen Interrupt auslösen, das GPIO Modulerkennt jedoch nicht, welcher Interrupt gerade die CPU veranlasst hat dieInterrupts zu überprüfen. Wenn von diesem Register gelesen wird, werdenalle Interrupts rückgesetzt und erst wieder aktiv, wenn eine entsprechendeÄnderung am Pin vorgefallen war.

KAPITEL 5. MODULE DER MICO8-CPU 29

Dieses Register kann nur gelesen werden, wurde in der aktuellen Versionjedoch nicht implementiert.

5.2 Vorteiler / Taktteiler

Dieses Modul teilt den Takteingang durch 8, 16, 32, 64, 128, 265, 512, 1024oder 2048. Die Ausgänge können zum Beispiel für den Timer verwendetwerden. Der Timer ist im Kapitel 5.3 beschrieben.

5.2.1 Ein-/Ausgänge des Moduls

1 entity isp8_clk_prescale_all is

2 port(

3 clk : in std_ulogic;

4 rst_n : in std_ulogic;

5

6 prescale8 : out std_ulogic;

7 prescale16 : out std_ulogic;

8 prescale32 : out std_ulogic;

9 prescale64 : out std_ulogic;

10 prescale128 : out std_ulogic;

11 prescale256 : out std_ulogic;

12 prescale512 : out std_ulogic;

13 prescale1024 : out std_ulogic;

14 prescale2048 : out std_ulogic

15 );

16 end isp8_clk_prescale_all;

Wie im VHDL-Code zu sehen, besitzt das Modul mehrere Ein- und Aus-gänge, welche verwendet werden müssen:

clk Takteingang, es werden bei steigender Flanke Daten übernommen odergesetzt

rst_n Reseteingang (low-Aktiv), Setzt alle Register zurück

prescaleX Vorteiler-Ausgang der das Taktsignal X mal teilt

5.3 16-Bit-Timer

Dieses Modul besteht aus einen 16-Bit-Timer. Diesem Timer kann man einenTop-Wert über ein Register mitteilen. Sobald dieser Top-Wert erreicht ist,wird ein Interrupt ausgelöst und der Timer startet wieder automatisch bei 0.Die Interrupt-Leitung ist so lange aktiv, bis das Status-Register ausgelesenwird. Der Timer kann Vorteiler benützen (1, 8, 16, 32, 64, 128, 256, 1024,2048), diese Vorteiler müssen auÿerhalb des Timers initiiert werden (Vorteiler

KAPITEL 5. MODULE DER MICO8-CPU 30

kann somit für mehrere Timer verwendet werden). Ein passender Vorteilerkann im Kapitel 5.2 gefunden werden. Dieses Design ist sehr ähnlich demDesign einiger AtMega-Controller im CTC2-Modus [2, S. 87].

5.3.1 Ein-/Ausgänge des Moduls

1 entity isp8_timer16 is

2 port(

3 clk : in std_ulogic;

4 rst_n : in std_ulogic;

5

6 cpu_in_data : in std_ulogic_vector(7 downto 0);

7 cpu_out_data : out std_logic_vector(7 downto 0);

8 reg_addr : in std_ulogic_vector(2 downto 0);

9 cpu_read : in std_ulogic;

10 cpu_write : in std_ulogic;

11

12 cs : in std_ulogic;

13 interrupt_out : out std_ulogic;

14

15 prescale8 : in std_ulogic;

16 prescale16 : in std_ulogic;

17 prescale32 : in std_ulogic;

18 prescale64 : in std_ulogic;

19 prescale128 : in std_ulogic;

20 prescale256 : in std_ulogic;

21 prescale512 : in std_ulogic;

22 prescale1024 : in std_ulogic;

23 prescale2048 : in std_ulogic

24 );

25 end isp8_timer16;

Wie im VHDL-Code zu sehen, besitzt das Modul mehrere Ein- und Aus-gänge, die verwendet werden müssen:

clk Takteingang, es werden bei steigender Flanke Daten übernommen odergesetzt

rst_n Reseteingang (low-Aktiv), Setzt alle Register zurück

cpu_in_data Dateneingang, Daten von der CPU

cpu_out_data Datenausgang, Daten für die CPU

reg_addr Registeradresse zum Lesen oder Schreiben

2Clear Timer on Compare

KAPITEL 5. MODULE DER MICO8-CPU 31

cpu_read Wenn aktiv, wird von dem ausgewählten Register gelesen

cpu_write Wenn aktiv, wird auf das ausgewählte Register geschrieben

cs ChipSelect, wenn aktiv, werden die Lese- und Schreib-Leitungen über-wacht

interrupt wird aktiv gesetzt, wenn ein Interrupt des Timers aktiviert wird

Folgende Vorteiler-Eingänge können verwendet werden:

prescaleX Vorteiler-Eingang der X mal langsamer als der Takt ist

5.3.2 Register

Das Timer-Modul hat 3 Register:

0x000 - Top-Wert (unteren 8 Bits)

In diesem Register können die unteren 8 Bits des Top-Wertes gesetzt werden.Der Top-Wert wird bei einem Reset auf 0xFFFF gesetzt.Dieses Register kann gelesen und beschrieben werden.

0x001 - Top-Wert (oberen 8 Bits)

In diesem Register können die oberen 8 Bits des Top-Wertes gesetzt werden.Der Top-Wert wird bei einem Reset auf 0xFFFF gesetzt.Dieses Register kann gelesen und beschrieben werden.

0x010 - Status-Register

Bit 0 - Wenn aktiv, ist der Timer eingeschaltet (kann geschrieben und gele-sen werden)Bit 1 - Wird aktiv, wenn ein Interrupt ausgelöst wurde (kann nur gelesenwerden)

In Tabelle 5.1 ist ersichtlich welche Bits für die jeweiligen Vorteiler benütztwerden müssen. Diese Bits können geschrieben und gelesen werden.

KAPITEL 5. MODULE DER MICO8-CPU 32

Bit 2 Bit 3 Bit 4 Bit 5 Vorteiler

0 0 0 0 10 0 0 1 80 0 1 0 160 0 1 1 320 1 0 0 640 1 0 1 1280 1 1 0 2650 1 1 1 5121 0 0 0 10241 0 0 1 2048

Tabelle 5.1: Vorteiler des Timers

Die restlichen Bits dieses Registers verändern den Timer in keiner Weise undkönnen somit auf '0' oder '1' gesetzt werden.

Kapitel 6

Programmieren derMico8-CPU

6.1 Assembler

Will man ein sehr schnelle Programm programmieren, ist ein Programm inAssembler meist besser als ein C-Programm. Weitere Informationen könnenaus [4, ab S. 20] bezogen werden.

6.2 C

Die Mico8-CPU kann nicht nur in Assembler sondern auch in C programmiertwerden.

6.2.1 Vorbereitung

Es wird von der Firma Lattice bereits eine Cygwin Installation zum Program-mieren in C bereitgestellt. Dazu muss die Setup-Datei von der Webseite derFirma Lattice heruntergeladen und installiert werden1.Nach der Installation kann über das Startmenü die LatticeMico System Cyg-

win Shell aufgerufen werden. Cygwin ist eine Unix-Umgebung in Windows.Weiter Informationen �nden man auf der Webseite von Cygwin [3].Der Compiler liest C-Code ein und gibt die Binary-Daten im elf-Formatwieder aus. Das elf-Format ist jedoch nicht kompatibel zu den PROM-Erstellungs-Werkzeugen und muss daher noch einmal durch ein Scipt in dasASCII-Hex-Format umgewandelt werden. Abhilfe scha�t hier ein Perl-Scriptnamens lm8-deployer.pl 2.

1Als Installationsordner wird zum Beispiel C:/Mico8 empfohlen. Die Daten solltennicht unter den Programm-Ordnern vonWindows installiert werden, da es dort bei neuerenWindowsversionen zu Rechteproblemen kommen kann.

2Leider vergaÿ Lattice beim Erstellen der Installation das Script lm8-deployer.pl an

33

KAPITEL 6. PROGRAMMIEREN DER MICO8-CPU 34

6.2.2 Kompilieren

Zum Kompilieren muss folgender Befehl in der Cygwin-Umgebung eingege-ben werden:$ lm8-elf-gcc -O0 -o main.elf main.c

In diesem Beispiel heiÿt die C-Datei main.c. Ausgegeben wird die Dateimain.elf im elf-Format. Der Zusatz von -O0 ist gegen Optimierungen wich-tig, da meist nach einer Optimierung als Ergebnis ein falsches Verhalten alszuvor auftritt.Mit folgendem Befehl kann die elf-Datei in das ASCII-Hex-Format überführtwerden:$ lm8-deployer.pl main.elf

Danach wird die so erstellte ASCII-Hex-Datei in ein VHDL-PROM mit demC++ Programm aus Kapitel 4.2.3 überführt und kann in das Design einge-bunden werden.

6.2.3 Zusätzliche C-Funktionen

Zusätzlich zu den normalen C-Konstruktionen (if, for, while, ...) gibt es spe-ziell für die Mico8-CPU zwei weitere Funktionen:

__builtin_export dient zum Exportieren von Daten in ein IO-Register(Compiler sucht sich aus, ob EXPORT oder EXPORTI verwendet wird)

__builtin_import dient zum Importieren von Daten aus einem IO-Register (Compiler sucht sich aus, ob IMPORT oder IMPORTI verwen-det wird)

6.2.4 Interrupt-Funktion

Um eine Interrupt-Funktion in C deklarieren zu können, muss zuerst eineFunktionsdeklaration angelegt werden. Dieser muss genau so wie gezeigt aus-sehen:

1 void __IRQ (void) __attribute__ ((interrupt));

Danach kann die Interrupt-Funktion angelegt werden:

1 void __IRQ(void)

2 {

3 return;

4 }

den richtigen Ort zu kopieren. Deswegen muss es händisch von �scripts� nach �cygwin\bin�verschoben werden. Zusätzlich muss die erste Zeile der Datei gelöscht werden, wodurch inder ersten Zeile �#!/usr/bin/perl -w� zu sehen ist.

KAPITEL 6. PROGRAMMIEREN DER MICO8-CPU 35

Die Funktion und die Funktionsdeklaration müssen genau so, wie gezeigt,benannt werden. Sollte dies nicht eingehalten werden, wird die Interrupt-Funktion nicht der Interruptquelle zugeordnet und stattdessen als normaleFunktion implementiert.

6.2.5 Register Tabelle für die SandboxX

Für eine bessere Übersicht, wurde eine Header-Datei mit allen wichtigenRegisterwerten für die SandboxX angelegt. Diese Datei ist auf der CD zu�nden.

Kapitel 7

Mico8-CPU auf der SandboxX

7.1 Allgemein

Der Test auf der SandboxX wurde relativ einfach gehalten. Es wurden 3GPIO- so wie 2 Timer-Module verwendet. Ein GPIO-Modul (PortA) wurdean den LEDs angeschlossen. Ein weiteres GPIO-Modul (PortB) wurde anden Tastern angeschlossen. Das letzte Modul (PortC) wird für die Auswahlder LED-Reihe oder der 7-Segmentanzeige verwendet. Zusätzlich be�ndetsich noch ein 256 Byte groÿes RAM im Design. Es kann über die Single-Step-Taste ein externer Interrupt ausgelöst werden.

7.2 Ein-/Ausgänge des Top-Level-Designs

1 port(

2 clk : in std_ulogic;

3 rst_n : in std_ulogic;

4

5 PORTA : inout std_logic_vector(7 downto 0);

6 PORTB : inout std_logic_vector(7 downto 0);

7 PORTC : inout std_logic_vector(7 downto 0);

8

9 EXT_INT : in std_ulogic

10 );

clk Takteingang, kommend vom Taktgenerator mit 50MHz

rst_n Reseteingang (low-Aktiv), kommend vom Resettaster

PORTA Port A, Ausgang auf die 7 Segmente bzw. 7 LEDs

PORTB Port B, Eingänge der 6 Taster von Bit 0 bis 5, auf Bit 6 ist dieRXD- und auf Bit 7 die TXD-Leitung

36

KAPITEL 7. MICO8-CPU AUF DER SANDBOXX 37

PORTC Port C, Ausgang der die 7-Segmentanzeigen oder die zwei LED-Reihen (drei unteren Bits) auswählen kann. Mit den fünf oberen Bits könnendie Servo-Ausgänge angesteuert werden

EXT_INT Externer-Interrupt-Eingang

7.3 Module

7.3.1 GPIO-Module im Design

Die GPIO-Module wurden noch einmal in den Adressen geteilt. Sind dieoberen fünf Bits der Adresse gleich 0b00000, wird das GPIO-Modul A ange-sprochen. Sind sie jedoch 0b00001 reagiert das Modul B. Das GPIO ModulC kann über die Adresse 0b00010 benützt werden. Diese Auswahl wird übereinige ChipSelect-Leitungen realisiert. Die GPIOs können über IO-Befehleder Mico8-CPU angesprochen werden. Sollte ein oder mehrere Interruptserfolgen, werden die Interrupt-Leitungen der Module durch ein oder zusam-mengeführt und der CPU zugeführt. Im Anhang A.4 ist der Aufbau und dieVerbindungen der Module zu sehen.

7.3.2 Timer-Module im Design

Ein Timer-Modul wird so wie ein GPIO-Modul über die oberen fünf Adressenausgewählt. Die oberen fünf Bits der Adressleitung des Timer1 sind 0b00011.Beim Timer2 sind die Bits hingegen 0b00100. Timer werden so wie die GPIO-Module über IO-Befehle angesprochen. Timer brauchen zusätzlich einen Vor-teiler, der die Taktleitung in verschiedene langsamere Taktleitungen teilt.Dies wird mit dem Teiler-Modul realisiert. Damit die Interrupts ausgelöstwerden, werden alle Interrupt-Leitungen durch ein oder zusammengeführt.Im Anhang A.5 ist der Aufbau mit den GPIO-Modulen zu sehen.

7.4 Testbench

Auch das Top-Level-Design wurde in einer Testbench getestet, dieser Testwurde jedoch sehr einfach gehalten. Es wurden lediglich die Ein- und Aus-gänge zur Verfügung gestellt und ein Taktsignal erzeugt. Diese Ein- und Aus-gänge konnten dann in das Wave-Diagramm eingefügt und visuell überprüftwerden um zu sehen ob sich die Ausgaben in Abhängigkeit zum Programmändern. Den Code der Testbench �ndet man im Anhang A.3.Die Testbench kann auch das Gate-Level-Design von Quartus simulieren.

KAPITEL 7. MICO8-CPU AUF DER SANDBOXX 38

7.5 Testen der Mico8-CPU

Es wurden verschiedene Tests für die SandboxX vorbereitet, welche zuersteiner RTL-Simulation unterzogen wurden. Danach wurde mit Quartus einGate-Level-Design erstellt und dieses simuliert. Nachdem auch diese Simula-tionen erfolgreich waren, wurden die Designs auf die SandboxX transferiertund dort getestet.

7.5.1 Test 1 - Lau�icht Test

Dieses Programm stellt ein einfaches Lau�icht auf den LEDs zur Verfügung.Da die Taktfrequenz nicht reduziert wird, wurden lediglich die einzelnenFrequenzen mit den simulierten Zeiten verglichen (siehe Tabelle 7.1). DasProgramm wurde in Assembler programmiert:

1 ; Testprogramm fuer Sandbox

2 ; Interrupt Adresse:

3 b start

4 ; Start des Programmes:

5 start:

6 movi r0, 0

7 movi r1, 0xFF

8 movi r2, 0

9

10 ; auf Ausgang setzen:

11 export r1, 0

12 ; auf Ausgang setzen:

13 export r1, 16

14 export r3, 17

15 loop:

16 addi r2, 1

17 export r2, 1

18 b loop

Led simulierte Frequenz [kHz] gemessene Frequenz [kHz]

2 1785,7 17853 892,86 8924 446,43 446,25 223,21 223,16 111,61 111,57 55,80 55,78 27,90 27,899 13,95 13,94

Tabelle 7.1: Vergleich von simulierter Frequenz mit realer Frequenz dereinzelnen LEDs, gemessen mit einem Multimeter (Im Anhang B.2 genaueBezeichnung)

KAPITEL 7. MICO8-CPU AUF DER SANDBOXX 39

7.5.2 Test 2 - Tasten-Test

Dieser Test liest die gedrückten Tasten aus und lässt die dazugehörigen LEDsleuchten. Dieses Programm wurde in Assembler und in C-Programmiert.

1 ; Testprogramm fuer Sandbox

2 ; Interrupt Adresse:

3 b start

4 ; Start des Programmes:

5 start:

6 movi r0, 0

7 movi r1, 0xFF

8 movi r2, 0

9 movi r3, 5

10

11 ; auf Ausgang setzen:

12 export r1, 0

13 ; auf Eingang setzen:

14 export r0, 8

15 export r1, 9

16 ; auf Ausgang setzen:

17 export r1, 16

18 export r3, 17

19 loop:

20 import r2, 12

21 ; Daten negieren:

22 xori r2, 0xFF

23 export r2, 1

24 b loop

1 #include "register.h"

2

3 int main(void)

4 {

5 unsigned char value = 0;

6

7 // Port A auf Ausgang setzen (LEDs):8 __builtin_export(0xFF, DDRA);

9

10 // Port B auf Eingang setzen (Taster):11 __builtin_export(0x00, DDRB);

12 // Pull-Ups aktivieren:13 __builtin_export(0xFF, PORTB);

14

15 // Port C auf Ausgang setztn und LEDs einschalten:16 __builtin_export(0xFF, DDRC);

17 __builtin_export(LEDS2, PORTC);

18

19 while(1)

20 {

21 // Werte vom Port B lesen:22 value = __builtin_import(PINB);

23 // Damit die LEDs nur bei gedrueckter Taste24 // leuchten, werden die Bits umgedreht:

KAPITEL 7. MICO8-CPU AUF DER SANDBOXX 40

25 value = ~value;

26 // Auf den Ausgang von Port A schreiben:27 __builtin_export(value, PORTA);

28 }

29

30 return 0;

31 }

7.5.3 Test 3 - Zähler-Test mit Timer

Dieser Test benützt zwei Timer und die GPIO-Module. Der Timer1 wirdbenützt, um einen einfachen Zähler zu erstellen. Timer2 wird benützt, umzwischen den vier 7-Segment-Anzeigen und den zwei LED-Leisten zu wech-seln. Dies wird durch das Multiplexverfahren bewerkstelligt. Die Zahl, welchehochgezählt wird, wird auf den 7-Segment-Anzeigen als Hex-Wert angezeigt,bei den LED-Leisten wird die Zahl binär dargestellt. Der maximale Wert beiden 7-Segment-Anzeigen ist jedoch mit 16 (0xF) de�niert. Das Programmwurde in C implementiert.

1 #include "register.h"

2

3 void __IRQ (void) __attribute__ ((interrupt));

4 unsigned char ConvertToSegment(unsigned char value);

5

6 #define SEGMENTS 6

7

8 volatile static unsigned char value = 0;

9 volatile static unsigned char current = 0;

10

11 int main(void)

12 {

13 unsigned char val;

14 // Port A auf Ausgang setzen (LEDs, 7-Segemnt):15 __builtin_export(0xFF, DDRA);

16

17 // Port C auf Ausgang setzen (Auswahl welche 7-Segment oder LEDs):18 __builtin_export(0xFF, DDRC);

19

20 // Timer 1:21 __builtin_export(0xFF, TIMER1L);

22 __builtin_export(0xFF, TIMER1H);

23 __builtin_export(TIMEREN | PRE128, TIMER1S);

24

25 // Timer 2:26 __builtin_export(0xFF, TIMER2L);

27 __builtin_export(0x0F, TIMER2H);

28 __builtin_export(TIMEREN | PRE8, TIMER2S);

29

30 while(1)

31 {

32 __builtin_export(current, PORTC);

33 val = value;

KAPITEL 7. MICO8-CPU AUF DER SANDBOXX 41

34 if(current < 4)

35 {

36 val = ConvertToSegment(value & 0x0F);

37 }

38 __builtin_export(val, PORTA);

39 }

40

41 return 0;

42 }

43

44 void __IRQ(void)

45 {

46 unsigned char val;

47 val = __builtin_import(TIMER2S);

48 if(val & TIMERINT)

49 {

50 current++;

51 if(current >= SEGMENTS)

52 {

53 current = 0;

54 }

55 return;

56 }

57 val = __builtin_import(TIMER1S);

58 if(val & TIMERINT)

59 {

60 value++;

61 return;

62 }

63 return;

64 }

Schön zu sehen ist hierbei der Ablauf der Interrupt-Service-Routine. Zu-nächst sollte immer der Interrupt abgehandelt werden, der am häu�gstenauftritt. Wird ein Interrupt abgearbeitet, sollte die Funktion wieder beendetwerden, da es nur sehr selten vorkommt, dass auch ein anderer Interrupt ak-tiv ist. Sollten zur gleichen Zeit zwei Interrupts aktiv sein, wird die Funktionnoch einmal ausgeführt.

Kapitel 8

Resultate und Ausblicke

8.1 Vergleich mit der Original-CPU

Zum Vergleich mit der Original-CPU konnten nicht die Daten aus Tabelle2.13 herangezogen werden. Vielmehr mussten neue Referenzdaten erzeugtwerden. Dabei wurde die Kon�guration, welche für die SandboxX verwen-det wurde, benützt. Dieses Design verwendet 32 Register, 256 Byte externenSpeicher, sowie 3 GPIO-Module und 2 Timer. Als PROM wurde das Pro-gramm aus Test 3 verwendet (siehe Kapitel 7.5.3). In Tabelle 8.1 ist dieOriginal-CPU mit den Daten, wie oben angegeben, synthetisiert worden. InTabelle 8.2 sind hingegen die Daten der neuen FSMD-CPU zu sehen.

FPGA-Chip LUTs Register SLICEs fmax(MHz)

LFXP-3C-4T144C 795 399 569 107.0LFE2-50E-5F484C 840 399 529 118.5

Tabelle 8.1: Original-CPU zum Vergleich

FPGA-Chip LUTs Register SLICEs fmax(MHz)

LFXP-3C-4T144C 2147 687 1342 62.3LFE2-50E-5F484C 2245 710 1420 79.6

Tabelle 8.2: FSMD-CPU zum Vergleich

Wie in den Tabellen 8.1 und 8.2 zu sehen, ist das Design deutlich gröÿergeworden (Faktor 2 bis 3).Zum Vergleich von zwei Designs muss immer das Ausgangsdesign berück-sichtigt werden. In diesem Fall ist das Ausgangsdesign bereits von Latticesehr stark für FPGAs optimiert. Somit kann das FSMD-Design nur mehrgleich groÿ oder gröÿer werden.

42

KAPITEL 8. RESULTATE UND AUSBLICKE 43

8.2 Resultat der Arbeit

Die Ergebnisse aus Kapitel 8.1 zeigen, dass es nicht immer gut ist, ein FSMD-Design zu verwirklichen, gerade wenn schon ein optimiertes Design vorliegt.Man könnte nun versuchen, die Original-CPU so umzubauen, dass sie unab-hängig von FPGA-Hersteller ist und dann erneut einen Vergleich anstellen.Trotzdem ist die Mico8-CPU sehr gut zu benützen, gerade auch für Anfän-ger. Sollte ein Design ohne Interrupt-Funktion realisiert werden, ist es auchfür einen Student machbar, der gerade VHDL lernt, denn gerade im Abhan-deln von Interrupts ist die Mico8-CPU sehr kompliziert und schwierig zuverstehen. Wenn jedoch nur die CPU ohne Interrupt realisiert werden soll,ist auch eine Implementierung von Studenten mit weniger VHDL Erfahrungmöglich.

8.3 Ausblick

Für die CPU können noch viele weitere Module entwickelt werden um soeinen gröÿeren SoC herstellen zu können. Wichtig wäre hierbei ein Modulmit welchem man über eine serielle Schnitstelle neue PROM-Daten schickenkönnte, damit diese im PROM abgelegt werden. So wäre kein erneutes Syn-thetisieren der gesamten CPU nötig.

Anhang A

VHDL Code

A.1 Dateiauslesendes ROM

1 library ieee;

2 use ieee.std_logic_1164.all;

3 use ieee.numeric_Std.all;

4

5 use std.textio.all;

6

7 entity SyncRom is

8 generic (

9 HEX_FILE : string := "tc_01.hex"

10 );

11 port (

12 iClk : in std_ulogic;

13 iAddr : in std_ulogic_vector(11 downto 0);

14 oData : out std_ulogic_vector(17 downto 0)

15 );

16 end entity SyncRom;

17

18 architecture RTL of SyncRom is

19

20 type tRamData is array (0 to (2**iAddr'length)-1) of std_ulogic_vector

(oData'range);

21 signal RamData : tRamData := (others => (others => 'X'));

22 signal ReadAddr : std_ulogic_vector(iAddr'range);

23

24 function str_to_stdvec(inp: string) return std_ulogic_vector is

25 variable temp: std_ulogic_vector(21 downto 0) := (others => 'X');

26 begin

27 −− umbauen auf schritweises schiften von string-hex auf hex (4 bit)28 for i in inp'range loop

29 case inp(i) is

30 when '0' =>

31 temp(3 downto 0) := x"0";

32 when '1' =>

33 temp(3 downto 0) := x"1";

34 when '2' =>

44

ANHANG A. VHDL CODE 45

35 temp(3 downto 0) := x"2";

36 when '3' =>

37 temp(3 downto 0) := x"3";

38 when '4' =>

39 temp(3 downto 0) := x"4";

40 when '5' =>

41 temp(3 downto 0) := x"5";

42 when '6' =>

43 temp(3 downto 0) := x"6";

44 when '7' =>

45 temp(3 downto 0) := x"7";

46 when '8' =>

47 temp(3 downto 0) := x"8";

48 when '9' =>

49 temp(3 downto 0) := x"9";

50 when 'A' =>

51 temp(3 downto 0) := x"A";

52 when 'B' =>

53 temp(3 downto 0) := x"B";

54 when 'C' =>

55 temp(3 downto 0) := x"C";

56 when 'D' =>

57 temp(3 downto 0) := x"D";

58 when 'E' =>

59 temp(3 downto 0) := x"E";

60 when 'F' =>

61 temp(3 downto 0) := x"F";

62 when others =>

63 assert (false) report "Fehler im ROM: keine Hex Zahl enthalten!"

severity failure;

64 end case;

65 temp(21 downto 4) := temp(17 downto 0);

66 end loop;

67 temp(17 downto 0) := temp(21 downto 4);

68 return temp(17 downto 0);

69 end function str_to_stdvec;

70

71 begin

72

73 RamProc: process(iClk) is

74 begin

75 if rising_edge(iClk) then

76 ReadAddr <= iAddr;

77 end if;

78 end process RamProc;

79

80 oData <= RamData(to_integer(unsigned(ReadAddr)));

81

82

83 −− init data:84 process is

85 variable counter : integer := 0;

86 file vector_file : text;

87 variable file_line : line;

ANHANG A. VHDL CODE 46

88 variable str : string(5 downto 1);

89 begin

90 file_open(vector_file, HEX_FILE, READ_MODE);

91 while not endfile(vector_file) loop

92 readline (vector_file, file_line);

93 read (file_line, str);

94 RamData(counter) <= str_to_stdvec(str);

95 counter := counter + 1;

96 end loop;

97 file_close(vector_file);

98 wait;

99 end process;

100

101 end architecture RTL;

A.2 RAM

1 library ieee;

2 use ieee.sTD_lOGIC_1164.all;

3 use ieee.numeric_Std.all;

4

5 entity SyncRam is

6 port (

7 iClk : in std_ulogic;

8 iWE : in std_ulogic;

9 iAddr : in std_ulogic_vector;

10 iData : in std_ulogic_vector;

11 oData : out std_ulogic_vector

12 );

13 end entity SyncRam;

14

15 architecture RTL of SyncRam is

16

17 type tRamData is array (0 to (2**iAddr'length)-1) of std_ulogic_vector

(iData'range);

18 signal RamData : tRamData := (others => (others => 'X'));

19 signal ReadAddr : std_ulogic_vector(iAddr'range);

20

21 begin

22

23 RamProc: process(iClk) is

24 begin

25 if rising_edge(iClk) then

26 if iWE = '1' then

27 RamData(to_integer(unsigned(iAddr))) <= iData;

28 end if;

29 ReadAddr <= iAddr;

30 end if;

31 end process RamProc;

32

33 oData <= RamData(to_integer(unsigned(ReadAddr)));

34

35 end architecture RTL;

ANHANG A. VHDL CODE 47

A.3 SandboxX Testbench

1 entity isp8_board_TB is

2 end isp8_board_TB;

3

4 architecture Rtl of isp8_board_TB is

5

6 signal clk : std_ulogic := '0';

7 signal rst_n : std_ulogic := '0';

8 signal PORTA : std_logic_vector(7 downto 0);

9 signal PORTB : std_logic_vector(7 downto 0) := (others => 'L');

10 signal PORTC : std_logic_vector(7 downto 0);

11 signal EXT_INT : std_ulogic := '0';

12 begin

13 clk <= not clk after 1 sec / 50E6;

14 rst_n <= '1' after 50 ns;

15

16 u1_board : entity work.isp8_board

17 port map(

18 clk => clk,

19 rst_n => rst_n,

20 PORTA => PORTA,

21 PORTB => PORTB,

22 PORTC => PORTC,

23 EXT_INT => EXT_INT);

24 end Rtl;

A.4 GPIOs in der SandboxX

1 CPU_IO_A : entity work.isp8_gpio

2 generic map (

3 DW => 8

4 )

5 port map(

6 clk => clk,

7 rst_n => rst_n,

8 cpu_in_data => ExtData,

9 cpu_out_data => ExtIOData,

10 reg_addr => ExtAddr(2 downto 0),

11 cpu_read => ExtIORead,

12 cpu_write => ExtIOWrite,

13 cs => CS_IO_A,

14 interrupt => Int_IO_A,

15 pin => PORTA

16 );

17

18 CPU_IO_B : entity work.isp8_gpio

19 generic map (

20 DW => 8

21 )

22 port map(

23 clk => clk,

24 rst_n => rst_n,

ANHANG A. VHDL CODE 48

25 cpu_in_data => ExtData,

26 cpu_out_data => ExtIOData,

27 reg_addr => ExtAddr(2 downto 0),

28 cpu_read => ExtIORead,

29 cpu_write => ExtIOWrite,

30 cs => CS_IO_B,

31 interrupt => Int_IO_B,

32 pin => PORTB

33 );

34

35 CPU_IO_C : entity work.isp8_gpio

36 generic map (

37 DW => 8

38 )

39 port map(

40 clk => clk,

41 rst_n => rst_n,

42 cpu_in_data => ExtData,

43 cpu_out_data => ExtIOData,

44 reg_addr => ExtAddr(2 downto 0),

45 cpu_read => ExtIORead,

46 cpu_write => ExtIOWrite,

47 cs => CS_IO_C,

48 interrupt => Int_IO_C,

49 pin => PORTC

50 );

51

52 CS_IO_A <= '1' when ExtAddr(7 downto 3) = "00000" else '0';

53 CS_IO_B <= '1' when ExtAddr(7 downto 3) = "00001" else '0';

54 CS_IO_C <= '1' when ExtAddr(7 downto 3) = "00010" else '0';

55

56 Interrupt <= Int_IO_A or Int_IO_B or Int_IO_C;

A.5 Timer in der SandboxX

1 u1_usp8_timer_1 : entity work.isp8_timer16

2 port map(

3 clk => clk,

4 rst_n => rst_n,

5 cpu_in_data => ExtData,

6 cpu_out_data => ExtIOData,

7 reg_addr => ExtAddr(2 downto 0),

8 cpu_read => ExtIORead,

9 cpu_write => ExtIOWrite,

10 cs => CS_TIMER_1,

11 interrupt_out => Int_TIMER_1,

12 prescale8 => prescale8,

13 prescale16 => prescale16,

14 prescale32 => prescale32,

15 prescale64 => prescale64,

16 prescale128 => prescale128,

17 prescale265 => prescale265,

18 prescale512 => prescale512,

ANHANG A. VHDL CODE 49

19 prescale1024 => prescale1024,

20 prescale2048 => prescale2048);

21

22 u1_usp8_timer_2 : entity work.isp8_timer16

23 port map(

24 clk => clk,

25 rst_n => rst_n,

26 cpu_in_data => ExtData,

27 cpu_out_data => ExtIOData,

28 reg_addr => ExtAddr(2 downto 0),

29 cpu_read => ExtIORead,

30 cpu_write => ExtIOWrite,

31 cs => CS_TIMER_2,

32 interrupt_out => Int_TIMER_2,

33 prescale8 => prescale8,

34 prescale16 => prescale16,

35 prescale32 => prescale32,

36 prescale64 => prescale64,

37 prescale128 => prescale128,

38 prescale265 => prescale265,

39 prescale512 => prescale512,

40 prescale1024 => prescale1024,

41 prescale2048 => prescale2048);

42

43 u1_usp8_prescaler : entity work.isp8_clk_prescale

44 port map(

45 clk => clk,

46 rst_n => rst_n,

47 prescale8 => prescale8,

48 prescale16 => prescale16,

49 prescale32 => prescale32,

50 prescale64 => prescale64,

51 prescale128 => prescale128,

52 prescale265 => prescale265,

53 prescale512 => prescale512,

54 prescale1024 => prescale1024,

55 prescale2048 => prescale2048);

56

57 CS_TIMER_1 <= '1' when ExtAddr(7 downto 3) = "00011" else '0';

58 CS_TIMER_2 <= '1' when ExtAddr(7 downto 3) = "00100" else '0';

59 Interrupt <= Int_IO_A or Int_IO_B or Int_IO_C or Int_TIMER_1 or

Int_TIMER_2 or Ext_Int_Syn2;

Anhang B

Arbeitsumgebung

B.1 Softwareumgebungen

Als Arbeitsumgebung wurde Windows 7 mit folgenden Tools für Syntheseund Simulation benützt:

� QuestaSim Simulationswerkzeug v6.5

� Altera Modelsim Simulationswerkzeug v6.5e

� Altera Quartus II Synthesewerkzeug v10.0

� Lattice Diamond Synthesewerkzeug 1.0

Zusätzlich wurden folgende Tools von Lattic für das Kompilieren und As-semblieren verwendet:

� Mico8-Assembler

� Mico8-gcc unter cygwin-Umgebung

Zum Erstellen von C++-Tools wurde Microsoft Visual Studio 2010 mit derEntwicklungsumgebung für C++ verwendet.

B.2 Messgeräte

Als Messgerät zum Messen der Frequenzen wurde das Multimeter VoltcraftVC840 verwendet. Dieses Messgerät hat laut Datenblatt eine Abweichungvon 0,1% beim Messen von Frequenzen.

50

Anhang C

Inhalt der CD-ROM

Format: CD-ROM, Single Layer, ISO9660-Format

C.1 PDF-Daten

Pfad: /

_BaMICO8.pdf . . . . Bachelorarbeit (Gesamtdokument)

_PrBericht.pdf . . . . . Praktikumsbericht

C.2 Dokumente

Pfad: /doc

LatticeMicro8ProductBrochure.pdf Produkt Broschüre für Mico8

LatticeMicro8UserGuide.pdf User Guid für Mico8

lm8_dev_tools_ug.pdf Handbuch zu den C-Tools für Mico8

ATmega8.pdf . . . . . . Praktikumsbericht

C.3 Latex-Daten

Pfad: /Latex

*.tex . . . . . . . . . . . Latex Daten für die Bachelorarbeit

hagenberg.sty . . . . . . Stil-Dokument der Fachhochschule Hagenberg

literatur.bib . . . . . . . Literatur Referenzen

Pfad: /Latex/images

*.jpg . . . . . . . . . . . Abbildungen für die Bachelorarbeit

51

ANHANG C. INHALT DER CD-ROM 52

C.4 VHDL-Code

Pfad: /Source

isp8*.vhd . . . . . . . . VHDL Daten für die neue CPU

prom.vhd . . . . . . . . PROM das die Daten aus einer Dateiauslesen kann

prom_generic.vhd . . . PROM das die Daten als generic gespeicherthat

ram.vhd . . . . . . . . . RAM

tbprom.vhd . . . . . . . Testbench für ein PROM

Pfad: /Source/gpio

gpio.vhd . . . . . . . . . GPIO-Modul zum Einbinden in einTop-Level Design

gpio_tb.vhd . . . . . . Testbench für das GPIO-Modul

Pfad: /Source/timer

timer16.vhd . . . . . . . Timer-Modul zum Einbinden in einTop-Level Design

timer16_tb.vhd . . . . . Testbench für das GPIO-Modul

clk_prescale.vhd . . . . Takt-Vorteiler-Modul

clk_prescale_all.vhd . . Takt-Vorteiler-Modul das alle gefordertenGeteilten Takte enthält für den Timer

C.5 Testbench-Daten

Pfad: /TestStation/models

* . . . . . . . . . . . . . Enthält alle Model-Daten die für Latticegebraucht werden

Pfad: /TestStation/simulation/modelsim

isp8 . . . . . . . . . . . Haupt-Do-Datei (ruft dann die anderenDo-Daten auf)

*.do . . . . . . . . . . . Do-Datei zum compilieren und erstellen derWave

Pfad: /TestStation/SourceOri

*.vhd . . . . . . . . . . Original VHDL-Daten vom Mico8

ANHANG C. INHALT DER CD-ROM 53

Pfad: /TestStation/testbench

*.vhd . . . . . . . . . . neu erstellte Testbench

Pfad: /TestStation/tests

*.s . . . . . . . . . . . . Assemblerdaten zum testen

create_all.bat . . . . . . Script das alle Test-PROMs erstellt

C.6 Assembler-Code

Pfad: /SandboxSyn/Test1

test1.s . . . . . . . . . . Assemblerdatei des ersten Testes

Pfad: /SandboxSyn/Test2

test2.s . . . . . . . . . . Assemblerdatei des zweiten Testes

C.7 C-Code

Pfad: /SandboxSyn/Test2

main.c . . . . . . . . . . C-Hauptdatei des zweiten Testes

register.h . . . . . . . . Registerdatei

Pfad: /SandboxSyn/Test3

main.c . . . . . . . . . . C-Hauptdatei des dritten Testes

register.h . . . . . . . . Registerdatei

C.8 C++-Code

Pfad: /ToHexConverter

*.cpp . . . . . . . . . . C++ Daten

*.h . . . . . . . . . . . . Header Daten

ToHexConverter.sln . . Visual Studio 2010 Projektdatei

C.9 Synthese

Pfad: /SandboxSyn

board.vhd . . . . . . . . Top-Level-Design für die SandboxX

board_tb.vhd . . . . . . Testbench des Top-Level-Designs

isp8_board.qpf . . . . . Projektdatei für Quartus

ANHANG C. INHALT DER CD-ROM 54

isp8_board.qsf . . . . . Projekteinstellungsdatei für Quartus

tbprom.vhd . . . . . . . Testbench für ein PROM

C.10 Tools

Pfad: /utils

isp8asm_win.exe . . . . Assembler für den Mico8

isp8sim_win.exe . . . . Programm das einen Mico8 Simulieren kann

ToHexConverter.exe . . Konvertiert eine ASCII-Hex-Datei in einVHDL-PROM

C.11 Installation

Pfad: /install

LatticeMico8_v1.exe . . Installation für die C-Umgebung

Literaturverzeichnis

[1] Ashenden, P. J.: The Designer's Guide to VHDL, Volume 3, Third

Edition (Systems on Silicon) (Systems on Silicon). Morgan KaufmannPublishers Inc., San Francisco, CA, USA, 2008.

[2] ATMEL: ATmega8(L) Complete Datasheet , Feb. 2011. URL, http://www.atmel.com/Images/doc2486.pdf.

[3] Cygwin: Cygwin Page, 2012. URL, http://www.cygwin.com/.

[4] Lattice: LatticeMico8 User Guide, Nov. 2010. URL, http://www.latticesemi.com/dynamic/view_document.cfm?document_id=9967.

55

Messbox zur Druckkontrolle

� Druckgröÿe kontrollieren! �

Breite = 100 mmHöhe = 50 mm

� Diese Seite nach dem Druck entfernen! �

56