<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Goldmomo</id>
	<title>Mikrocontroller.net - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Goldmomo"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/Goldmomo"/>
	<updated>2026-04-08T11:46:25Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=86695</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=86695"/>
		<updated>2015-01-16T11:11:30Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: PS/2 Reset dokumentiert + Kleinigkeiten&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein &#039;Computer&#039;system, welches nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses nachbildet.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen, welches vollständig&#039;&#039;&#039;*&#039;&#039;&#039; selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (&#039;&#039;&#039;*&#039;&#039;&#039;FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL verwendet, für Emulation und Tools (Assembler etc.) wird C# mit .NET benutzt.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 zur Verfügung gestellt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE = Utility Core), welcher über einen memorymapped UCTRL-Komponente vollständigen Zugriff auf alle Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* Programmierbares Audio Interface&lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Zwei Timer/Counter&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCORE) ist der &#039;&#039;&#039;zentrale&#039;&#039;&#039; Prozessor im System, d.h. er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist dazu gedacht, eine einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn, für alle meine Demos/Spiele, als Hauptprozessor benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In einen experimentellen Zustand befindet sich noch der HCORE Block. Dieser Block enthält mehre (konfigurierbar) 32 Bit Prozessoren die über spezielle Techniken (Hardwaresemaphoren, parallele Sprünge, … ) eine parallele Verarbeitung von Software vereinfachen sollen und Latenzprobleme bei Multithreading vermeiden. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
[[Datei:Goldmomo emulator.png|miniatur|rechts|Emulator]]&lt;br /&gt;
Um die Softwareentwicklung (Debuggen etc.) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Registerstatus, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (in Emulator integriert). Ein Compiler (z.B.: für C) existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/8i5pzlncr77cl1v/AADt708pu8p6irXm-YO-1so2a/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo endlos Sheriff2213.png|miniatur|Sheriff 2213]]&lt;br /&gt;
[[Datei:Goldmomo endlos SpacePilotOfDeath.png|miniatur|SpacePilotOfDeath]]&lt;br /&gt;
[[Datei:Goldmomo endlos ModPlayer.png|miniatur|MOD Player]]&lt;br /&gt;
[[Datei:Goldmomo endlos GfxExtension.png|miniatur|GFX Extension]]&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= UCORE Programmierung =&lt;br /&gt;
&lt;br /&gt;
UCORE unterscheidet sich einigen Teilen von einem &#039;&#039;normalen&#039;&#039; Prozessordesign.&lt;br /&gt;
Die Gründe bzw. Ziele welche verfolgt wurden, waren eine möglichst hohe Taktrate und ein möglichst geringe Benutzung von Hardwareressourcen, aber dennoch eine hohe Verarbeitungsgeschwindigkeit.&lt;br /&gt;
Dadurch ergeben sich einige Besonderheiten, welche bei der Programmierung beachtet werden &#039;&#039;&#039;müssen&#039;&#039;&#039; (siehe Registerzugriffe, Branch/Jump Delayslots, Request/Load Zugriffe).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pipeline ===&lt;br /&gt;
&lt;br /&gt;
Wie gesagt hat dieser Core eine sechsstufige Pipeline:&lt;br /&gt;
&lt;br /&gt;
# 1 Prepare Fetch (adressiere Daten)&lt;br /&gt;
# 2 Fetch (hole Daten)&lt;br /&gt;
# 3 Decode (dekodiere Daten)&lt;br /&gt;
# 4 Read Register (lese Register)&lt;br /&gt;
# 5 Execute (ausführen)&lt;br /&gt;
# 6 Write Register (schreibe Register (hat einen Bypass zu Stufe 4, somit keine extra Delay) &lt;br /&gt;
&lt;br /&gt;
Jede Instruktion wird in einem Cycle ausgeführt, nur der externe Speicherzugriff (nur Daten) kann einen Stall (Stillstand) der Pipeline verursachen.&lt;br /&gt;
&lt;br /&gt;
== Interne Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
In meinem System wird die folgende interne Speichermap verwendet (16 Bit interner Adressraum).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$0000 code / data memory&lt;br /&gt;
*     16384 * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$3fff&lt;br /&gt;
$4000 code / data memory MIRROR&lt;br /&gt;
*     &lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$7fff&lt;br /&gt;
$8000 uctrl / memory			StackPointer start at $8000 on reset&lt;br /&gt;
*     XXXX * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$XXXX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Reset-Vektor befindet sich an Adresse $0000, der Stackpointer an Adresse $8000 (am Ende des internen RAMs).&amp;lt;br&amp;gt; &lt;br /&gt;
Der Interruptvektor zeigt nach dem Reset auf Adresse $0010 (sollte nach dem Reset an die benötigte Position verschoben werden).&amp;lt;br&amp;gt; &lt;br /&gt;
Ab Adresse $8000 wird die Komponente UCtrl in den Adressraum &#039;gemappt&#039; (diese Komponente enthält Register für externe Hardware Peripherie etc.).&lt;br /&gt;
&lt;br /&gt;
== externe Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
Über den &#039;externen&#039; Datenbus (32 Bit Adressraum) kann auf folgende Komponenten zugegriffen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$a000 0000 - $a000 001f SDCard-Controller&lt;br /&gt;
$d000 0000 - $d3ff ffff SDRAM&lt;br /&gt;
$e000 0000 - $e03f ffff FLASH&lt;br /&gt;
$f000 0000 - $f00f ffff SRAM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei den meisten meiner Programme wird ein Boot-Programm aus dem FLASH-Speicher gelesen, welches einen Speichertest ausführt und auf das Einlegen einer SD-Karte, mit dem zu ladenden Programm, wartet.&lt;br /&gt;
&lt;br /&gt;
== Opcodes/Operanten ==&lt;br /&gt;
&lt;br /&gt;
UCore hat keine &#039;RISC&#039;-Typischen Befehlssatz (benutzt viele Befehle, aber mit geringe Komplexität).&amp;lt;br&amp;gt;&lt;br /&gt;
Da ein Instruktions-Wort nur eine Breite von 16 Bit hat, können nur bedingte Mengen an Operanden verwendet werden. Um jedoch die Programmierung flexibler zu gestalten, haben viele Opcodes mehrere Arten von Operanden. Für die Ausführungseinheit (ALU) ergibt sich dadurch keine Ressourcenveränderung, da der Decoder nur die Opcodes/Operanden in ein internes einheitliches Format auflöst.&amp;lt;br&amp;gt;&lt;br /&gt;
Operanden können bis zu drei Register verwenden und je nach Typ einen festen Wert, dieser Wert ist je nach Typ in seiner Bitbreite beschränkt (kann mittels Decoderinstruktion &#039;&#039;&#039;dexti&#039;&#039;&#039; erweitert werden).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Operanden Formate ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dc,imm8       Register, 8 Bit Wert (unsigned)&lt;br /&gt;
 dc,db,da      Register, Register , Register&lt;br /&gt;
 dc,db,imm3    Register, Register, 3 Bit Wert (unsigned)&lt;br /&gt;
 imm12         12 Bit Wert (signed)&lt;br /&gt;
 db,da         Register, Register&lt;br /&gt;
 imm6          6 Bit wert (unsigned)&lt;br /&gt;
 da            Register&lt;br /&gt;
 kein Operant&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Opcodes selber können in folgenden (klassischen) Typen eingeordnet werden.&lt;br /&gt;
* Transfer-Befehle (move, ld, st, rqld ,...)&lt;br /&gt;
* Arithmetische Befehle (add, sub, mul, neg,…)&lt;br /&gt;
* Logische Befehle (and, or, xor, bic,…)&lt;br /&gt;
* Bit-Befehle (bset,bclr,bffo,..)&lt;br /&gt;
* Vergleichs-Befehle (cmpeq, cmplo,…)&lt;br /&gt;
* Schiebe-Befehle (lsr,asr, swp,…)&lt;br /&gt;
* Programmsteuerungs-Befehle (br, jmp, rti…)&lt;br /&gt;
* Status-Befehle (sei,cli, getssr, …)&lt;br /&gt;
&lt;br /&gt;
==== Opcode / Operand(en) / Beschreibung ==== &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
movei     	dc,imm8		dc = imm&lt;br /&gt;
moveih    	dc,imm8		dc[15..8] = imm &amp;lt;&amp;lt; 8 | dc[7..0]&lt;br /&gt;
addi      	dc,imm8		dc = dc + imm&lt;br /&gt;
subi      	dc,imm8		dc = dc - imm&lt;br /&gt;
lsri      	dc,imm8		dc = dc &amp;gt;&amp;gt; imm&lt;br /&gt;
asri      	dc,imm8		dc = ((signed)dc) &amp;gt;&amp;gt; imm&lt;br /&gt;
muli      	dc,imm8		dc = dc * imm&lt;br /&gt;
cmpeqi    	dc,imm8		t = set if dc == imm else cleared&lt;br /&gt;
cmploi    	dc,imm8		t = set if dc &amp;lt; imm else cleared&lt;br /&gt;
cmplosi   	dc,imm8		t = set if  (signed)dc &amp;lt; (signed) imm else cleared&lt;br /&gt;
gpci      	dc,imm8		dc = pc + imm&lt;br /&gt;
jmpi      	dc,imm8		pc = dc + imm&lt;br /&gt;
extri     	dc,imm8		t = bit #imm of dc&lt;br /&gt;
rqldi     	dc,imm8		request (internal) mem; address = dc + imm&lt;br /&gt;
getsp     	dc,imm8		dc = sp + imm&lt;br /&gt;
dexti     	imm11		store imm as extension for next instruction&lt;br /&gt;
&lt;br /&gt;
add		dc,db,da	dc = db + da&lt;br /&gt;
sub     	dc,db,da	dc = db - da&lt;br /&gt;
lsr     	dc,db,da	dc = db &amp;gt;&amp;gt; da&lt;br /&gt;
asr     	dc,db,da	dc = ((signed)db) &amp;gt;&amp;gt; da&lt;br /&gt;
mul     	dc,db,da	dc = db * da&lt;br /&gt;
addt    	dc,db,da	dc = db + da + t&lt;br /&gt;
subt    	dc,db,da	dc = db - da - t&lt;br /&gt;
muls    	dc,db,da	dc = db * da&lt;br /&gt;
movets  	dc,db,da	dc = db if t = set else da&lt;br /&gt;
and     	dc,db,da	dc = db &amp;amp; da&lt;br /&gt;
or      	dc,db,da	dc = db | da&lt;br /&gt;
xor     	dc,db,da	dc = db ^ da&lt;br /&gt;
bic     	dc,db,da	dc = db &amp;amp; ~da&lt;br /&gt;
&lt;br /&gt;
addqi		dc,db,imm3	dc = db + imm&lt;br /&gt;
subqi   	dc,db,imm3	dc = db - imm&lt;br /&gt;
lsrqi   	dc,db,imm3	dc = db &amp;gt;&amp;gt; imm&lt;br /&gt;
asrqi   	dc,db,imm3	dc = ((signed)db) &amp;gt;&amp;gt; imm&lt;br /&gt;
mulqi   	dc,db,imm3	dc = db * imm3&lt;br /&gt;
addtqi  	dc,db,imm3	dc = db + imm + t&lt;br /&gt;
subtqi  	dc,db,imm3	dc = db - imm - t&lt;br /&gt;
edrqldi 	db,da,imm3	request (external) mem; address = (db:da) + imm3&lt;br /&gt;
&lt;br /&gt;
br		imm12		pc = pc + signed(imm)&lt;br /&gt;
brts		imm12		pc = pc + signed(imm) if t is set&lt;br /&gt;
brtc		imm12		pc = pc + signed(imm) if t is cleared&lt;br /&gt;
	             &lt;br /&gt;
cmpeq		db,da		t = set if db == da else cleared		&lt;br /&gt;
cmplo   	db,da           t = set if db &amp;lt; da else cleared&lt;br /&gt;
cmplos  	db,da           t = set if  (signed)db &amp;lt; (signed) da else cleared&lt;br /&gt;
esadr   	db,da		esadr = db:da&lt;br /&gt;
swp     	db,da		db = da[7..0]:da[15..8] &lt;br /&gt;
swptc   	db,da		db = da[7..0]:da[15..8] if t = set else da&lt;br /&gt;
st      	db,da		imem[db] = da&lt;br /&gt;
stinc   	db,da		imem[db] = da; db = db + 1&lt;br /&gt;
bffo    	db,da		db is first bit that is 1 found in da (from MSB to LSB)&lt;br /&gt;
bset    	db,da		db = db | 1 &amp;lt;&amp;lt; da&lt;br /&gt;
bclr    	db,da		db = db &amp;amp; ~ (1 &amp;lt;&amp;lt; da)&lt;br /&gt;
cmple   	db,da		t = set if db &amp;lt;= da else cleared&lt;br /&gt;
cmples  	db,da		t = set if  (signed)db &amp;lt;= (signed) da else cleared&lt;br /&gt;
rqld    	db,da		request (internal) mem; address = db + da&lt;br /&gt;
extb    	db,da		db = da byte to word singed extended&lt;br /&gt;
stwo    	db,da		imem[db + STORE_OFFSET] = da&lt;br /&gt;
andts   	db,da		db = db &amp;amp; da if t = set else da&lt;br /&gt;
orts    	db,da           db = db | da if t = set else da&lt;br /&gt;
xorts   	db,da           db = db ^ da if t = set else da&lt;br /&gt;
bicts   	db,da           db = db &amp;amp; ~da if t = set else da&lt;br /&gt;
lsrts   	db,da		db = db &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
asrts   	db,da           db = ((signed)db) &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
mults   	db,da           db = db * da if t = set else da&lt;br /&gt;
mulsts  	db,da		db = (signed)db * (signed)da if t = set else da&lt;br /&gt;
&lt;br /&gt;
erqldi		imm6		request (external) mem; address = esadr + imm	&lt;br /&gt;
ssto		imm6		STORE_OFFSET = imm&lt;br /&gt;
udivinit	imm6		udivqoutient = 0; udivrest = 0; udivbitcounter = imm&lt;br /&gt;
&lt;br /&gt;
eld		da		da = requested value from external memory&lt;br /&gt;
push            da		sp = sp – 1; imem[sp] = da&lt;br /&gt;
gmulhi          da		da = multiply result [31..15] from last multiplication&lt;br /&gt;
ld/pop          da		da = requested value from internal memory&lt;br /&gt;
poparqp         da		da = requested value from internal memory; request in internal memory adr = sp; sp = sp + 1&lt;br /&gt;
neg             da		da = 0 - da&lt;br /&gt;
udivgq          da		get division qoutinent&lt;br /&gt;
udivgr          da		get division remainder&lt;br /&gt;
udivgqh         da		get division qoutinent high [31 ..16]&lt;br /&gt;
udivgrh         da              get division remainder high [31 ..16]&lt;br /&gt;
udivsdd         da		set division divident &lt;br /&gt;
udivsdv         da		set division divider&lt;br /&gt;
udivsddh        da		set division divident high [31 ..16]&lt;br /&gt;
udivsdvh        da		set division divider  high [31 ..16]&lt;br /&gt;
erqld           da		request (external) mem; address = esadr + da&lt;br /&gt;
setsp           da		sp = da&lt;br /&gt;
erqldb          da		request (external) mem; address = esadr + da / 2&lt;br /&gt;
jmpts           da		pc = da if t = set&lt;br /&gt;
jmptc           da		pc = da if t = cleared&lt;br /&gt;
negts           da		da = 0 - da if t = set else da&lt;br /&gt;
&lt;br /&gt;
rqpop				internal memory request address = sp; sp = sp + 1&lt;br /&gt;
cli				disable interrupts&lt;br /&gt;
sei				enable interrupts&lt;br /&gt;
rti				pc = pc_before interrput&lt;br /&gt;
tnt				t = not t&lt;br /&gt;
vtt				t = v (overflow/underflow wrom add/sub)			&lt;br /&gt;
epushsadrl			sp = sp – 1; imem[sp] = esadr[15..0]&lt;br /&gt;
epushsadrh			sp = sp – 1; imem[sp] = esadr[31..16]&lt;br /&gt;
epopsadrl			esadr[15..0] = requested value from internal memory&lt;br /&gt;
epopsadrh			esadr[31..16] = requested value from internal memory&lt;br /&gt;
udivstep			performe one division step &lt;br /&gt;
nop				do nothing&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Registerzugriffe ==&lt;br /&gt;
&lt;br /&gt;
Da Register vor der Ausführungseinheit (ALU) gelesen werden und nach der Ausführungseinheit geschrieben werden, ergibt sich eine Latenz zwischen Register Zugriffen. Der Grund für diese Implementierungsart ist, schlicht und einfach, die Performanz zu erhöhen (weniger Logik pro Takt). Als Nebeneffekt entsteht eine Latenz zwischen den Zugriffen. Es bieten sich mehrere Möglichkeiten an, diese Register-&#039;Hazards&#039; in Hardware zu vermeiden (Registerscoring, Renaming etc.). Um den Hardwareimplementierung klein und schnell zu halten, wird in UCore auf einen Hardwaretest verzichtet. Als Resultat, &#039;&#039;&#039;muss&#039;&#039;&#039; der Anwender Registerabhängigkeiten im Programm-Code behandeln/beachten.&lt;br /&gt;
Der einzige Nachteil (der durch eine Latenz entsteht) ergibt sich in einer RAW (Read after Write) Abhängigkeit (da die Latenz hier eine Cycle beträgt). In diesem Fall sollte/muss eine andere Instruktion (z.B. nop) eingefügt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreiben eines Registers und späteres Lesen): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae	; &lt;br /&gt;
	nop		;write r0 = ae wird ausgeführt&lt;br /&gt;
	addi	r0,1	;r0 = r0 ($ae) + 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Im einfachsten Fall sollte eine &#039;&#039;nop&#039;&#039; Operation bei solchen Abhängigkeit verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (nicht optimiert mit nop - 6 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	nop&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	nop&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In den meisten Fällen kann aber eine andere Operationen als &#039;Füllung&#039; bei Registerabhängigkeiten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (optimiert - 4 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um versehentlich programmierte RAW-&#039;Hazards&#039; zu erkennen, erzeugt der Assembler Warnungen, ebenfalls kann der Emulator diese zur Laufzeit erkennen.&lt;br /&gt;
Prinzipiell ist es möglich, in gewissen Situationen, RAW-&#039;Hazards&#039; absichtlich zuzulassen (z.B. Optimierungen um Register zu sparen), wovon aber im Normalfall abzuraten ist.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Arithmetische Befehle ==&lt;br /&gt;
&lt;br /&gt;
Arithmetische Befehle unterscheiden sich, in UCore, nicht von anderen Prozessoren–Designs.&lt;br /&gt;
Neben Addition, Subtraktion, Multiplikation existiert noch eine Instruktion zum Negieren. &lt;br /&gt;
Division wird über mehre Instruktion unterstützt (siehe Division).&lt;br /&gt;
Zu beachten ist, dass bei Addition, Subtraktionen Carry/Borrow immer ins t-Flag übernommen wird und das Overflow-Flag in den Statusregister gespeichert wird.&lt;br /&gt;
&lt;br /&gt;
Arithmetische Befehle wie &#039;&#039;&#039;addt&#039;&#039;&#039;,&#039;&#039;&#039;subt&#039;&#039;&#039;,… benutzen das t-Flag als Carry/Borrow-In. &lt;br /&gt;
Durch diesen Mechanismus können Operationen mit mehr als 16 Bit-Breite (32 Bit etc.) einfach implementiert werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (32 Bit Addition) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	add	r0,r0,r2&lt;br /&gt;
	addt	r1,r1,r3		;r1:r0 = r1:r0 + r3:r2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Multiplikationsoperationen haben als Ergebnis ein 32 Bit wert. &lt;br /&gt;
Die unteren 16 Bit dieses Wertes geben die Multiplikationen selbst zurück. &lt;br /&gt;
Die oberen 16 Bit werden intern gespeichert und können mit der Instruktion &#039;&#039;&#039;gmulhi&#039;&#039;&#039; in einen Register transferiert werden.&lt;br /&gt;
Logische Befehle:&lt;br /&gt;
&lt;br /&gt;
Neben den üblichen logischen Befehlen wie &#039;&#039;&#039;and&#039;&#039;&#039;, &#039;&#039;&#039;or&#039;&#039;&#039;, &#039;&#039;&#039;xor&#039;&#039;&#039;, ist die Instruktion &#039;&#039;&#039;bic&#039;&#039;&#039; (bit clear = and not) implementiert. Alle logischen Befehle können mit zusätzlicher Bedingung ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (bedingter logischer Befehl) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	cmplosi		r0,0	;t = true wenn r0 &amp;lt; 0 &lt;br /&gt;
	xorts		r0,r0	;wenn t = true r0 = r0 xor r0 (r0 = 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bit Befehle ==&lt;br /&gt;
&lt;br /&gt;
Da die Breite vom Immediate-Werte, je nach Instruktions-Typ, begrenzt ist, sind Bitoperationen mit logischen Befehlen meist umständlich, in Software, zu implementieren. &lt;br /&gt;
Zum Setzen bzw. Löschen sind die Instruktionen &#039;&#039;&#039;bset&#039;&#039;, &#039;&#039;&#039;bclr&#039;&#039; implementiert worden. Die Instruktion &#039;&#039;&#039;bffo&#039;&#039;&#039; (bit find first one) sucht von MSB zu LSB, das erste Bit mit Wert Eins. &lt;br /&gt;
&lt;br /&gt;
Die Instruktion &#039;&#039;&#039;extri&#039;&#039;&#039; (extract immediat), transferiert das angegeben Bit in das t-Flag.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (extri) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	extri	r0,15	;bit 15 in r0 -&amp;gt; t-Flag (ist Wert negative)&lt;br /&gt;
	negts	r0	;wenn t = true dann r0=0-r0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Schiebeoperationen ==&lt;br /&gt;
&lt;br /&gt;
UCore implementiert nur Schiebeoperation in die „rechte“ – Richtung (Arithmetisch rechts schieben (&#039;&#039;&#039;asr&#039;&#039;&#039;), Logisch rechts schieben (&#039;&#039;&#039;lsr&#039;&#039;&#039;)). Um Werte nach links zu schieben, sollte die Multiplikationoperation verwendet werden. Um Bytes in einem Register zu tauschen sollte die Operation &#039;&#039;&#039;swp&#039;&#039;&#039; (swap) verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Vergleichsoperationen ==&lt;br /&gt;
&lt;br /&gt;
Vergleichsoperation setzen in UCore immer als Ergebnis das t-Flag (siehe Bedingungen), d.h. jede Art von Vergleich hat ihren eigenen Befehl (keine Statusflags wie z.B. bei 68k). &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Neben dem Vergleich auf den gleichen Wert (&#039;&#039;&#039;cmpeq&#039;&#039;&#039; = compare equal), gibt es Vergleiche auf ‚&amp;lt;=‘ (&#039;&#039;&#039;cmple[s]&#039;&#039;&#039; (unsigned und signed)) und auf ‚&amp;lt;‘ (&#039;&#039;&#039;cmplo[s]&#039;&#039;&#039; ] (unsigned und signed)). Vergleiche auf ‚&amp;gt;‘‚ ‘&amp;gt;=‘ bzw. nicht gleich sind nicht vorhanden, da sie logisch durch den Wert des t-Flags, bei der Benutzung der gegenteiligen Operationen, bestimmt werden können.&lt;br /&gt;
&lt;br /&gt;
== Bedingungen ==&lt;br /&gt;
&lt;br /&gt;
UCore benutzt ein T-Bit (true/wahr Bit) um Bedingungen zu beschreiben/verarbeiten. Normalerweise (nicht ausschließlich) wird dieses Bit von Vergleichsoperationen gesetzt und kann nachfolgend von Operationen benutzt werden welche das T-Bit abfragen (z.B. bedingte Sprünge).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel:====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	cmpeqi	r0,0		;vergleiche auf r0 gleich 0, wenn wahr da (t=1) ansonsten (t=0)&lt;br /&gt;
	brts	r0IstNull	;springe zum &#039;r0IstNull&#039; Label wenn t set (t=1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist notwendig Register nur dann zu setzen, wenn bestimmte Bedingungen eintreten. In solchen Fällen ist es ärgerlich bedingte Sprünge auszuführen, da sie etwas Zeit benötigen (siehe Delay Slots) und den Programmcode unübersichtlich machen (Spaghetticode).&amp;lt;br&amp;gt;&lt;br /&gt;
Aus diesem Grund, unterstützen einige Befehle eine bedingte Ausführung.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	move	r1,123&lt;br /&gt;
	move 	r2,23&lt;br /&gt;
	…&lt;br /&gt;
	cmplo	r0,r1		;r0 &amp;lt; r1&lt;br /&gt;
	movets	r0,r2,r0	;wenn wahr/true r0 = r2 (23) ansonsten r0 = r0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sprünge ==&lt;br /&gt;
&lt;br /&gt;
Ein (bedingter) Sprung benötigt, wie jede andere Instruktion, einen Cycle um ausgeführt zu werden.&lt;br /&gt;
Da UCore keine Branchprediction bzw. keine spekulative Ausführung etc. unterstützt und es auch nicht gewollt ist Opcodes in der Pipeline zu verwerfen (wie z.B. bei MC68020), entstehen nach Sprungbefehlen sogenannte &#039;Delay Slots&#039;. Die Anzahl dieser &#039;Delay Slots&#039; ergeben sich aus der Anzahl der Pipelinestufen vor der Ausführungseinheit (da sie den Programmcounter verändert).&lt;br /&gt;
Kurzum programlauftechnisch werden Instruktionen in diesen &#039;Delay Slots&#039; ausgeführt bevor der Sprung in Wirklichkeit ausgeführt wird (bzw. &#039;gefetched&#039; werden).&lt;br /&gt;
Die kleinst mögliche Schleife benötigt deshalb fünf Instruktionen für einen Durchlauf.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loop	br	loop		;branch zu loop&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In vielen Fällen können &#039;Delay Slots&#039; sinnvoll genutzt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 1 (nicht optimiert - 8 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,1	;r1 = x Parameter&lt;br /&gt;
	movei	r1,7	;r2 = y Parameter&lt;br /&gt;
	gpci	r7,2	;r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 1 (optimiert - 6 Cycles): ====&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	gpci	r7,2	r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	movei	r0,1	;delay slot	r1 = x Parameter&lt;br /&gt;
	movei	r1,7	;delay slot     r2 = y Parameter&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 2 (nicht optimiert - 8 * n + 3 Cycles -&amp;gt; if n 128 -&amp;gt; total 1027 Cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127	;r0 = loop counter - 1&lt;br /&gt;
	movei	r1,0	;r1 = Füllwert&lt;br /&gt;
	nop&lt;br /&gt;
	&lt;br /&gt;
loop	st	r1,r6	;imem[r1] = r6&lt;br /&gt;
	addi	r1,1	;r1++&lt;br /&gt;
	subi	r0,1	;r0-- (t clear bei &amp;lt; 0)&lt;br /&gt;
	brts	loop	;branch loop solange t set&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 2 (optimiert - 6 * n + 2 Cycles -&amp;gt; if n 128 -&amp;gt; total 770 Cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127&lt;br /&gt;
	movei	r1,0&lt;br /&gt;
	&lt;br /&gt;
loop	subi	r0,1	;da t später verwendet wird nicht in delay slot benutzen (siehe Interruptverarbeitung)&lt;br /&gt;
	brts	loop&lt;br /&gt;
	st	r1,r6	;delay slot&lt;br /&gt;
	addi	r1,1	;delay slot	&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Speicherzugriffe ==&lt;br /&gt;
&lt;br /&gt;
UCore besitzt keine &#039;gewöhnlichen&#039; Lesebefehle für interne/externe Speicherzugriffe.&lt;br /&gt;
Um Pipeline-Stalls beim Lesen von Daten zu vermeiden (Latenz zum Speicher), wird eine Lesebefehl in zwei Operationen aufgeteilt.&lt;br /&gt;
Der erste Befehl ist ein &#039;Request&#039;, er teilt dem Core mit von welcher Adresse er etwas lesen soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Der zweite Befehl ist dann der &#039;Load&#039;, er holt sich die angekommenen Daten ab und speichert sie in einem Register.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== interner Speicherzugriff ====&lt;br /&gt;
&lt;br /&gt;
Bei internen Speicherzugriffen ist die Latenz zwischen Request und Load statisch (3 Cycles), bei externen Zugriff variable (hier wird im Fall eines Load ohne vorhandene Daten ein Stall ausgelöst).&lt;br /&gt;
&lt;br /&gt;
Mit den Opcode &#039;&#039;rqld&#039;&#039; (request load) und &#039;&#039;ld&#039;&#039; (load) kann vom internen Speicher gelesen werden.&lt;br /&gt;
Da die Daten erst zwei Operationen nach dem Request verfügbar sind, muss hier eine andere Instruktion ausgeführt werde (z.B. &#039;&#039;nop&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0	;send load to address (r0+0)&lt;br /&gt;
	nop		;data send to memory&lt;br /&gt;
	nop		;data will read&lt;br /&gt;
	ld	r1	;readed data to r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Da der interne Speicher immer innerhalb von einem Cycles antwortet und die Latenz durch Pipelinestufen entsteht, können internen Speicherzugriff bis zu drei Request hintereinander verwenden.&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0&lt;br /&gt;
	rqld	r0,1&lt;br /&gt;
	rqld	r0,2&lt;br /&gt;
	ld	r1	;r1 &amp;lt;- internal_mem[r0+0]&lt;br /&gt;
	ld	r2	;r2 &amp;lt;- internal_mem[r0+1]&lt;br /&gt;
	ld	r3	;r3 &amp;lt;- internal_mem[r0+2]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Bei Schreibzugriffen wird, wie bei anderen Prozessoren, ein &#039;&#039;st&#039;&#039; (Store-Kommando) verwendet.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti	$80	;imm extend&lt;br /&gt;
	move	r4,$01	;r4 = $8001&lt;br /&gt;
	move	r0,12	;r0 = 12&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	st	r0,r4	;imem[r4] = r0; $8001 = 12&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
Da ein &#039;&#039;st&#039;&#039;ore Befehl nur einen Register als Zieladresse benutzt, ist es vielen Fällen ärgerlich, diesen bei mehrfachen Schreiben zu verändern. Um in diesem Fall Abhilfe zu schaffen, wurde der Befehl &#039;&#039;ssto&#039;&#039; (Set Store Offset) und &#039;&#039;stwo&#039;&#039; (Store with Offset) implementiert. Mit &#039;&#039;ssto&#039;&#039; kann ein Offset für &#039;&#039;stwo&#039;&#039; gesetzt werden, d.h. der Wert der mit &#039;&#039;ssto&#039;&#039; gesetzt wird auf die Zieladresse von &#039;&#039;stwo&#039;&#039; addiert.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	stwo 1&lt;br /&gt;
	ssto r0,r7 ;imem[r7+1] = r0&lt;br /&gt;
	stwo 2&lt;br /&gt;
	ssto r1,r7 ;imem[r7+2] = r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist es leider etwas unangenehm mit der statischen Latenz bei internen Lesezugriffen, da man hier etwas mehr schreiben muss als man es von anderen Prozessoren gewöhnt ist.&lt;br /&gt;
&lt;br /&gt;
==== externe Speicherzugriffe ====&lt;br /&gt;
&lt;br /&gt;
Externe Speicherzugriffe verhalten sich ähnlich wie interne Zugriff.&lt;br /&gt;
Unterschiede gibt es in der Adressbreite (extern 32 Bit) und in der variablen Latenz (bestimmt durch mehre Faktoren).&lt;br /&gt;
Es gibt eine externe Hauptadresse (Base) die mit &#039;&#039;&#039;allen&#039;&#039;&#039; (bis auf edrqldi) externen Speicherzugriffsinstruktionen verwendet wird.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel Hauptadresse setzen: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;Hauptadresse ist r1:r0 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel schreibe in externen Speicher: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r4,$af&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	esadr	r1,r0	;Hauptadresse (esadr) is r1:r0&lt;br /&gt;
	est	r4,0	;externSpeicher[esadr + 0] = r4&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
Beim Lesen vom externen Speicher werden ebenfalls Request/Load Befehle verwendet um Latenzen, wenn möglich, zu vermeiden. Da die Latenz (meist) nicht vorhersehbar ist, wird bei nicht vorhandenen Daten solange gewartet bis sie vorhanden sind (Stall).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;Hauptadresse (esadr) ist r1:r0 &lt;br /&gt;
	erqld	0	;lade von externSpeicher[r0:r1 + 0]&lt;br /&gt;
	eld	r7	;lade externe Daten (evtl. Stall solange bis Daten vorhanden)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um Lade/Schreiblatenzen zu vermeiden bzw. zu reduzieren, können mehre Stores oder Request hintereinander ausgeführt werden (maximal 256 Requestzugriffe, keine Begrenzung bei Stores).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreibe 8 Worte in externen Speicher, kein Stall solange Schreibpuffer nicht voll): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,0&lt;br /&gt;
	esadr	r7,r6	;Hauptadresse (easdr) ist r7:r6 &lt;br /&gt;
	est	r0,0    ;externSpeicher[esadr + 0] = r0&lt;br /&gt;
	est	r0,1    ;externSpeicher[esadr + 1] = r0&lt;br /&gt;
	est	r0,2    ;....&lt;br /&gt;
	est	r0,3&lt;br /&gt;
	est	r0,4&lt;br /&gt;
	est	r0,5&lt;br /&gt;
	est	r0,6&lt;br /&gt;
	est	r0,7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (vermeiden von Leselatenzen) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r7,r6  ;Hauptadresse (easdr) ist r7:r6 &lt;br /&gt;
	erqld	0      ;request 4 von Worten request externSpeicher[easdr+0]&lt;br /&gt;
	erqld	1      ;                     request externSpeicher[easdr+1]&lt;br /&gt;
	erqld	2      ;...&lt;br /&gt;
	erqld	3      &lt;br /&gt;
	&lt;br /&gt;
	....		;mach irgendwas (Daten werden im &#039;Hintergrund&#039; geladen)&lt;br /&gt;
	&lt;br /&gt;
	eld	r0	;Daten von erstem request  (  externSpeicher[easdr+0] )&lt;br /&gt;
	eld	r1      ;Daten von zweiten request (  externSpeicher[easdr+1] )&lt;br /&gt;
	eld	r2      ;...&lt;br /&gt;
	eld	r3	;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Stack ==&lt;br /&gt;
&lt;br /&gt;
Der Stackpointer zeigt nach dem Reset auf Adresse $8000 (also am oberen Ende des internen Speichers).&lt;br /&gt;
Das Verhalten von &#039;&#039;push&#039;&#039;, &#039;&#039;request pops&#039;&#039; und &#039;&#039;pops&#039;&#039; sind gleich dem internen Speicherzugriffsverhalten (3 Cycles Latenz, Pipelined).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (1 pop): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r4	;sp--; imem[sp] = r4&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop		;request imem[sp], sp++&lt;br /&gt;
	nop&lt;br /&gt;
	nop&lt;br /&gt;
	pop	r4	;r4 = imem[sp]&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel (3 Werte auf Stack und wieder herunter) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r1&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r3&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop		;durch Latenz maximal 3 rqpop dann Daten (ansonsten &#039;poparqp&#039; benutzen (kann Request und Load gleichzeitig))&lt;br /&gt;
	push	r3&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Decoder extend ==&lt;br /&gt;
&lt;br /&gt;
Da viele Operationen konstante Werte (in Operand kodiert) benutzen können, aber diese aus Gründen der Befehlsbreite (16 Bit) je nach Befehl/Operanden nur eine teilweise unzureichende Größe/Breite verwenden können, wurde eine Dekoder Instruktion &#039;&#039;dexti&#039;&#039; (decoder extend immediate) eingeführt.&amp;lt;br&amp;gt;&lt;br /&gt;
Dieser Befehl wird vom Dekoder ausgeführt und wird in der eigentlichen Ausführungseinheit ignoriert (&#039;&#039;nop&#039;&#039;).&lt;br /&gt;
Sinn dieses Befehls ist es, konstante Werte um einen 8 Bit breiten Wert zu erweitern. Um Fehler zu vermeiden ist dieser Wert nur einen Cycle nach &#039;&#039;dexti&#039;&#039; verfügbar.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (16 Bit immediate Addition) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti     $12&lt;br /&gt;
	addi	  r0,$34	;r0 = r0 + $1234&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interrupts ==&lt;br /&gt;
&lt;br /&gt;
Interrupts sind in einem Pipeline basierenden Design immer ärgerlich (IMHO) zu handhaben. Da UCore nicht, wie viele Mikrokontroller, möglichst kurze Interrupt-Latenzen ermöglichen muss, gibt es in diesem Design auch keine garantierten Zeiten in welchen der Interrupt ausgeführt wird.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Um den Hardwareaufwand gering wie möglich zu halten, habe ich eine sogenannte &#039;&#039;Branch-Injektion&#039;&#039; implementiert. Der Hintergedanke ist, dass Sprünge sehr oft im Code ausgeführt werden und diese, im Fall eines Interrupts, dazu &#039;&#039;missbraucht&#039;&#039; werden können, direkt zum Interrupt-Service-Vector zu springen, anstatt ihren eigentlichen definierten Sprung auszuführen (dieser wird gespeichert und später ausgeführt).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Der Vorteil dieser Implementierung ist, ein sehr geringer Hardwareaufwand, der Nachteil ist, dass die Interrupt-Latenz variiert (Delta zwischen zwei Sprüngen) und sich Verhaltensregeln für &#039;Delay-Slots&#039; ergeben.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;	&lt;br /&gt;
	sei			;irq enable&lt;br /&gt;
	br	anySubroutine	;if irq is enabled and occure a branch is taken to irq vector and after irq is finished (rte) the give branch will taken&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In &#039;Delay-Slots&#039; sollten kein T-Bit gesetzt werden, welches für spätere Verwendungen gebraucht wird.&amp;lt;br&amp;gt; Außerdem sollten keine Speicher-Request (ohne Loads) an diesen Stellen ausgeführt werden.&lt;br /&gt;
Um Fehler zu vermeiden warnt der Assembler bei solchen Konstrukten.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
	sei&lt;br /&gt;
	br	anySubroutine&lt;br /&gt;
	addt	r0,r1	;delay slot	(t is not save in delay slot if irq is enabled, because t is only store at br instruction)&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dividieren ==&lt;br /&gt;
&lt;br /&gt;
Viele Prozessoren die auf geringen &#039;Platzverbrauch&#039; optimiert sind, versuchen wenn möglich Divisions-Operationen zu vermeiden oder führen diesen nicht in einer Pipeline-Implementierung aus.&amp;lt;br&amp;gt;&lt;br /&gt;
Auf der Softwareseite sind Divisionen in vielen Fällen vermeidbar oder durch bestimmte Methoden ersetzbar. Prinzipiell ist eine Division einfach in Software zu implementieren, in diesem Fall ist die Geschwindigkeit einer Hardwareimplementierung meist nicht annähernd zu erreichen.&amp;lt;br&amp;gt;&lt;br /&gt;
UCore bietet spezielle Befehle an, um einen Kompromiss aus Geschwindigkeit und Hardwareaufwand zu ermöglichen.&lt;br /&gt;
Wie bei einer normalen Division wird der Divisor und Dividend gesetzt, zusätzlich muss noch die Divsions-Bitbreite angegeben werden (max. 32 Bit). Durch den Befehl &#039;&#039;udivstep&#039;&#039; wird eine &#039;1-Bit Division&#039; ausgeführt, d.h. &#039;&#039;udivstep&#039;&#039; muss/kann sooft ausgeführt werden wie die Divisionsbreite gewählt ist. Als Resultat der Division ergeben sich der Quotient und der Rest.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* udiv16&lt;br /&gt;
;* &lt;br /&gt;
;* r0 	 	divident&lt;br /&gt;
;* r1		divisor&lt;br /&gt;
;*&lt;br /&gt;
;* return&lt;br /&gt;
;*&lt;br /&gt;
;* r2		qoutient&lt;br /&gt;
;* r3		remainder&lt;br /&gt;
;*&lt;br /&gt;
;* needs 34 cycles&lt;br /&gt;
;*&lt;br /&gt;
	&lt;br /&gt;
udiv16	&lt;br /&gt;
	udivinit	15&lt;br /&gt;
	udivsdd		r0&lt;br /&gt;
	udivsdv		r1&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,3	;(3+1)*4 = 16&lt;br /&gt;
	cli		;disable irq&lt;br /&gt;
udiv16Loop	&lt;br /&gt;
	subi	r0,1&lt;br /&gt;
	brts	udiv16Loop&lt;br /&gt;
	udivstep	;delay slot	!!!! note udivstep is not irq save, so use cli/sei lock&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	udivgq		r2	;delay slot		get qoutient&lt;br /&gt;
	udivgr		r3	;delay slot		get remainder&lt;br /&gt;
	sei			;delay slot		enable irqs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== weiter Beispiele ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
= UCtrl =&lt;br /&gt;
&lt;br /&gt;
UCtrl ist eine Abstraktionsschicht für einen Großteil der externen (Altera-DE2-115) Peripherien und stellt zusätzlich hilfreiche Element (Timer,…) zur Verfügung.&amp;lt;br&amp;gt;&lt;br /&gt;
Direkten Zugriff auf diese Komponente hat nur UCore (siehe Memorymap).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCtrl bietet dem Benutzer zugriff auf:&lt;br /&gt;
*LEDS &lt;br /&gt;
*SWITCHES&lt;br /&gt;
*7-Segment Anzeige&lt;br /&gt;
*LCD (zweizeilig auf DE2-115)&lt;br /&gt;
*Interrupt Kontrolle (für UCore)&lt;br /&gt;
*Timer/Counter&lt;br /&gt;
*Video Setup (inkl. Counter und Vertikal-‚Hit‘-Erkennung)&lt;br /&gt;
*PS/2 Port (in/out, zwei Ports)&lt;br /&gt;
*I2C (zwei Ports)&lt;br /&gt;
*Audio (DAC/ADC)&lt;br /&gt;
*HCore Setup und Daten (beschreibe ich später)&lt;br /&gt;
&lt;br /&gt;
== Register ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8000&lt;br /&gt;
name = LEDG_SW&lt;br /&gt;
read            fedcba9876543210&lt;br /&gt;
                SSSSSSSSSSSSSSSS&lt;br /&gt;
                &lt;br /&gt;
                S = switches on DE2-115&lt;br /&gt;
                &lt;br /&gt;
write           fedcba9876543210&lt;br /&gt;
                -------GGGGGGGGG&lt;br /&gt;
                &lt;br /&gt;
                G = LED Green (&#039;1&#039; is ON)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8001&lt;br /&gt;
name = LEDR&lt;br /&gt;
read            fedcba9876543210&lt;br /&gt;
                --------------ME&lt;br /&gt;
        &lt;br /&gt;
                M = &#039;1&#039; if running in modelsim&lt;br /&gt;
                E = &#039;1&#039; if running in emulator&lt;br /&gt;
                &lt;br /&gt;
write                fedcba9876543210&lt;br /&gt;
                -------RRRRRRRRR&lt;br /&gt;
                &lt;br /&gt;
                R = LED Red (&#039;1&#039; is ON)&lt;br /&gt;
&lt;br /&gt;
                 &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8002 - $8005&lt;br /&gt;
name = 7SEG&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                2 ----------------&lt;br /&gt;
                3 ----------------&lt;br /&gt;
                4 ----------------&lt;br /&gt;
                5 ----------------&lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                2 -6543210-6543210&lt;br /&gt;
                3 -6543210-6543210&lt;br /&gt;
                4 -6543210-6543210&lt;br /&gt;
                5 -6543210-6543210&lt;br /&gt;
                &lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 1 / 0 (&#039;1&#039; is ON)                &lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 3 / 2 (&#039;1&#039; is ON)&lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 4 / 4 (&#039;1&#039; is ON)&lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 5 / 6 (&#039;1&#039; is ON)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8006 - $8007&lt;br /&gt;
name = LCD&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                6 -------BDDDDDDDD&lt;br /&gt;
                7 ----------------&lt;br /&gt;
                &lt;br /&gt;
                B = &#039;1&#039; if read/write request is busy&lt;br /&gt;
                D = Data after request&lt;br /&gt;
                &lt;br /&gt;
                note: wait 1 cycle after read/write request before read&lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                6 ------WRDDDDDDDD&lt;br /&gt;
                7 ----------------&lt;br /&gt;
                &lt;br /&gt;
                W = &#039;0&#039; is request write, &#039;1&#039; is request read&lt;br /&gt;
                R = LCS RS&lt;br /&gt;
                D = data to write&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8008 - $8009&lt;br /&gt;
name = IRQ&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                8 -----------HADTT IRQ MSK&lt;br /&gt;
                9 -----------HADTT IRQ MEMORY&lt;br /&gt;
                &lt;br /&gt;
                TT = Timer 2/1 IRQ&lt;br /&gt;
                D  = Audio DAC FIFO run low&lt;br /&gt;
                A  = Audio ADC FIFO run full&lt;br /&gt;
                H  = HCORE has data&lt;br /&gt;
                &lt;br /&gt;
write                  fedcba9876543210&lt;br /&gt;
                8 -----------HADTT IRQ MSK&lt;br /&gt;
                9 -----------HADTT IRQ MEMORY&lt;br /&gt;
                &lt;br /&gt;
                TT = Timer 2/1 IRQ&lt;br /&gt;
                D  = Audio DAC FIFO run low&lt;br /&gt;
                A  = Audio ADC FIFO run full&lt;br /&gt;
                H  = HCORE has data&lt;br /&gt;
                &lt;br /&gt;
description:&lt;br /&gt;
&lt;br /&gt;
                IRQ MSK is used to enable given interrupts (for example D = &#039;1&#039; then Audio DAC irq will be used)&lt;br /&gt;
                IRQ MEMORY reflect after interrupt which interrupt is the source (for example TT = &#039;01&#039; then Timer 1 made this interrupt)&lt;br /&gt;
                &lt;br /&gt;
                You should/have to clear the given interrupt bit in IRQ MEMORY before leaving interrupt service routine.&lt;br /&gt;
                        &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $800A - $800F&lt;br /&gt;
name = TIMERS&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                A DDDDDDDDDDDDDDDD TIMER_1_LOW  (Timer 1 value low)&lt;br /&gt;
                B DDDDDDDDDDDDDDDD TIMER_1_HIGH (Timer 1 value high, note: low/high needs capture first to be updated)&lt;br /&gt;
                C ----------------&lt;br /&gt;
                D DDDDDDDDDDDDDDDD TIMER_2_LOW  (Timer 2 value low)&lt;br /&gt;
                E DDDDDDDDDDDDDDDD TIMER_2_HIGH (Timer 2 value high, note: low/high needs capture first to be updated)&lt;br /&gt;
                F ----------------&lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                A DDDDDDDDDDDDDDDD TIMER_1_LOW  (Timer 1 value low)&lt;br /&gt;
                B DDDDDDDDDDDDDDDD TIMER_1_HIGH (Timer 1 value high, write to high will update)&lt;br /&gt;
                C ------------CLSR TIMER_1_CTRL&lt;br /&gt;
                D DDDDDDDDDDDDDDDD TIMER_2_LOW  (Timer 1 value low)&lt;br /&gt;
                E DDDDDDDDDDDDDDDD TIMER_2_HIGH (Timer 1 value high, write to high will update)&lt;br /&gt;
                F ------------CLSR TIMER_2_CTRL&lt;br /&gt;
                &lt;br /&gt;
                C = Capture counter value for read (copy current counter value to $A/B $D/E)&lt;br /&gt;
                L = Enable Auto Reload Value (after counter value runs to 0 next value is $A/B $D/E)&lt;br /&gt;
                S = Stop timer&lt;br /&gt;
                R = Start timer (will do a Autoreload from $A/B $D/E)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8010 - $802F&lt;br /&gt;
name = VIDEO&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                10 00000DDDDDDDDDDD current HCount (11..0)&lt;br /&gt;
                11 000000DDDDDDDDDD current VCount (10..0)&lt;br /&gt;
                12 ---------------H Hit of programmed VCOUNT&lt;br /&gt;
                13 ---------------- &lt;br /&gt;
                14 ---------------- &lt;br /&gt;
                15 ----------------&lt;br /&gt;
                16 ----------------&lt;br /&gt;
                17 ---------------- &lt;br /&gt;
                18 ---------------- &lt;br /&gt;
                19 ----------------&lt;br /&gt;
                1a ----------------&lt;br /&gt;
                1b ---------------- &lt;br /&gt;
                1c ---------------- &lt;br /&gt;
                1d ----------------&lt;br /&gt;
                1e ----------------&lt;br /&gt;
                1f ---------------- &lt;br /&gt;
                20 ---------------- &lt;br /&gt;
                21 ----------------                &lt;br /&gt;
                22 ----------------&lt;br /&gt;
                23 ---------------- &lt;br /&gt;
                24 ---------------- &lt;br /&gt;
                25 ----------------&lt;br /&gt;
                26 ----------------&lt;br /&gt;
                27 ---------------- &lt;br /&gt;
                28 ---------------- &lt;br /&gt;
                29 ----------------&lt;br /&gt;
                2a ----------------&lt;br /&gt;
                2b ---------------- &lt;br /&gt;
                2c ---------------- &lt;br /&gt;
                2d ----------------&lt;br /&gt;
                2e ----------------&lt;br /&gt;
                2f ---------------- &lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                10 ---------------D VIDEO ON if &#039;1&#039;&lt;br /&gt;
                11 ------DDDDDDDDDD HSYNC&lt;br /&gt;
                12 ------DDDDDDDDDD HSTART&lt;br /&gt;
                13 ------DDDDDDDDDD HMEMSTART&lt;br /&gt;
                14 ------DDDDDDDDDD HSTOP &lt;br /&gt;
                15 ------DDDDDDDDDD HTOTAL&lt;br /&gt;
                16 -------DDDDDDDDD VSYNC&lt;br /&gt;
                17 -------DDDDDDDDD VSTART&lt;br /&gt;
                18 -------DDDDDDDDD VSTOP&lt;br /&gt;
                19 -------DDDDDDDDD VTOTAL&lt;br /&gt;
                1a DDDDDDDDDDDDDDDD LINE CACHE ADDRESS ADD LOW&lt;br /&gt;
                1b DDDDDDDDDDDDDDDD LINE CACHE ADDRESS ADD HIGH &lt;br /&gt;
                1c ---------------- LINE CACHE LATCH VALUE&lt;br /&gt;
                1d -------DDDDDDDDD LINE CACHE START ADDRESS (Pixel offset)&lt;br /&gt;
                1e --------DDDDDDDD HITVCOUNT (see description)&lt;br /&gt;
                1f ---------------- &lt;br /&gt;
                20 ------DDDDDDDDDD HLOADSTART&lt;br /&gt;
                21 ------DDDDDDDDDD HLOADSTOP                &lt;br /&gt;
                22 -------DDDDDDDDD VLOADSTART&lt;br /&gt;
                23 -------DDDDDDDDD VLOADSTOP&lt;br /&gt;
                24 -------DDDDDDDDD VLOADNEXT&lt;br /&gt;
                25 DDDDDDDDDDDDDDDD EXTERNAL MEMORY START ADDRESS (low)&lt;br /&gt;
                26 DDDDDDDDDDDDDDDD EXTERNAL MEMORY START ADDRESS (high)&lt;br /&gt;
                27 DDDDDDDDDDDDDDDD EXTERNAL MEMORY LINE OFFSET (low)&lt;br /&gt;
                28 DDDDDDDDDDDDDDDD EXTERNAL MEMORY LINE OFFSET (high)&lt;br /&gt;
                29 --------------DD MEMORY Convertion MODE&lt;br /&gt;
                2a ---------------- LATCH MEMORY CONFIG&lt;br /&gt;
                2b ---------------- &lt;br /&gt;
                2c ---------------- &lt;br /&gt;
                2d ----------------&lt;br /&gt;
                2e ----------------&lt;br /&gt;
                2f ----------------                                 &lt;br /&gt;
                &lt;br /&gt;
        HITVCOUNT = Programmable VCOUNT if this Value is written $12 bit 0 is set to &#039;1&#039; if VCOUNT is equal to this value&lt;br /&gt;
                  $12 bit 0 is cleared at write to this register&lt;br /&gt;
&lt;br /&gt;
        EXTERNAL MEMORY LINE OFFSET = will be add after every loaded line (for non interleaved video setup)&lt;br /&gt;
        &lt;br /&gt;
        MEMORY Convertion MODE = defines the format of data converted from external memory (ever 32Bit fetch) to line cache&lt;br /&gt;
        &lt;br /&gt;
                00 = X8 R8 G8 B8                       (32 Bit = (8 Bit for Red/Gree/Blue))&lt;br /&gt;
                01 = R5 R6 R5 R5 R6 R5                 (2 * 16 Bit = (5 Bit for Red/Blue and 6 Bit for Green))&lt;br /&gt;
                10 = X1 R5 R5 X1 R5 R5 R5 R5         (2 * 16 Bit = (5 Bit for Red/Gree/Blue))&lt;br /&gt;
                11 = X4 R4 R4 R4 X4 R4 R4 R4          (2 * 16 Bit = (4 Bit for Red/Gree/Blue))&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8030 - $8031&lt;br /&gt;
name = PS/2 port a/b&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                30 -----FWVDDDDDDDD        PS2_PORT_A (port A)&lt;br /&gt;
                31 -----FWVDDDDDDDD        PS2_PORT_B (port B)&lt;br /&gt;
                &lt;br /&gt;
                D = PS/2 DATA (Scan Code) valid if A = &#039;1&#039;&lt;br /&gt;
                V = Data valid&lt;br /&gt;
                W = Write FIFO not full&lt;br /&gt;
                F = all writes finished (Fifo with 16 entries)&lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
                note: wait 1 cycle after read/write request before read&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                30 R-----WADDDDDDDD        PS2_PORT_A (port A)&lt;br /&gt;
                31 R-----WADDDDDDDD        PS2_PORT_B (port B)&lt;br /&gt;
                &lt;br /&gt;
                D = PS/2 DATA to write&lt;br /&gt;
                A = get next scan code (read 2 cycles after this from $30/$31)&lt;br /&gt;
                W = Write data to PS/2 device&lt;br /&gt;
                R = reset PS/2 state machine (in/out)&lt;br /&gt;
&lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8032 - $8033&lt;br /&gt;
name = I2C port a/b&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                30 ------------D---       I2C_PORT_A (port A (eeprom on DE2-115))&lt;br /&gt;
                31 ------------D---       I2C_PORT_B (port B (audio/video in on DE2-115))&lt;br /&gt;
                &lt;br /&gt;
                D = data in from port A/B&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                30 ----EEE------ICD       I2C_PORT_A&lt;br /&gt;
                31 ----EEE------ICD       I2C_PORT_B&lt;br /&gt;
                &lt;br /&gt;
                D = data out value&lt;br /&gt;
                C = clock out value&lt;br /&gt;
                I = direction of data (&#039;0&#039; = in / &#039;1&#039; = out)&lt;br /&gt;
                &lt;br /&gt;
                EEE = is write enable for ICD&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8034 - $803b&lt;br /&gt;
name = AUDIO&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                34 DDDDDDDDDDDDDDDD ADC_DATA_LEFT_HIGH       &lt;br /&gt;
                35 --------DDDDDDDD ADC_DATA_LEFT_LOW                 &lt;br /&gt;
                36 DDDDDDDDDDDDDDDD ADC_DATA_RIGHT_HIGH                  &lt;br /&gt;
                37 --------DDDDDDDD ADC_DATA_RIGHT_LOW       &lt;br /&gt;
                38 ----------------&lt;br /&gt;
                39 ----------------&lt;br /&gt;
                3a ----------------&lt;br /&gt;
                3b ----------------&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                   fedcba9876543210&lt;br /&gt;
                34 DDDDDDDDDDDDDDDD DAC_DATA_LEFT_HIGH       &lt;br /&gt;
                35 --------DDDDDDDD DAC_DATA_LEFT_LOW            &lt;br /&gt;
                36 DDDDDDDDDDDDDDDD DAC_DATA_RIGHT_HIGH               &lt;br /&gt;
                37 --------DDDDDDDD DAC_DATA_RIGHT_LOW         &lt;br /&gt;
                38 AAAAAAAADDDDDDDD ADAC_CTRL (Data)&lt;br /&gt;
                39 --------DDDDDDDD DAC_IRQ_GEN (interrupt generate if lower) &lt;br /&gt;
                3a --------DDDDDDDD ADC_IRQ_GEN (interrupt generate if higher)&lt;br /&gt;
                3b ---------------- ADC_NEXT (recive values (after 2 cycles available in ADC_DATA ($34-$37)))&lt;br /&gt;
                &lt;br /&gt;
                ADAC_CTRL (Data) = configure internal ADC/DAC controller&lt;br /&gt;
                &lt;br /&gt;
                Adr 76543210&lt;br /&gt;
                0   -------- ignore&lt;br /&gt;
                1   -------E enable DAC&lt;br /&gt;
                2   ----CCCC DAC push counter (96KHz at 0, 48KHz at 1, 32KHz at 2 ....)&lt;br /&gt;
                3   -------E enable ADC&lt;br /&gt;
                4   ----CCCC ADC pull counter (96KHz at 0, 48KHz at 1, 32KHz at 2 ....)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $803c - $8044&lt;br /&gt;
name = HCORE CTRL/IO (in experimental state)                                &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Videosetup im Detail ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:16 32Bit Computer Konsole Uctrl video setup.png|miniatur|Video Setup]]&lt;br /&gt;
&lt;br /&gt;
UCore und UCtrl (also auch der Videokontoller) haben eine Taktfrequenz von 106,481 MHz, mit dieser Frequenz ist es möglich eine maximale Auflösung von 1440 x 900 Bildpunkten bei 60 Hz zu programmieren.&amp;lt;br&amp;gt;&lt;br /&gt;
Da diese Auflösung in vielen Fällen zu hoch ist, bzw. die Performance für eine flüssige Bildberechnung nicht immer ausreicht, kann ein interner Zeilen-Cache so programmiert werden, dass er nur eine bestimmte Anzahl an Pixeln pro Zeile ausgibt (H-Skaliert) und nur eine definierte Anzahl von Zeilen neu geladen wird (V-Skaliert).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Wie üblich können (siehe Bild), HSYNC, HSTART etc. frei programmiert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Als Quelle für die Bilddaten kann der SDRAM oder SRAM benutzt werden (siehe EXTERNAL_MEMORY_START_ADDRESS).&lt;br /&gt;
Das Farbformat kann zwischen einem 32 Bit Format (8Bit für R/G/B) und drei 16 Bit Formaten gewählt werden (siehe MEMORY Convertion MODE).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Support von Bitplanes oder Tiled-Grafiken gibt es nicht.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Video setup 360x225 4X4R4G4B Mode ($d0000000 ist Quelle (SDRAM)):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* setupVideo&lt;br /&gt;
;*&lt;br /&gt;
&lt;br /&gt;
setupVideo&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,videoDefault		;source&lt;br /&gt;
	movei	r1,UcTimer2Ctrl		;dest-1&lt;br /&gt;
	moveih	r0,&amp;gt;videoDefault&lt;br /&gt;
	moveih	r1,&amp;gt;UcTimer2Ctrl			&lt;br /&gt;
	movei	r2,26			;27-1&lt;br /&gt;
	&lt;br /&gt;
setupVideoLoop&lt;br /&gt;
&lt;br /&gt;
	rqldi	r0,0&lt;br /&gt;
	addi	r0,1&lt;br /&gt;
	addi	r1,1&lt;br /&gt;
	ld	r3&lt;br /&gt;
	subi	r2,1&lt;br /&gt;
	brts	setupVideoLoop&lt;br /&gt;
	st	r1,r3	;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
		&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
	&lt;br /&gt;
;*********************************************************************&lt;br /&gt;
;* data&lt;br /&gt;
;*********************************************************************&lt;br /&gt;
	&lt;br /&gt;
videoDefault		;AD NAME					&lt;br /&gt;
	&lt;br /&gt;
	word	$0001	;10 VIDEO_ON					&lt;br /&gt;
	word	$0097	;11 HSYNC (D = 11 .. 0)				&lt;br /&gt;
	word	$017f	;12 HSTART (D = 11 .. 0)			&lt;br /&gt;
	word	$017d	;13 HMEMSTART (D = 11 .. 0)			&lt;br /&gt;
	word	$071f	;14 HSTOP (D = 11 .. 0)				&lt;br /&gt;
	word	$076f	;15 HTOTAL (D = 11 .. 0)			&lt;br /&gt;
	word	$0002	;16 VSYNC (D = 10 .. 0)				&lt;br /&gt;
	word	$001e	;17 VSTART (D = 10 .. 0)			&lt;br /&gt;
	word	$03a2	;18 VSTOP  (D = 10 .. 0)			&lt;br /&gt;
	word	$03a3	;19 VTOTAL  (D = 10 .. 0)			&lt;br /&gt;
	word	$0000	;1a LC ADDER LOW				&lt;br /&gt;
	word	$0040	;1b LC ADDER HIGH				&lt;br /&gt;
	word	$0000	;1c LC ADDER LATCH				&lt;br /&gt;
	word	$0000	;1d LC START (10 .. 0) Pixeloffset		&lt;br /&gt;
	word	$0000	;1e						&lt;br /&gt;
	word	$0000	;1f						&lt;br /&gt;
	word	$0008	;20 HLOADSTART 					&lt;br /&gt;
	word	$00bc	;21 HLOADSTOP					&lt;br /&gt;
	word	$001e	;22 VLOADSTART 					&lt;br /&gt;
	word	$03a2	;23 VLOADSTOP 					&lt;br /&gt;
	word	$0004	;24 VLOADNEXT					&lt;br /&gt;
	word	$0000	;25 MEM_STARTADR_store low			&lt;br /&gt;
	word	$d000	;26 MEM_STARTADR_store high			&lt;br /&gt;
	word	$0000	;27 MEM_LINEOFFSET_store low			&lt;br /&gt;
	word	$0000	;28 MEM_LINEOFFSET_store high			&lt;br /&gt;
	word	$0002	;29 MEM_MODE_store 				&lt;br /&gt;
	word	$0000	;2a LATCH MEM_STARTADR/LINEOFFSET/MODE		&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Audiosetup im Detail ==&lt;br /&gt;
[[Datei:Uctrl audio overview.png|miniatur|rechts|audio simple]]&lt;br /&gt;
Da das DE-115 einen Wolfson WM8731 besitzt, unterteilt sich die Ansteuerung für die Audio-Ein/Ausgabe in zwei Teile.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Erste, ist die Konfiguration des WM8731, hierfür wird I2C Port B von UCTRL verwendet.&amp;lt;br&amp;gt;&lt;br /&gt;
Um die Konfiguration einfach zu halten sind Komponenten zur Initialisierung über I2C vorhanden (initAudio), es muss nur eine Tabelle mit den gewünschten Einstellungen übergeben werden (Register, Wert siehe WM8731 Registerbeschreibung).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Setup:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
audioDefault&lt;br /&gt;
	&lt;br /&gt;
	;&lt;br /&gt;
				;A =  8 7654 3210&lt;br /&gt;
	.data   $9,$0000	;9 =  0 0000 0000 	(inactivate interface)&lt;br /&gt;
	.data	$0,$0097	;0 =  0 1001 0111	;left line in mute&lt;br /&gt;
	.data	$1,$0097	;1 =  0 1001 0111	;right line in mute&lt;br /&gt;
	.data	$2,$006e	;2 =  0 0111 1001	;+6db left out&lt;br /&gt;
	.data	$3,$006e	;3 =  0 0111 1001	;0db right out&lt;br /&gt;
	.data	$4,$0012	;4 =  0 0001 0010	;0=0 mic boost off;&lt;br /&gt;
							;1=1 enable line input mute&lt;br /&gt;
							;2=1 line input to adc&lt;br /&gt;
							;3=0 disable bypass&lt;br /&gt;
							;4=1 DAC select&lt;br /&gt;
							;5=0 side tone disable&lt;br /&gt;
							;76=0 -6db sidetone						&lt;br /&gt;
	.data	$5,$0000	;5 =  0 0000 0000	;DAC soft Mute off, no Filer&lt;br /&gt;
	.data	$6,$0067	;6 =  0 0110 0111 	;DAC Power, Output Power, Device Power on&lt;br /&gt;
	.data	$7,$0009	;7 =  0 0000 1001 	;left justified, 24 bit&lt;br /&gt;
	.data	$8,$001e	;8 =  0 0001 1110	;0=0 normal mode&lt;br /&gt;
							;1=1 bosr (384/192)&lt;br /&gt;
							;5432=0111 96khz&lt;br /&gt;
							;78=00 no clk dividing	&lt;br /&gt;
	.data   $9,$0001	;9 =  0 0000 0001 	(activate interface)&lt;br /&gt;
	.data	$ff,$0000	;stop&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der zweite Teil, das Senden und Empfangen der Audio Daten wird über UCTRL Register $34 bis $3b ermöglicht(&#039;&#039;&#039;ADC&#039;&#039;&#039;/&#039;&#039;&#039;DAC_DATA&#039;&#039;&#039;, &#039;&#039;&#039;ADAC_CTRL&#039;&#039;&#039;, &#039;&#039;&#039;ADC&#039;&#039;&#039;/&#039;&#039;&#039;DAC_IRQ_GEN&#039;&#039;&#039;, &#039;&#039;&#039;ADC_NEXT&#039;&#039;&#039;).&amp;lt;br&amp;gt;&lt;br /&gt;
Für ADC und DAC gibt es jeweils für den linken &amp;amp; rechten Kanal je 24 Bit Daten zu empfangen/senden. &amp;lt;br&amp;gt;&lt;br /&gt;
ADC/DAC besitzen je einen 256 Worte (2 * 24 Bit) großen Queue, im Register &#039;&#039;&#039;DAC_IRQ_GEN&#039;&#039;&#039; ($39) bzw. &#039;&#039;&#039;ADC_IRQ_GEN&#039;&#039;&#039; ($3a) können die die Unter/Überlaufwerte, welche zu einem Interrupt führen, konfiguriert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
D.h. für einen Audioausgabe, konfiguriert man z.B. den DAC Queue auf den Wert 128 um beim Erreichen (kleiner als) einen Interrupt auszulösen (in welchen der Queue befüllt wird).&amp;lt;br&amp;gt;&lt;br /&gt;
Dadurch ist eine unterbrechungsfreie Wiedergabe/Aufnahme möglich ohne (je nach Einstellung) zu viele Interrupts auszulösen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die ADC/DAC Komponente in UCTRL kann über Register &#039;&#039;&#039;ADAC_CTRL&#039;&#039;&#039; ($38) konfiguriert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Die oberen 8 Bit des Datenworts bestimmen die Adresse, die unteren 8 Bit die Daten.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCTRL Audio Config:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name			address		876543210	comment&lt;br /&gt;
&lt;br /&gt;
nop			0		XXXXXXXXX	do nothing&lt;br /&gt;
ctrl			1		XXXXXXXXE	E = enable audio (default off)&lt;br /&gt;
set fifo read count	2		XXXXXXCCC	96KHz/C = fread [0..15]&lt;br /&gt;
set fifo write count	3		XXXXXXCCC	96KHz/C = fwrite [0..15]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Hier sollte vor der eigentlich Audio Ausgabe/Aufnahme, der jeweilige Counter für den ADC/DAC gesetzt werden (Counter der bei erreichen von 0 liest/schreibt). Z.B. den Wert 2 um eine 32 KHz Ausgabe einzustellen. Um die Queues zu lesen/schreiben muss noch unter Adresse 1 die Komponente aktiviert werden.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Audioausgabe von zwei 16 Bit Werten (links/rechts).&lt;br /&gt;
&amp;lt;br&amp;gt;	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	;r2 Audiobase $34&lt;br /&gt;
	;r1 = Wert für L, r4 = Wert für R&lt;br /&gt;
&lt;br /&gt;
	movei	r3,0&lt;br /&gt;
	stinc	r2,r1	;dac left high = value&lt;br /&gt;
	movei	r7,$1&lt;br /&gt;
	stinc	r2,r3	;dac left low = 0&lt;br /&gt;
	moveih	r7,$1&lt;br /&gt;
	stinc	r2,r4	;dac right high = value&lt;br /&gt;
	nop&lt;br /&gt;
	stinc	r2,r3	;dac right low = 0&lt;br /&gt;
	nop&lt;br /&gt;
	st	r2,r7	;dac address/ctrl = $0101	;ctrl = enable audio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Audio Tools ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Um eine einfache Handhabung der Audioausgabe zu ermöglichen, gibt es unter dem Verzeichnis &#039;&#039;assembler_files\ucore\components&#039;&#039; Funktionen, die eine einfache Audioausgabe (Sample) und das Abspielen von MOD (Musik-Module) ermöglichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PS/2 im Detail==&lt;br /&gt;
Mit den Registern &#039;&#039;&#039;PS2_PORT_A/B&#039;&#039;&#039; kann auf die PS/2 Schnittstelle des DE2-115 zugegriffen werden. Um alle Scancodes zu verarbeiten, ist ein Eingangsqueue (von PS/2) mit 16 Einträgen und einen Ausgangsqueue (zu PS/2) mit 8 Einträgen implementiert worden &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Zum Schreiben eines 8 Bit breiten Wertes zum PS/2-Device kann/sollte vor dem eigentlichen Transfer geprüft werden, ob der Ausgangsqueue voll ist (Bit 9 = &#039;&#039;&#039;W&#039;&#039;&#039; in &#039;&#039;&#039;PS2_PORT_A/B&#039;&#039;&#039;).&amp;lt;br&amp;gt;&lt;br /&gt;
Der zu sendende Datenwert muss in den unteren 8 Bit des Registers (&#039;&#039;&#039;PS2_PORT_A/B&#039;&#039;&#039;) geschrieben werden. Mit Bit 9 (&#039;&#039;&#039;W&#039;&#039;&#039; = write) wird er dann schließlich in den Ausgangsqueue übertragen.&amp;lt;br&amp;gt;&lt;br /&gt;
Mit Bit 10 (&#039;&#039;&#039;F&#039;&#039;&#039; = writes finish) kann, je nach Bedarf, überprüft werden ob alle Daten übermittelt wurden.&amp;lt;br&amp;gt;&lt;br /&gt;
Da es unter Umständen beim Schreiben zu Fehlern kommen kann (PS/2 Device defekt oder nicht angeschlossen bzw. es generiert keinen Takt), ist es möglich mittels Bit 15 &#039;&#039;&#039;R&#039;&#039;&#039; die State-Maschine zurückzusetzen.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Beim Lesen eine Wertes von dem PS/2-Device, muss mittels Bit 8 (&#039;&#039;&#039;V&#039;&#039;&#039; = data valid (lesen)) geprüft werden, ob Daten im Eingangsqueue vorhanden sind, wenn dies zutrifft, wird mit setzen von Bit 8 (&#039;&#039;&#039;A&#039;&#039;&#039; = ACK (schreiben)) das Datenwort in die unteren 8 Bit des Register übertragen (zwei Cycles delay).&amp;lt;br&amp;gt;&lt;br /&gt;
Um die Handhabung mit einer PS/2 Tastatur zu vereinfachen, sind unter &#039;&#039;components/ps2keyboards.s&#039;&#039; Funktionen implementiert, welche die Steuerung und Auswertung (zu Ascii etc.) übernehmen.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel: testen auf Taste &#039;Escape&#039;:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	;process keys (read from PS/2 Device and process)&lt;br /&gt;
	&lt;br /&gt;
	gpci	r7,2		;lr&lt;br /&gt;
	br	PS2Process&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	&lt;br /&gt;
	;key test (ESC)&lt;br /&gt;
	&lt;br /&gt;
	gpci	r7,2		;lr&lt;br /&gt;
	br	PS2TestKey&lt;br /&gt;
	movei	r0,118		;test again &#039;ESC&#039; 	delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	&lt;br /&gt;
	;&lt;br /&gt;
	&lt;br /&gt;
	cmpeqi	r0,0		;r0 = 0 no key pressed&lt;br /&gt;
	brtc	escIsPressed	;jump &lt;br /&gt;
	&lt;br /&gt;
	.&lt;br /&gt;
	.&lt;br /&gt;
	.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==I2C Ports im Detail==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Auf dem Altera DE2-115 befinden sich mehrere Komponenten (Audio-Codec, Video-In, EEPROM)  die mittels des I2C-Protokolls konfiguriert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Um diese Komponenten ansteuern zu können, besitzt UCtrl zwei Ports welche die jeweiligen Pins (SDA/SCK) der Komponenten bedienen können. Das eigentliche I2C-Protokoll ist in Software umgesetzt, d.h. mit den &#039;&#039;&#039;I2C_PORT_A/B&#039;&#039;&#039; Registern können nur Pins gesetzt bzw. ihr Zustand gelesen werden.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Zum Daten lesen (SDA) wird Bit 3 (&#039;&#039;&#039;D&#039;&#039;&#039;) von Register &#039;&#039;&#039;I2C_PORT_A/B&#039;&#039;&#039; benutzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Zum Konfigurieren des Daten-Pins (Datenrichtung) wird Bit 2 (&#039;&#039;&#039;I&#039;&#039;&#039;) verwendet. Hierbei ist zu beachten, dass beim Schreiben immer das zugehörige Enable gesetzt werden muss (Bit 11-9). Also beim setzen des CLK-Pins (z.B.: $22 = Enable CLK, setze CLK = &#039;1&#039;).&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Wie schon erwähnt, ist das eigentliche I2C Protokoll in Software umgesetzt. Unter &#039;&#039;components/i2c.s&#039;&#039; sind die benötigten Funktionen implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Timer im Detail==&lt;br /&gt;
UCtrl besitzt zwei integrierte 32 Bit große Timer/Counter.&amp;lt;br&amp;gt;&lt;br /&gt;
Konfiguriert werden kann jeder Timer über Register &#039;&#039;&#039;TIMER_1/2_CTRL&#039;&#039;&#039;.&amp;lt;br&amp;gt;&lt;br /&gt;
Um den Startwert bzw. den aktuellen Wert des Timers/Counters zu lesen (bzw. zu schreiben) werden die Register &#039;&#039;&#039;TIMER_1/2_LOW/HIGH&#039;&#039;&#039; benutzt.&amp;lt;br&amp;gt; &lt;br /&gt;
Beim Schreiben ist zu beachten, dass &#039;&#039;&#039;TIMER_1/2_HIGH&#039;&#039;&#039; nach &#039;&#039;&#039;TIMER_1/2_LOW&#039;&#039;&#039; geschrieben werden muss.&amp;lt;br&amp;gt;&lt;br /&gt;
Beim Lesen muss das Bit 3 (&#039;&#039;&#039;C&#039;&#039;&#039; = Capture Counter) einmalig gesetzt werden um den aktuellen Wert in die Register &#039;&#039;&#039;TIMER_1/2_HIGH/LOW&#039;&#039;&#039; (Lesezugriff) zu laden.&amp;lt;br&amp;gt;&lt;br /&gt;
Gestartet und gestoppt wird jeder Timer mit Bit 1/0 (&#039;&#039;&#039;S&#039;&#039;&#039; = Stop, &#039;&#039;&#039;R&#039;&#039;&#039; = Start) im Register &#039;&#039;&#039;TIMER_1/2_CTRL&#039;&#039;&#039;.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Timer übernimmt beim Start den 32 Bit großen/breiten Wert aus Register &#039;&#039;&#039;TIMER_1/2_LOW/HIGH&#039;&#039;&#039; und dekrementiert (-1) diesen solange bis er den Wert 0 erreicht.&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn der Wert 0 erreicht ist, wird ein &amp;quot;Timer-Hit&amp;quot; ausgelöst. Dieser kann je nach Bedarf einen Interrupt auslösen (siehe Register &#039;&#039;&#039;IRQ_MSK/MEMORY&#039;&#039;&#039;).&amp;lt;br&amp;gt;&lt;br /&gt;
Um einen kontinuierlichen Lauf zu ermöglichen, kann Bit 2 (&#039;&#039;&#039;L&#039;&#039;&#039; = Auto Reload) aktiviert werden, in diesem Fall wird bei dem Erreichen von Wert 0, der Wert aus &#039;&#039;&#039;TIMER_1/2_LOW/HIGH&#039;&#039;&#039; geladen und der Timer startet erneut.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel vom Setzen und Starten des Timers 2:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti	&amp;gt;UcTimer2LowValue&lt;br /&gt;
	movei	r2,UcTimer2LowValue	;timer 2 base&lt;br /&gt;
		&lt;br /&gt;
	move	r0,240		;low value&lt;br /&gt;
	move	r1,0		;high value&lt;br /&gt;
	&lt;br /&gt;
	stinc	r2,r0		;low&lt;br /&gt;
	movei	r0,5		;start with auto reload&lt;br /&gt;
	stinc	r2,r1		;high		&lt;br /&gt;
	nop&lt;br /&gt;
	stinc	r2,r0		;write config (lets go)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== SD-Zugriff im Detail ==&lt;br /&gt;
Über die Implementierung der SD-Karten Schnittstelle möchte ich hier nicht im Detail eingehen (es sei denn, es wird gewünscht).&amp;lt;br&amp;gt;&lt;br /&gt;
Zum benutzen der SD-Karte sind unter &#039;&#039;components/sdCardLoader.s&#039;&#039; Funktionen vorhanden.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Software (Block-IO) unterstützt SD-SC/HC/XC Karten, als Ziel für die zu lesenden Daten kann der SRAM/DRAM benutzt werden. Die maximale Transfergeschwindigkeit beträgt 100Mbit.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel, nachladen von 16384 Blöcken (a 256 Bytes):&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ;read sdcard to s/sdram&lt;br /&gt;
	&lt;br /&gt;
        dexti	&amp;gt;startBlock&lt;br /&gt;
	movei	r0,startBlock&lt;br /&gt;
	nop&lt;br /&gt;
	rqldi	r0,0	;low&lt;br /&gt;
	rqldi	r0,1	;high&lt;br /&gt;
	nop&lt;br /&gt;
	ld	r2&lt;br /&gt;
	ld	r3&lt;br /&gt;
	&lt;br /&gt;
	addi	r2,64	;64 blocks offset (ucore code/data)&lt;br /&gt;
	addtqi	r3,r3,0&lt;br /&gt;
	&lt;br /&gt;
	;set destination address&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,$10&lt;br /&gt;
	movei	r1,$02&lt;br /&gt;
	moveih	r0,$b1&lt;br /&gt;
	moveih	r1,$d0		;r1:r0 = $d002 b110 (dest start)&lt;br /&gt;
	&lt;br /&gt;
	dexti	&amp;gt;sdCardReadBlocks&lt;br /&gt;
	movei	r6,sdCardReadBlocks&lt;br /&gt;
	gpci	r7,2		;lr&lt;br /&gt;
	jmpi	r6,0&lt;br /&gt;
	movei	r4,$ff		;16384 blocks-1	delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	moveih	r4,$2f		;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Emulator ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:Ucore emulator4 info.png|miniatur]]&lt;br /&gt;
[[Datei:Ucore emulator3 info.png|miniatur]]&lt;br /&gt;
&lt;br /&gt;
Um den Test von Software zu vereinfachen, habe ich einen Emulator entwickelt, welcher das System auf einen ‚Windows‘ – System  (als Host) emuliert.  Der Emulator emuliert, in vielen Bereichen, Zyklen genau. &lt;br /&gt;
d.h. das Verhalten zwischen der Hardwareimplementierung und den Emulator ist identisch (nicht die Geschwindigkeit des Systems).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Um ein Sammelsurium von Tools beim Entwickelt zu vermeiden, sind mehre Tools im Emulator integriert (können aber auch einzeln ausgeführt werden):&lt;br /&gt;
&lt;br /&gt;
*Assembler (UCore, HCore)&lt;br /&gt;
*Grafikkonverter&lt;br /&gt;
*SD-Karten RAW IO (lesen/schreiben)&lt;br /&gt;
&lt;br /&gt;
Um den Status der Hardware zu überprüfen, wurden Hardware-Views implementiert:&lt;br /&gt;
&lt;br /&gt;
*UCore (Disassembler, Register, Status, Pipeline, …)&lt;br /&gt;
*HCore (Disassembler,…)&lt;br /&gt;
*Video Registerübersicht&lt;br /&gt;
*Audio Registerübersicht&lt;br /&gt;
*SD-Karten IO-Übersicht&lt;br /&gt;
*Speicheransicht (IRAM,SRAM,SDRAM, …)&lt;br /&gt;
&lt;br /&gt;
Die Geschwindigkeit der Emulation ist ungefähr 10-20 mal langsamer als auf der eigentlich Hardware. Um das Debuggen /Testen zu beschleunigen, kann die Software erkennen (wenn gewünscht) ob sie in einer Emulation läuft und so diverse Wartefunktionnen überspringen (z.B. warten auf VBlank).&lt;br /&gt;
&lt;br /&gt;
=== Starten des Emulators ===&lt;br /&gt;
&lt;br /&gt;
Unter dem Verzeichnis &#039;&#039;&#039;cross_development\binaries&#039;&#039;&#039; die Dateien &#039;&#039;&#039;ucore_emulator.exe&#039;&#039;&#039; ausführen. Unter Windows 8 kann es vorkommen, dass diese Datei als von einem unbekannten Hersteller angezeigt wird und das Ausführen extra bestätigt werden muss. Administratorrechte etc. werden nicht benötigt.&lt;br /&gt;
&lt;br /&gt;
=== Laden eines Packages ===&lt;br /&gt;
&lt;br /&gt;
Packages sind generierte Archive in denen sich alle benötigten Daten (IRAM, Flash, SDData,…) für einen Testlauf befinden. Sie sind mit wenigen Aufwand ladbar und vereinfachen die Handbarkeit des Emulators (wenn kein Debuggen erwünscht ist).&amp;lt;br&amp;gt;&lt;br /&gt;
Um ein Packages zu laden, muss unter dem Reiter &#039;&#039;&#039;io&#039;&#039;&#039; im Bereich &#039;&#039;&#039;package&#039;&#039;&#039; das gewollte Package ausgewählt werden ‚&#039;&#039;&#039;…&#039;&#039;&#039;. (Alle generierten Packages sind unter dem Verzeichnis &#039;&#039;&#039;packages &#039;&#039;&#039; verfügbar). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Ucore emulator2 info.png|miniatur|zentriert]]&lt;br /&gt;
&lt;br /&gt;
Danach mittels des Buttons &#039;&#039;&#039;Load&#039;&#039;&#039; kann das Package geladen werden. Wenn das erfolgt ist, kann das Programm mittels &#039;&#039;&#039;Start&#039;&#039;&#039; (Play-Knopf in der Toolleiste) gestartet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Ucore emulator1 info.png|miniatur|zentriert]]&lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/310121&lt;br /&gt;
&lt;br /&gt;
= Homepage =&lt;br /&gt;
&lt;br /&gt;
http://www.goldmomo.de&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=85081</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=85081"/>
		<updated>2014-10-03T11:34:41Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: Crashkurs Emulator&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein &#039;Computer&#039;system, welches nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses nachbildet.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen, welches vollständig&#039;&#039;&#039;*&#039;&#039;&#039; selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (&#039;&#039;&#039;*&#039;&#039;&#039;FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL verwendet, für Emulation und Tools (Assembler etc.) wird C# mit .NET benutzt.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 zur Verfügung gestellt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE = Utility Core), welcher über einen memorymapped UCTRL-Komponente vollständigen Zugriff auf alle Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* Programmierbares Audio Interface&lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Zwei Timer/Counter&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCORE) ist der &#039;&#039;&#039;zentrale&#039;&#039;&#039; Prozessor im System, d.h. er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist dazu gedacht, eine einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn, für alle meine Demos/Spiele, als Hauptprozessor benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In einen experimentellen Zustand befindet sich noch der HCORE Block. Dieser Block enthält mehre (konfigurierbar) 32 Bit Prozessoren die über spezielle Techniken (Hardwaresemaphoren, parallele Sprünge, … ) eine parallele Verarbeitung von Software vereinfachen sollen und Latenzprobleme bei Multithreading vermeiden. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
[[Datei:Goldmomo emulator.png|miniatur|rechts|Emulator]]&lt;br /&gt;
Um die Softwareentwicklung (Debuggen etc.) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Registerstatus, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (in Emulator integriert). Ein Compiler (z.B.: für C) existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/8i5pzlncr77cl1v/AADt708pu8p6irXm-YO-1so2a/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo endlos Sheriff2213.png|miniatur|Sheriff 2213]]&lt;br /&gt;
[[Datei:Goldmomo endlos SpacePilotOfDeath.png|miniatur|SpacePilotOfDeath]]&lt;br /&gt;
[[Datei:Goldmomo endlos ModPlayer.png|miniatur|MOD Player]]&lt;br /&gt;
[[Datei:Goldmomo endlos GfxExtension.png|miniatur|GFX Extension]]&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= UCORE Programmierung =&lt;br /&gt;
&lt;br /&gt;
UCORE unterscheidet sich einigen Teilen von einem &#039;&#039;normalen&#039;&#039; Prozessordesign.&lt;br /&gt;
Die Gründe bzw. Ziele welche verfolgt wurden, waren eine möglichst hohe Taktrate und ein möglichst geringe Benutzung von Hardwareressourcen, aber dennoch eine hohe Verarbeitungsgeschwindigkeit.&lt;br /&gt;
Dadurch ergeben sich einige Besonderheiten, welche bei der Programmierung beachtet werden &#039;&#039;&#039;müssen&#039;&#039;&#039; (siehe Registerzugriffe, Branch/Jump Delayslots, Request/Load Zugriffe).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pipeline ===&lt;br /&gt;
&lt;br /&gt;
Wie gesagt hat dieser Core eine sechsstufige Pipeline:&lt;br /&gt;
&lt;br /&gt;
# 1 Prepare Fetch (adressiere Daten)&lt;br /&gt;
# 2 Fetch (hole Daten)&lt;br /&gt;
# 3 Decode (dekodiere Daten)&lt;br /&gt;
# 4 Read Register (lese Register)&lt;br /&gt;
# 5 Execute (ausführen)&lt;br /&gt;
# 6 Write Register (schreibe Register (hat einen Bypass zu Stufe 4, somit keine extra Delay) &lt;br /&gt;
&lt;br /&gt;
Jede Instruktion wird in einem Cycle ausgeführt, nur der externe Speicherzugriff (nur Daten) kann einen Stall (Stillstand) der Pipeline verursachen.&lt;br /&gt;
&lt;br /&gt;
== Interne Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
In meinem System wird die folgende interne Speichermap verwendet (16 Bit interner Adressraum).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$0000 code / data memory&lt;br /&gt;
*     16384 * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$3fff&lt;br /&gt;
$4000 code / data memory MIRROR&lt;br /&gt;
*     &lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$7fff&lt;br /&gt;
$8000 uctrl / memory			StackPointer start at $8000 on reset&lt;br /&gt;
*     XXXX * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$XXXX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Reset-Vektor befindet sich an Adresse $0000, der Stackpointer an Adresse $8000 (am Ende des internen RAMs).&amp;lt;br&amp;gt; &lt;br /&gt;
Der Interruptvektor zeigt nach dem Reset auf Adresse $0010 (sollte nach dem Reset an die benötigte Position verschoben werden).&amp;lt;br&amp;gt; &lt;br /&gt;
Ab Adresse $8000 wird die Komponente UCtrl in den Adressraum &#039;gemappt&#039; (diese Komponente enthält Register für externe Hardware Peripherie etc.).&lt;br /&gt;
&lt;br /&gt;
== externe Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
Über den &#039;externen&#039; Datenbus (32 Bit Adressraum) kann auf folgende Komponenten zugegriffen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$a000 0000 - $a000 001f SDCard-Controller&lt;br /&gt;
$d000 0000 - $d3ff ffff SDRAM&lt;br /&gt;
$e000 0000 - $e03f ffff FLASH&lt;br /&gt;
$f000 0000 - $f00f ffff SRAM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei den meisten meiner Programme wird ein Boot-Programm aus dem FLASH-Speicher gelesen, welches einen Speichertest ausführt und auf das Einlegen einer SD-Karte, mit dem zu ladenden Programm, wartet.&lt;br /&gt;
&lt;br /&gt;
== Opcodes/Operanten ==&lt;br /&gt;
&lt;br /&gt;
UCore hat keine &#039;RISC&#039;-Typischen Befehlssatz (benutzt viele Befehle, aber mit geringe Komplexität).&amp;lt;br&amp;gt;&lt;br /&gt;
Da ein Instruktions-Wort nur eine Breite von 16 Bit hat, können nur bedingte Mengen an Operanden verwendet werden. Um jedoch die Programmierung flexibler zu gestalten, haben viele Opcodes mehrere Arten von Operanden. Für die Ausführungseinheit (ALU) ergibt sich dadurch keine Ressourcenveränderung, da der Decoder nur die Opcodes/Operanden in ein internes einheitliches Format auflöst.&amp;lt;br&amp;gt;&lt;br /&gt;
Operanden können bis zu drei Register verwenden und je nach Typ einen festen Wert, dieser Wert ist je nach Typ in seiner Bitbreite beschränkt (kann mittels Decoderinstruktion &#039;&#039;&#039;dexti&#039;&#039;&#039; erweitert werden).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Operanden Formate ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dc,imm8       Register, 8 Bit Wert&lt;br /&gt;
 dc,db,da      Register, Register , Register&lt;br /&gt;
 dc,db,imm3    Register, Register, 3 Bit Wert&lt;br /&gt;
 imm12         12 Bit Wert&lt;br /&gt;
 db,da         Register, Register&lt;br /&gt;
 imm6          6 Bit wert&lt;br /&gt;
 da            Register&lt;br /&gt;
 kein Operant&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Opcodes selber können in folgenden (klassischen) Typen eingeordnet werden.&lt;br /&gt;
* Transfer-Befehle (move, ld, st, rqld ,...)&lt;br /&gt;
* Arithmetische Befehle (add, sub, mul, neg,…)&lt;br /&gt;
* Logische Befehle (and, or, xor, bic,…)&lt;br /&gt;
* Bit-Befehle (bset,bclr,bffo,..)&lt;br /&gt;
* Vergleichs-Befehle (cmpeq, cmplo,…)&lt;br /&gt;
* Schiebe-Befehle (lsr,asr, swp,…)&lt;br /&gt;
* Programmsteuerungs-Befehle (br, jmp, rti…)&lt;br /&gt;
* Status-Befehle (sei,cli, getssr, …)&lt;br /&gt;
&lt;br /&gt;
==== Opcode / Operand(en) / Beschreibung ==== &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
movei     	dc,imm8		dc = imm&lt;br /&gt;
moveih    	dc,imm8		dc[15..8] = imm &amp;lt;&amp;lt; 8 | dc[7..0]&lt;br /&gt;
addi      	dc,imm8		dc = dc + imm&lt;br /&gt;
subi      	dc,imm8		dc = dc - imm&lt;br /&gt;
lsri      	dc,imm8		dc = dc &amp;gt;&amp;gt; imm&lt;br /&gt;
asri      	dc,imm8		dc = ((signed)dc) &amp;gt;&amp;gt; imm&lt;br /&gt;
muli      	dc,imm8		dc = dc * imm&lt;br /&gt;
cmpeqi    	dc,imm8		t = set if dc == imm else cleared&lt;br /&gt;
cmploi    	dc,imm8		t = set if dc &amp;lt; imm else cleared&lt;br /&gt;
cmplosi   	dc,imm8		t = set if  (signed)dc &amp;lt; (signed) imm else cleared&lt;br /&gt;
gpci      	dc,imm8		dc = pc + imm&lt;br /&gt;
jmpi      	dc,imm8		pc = dc + imm&lt;br /&gt;
extri     	dc,imm8		t = bit #imm of dc&lt;br /&gt;
rqldi     	dc,imm8		request (internal) mem; address = dc + imm&lt;br /&gt;
getsp     	dc,imm8		dc = sp + imm&lt;br /&gt;
dexti     	imm11		store imm as extension for next instruction&lt;br /&gt;
&lt;br /&gt;
add		dc,db,da	dc = db + da&lt;br /&gt;
sub     	dc,db,da	dc = db - da&lt;br /&gt;
lsr     	dc,db,da	dc = db &amp;gt;&amp;gt; da&lt;br /&gt;
asr     	dc,db,da	dc = ((signed)db) &amp;gt;&amp;gt; da&lt;br /&gt;
mul     	dc,db,da	dc = db * da&lt;br /&gt;
addt    	dc,db,da	dc = db + da + t&lt;br /&gt;
subt    	dc,db,da	dc = db - da - t&lt;br /&gt;
muls    	dc,db,da	dc = db * da&lt;br /&gt;
movets  	dc,db,da	dc = db if t = set else da&lt;br /&gt;
and     	dc,db,da	dc = db &amp;amp; da&lt;br /&gt;
or      	dc,db,da	dc = db | da&lt;br /&gt;
xor     	dc,db,da	dc = db ^ da&lt;br /&gt;
bic     	dc,db,da	dc = db &amp;amp; ~da&lt;br /&gt;
&lt;br /&gt;
addqi		dc,db,imm3	dc = db + imm&lt;br /&gt;
subqi   	dc,db,imm3	dc = db - imm&lt;br /&gt;
lsrqi   	dc,db,imm3	dc = db &amp;gt;&amp;gt; imm&lt;br /&gt;
asrqi   	dc,db,imm3	dc = ((signed)db) &amp;gt;&amp;gt; imm&lt;br /&gt;
mulqi   	dc,db,imm3	dc = db * imm3&lt;br /&gt;
addtqi  	dc,db,imm3	dc = db + imm + t&lt;br /&gt;
subtqi  	dc,db,imm3	dc = db - imm - t&lt;br /&gt;
edrqldi 	db,da,imm3	request (external) mem; address = (db:da) + imm3&lt;br /&gt;
&lt;br /&gt;
br		imm12		pc = pc + signed(imm)&lt;br /&gt;
brts		imm12		pc = pc + signed(imm) if t is set&lt;br /&gt;
brtc		imm12		pc = pc + signed(imm) if t is cleared&lt;br /&gt;
	             &lt;br /&gt;
cmpeq		db,da		t = set if db == da else cleared		&lt;br /&gt;
cmplo   	db,da           t = set if db &amp;lt; da else cleared&lt;br /&gt;
cmplos  	db,da           t = set if  (signed)db &amp;lt; (signed) da else cleared&lt;br /&gt;
esadr   	db,da		esadr = db:da&lt;br /&gt;
swp     	db,da		db = da[7..0]:da[15..8] &lt;br /&gt;
swptc   	db,da		db = da[7..0]:da[15..8] if t = set else da&lt;br /&gt;
st      	db,da		imem[db] = da&lt;br /&gt;
stinc   	db,da		imem[db] = da; db = db + 1&lt;br /&gt;
bffo    	db,da		db is first bit that is 1 found in da (from MSB to LSB)&lt;br /&gt;
bset    	db,da		db = db | 1 &amp;lt;&amp;lt; da&lt;br /&gt;
bclr    	db,da		db = db &amp;amp; ~ (1 &amp;lt;&amp;lt; da)&lt;br /&gt;
cmple   	db,da		t = set if db &amp;lt;= da else cleared&lt;br /&gt;
cmples  	db,da		t = set if  (signed)db &amp;lt;= (signed) da else cleared&lt;br /&gt;
rqld    	db,da		request (internal) mem; address = db + da&lt;br /&gt;
extb    	db,da		db = da byte to word singed extended&lt;br /&gt;
stwo    	db,da		imem[db + STORE_OFFSET] = da&lt;br /&gt;
andts   	db,da		db = db &amp;amp; da if t = set else da&lt;br /&gt;
orts    	db,da           db = db | da if t = set else da&lt;br /&gt;
xorts   	db,da           db = db ^ da if t = set else da&lt;br /&gt;
bicts   	db,da           db = db &amp;amp; ~da if t = set else da&lt;br /&gt;
lsrts   	db,da		db = db &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
asrts   	db,da           db = ((signed)db) &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
mults   	db,da           db = db * da if t = set else da&lt;br /&gt;
mulsts  	db,da		db = (signed)db * (signed)da if t = set else da&lt;br /&gt;
&lt;br /&gt;
erqldi		imm6		request (external) mem; address = esadr + imm	&lt;br /&gt;
ssto		imm6		STORE_OFFSET = imm&lt;br /&gt;
udivinit	imm6		udivqoutient = 0; udivrest = 0; udivbitcounter = imm&lt;br /&gt;
&lt;br /&gt;
eld		da		da = requested value from external memory&lt;br /&gt;
push            da		sp = sp – 1; imem[sp] = da&lt;br /&gt;
gmulhi          da		da = multiply result [31..15] from last multiplication&lt;br /&gt;
ld/pop          da		da = requested value from internal memory&lt;br /&gt;
poparqp         da		da = requested value from internal memory; request in internal memory adr = sp; sp = sp + 1&lt;br /&gt;
neg             da		da = 0 - da&lt;br /&gt;
udivgq          da		get division qoutinent&lt;br /&gt;
udivgr          da		get division remainder&lt;br /&gt;
udivgqh         da		get division qoutinent high [31 ..16]&lt;br /&gt;
udivgrh         da              get division remainder high [31 ..16]&lt;br /&gt;
udivsdd         da		set division divident &lt;br /&gt;
udivsdv         da		set division divider&lt;br /&gt;
udivsddh        da		set division divident high [31 ..16]&lt;br /&gt;
udivsdvh        da		set division divider  high [31 ..16]&lt;br /&gt;
erqld           da		request (external) mem; address = esadr + da&lt;br /&gt;
setsp           da		sp = da&lt;br /&gt;
erqldb          da		request (external) mem; address = esadr + da / 2&lt;br /&gt;
jmpts           da		pc = da if t = set&lt;br /&gt;
jmptc           da		pc = da if t = cleared&lt;br /&gt;
negts           da		da = 0 - da if t = set else da&lt;br /&gt;
&lt;br /&gt;
rqpop				internal memory request address = sp; sp = sp + 1&lt;br /&gt;
cli				disable interrupts&lt;br /&gt;
sei				enable interrupts&lt;br /&gt;
rti				pc = pc_before interrput&lt;br /&gt;
tnt				t = not t&lt;br /&gt;
vtt				t = v (overflow/underflow wrom add/sub)			&lt;br /&gt;
epushsadrl			sp = sp – 1; imem[sp] = esadr[15..0]&lt;br /&gt;
epushsadrh			sp = sp – 1; imem[sp] = esadr[31..16]&lt;br /&gt;
epopsadrl			esadr[15..0] = requested value from internal memory&lt;br /&gt;
epopsadrh			esadr[31..16] = requested value from internal memory&lt;br /&gt;
udivstep			performe one division step &lt;br /&gt;
nop				do nothing&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Registerzugriffe ==&lt;br /&gt;
&lt;br /&gt;
Da Register vor der Ausführungseinheit (ALU) gelesen werden und nach der Ausführungseinheit geschrieben werden, ergibt sich eine Latenz zwischen Register Zugriffen. Der Grund für diese Implementierungsart ist, schlicht und einfach, die Performanz zu erhöhen (weniger Logik pro Takt). Als Nebeneffekt entsteht eine Latenz zwischen den Zugriffen. Es bieten sich mehrere Möglichkeiten an, diese Register-&#039;Hazards&#039; in Hardware zu vermeiden (Registerscoring, Renaming etc.). Um den Hardwareimplementierung klein und schnell zu halten, wird in UCore auf einen Hardwaretest verzichtet. Als Resultat, &#039;&#039;&#039;muss&#039;&#039;&#039; der Anwender Registerabhängigkeiten im Programm-Code behandeln/beachten.&lt;br /&gt;
Der einzige Nachteil (der durch eine Latenz entsteht) ergibt sich in einer RAW (Read after Write) Abhängigkeit (da die Latenz hier eine Cycle beträgt). In diesem Fall sollte/muss eine andere Instruktion (z.B. nop) eingefügt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreiben eines Registers und späteres Lesen): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae	; &lt;br /&gt;
	nop		;write r0 = ae wird ausgeführt&lt;br /&gt;
	addi	r0,1	;r0 = r0 ($ae) + 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Im einfachsten Fall sollte eine &#039;&#039;nop&#039;&#039; Operation bei solchen Abhängigkeit verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (nicht optimiert mit nop - 6 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	nop&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	nop&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In den meisten Fällen kann aber eine andere Operationen als &#039;Füllung&#039; bei Registerabhängigkeiten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (optimiert - 4 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um versehentlich programmierte RAW-&#039;Hazards&#039; zu erkennen, erzeugt der Assembler Warnungen, ebenfalls kann der Emulator diese zur Laufzeit erkennen.&lt;br /&gt;
Prinzipiell ist es möglich, in gewissen Situationen, RAW-&#039;Hazards&#039; absichtlich zuzulassen (z.B. Optimierungen um Register zu sparen), wovon aber im Normalfall abzuraten ist.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Arithmetische Befehle ==&lt;br /&gt;
&lt;br /&gt;
Arithmetische Befehle unterscheiden sich, in UCore, nicht von anderen Prozessoren–Designs.&lt;br /&gt;
Neben Addition, Subtraktion, Multiplikation existiert noch eine Instruktion zum Negieren. &lt;br /&gt;
Division wird über mehre Instruktion unterstützt (siehe Division).&lt;br /&gt;
Zu beachten ist, dass bei Addition, Subtraktionen Carry/Borrow immer ins t-Flag übernommen wird und das Overflow-Flag in den Statusregister gespeichert wird.&lt;br /&gt;
&lt;br /&gt;
Arithmetische Befehle wie &#039;&#039;&#039;addt&#039;&#039;&#039;,&#039;&#039;&#039;subt&#039;&#039;&#039;,… benutzen das t-Flag als Carry/Borrow-In. &lt;br /&gt;
Durch diesen Mechanismus können Operationen mit mehr als 16 Bit-Breite (32 Bit etc.) einfach implementiert werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (32 Bit Addition) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	add	r0,r0,r2&lt;br /&gt;
	addt	r1,r1,r3		;r1:r0 = r1:r0 + r3:r2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Multiplikationsoperationen haben als Ergebnis ein 32 Bit wert. &lt;br /&gt;
Die unteren 16 Bit dieses Wertes geben die Multiplikationen selbst zurück. &lt;br /&gt;
Die oberen 16 Bit werden intern gespeichert und können mit der Instruktion &#039;&#039;&#039;gmulhi&#039;&#039;&#039; in einen Register transferiert werden.&lt;br /&gt;
Logische Befehle:&lt;br /&gt;
&lt;br /&gt;
Neben den üblichen logischen Befehlen wie &#039;&#039;&#039;and&#039;&#039;&#039;, &#039;&#039;&#039;or&#039;&#039;&#039;, &#039;&#039;&#039;xor&#039;&#039;&#039;, ist die Instruktion &#039;&#039;&#039;bic&#039;&#039;&#039; (bit clear = and not) implementiert. Alle logischen Befehle können mit zusätzlicher Bedingung ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (bedingter logischer Befehl) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	cmplosi		r0,0	;t = true wenn r0 &amp;lt; 0 &lt;br /&gt;
	xorts		r0,r0	;wenn t = true r0 = r0 xor r0 (r0 = 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bit Befehle ==&lt;br /&gt;
&lt;br /&gt;
Da die Breite vom Immediate-Werte, je nach Instruktions-Typ, begrenzt ist, sind Bitoperationen mit logischen Befehlen meist umständlich, in Software, zu implementieren. &lt;br /&gt;
Zum Setzen bzw. Löschen sind die Instruktionen &#039;&#039;&#039;bset&#039;&#039;, &#039;&#039;&#039;bclr&#039;&#039; implementiert worden. Die Instruktion &#039;&#039;&#039;bffo&#039;&#039;&#039; (bit find first one) sucht von MSB zu LSB, das erste Bit mit Wert Eins. &lt;br /&gt;
&lt;br /&gt;
Die Instruktion &#039;&#039;&#039;extri&#039;&#039;&#039; (extract immediat), transferiert das angegeben Bit in das t-Flag.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (extri) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	extri	r0,15	;bit 15 in r0 -&amp;gt; t-Flag (ist Wert negative)&lt;br /&gt;
	negts	r0	;wenn t = true dann r0=0-r0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Schiebeoperationen ==&lt;br /&gt;
&lt;br /&gt;
UCore implementiert nur Schiebeoperation in die „rechte“ – Richtung (Arithmetisch rechts schieben (&#039;&#039;&#039;asr&#039;&#039;&#039;), Logisch rechts schieben (&#039;&#039;&#039;lsr&#039;&#039;&#039;)). Um Werte nach links zu schieben, sollte die Multiplikationoperation verwendet werden. Um Bytes in einem Register zu tauschen sollte die Operation &#039;&#039;&#039;swp&#039;&#039;&#039; (swap) verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Vergleichsoperationen ==&lt;br /&gt;
&lt;br /&gt;
Vergleichsoperation setzen in UCore immer als Ergebnis das t-Flag (siehe Bedingungen), d.h. jede Art von Vergleich hat ihren eigenen Befehl (keine Statusflags wie z.B. bei 68k). &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Neben dem Vergleich auf den gleichen Wert (&#039;&#039;&#039;cmpeq&#039;&#039;&#039; = compare equal), gibt es Vergleiche auf ‚&amp;lt;=‘ (&#039;&#039;&#039;cmple[s]&#039;&#039;&#039; (unsigned und signed)) und auf ‚&amp;lt;‘ (&#039;&#039;&#039;cmplo[s]&#039;&#039;&#039; ] (unsigned und signed)). Vergleiche auf ‚&amp;gt;‘‚ ‘&amp;gt;=‘ bzw. nicht gleich sind nicht vorhanden, da sie logisch durch den Wert des t-Flags, bei der Benutzung der gegenteiligen Operationen, bestimmt werden können.&lt;br /&gt;
&lt;br /&gt;
== Bedingungen ==&lt;br /&gt;
&lt;br /&gt;
UCore benutzt ein T-Bit (true/wahr Bit) um Bedingungen zu beschreiben/verarbeiten. Normalerweise (nicht ausschließlich) wird dieses Bit von Vergleichsoperationen gesetzt und kann nachfolgend von Operationen benutzt werden welche das T-Bit abfragen (z.B. bedingte Sprünge).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel:====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	cmpeqi	r0,0		;vergleiche auf r0 gleich 0, wenn wahr da (t=1) ansonsten (t=0)&lt;br /&gt;
	brts	r0IstNull	;springe zum &#039;r0IstNull&#039; Label wenn t set (t=1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist notwendig Register nur dann zu setzen, wenn bestimmte Bedingungen eintreten. In solchen Fällen ist es ärgerlich bedingte Sprünge auszuführen, da sie etwas Zeit benötigen (siehe Delay Slots) und den Programmcode unübersichtlich machen (Spaghetticode).&amp;lt;br&amp;gt;&lt;br /&gt;
Aus diesem Grund, unterstützen einige Befehle eine bedingte Ausführung.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	move	r1,123&lt;br /&gt;
	move 	r2,23&lt;br /&gt;
	…&lt;br /&gt;
	cmplo	r0,r1		;r0 &amp;lt; r1&lt;br /&gt;
	movets	r0,r2,r0	;wenn wahr/true r0 = r2 (23) ansonsten r0 = r0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sprünge ==&lt;br /&gt;
&lt;br /&gt;
Ein (bedingter) Sprung benötigt, wie jede andere Instruktion, einen Cycle um ausgeführt zu werden.&lt;br /&gt;
Da UCore keine Branchprediction bzw. keine spekulative Ausführung etc. unterstützt und es auch nicht gewollt ist Opcodes in der Pipeline zu verwerfen (wie z.B. bei MC68020), entstehen nach Sprungbefehlen sogenannte &#039;Delay Slots&#039;. Die Anzahl dieser &#039;Delay Slots&#039; ergeben sich aus der Anzahl der Pipelinestufen vor der Ausführungseinheit (da sie den Programmcounter verändert).&lt;br /&gt;
Kurzum programlauftechnisch werden Instruktionen in diesen &#039;Delay Slots&#039; ausgeführt bevor der Sprung in Wirklichkeit ausgeführt wird (bzw. &#039;gefetched&#039; werden).&lt;br /&gt;
Die kleinst mögliche Schleife benötigt deshalb fünf Instruktionen für einen Durchlauf.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loop	br	loop		;branch zu loop&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In vielen Fällen können &#039;Delay Slots&#039; sinnvoll genutzt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 1 (nicht optimiert - 8 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,1	;r1 = x Parameter&lt;br /&gt;
	movei	r1,7	;r2 = y Parameter&lt;br /&gt;
	gpci	r7,2	;r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 1 (optimiert - 6 Cycles): ====&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	gpci	r7,2	r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	movei	r0,1	;delay slot	r1 = x Parameter&lt;br /&gt;
	movei	r1,7	;delay slot     r2 = y Parameter&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 2 (nicht optimiert - 8 * n + 3 Cycles -&amp;gt; if n 128 -&amp;gt; total 1027 Cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127	;r0 = loop counter - 1&lt;br /&gt;
	movei	r1,0	;r1 = Füllwert&lt;br /&gt;
	nop&lt;br /&gt;
	&lt;br /&gt;
loop	st	r1,r6	;imem[r1] = r6&lt;br /&gt;
	addi	r1,1	;r1++&lt;br /&gt;
	subi	r0,1	;r0-- (t clear bei &amp;lt; 0)&lt;br /&gt;
	brts	loop	;branch loop solange t set&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 2 (optimiert - 6 * n + 2 Cycles -&amp;gt; if n 128 -&amp;gt; total 770 Cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127&lt;br /&gt;
	movei	r1,0&lt;br /&gt;
	&lt;br /&gt;
loop	subi	r0,1	;da t später verwendet wird nicht in delay slot benutzen (siehe Interruptverarbeitung)&lt;br /&gt;
	brts	loop&lt;br /&gt;
	st	r1,r6	;delay slot&lt;br /&gt;
	addi	r1,1	;delay slot	&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Speicherzugriffe ==&lt;br /&gt;
&lt;br /&gt;
UCore besitzt keine &#039;gewöhnlichen&#039; Lesebefehle für interne/externe Speicherzugriffe.&lt;br /&gt;
Um Pipeline-Stalls beim Lesen von Daten zu vermeiden (Latenz zum Speicher), wird eine Lesebefehl in zwei Operationen aufgeteilt.&lt;br /&gt;
Der erste Befehl ist ein &#039;Request&#039;, er teilt dem Core mit von welcher Adresse er etwas lesen soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Der zweite Befehl ist dann der &#039;Load&#039;, er holt sich die angekommenen Daten ab und speichert sie in einem Register.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== interner Speicherzugriff ====&lt;br /&gt;
&lt;br /&gt;
Bei internen Speicherzugriffen ist die Latenz zwischen Request und Load statisch (3 Cycles), bei externen Zugriff variable (hier wird im Fall eines Load ohne vorhandene Daten ein Stall ausgelöst).&lt;br /&gt;
&lt;br /&gt;
Mit den Opcode &#039;&#039;rqld&#039;&#039; (request load) und &#039;&#039;ld&#039;&#039; (load) kann vom internen Speicher gelesen werden.&lt;br /&gt;
Da die Daten erst zwei Operationen nach dem Request verfügbar sind, muss hier eine andere Instruktion ausgeführt werde (z.B. &#039;&#039;nop&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0	;send load to address (r0+0)&lt;br /&gt;
	nop		;data send to memory&lt;br /&gt;
	nop		;data will read&lt;br /&gt;
	ld	r1	;readed data to r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Da der interne Speicher immer innerhalb von einem Cycles antwortet und die Latenz durch Pipelinestufen entsteht, können internen Speicherzugriff bis zu drei Request hintereinander verwenden.&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0&lt;br /&gt;
	rqld	r0,1&lt;br /&gt;
	rqld	r0,2&lt;br /&gt;
	ld	r1	;r1 &amp;lt;- internal_mem[r0+0]&lt;br /&gt;
	ld	r2	;r2 &amp;lt;- internal_mem[r0+1]&lt;br /&gt;
	ld	r3	;r3 &amp;lt;- internal_mem[r0+2]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Bei Schreibzugriffen wird, wie bei anderen Prozessoren, ein &#039;&#039;st&#039;&#039; (Store-Kommando) verwendet.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti	$80	;imm extend&lt;br /&gt;
	move	r4,$01	;r4 = $8001&lt;br /&gt;
	move	r0,12	;r0 = 12&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	st	r0,r4	;imem[r4] = r0; $8001 = 12&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
Da ein &#039;&#039;st&#039;&#039;ore Befehl nur einen Register als Zieladresse benutzt, ist es vielen Fällen ärgerlich, diesen bei mehrfachen Schreiben zu verändern. Um in diesem Fall Abhilfe zu schaffen, wurde der Befehl &#039;&#039;ssto&#039;&#039; (Set Store Offset) und &#039;&#039;stwo&#039;&#039; (Store with Offset) implementiert. Mit &#039;&#039;ssto&#039;&#039; kann ein Offset für &#039;&#039;stwo&#039;&#039; gesetzt werden, d.h. der Wert der mit &#039;&#039;ssto&#039;&#039; gesetzt wird auf die Zieladresse von &#039;&#039;stwo&#039;&#039; addiert.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	stwo 1&lt;br /&gt;
	ssto r0,r7 ;imem[r7+1] = r0&lt;br /&gt;
	stwo 2&lt;br /&gt;
	ssto r1,r7 ;imem[r7+2] = r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist es leider etwas unangenehm mit der statischen Latenz bei internen Lesezugriffen, da man hier etwas mehr schreiben muss als man es von anderen Prozessoren gewöhnt ist.&lt;br /&gt;
&lt;br /&gt;
==== externe Speicherzugriffe ====&lt;br /&gt;
&lt;br /&gt;
Externe Speicherzugriffe verhalten sich ähnlich wie interne Zugriff.&lt;br /&gt;
Unterschiede gibt es in der Adressbreite (extern 32 Bit) und in der variablen Latenz (bestimmt durch mehre Faktoren).&lt;br /&gt;
Es gibt eine externe Hauptadresse (Base) die mit &#039;&#039;&#039;allen&#039;&#039;&#039; (bis auf edrqldi) externen Speicherzugriffsinstruktionen verwendet wird.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel Hauptadresse setzen: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel schreibe in externen Speicher: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r4,$af&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	esadr	r1,r0	;Hauptadresse (esadr) is r1:r0&lt;br /&gt;
	est	r4,0	;externSpeicher[esadr + 0] = r4&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
Beim Lesen vom externen Speicher werden ebenfalls Request/Load Befehle verwendet um Latenzen, wenn möglich, zu vermeiden. Da die Latenz (meist) nicht vorhersehbar ist, wird bei nicht vorhandenen Daten solange gewartet bis sie vorhanden sind (Stall).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
	erqld	0	;load from [r0:r1 + 0]&lt;br /&gt;
	eld	r7	;get external data (Stall solange bis Daten vorhanden)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um Lade/Schreiblatenzen zu vermeiden bzw. zu reduzieren, können mehre Stores oder Request hintereinander ausgeführt werden (maximal 256 Requestzugriffe, keine Begrenzung bei Stores).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreibe 8 Worte in externen Speicher, kein Stall solange Schreibpuffer nicht voll): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,0&lt;br /&gt;
	esadr	r7,r6	;external address is r7:r6 &lt;br /&gt;
	est	r0,0&lt;br /&gt;
	est	r0,1&lt;br /&gt;
	est	r0,2&lt;br /&gt;
	est	r0,3&lt;br /&gt;
	est	r0,4&lt;br /&gt;
	est	r0,5&lt;br /&gt;
	est	r0,6&lt;br /&gt;
	est	r0,7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (vermeiden von Leselatenzen) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r7,r6&lt;br /&gt;
	erqld	0&lt;br /&gt;
	erqld	1&lt;br /&gt;
	erqld	2&lt;br /&gt;
	erqld	3	;request 4 Worte&lt;br /&gt;
	&lt;br /&gt;
	....		;mach irgendwas&lt;br /&gt;
	&lt;br /&gt;
	eld	r0	&lt;br /&gt;
	eld	r1&lt;br /&gt;
	eld	r2&lt;br /&gt;
	eld	r3	;bekomme Daten (evtl. kein Stall, da Daten schnell genug vorhanden)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Stack ==&lt;br /&gt;
&lt;br /&gt;
Der Stackpointer zeigt nach dem Reset auf Adresse $8000 (also am oberen Ende des internen Speichers).&lt;br /&gt;
Das Verhalten von &#039;&#039;push&#039;&#039;, &#039;&#039;request pops&#039;&#039; und &#039;&#039;pops&#039;&#039; sind gleich dem internen Speicherzugriffsverhalten (3 Cycles Latenz, Pipelined).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (1 pop): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r4	;sp--; imem[sp] = r4&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop		;request imem[sp], sp++&lt;br /&gt;
	nop&lt;br /&gt;
	nop&lt;br /&gt;
	pop	r4	;r4 = imem[sp]&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel (3 Werte auf Stack und wieder herunter) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r1&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r3&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop		;durch Latenz maximal 3 rqpop dann Daten (ansonsten &#039;poparqp&#039; benutzen (kann Request und Load gleichzeitig))&lt;br /&gt;
	push	r3&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Decoder extend ==&lt;br /&gt;
&lt;br /&gt;
Da viele Operationen konstante Werte (in Operand kodiert) benutzen können, aber diese aus Gründen der Befehlsbreite (16 Bit) je nach Befehl/Operanden nur eine teilweise unzureichende Größe/Breite verwenden können, wurde eine Dekoder Instruktion &#039;&#039;dexti&#039;&#039; (decoder extend immediate) eingeführt.&amp;lt;br&amp;gt;&lt;br /&gt;
Dieser Befehl wird vom Dekoder ausgeführt und wird in der eigentlichen Ausführungseinheit ignoriert (&#039;&#039;nop&#039;&#039;).&lt;br /&gt;
Sinn dieses Befehls ist es, konstante Werte um einen 8 Bit breiten Wert zu erweitern. Um Fehler zu vermeiden ist dieser Wert nur einen Cycle nach &#039;&#039;dexti&#039;&#039; verfügbar.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (16 Bit immediate Addition) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti     $12&lt;br /&gt;
	addi	  r0,$34	;r0 = r0 + $1234&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interrupts ==&lt;br /&gt;
&lt;br /&gt;
Interrupts sind in einem Pipeline basierenden Design immer ärgerlich (IMHO) zu handhaben. Da UCore nicht, wie viele Mikrokontroller, möglichst kurze Interrupt-Latenzen ermöglichen muss, gibt es in diesem Design auch keine garantierten Zeiten in welchen der Interrupt ausgeführt wird.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Um den Hardwareaufwand gering wie möglich zu halten, habe ich eine sogenannte &#039;&#039;Branch-Injektion&#039;&#039; implementiert. Der Hintergedanke ist, dass Sprünge sehr oft im Code ausgeführt werden und diese, im Fall eines Interrupts, dazu &#039;&#039;missbraucht&#039;&#039; werden können, direkt zum Interrupt-Service-Vector zu springen, anstatt ihren eigentlichen definierten Sprung auszuführen (dieser wird gespeichert und später ausgeführt).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Der Vorteil dieser Implementierung ist, ein sehr geringer Hardwareaufwand, der Nachteil ist, dass die Interrupt-Latenz variiert (Delta zwischen zwei Sprüngen) und sich Verhaltensregeln für &#039;Delay-Slots&#039; ergeben.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;	&lt;br /&gt;
	sei			;irq enable&lt;br /&gt;
	br	anySubroutine	;if irq is enabled and occure a branch is taken to irq vector and after irq is finished (rte) the give branch will taken&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In &#039;Delay-Slots&#039; sollten kein T-Bit gesetzt werden, welches für spätere Verwendungen gebraucht wird.&amp;lt;br&amp;gt; Außerdem sollten keine Speicher-Request (ohne Loads) an diesen Stellen ausgeführt werden.&lt;br /&gt;
Um Fehler zu vermeiden warnt der Assembler bei solchen Konstrukten.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
	sei&lt;br /&gt;
	br	anySubroutine&lt;br /&gt;
	addt	r0,r1	;delay slot	(t is not save in delay slot if irq is enabled, because t is only store at br instruction)&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dividieren ==&lt;br /&gt;
&lt;br /&gt;
Viele Prozessoren die auf geringen &#039;Platzverbrauch&#039; optimiert sind, versuchen wenn möglich Divisions-Operationen zu vermeiden oder führen diesen nicht in einer Pipeline-Implementierung aus.&amp;lt;br&amp;gt;&lt;br /&gt;
Auf der Softwareseite sind Divisionen in vielen Fällen vermeidbar oder durch bestimmte Methoden ersetzbar. Prinzipiell ist eine Division einfach in Software zu implementieren, in diesem Fall ist die Geschwindigkeit einer Hardwareimplementierung meist nicht annähernd zu erreichen.&amp;lt;br&amp;gt;&lt;br /&gt;
UCore bietet spezielle Befehle an, um einen Kompromiss aus Geschwindigkeit und Hardwareaufwand zu ermöglichen.&lt;br /&gt;
Wie bei einer normalen Division wird der Divisor und Dividend gesetzt, zusätzlich muss noch die Divsions-Bitbreite angegeben werden (max. 32 Bit). Durch den Befehl &#039;&#039;udivstep&#039;&#039; wird eine &#039;1-Bit Division&#039; ausgeführt, d.h. &#039;&#039;udivstep&#039;&#039; muss/kann sooft ausgeführt werden wie die Divisionsbreite gewählt ist. Als Resultat der Division ergeben sich der Quotient und der Rest.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* udiv16&lt;br /&gt;
;* &lt;br /&gt;
;* r0 	 	divident&lt;br /&gt;
;* r1		divisor&lt;br /&gt;
;*&lt;br /&gt;
;* return&lt;br /&gt;
;*&lt;br /&gt;
;* r2		qoutient&lt;br /&gt;
;* r3		remainder&lt;br /&gt;
;*&lt;br /&gt;
;* needs 34 cycles&lt;br /&gt;
;*&lt;br /&gt;
	&lt;br /&gt;
udiv16	&lt;br /&gt;
	udivinit	15&lt;br /&gt;
	udivsdd		r0&lt;br /&gt;
	udivsdv		r1&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,3	;(3+1)*4 = 16&lt;br /&gt;
	cli		;disable irq&lt;br /&gt;
udiv16Loop	&lt;br /&gt;
	subi	r0,1&lt;br /&gt;
	brts	udiv16Loop&lt;br /&gt;
	udivstep	;delay slot	!!!! note udivstep is not irq save, so use cli/sei lock&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	udivgq		r2	;delay slot		get qoutient&lt;br /&gt;
	udivgr		r3	;delay slot		get remainder&lt;br /&gt;
	sei			;delay slot		enable irqs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== weiter Beispiele ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
= UCtrl =&lt;br /&gt;
&lt;br /&gt;
UCtrl ist eine Abstraktionsschicht für einen Großteil der externen (Altera-DE2-115) Peripherien und stellt zusätzlich hilfreiche Element (Timer,…) zur Verfügung.&amp;lt;br&amp;gt;&lt;br /&gt;
Direkten Zugriff auf diese Komponente hat nur UCore (siehe Memorymap).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCtrl bietet dem Benutzer zugriff auf:&lt;br /&gt;
*LEDS &lt;br /&gt;
*SWITCHES&lt;br /&gt;
*7-Segment Anzeige&lt;br /&gt;
*LCD (zweizeilig auf DE2-115)&lt;br /&gt;
*Interrupt Kontrolle (für UCore)&lt;br /&gt;
*Timer/Counter&lt;br /&gt;
*Video Setup (inkl. Counter und Vertikal-‚Hit‘-Erkennung)&lt;br /&gt;
*PS/2 Port (in/out, zwei Ports)&lt;br /&gt;
*I2C (zwei Ports)&lt;br /&gt;
*Audio (DAC/ADC)&lt;br /&gt;
*HCore Setup und Daten (beschreibe ich später)&lt;br /&gt;
&lt;br /&gt;
== Register ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8000&lt;br /&gt;
name = LEDG_SW&lt;br /&gt;
read            fedcba9876543210&lt;br /&gt;
                SSSSSSSSSSSSSSSS&lt;br /&gt;
                &lt;br /&gt;
                S = switches on DE2-115&lt;br /&gt;
                &lt;br /&gt;
write           fedcba9876543210&lt;br /&gt;
                -------GGGGGGGGG&lt;br /&gt;
                &lt;br /&gt;
                G = LED Green (&#039;1&#039; is ON)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8001&lt;br /&gt;
name = LEDR&lt;br /&gt;
read            fedcba9876543210&lt;br /&gt;
                --------------ME&lt;br /&gt;
        &lt;br /&gt;
                M = &#039;1&#039; if running in modelsim&lt;br /&gt;
                E = &#039;1&#039; if running in emulator&lt;br /&gt;
                &lt;br /&gt;
write                fedcba9876543210&lt;br /&gt;
                -------RRRRRRRRR&lt;br /&gt;
                &lt;br /&gt;
                R = LED Red (&#039;1&#039; is ON)&lt;br /&gt;
&lt;br /&gt;
                 &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8002 - $8005&lt;br /&gt;
name = 7SEG&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                2 ----------------&lt;br /&gt;
                3 ----------------&lt;br /&gt;
                4 ----------------&lt;br /&gt;
                5 ----------------&lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                2 -6543210-6543210&lt;br /&gt;
                3 -6543210-6543210&lt;br /&gt;
                4 -6543210-6543210&lt;br /&gt;
                5 -6543210-6543210&lt;br /&gt;
                &lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 1 / 0 (&#039;1&#039; is ON)                &lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 3 / 2 (&#039;1&#039; is ON)&lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 4 / 4 (&#039;1&#039; is ON)&lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 5 / 6 (&#039;1&#039; is ON)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8006 - $8007&lt;br /&gt;
name = LCD&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                6 -------BDDDDDDDD&lt;br /&gt;
                7 ----------------&lt;br /&gt;
                &lt;br /&gt;
                B = &#039;1&#039; if read/write request is busy&lt;br /&gt;
                D = Data after request&lt;br /&gt;
                &lt;br /&gt;
                note: wait 1 cycle after read/write request before read&lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                6 ------WRDDDDDDDD&lt;br /&gt;
                7 ----------------&lt;br /&gt;
                &lt;br /&gt;
                W = &#039;0&#039; is request write, &#039;1&#039; is request read&lt;br /&gt;
                R = LCS RS&lt;br /&gt;
                D = data to write&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8008 - $8009&lt;br /&gt;
name = IRQ&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                8 -----------HADTT IRQ MSK&lt;br /&gt;
                9 -----------HADTT IRQ MEMORY&lt;br /&gt;
                &lt;br /&gt;
                TT = Timer 2/1 IRQ&lt;br /&gt;
                D  = Audio DAC FIFO run low&lt;br /&gt;
                A  = Audio ADC FIFO run full&lt;br /&gt;
                H  = HCORE has data&lt;br /&gt;
                &lt;br /&gt;
write                  fedcba9876543210&lt;br /&gt;
                8 -----------HADTT IRQ MSK&lt;br /&gt;
                9 -----------HADTT IRQ MEMORY&lt;br /&gt;
                &lt;br /&gt;
                TT = Timer 2/1 IRQ&lt;br /&gt;
                D  = Audio DAC FIFO run low&lt;br /&gt;
                A  = Audio ADC FIFO run full&lt;br /&gt;
                H  = HCORE has data&lt;br /&gt;
                &lt;br /&gt;
description:&lt;br /&gt;
&lt;br /&gt;
                IRQ MSK is used to enable given interrupts (for example D = &#039;1&#039; then Audio DAC irq will be used)&lt;br /&gt;
                IRQ MEMORY reflect after interrupt which interrupt is the source (for example TT = &#039;01&#039; then Timer 1 made this interrupt)&lt;br /&gt;
                &lt;br /&gt;
                You should/have to clear the given interrupt bit in IRQ MEMORY before leaving interrupt service routine.&lt;br /&gt;
                        &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $800A - $800F&lt;br /&gt;
name = TIMERS&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                A DDDDDDDDDDDDDDDD TIMER_1_LOW  (Timer 1 value low)&lt;br /&gt;
                B DDDDDDDDDDDDDDDD TIMER_1_HIGH (Timer 1 value high, note: low/high needs capture first to be updated)&lt;br /&gt;
                C ----------------&lt;br /&gt;
                D DDDDDDDDDDDDDDDD TIMER_2_LOW  (Timer 2 value low)&lt;br /&gt;
                E DDDDDDDDDDDDDDDD TIMER_2_HIGH (Timer 2 value high, note: low/high needs capture first to be updated)&lt;br /&gt;
                F ----------------&lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                A DDDDDDDDDDDDDDDD TIMER_1_LOW  (Timer 1 value low)&lt;br /&gt;
                B DDDDDDDDDDDDDDDD TIMER_1_HIGH (Timer 1 value high, write to high will update)&lt;br /&gt;
                C ------------CLSR TIMER_1_CTRL&lt;br /&gt;
                D DDDDDDDDDDDDDDDD TIMER_2_LOW  (Timer 1 value low)&lt;br /&gt;
                E DDDDDDDDDDDDDDDD TIMER_2_HIGH (Timer 1 value high, write to high will update)&lt;br /&gt;
                F ------------CLSR TIMER_2_CTRL&lt;br /&gt;
                &lt;br /&gt;
                C = Capture counter value for read (copy current counter value to $A/B $D/E)&lt;br /&gt;
                L = Enable Auto Reload Value (after counter value runs to 0 next value is $A/B $D/E)&lt;br /&gt;
                S = Stop timer&lt;br /&gt;
                R = Start timer (will do a Autoreload from $A/B $D/E)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8010 - $802F&lt;br /&gt;
name = VIDEO&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                10 00000DDDDDDDDDDD current HCount (11..0)&lt;br /&gt;
                11 000000DDDDDDDDDD current VCount (10..0)&lt;br /&gt;
                12 ---------------H Hit of programmed VCOUNT&lt;br /&gt;
                13 ---------------- &lt;br /&gt;
                14 ---------------- &lt;br /&gt;
                15 ----------------&lt;br /&gt;
                16 ----------------&lt;br /&gt;
                17 ---------------- &lt;br /&gt;
                18 ---------------- &lt;br /&gt;
                19 ----------------&lt;br /&gt;
                1a ----------------&lt;br /&gt;
                1b ---------------- &lt;br /&gt;
                1c ---------------- &lt;br /&gt;
                1d ----------------&lt;br /&gt;
                1e ----------------&lt;br /&gt;
                1f ---------------- &lt;br /&gt;
                20 ---------------- &lt;br /&gt;
                21 ----------------                &lt;br /&gt;
                22 ----------------&lt;br /&gt;
                23 ---------------- &lt;br /&gt;
                24 ---------------- &lt;br /&gt;
                25 ----------------&lt;br /&gt;
                26 ----------------&lt;br /&gt;
                27 ---------------- &lt;br /&gt;
                28 ---------------- &lt;br /&gt;
                29 ----------------&lt;br /&gt;
                2a ----------------&lt;br /&gt;
                2b ---------------- &lt;br /&gt;
                2c ---------------- &lt;br /&gt;
                2d ----------------&lt;br /&gt;
                2e ----------------&lt;br /&gt;
                2f ---------------- &lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                10 ---------------D VIDEO ON if &#039;1&#039;&lt;br /&gt;
                11 ------DDDDDDDDDD HSYNC&lt;br /&gt;
                12 ------DDDDDDDDDD HSTART&lt;br /&gt;
                13 ------DDDDDDDDDD HMEMSTART&lt;br /&gt;
                14 ------DDDDDDDDDD HSTOP &lt;br /&gt;
                15 ------DDDDDDDDDD HTOTAL&lt;br /&gt;
                16 -------DDDDDDDDD VSYNC&lt;br /&gt;
                17 -------DDDDDDDDD VSTART&lt;br /&gt;
                18 -------DDDDDDDDD VSTOP&lt;br /&gt;
                19 -------DDDDDDDDD VTOTAL&lt;br /&gt;
                1a DDDDDDDDDDDDDDDD LINE CACHE ADDRESS ADD LOW&lt;br /&gt;
                1b DDDDDDDDDDDDDDDD LINE CACHE ADDRESS ADD HIGH &lt;br /&gt;
                1c ---------------- LINE CACHE LATCH VALUE&lt;br /&gt;
                1d -------DDDDDDDDD LINE CACHE START ADDRESS (Pixel offset)&lt;br /&gt;
                1e --------DDDDDDDD HITVCOUNT (see description)&lt;br /&gt;
                1f ---------------- &lt;br /&gt;
                20 ------DDDDDDDDDD HLOADSTART&lt;br /&gt;
                21 ------DDDDDDDDDD HLOADSTOP                &lt;br /&gt;
                22 -------DDDDDDDDD VLOADSTART&lt;br /&gt;
                23 -------DDDDDDDDD VLOADSTOP&lt;br /&gt;
                24 -------DDDDDDDDD VLOADNEXT&lt;br /&gt;
                25 DDDDDDDDDDDDDDDD EXTERNAL MEMORY START ADDRESS (low)&lt;br /&gt;
                26 DDDDDDDDDDDDDDDD EXTERNAL MEMORY START ADDRESS (high)&lt;br /&gt;
                27 DDDDDDDDDDDDDDDD EXTERNAL MEMORY LINE OFFSET (low)&lt;br /&gt;
                28 DDDDDDDDDDDDDDDD EXTERNAL MEMORY LINE OFFSET (high)&lt;br /&gt;
                29 --------------DD MEMORY Convertion MODE&lt;br /&gt;
                2a ---------------- LATCH MEMORY CONFIG&lt;br /&gt;
                2b ---------------- &lt;br /&gt;
                2c ---------------- &lt;br /&gt;
                2d ----------------&lt;br /&gt;
                2e ----------------&lt;br /&gt;
                2f ----------------                                 &lt;br /&gt;
                &lt;br /&gt;
        HITVCOUNT = Programmable VCOUNT if this Value is written $12 bit 0 is set to &#039;1&#039; if VCOUNT is equal to this value&lt;br /&gt;
                  $12 bit 0 is cleared at write to this register&lt;br /&gt;
&lt;br /&gt;
        EXTERNAL MEMORY LINE OFFSET = will be add after every loaded line (for non interleaved video setup)&lt;br /&gt;
        &lt;br /&gt;
        MEMORY Convertion MODE = defines the format of data converted from external memory (ever 32Bit fetch) to line cache&lt;br /&gt;
        &lt;br /&gt;
                00 = X8 R8 G8 B8                       (32 Bit = (8 Bit for Red/Gree/Blue))&lt;br /&gt;
                01 = R5 R6 R5 R5 R6 R5                 (2 * 16 Bit = (5 Bit for Red/Blue and 6 Bit for Green))&lt;br /&gt;
                10 = X1 R5 R5 X1 R5 R5 R5 R5         (2 * 16 Bit = (5 Bit for Red/Gree/Blue))&lt;br /&gt;
                11 = X4 R4 R4 R4 X4 R4 R4 R4          (2 * 16 Bit = (4 Bit for Red/Gree/Blue))&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8030 - $8031&lt;br /&gt;
name = PS/2 port a/b&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                30 -----FWVDDDDDDDD        PS2_PORT_A (port A)&lt;br /&gt;
                31 -----FWVDDDDDDDD        PS2_PORT_B (port B)&lt;br /&gt;
                &lt;br /&gt;
                D = PS/2 DATA (Scan Code) valid if A = &#039;1&#039;&lt;br /&gt;
                V = Data valid&lt;br /&gt;
                W = Write FIFO not full&lt;br /&gt;
                F = all writes finished (Fifo with 16 entries)&lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
                note: wait 1 cycle after read/write request before read&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                30 ------WADDDDDDDD        PS2_PORT_A (port A)&lt;br /&gt;
                31 ------WADDDDDDDD        PS2_PORT_B (port B)&lt;br /&gt;
                &lt;br /&gt;
                D = PS/2 DATA to write&lt;br /&gt;
                A = get next scan code (read 2 cycles after this from $30/$31)&lt;br /&gt;
                W = Write data to PS/2 device&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8032 - $8033&lt;br /&gt;
name = I2C port a/b&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                30 ------------D---       I2C_PORT_A (port A (eeprom on DE2-115))&lt;br /&gt;
                31 ------------D---       I2C_PORT_B (port B (audio/video in on DE2-115))&lt;br /&gt;
                &lt;br /&gt;
                D = data in from port A/B&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                30 ----EEE------ICD       I2C_PORT_A&lt;br /&gt;
                31 ----EEE------ICD       I2C_PORT_B&lt;br /&gt;
                &lt;br /&gt;
                D = data out value&lt;br /&gt;
                C = clock out value&lt;br /&gt;
                I = direction of data (&#039;0&#039; = in / &#039;1&#039; = out)&lt;br /&gt;
                &lt;br /&gt;
                EEE = is write enable for ICD&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8034 - $803b&lt;br /&gt;
name = AUDIO&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                34 DDDDDDDDDDDDDDDD ADC_DATA_LEFT_HIGH       &lt;br /&gt;
                35 --------DDDDDDDD ADC_DATA_LEFT_LOW                 &lt;br /&gt;
                36 DDDDDDDDDDDDDDDD ADC_DATA_RIGHT_HIGH                  &lt;br /&gt;
                37 --------DDDDDDDD ADC_DATA_RIGHT_LOW       &lt;br /&gt;
                38 ----------------&lt;br /&gt;
                39 ----------------&lt;br /&gt;
                3a ----------------&lt;br /&gt;
                3b ----------------&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                   fedcba9876543210&lt;br /&gt;
                34 DDDDDDDDDDDDDDDD DAC_DATA_LEFT_HIGH       &lt;br /&gt;
                35 --------DDDDDDDD DAC_DATA_LEFT_LOW            &lt;br /&gt;
                36 DDDDDDDDDDDDDDDD DAC_DATA_RIGHT_HIGH               &lt;br /&gt;
                37 --------DDDDDDDD DAC_DATA_RIGHT_LOW         &lt;br /&gt;
                38 AAAAAAAADDDDDDDD ADAC_CTRL (Data)&lt;br /&gt;
                39 --------DDDDDDDD DAC_IRQ_GEN (interrupt generate if lower) &lt;br /&gt;
                3a --------DDDDDDDD ADC_IRQ_GEN (interrupt generate if higher)&lt;br /&gt;
                3b ---------------- ADC_NEXT (recive values (after 2 cycles available in ADC_DATA ($34-$37)))&lt;br /&gt;
                &lt;br /&gt;
                ADAC_CTRL (Data) = configure internal ADC/DAC controller&lt;br /&gt;
                &lt;br /&gt;
                Adr 76543210&lt;br /&gt;
                0   -------- ignore&lt;br /&gt;
                1   -------E enable DAC&lt;br /&gt;
                2   ----CCCC DAC push counter (96KHz at 0, 48KHz at 1, 32KHz at 2 ....)&lt;br /&gt;
                3   -------E enable ADC&lt;br /&gt;
                4   ----CCCC ADC pull counter (96KHz at 0, 48KHz at 1, 32KHz at 2 ....)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $803c - $8044&lt;br /&gt;
name = HCORE CTRL/IO (in experimental state)                                &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Videosetup im Detail ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:16 32Bit Computer Konsole Uctrl video setup.png|miniatur|Video Setup]]&lt;br /&gt;
&lt;br /&gt;
UCore und UCtrl (also auch der Videokontoller) haben eine Taktfrequenz von 106,481 MHz, mit dieser Frequenz ist es möglich eine maximale Auflösung von 1440 x 900 Bildpunkten bei 60 Hz zu programmieren.&amp;lt;br&amp;gt;&lt;br /&gt;
Da diese Auflösung in vielen Fällen zu hoch ist, bzw. die Performance für eine flüssige Bildberechnung nicht immer ausreicht, kann ein interner Zeilen-Cache so programmiert werden, dass er nur eine bestimmte Anzahl an Pixeln pro Zeile ausgibt (H-Skaliert) und nur eine definierte Anzahl von Zeilen neu geladen wird (V-Skaliert).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Wie üblich können (siehe Bild), HSYNC, HSTART etc. frei programmiert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Als Quelle für die Bilddaten kann der SDRAM oder SRAM benutzt werden (siehe EXTERNAL_MEMORY_START_ADDRESS).&lt;br /&gt;
Das Farbformat kann zwischen einem 32 Bit Format (8Bit für R/G/B) und drei 16 Bit Formaten gewählt werden (siehe MEMORY Convertion MODE).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Support von Bitplanes oder Tiled-Grafiken gibt es nicht.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Video setup 360x225 4X4R4G4B Mode ($d0000000 ist Quelle (SDRAM)):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* setupVideo&lt;br /&gt;
;*&lt;br /&gt;
&lt;br /&gt;
setupVideo&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,videoDefault		;source&lt;br /&gt;
	movei	r1,UcTimer2Ctrl		;dest-1&lt;br /&gt;
	moveih	r0,&amp;gt;videoDefault&lt;br /&gt;
	moveih	r1,&amp;gt;UcTimer2Ctrl			&lt;br /&gt;
	movei	r2,26			;27-1&lt;br /&gt;
	&lt;br /&gt;
setupVideoLoop&lt;br /&gt;
&lt;br /&gt;
	rqldi	r0,0&lt;br /&gt;
	addi	r0,1&lt;br /&gt;
	addi	r1,1&lt;br /&gt;
	ld	r3&lt;br /&gt;
	subi	r2,1&lt;br /&gt;
	brts	setupVideoLoop&lt;br /&gt;
	st	r1,r3	;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
		&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
	&lt;br /&gt;
;*********************************************************************&lt;br /&gt;
;* data&lt;br /&gt;
;*********************************************************************&lt;br /&gt;
	&lt;br /&gt;
videoDefault		;AD NAME					&lt;br /&gt;
	&lt;br /&gt;
	word	$0001	;10 VIDEO_ON					&lt;br /&gt;
	word	$0097	;11 HSYNC (D = 11 .. 0)				&lt;br /&gt;
	word	$017f	;12 HSTART (D = 11 .. 0)			&lt;br /&gt;
	word	$017d	;13 HMEMSTART (D = 11 .. 0)			&lt;br /&gt;
	word	$071f	;14 HSTOP (D = 11 .. 0)				&lt;br /&gt;
	word	$076f	;15 HTOTAL (D = 11 .. 0)			&lt;br /&gt;
	word	$0002	;16 VSYNC (D = 10 .. 0)				&lt;br /&gt;
	word	$001e	;17 VSTART (D = 10 .. 0)			&lt;br /&gt;
	word	$03a2	;18 VSTOP  (D = 10 .. 0)			&lt;br /&gt;
	word	$03a3	;19 VTOTAL  (D = 10 .. 0)			&lt;br /&gt;
	word	$0000	;1a LC ADDER LOW				&lt;br /&gt;
	word	$0040	;1b LC ADDER HIGH				&lt;br /&gt;
	word	$0000	;1c LC ADDER LATCH				&lt;br /&gt;
	word	$0000	;1d LC START (10 .. 0) Pixeloffset		&lt;br /&gt;
	word	$0000	;1e						&lt;br /&gt;
	word	$0000	;1f						&lt;br /&gt;
	word	$0008	;20 HLOADSTART 					&lt;br /&gt;
	word	$00bc	;21 HLOADSTOP					&lt;br /&gt;
	word	$001e	;22 VLOADSTART 					&lt;br /&gt;
	word	$03a2	;23 VLOADSTOP 					&lt;br /&gt;
	word	$0004	;24 VLOADNEXT					&lt;br /&gt;
	word	$0000	;25 MEM_STARTADR_store low			&lt;br /&gt;
	word	$d000	;26 MEM_STARTADR_store high			&lt;br /&gt;
	word	$0000	;27 MEM_LINEOFFSET_store low			&lt;br /&gt;
	word	$0000	;28 MEM_LINEOFFSET_store high			&lt;br /&gt;
	word	$0002	;29 MEM_MODE_store 				&lt;br /&gt;
	word	$0000	;2a LATCH MEM_STARTADR/LINEOFFSET/MODE		&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Audiosetup im Detail ==&lt;br /&gt;
[[Datei:Uctrl audio overview.png|miniatur|rechts|audio simple]]&lt;br /&gt;
Da das DE-115 einen Wolfson WM8731 besitzt, unterteilt sich die Ansteuerung für die Audio-Ein/Ausgabe in zwei Teile.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Erste, ist die Konfiguration des WM8731, hierfür wird I2C Port B von UCTRL verwendet.&amp;lt;br&amp;gt;&lt;br /&gt;
Um die Konfiguration einfach zu halten sind Komponenten zur Initialisierung über I2C vorhanden (initAudio), es muss nur eine Tabelle mit den gewünschten Einstellungen übergeben werden (Register, Wert siehe WM8731 Registerbeschreibung).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Setup:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
audioDefault&lt;br /&gt;
	&lt;br /&gt;
	;&lt;br /&gt;
				;A =  8 7654 3210&lt;br /&gt;
	.data   $9,$0000	;9 =  0 0000 0000 	(inactivate interface)&lt;br /&gt;
	.data	$0,$0097	;0 =  0 1001 0111	;left line in mute&lt;br /&gt;
	.data	$1,$0097	;1 =  0 1001 0111	;right line in mute&lt;br /&gt;
	.data	$2,$006e	;2 =  0 0111 1001	;+6db left out&lt;br /&gt;
	.data	$3,$006e	;3 =  0 0111 1001	;0db right out&lt;br /&gt;
	.data	$4,$0012	;4 =  0 0001 0010	;0=0 mic boost off;&lt;br /&gt;
							;1=1 enable line input mute&lt;br /&gt;
							;2=1 line input to adc&lt;br /&gt;
							;3=0 disable bypass&lt;br /&gt;
							;4=1 DAC select&lt;br /&gt;
							;5=0 side tone disable&lt;br /&gt;
							;76=0 -6db sidetone						&lt;br /&gt;
	.data	$5,$0000	;5 =  0 0000 0000	;DAC soft Mute off, no Filer&lt;br /&gt;
	.data	$6,$0067	;6 =  0 0110 0111 	;DAC Power, Output Power, Device Power on&lt;br /&gt;
	.data	$7,$0009	;7 =  0 0000 1001 	;left justified, 24 bit&lt;br /&gt;
	.data	$8,$001e	;8 =  0 0001 1110	;0=0 normal mode&lt;br /&gt;
							;1=1 bosr (384/192)&lt;br /&gt;
							;5432=0111 96khz&lt;br /&gt;
							;78=00 no clk dividing	&lt;br /&gt;
	.data   $9,$0001	;9 =  0 0000 0001 	(activate interface)&lt;br /&gt;
	.data	$ff,$0000	;stop&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der zweite Teil, das Senden und Empfangen der Audio Daten wird über UCTRL Register $34 bis $3b ermöglicht(&#039;&#039;&#039;ADC&#039;&#039;&#039;/&#039;&#039;&#039;DAC_DATA&#039;&#039;&#039;, &#039;&#039;&#039;ADAC_CTRL&#039;&#039;&#039;, &#039;&#039;&#039;ADC&#039;&#039;&#039;/&#039;&#039;&#039;DAC_IRQ_GEN&#039;&#039;&#039;, &#039;&#039;&#039;ADC_NEXT&#039;&#039;&#039;).&amp;lt;br&amp;gt;&lt;br /&gt;
Für ADC und DAC gibt es jeweils für den linken &amp;amp; rechten Kanal je 24 Bit Daten zu empfangen/senden. &amp;lt;br&amp;gt;&lt;br /&gt;
ADC/DAC besitzen je einen 256 Worte (2 * 24 Bit) großen Queue, im Register &#039;&#039;&#039;DAC_IRQ_GEN&#039;&#039;&#039; ($39) bzw. &#039;&#039;&#039;ADC_IRQ_GEN&#039;&#039;&#039; ($3a) können die die Unter/Überlaufwerte, welche zu einem Interrupt führen, konfiguriert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
D.h. für einen Audioausgabe, konfiguriert man z.B. den DAC Queue auf den Wert 128 um beim Erreichen (kleiner als) einen Interrupt auszulösen (in welchen der Queue befüllt wird).&amp;lt;br&amp;gt;&lt;br /&gt;
Dadurch ist eine unterbrechungsfreie Wiedergabe/Aufnahme möglich ohne (je nach Einstellung) zu viele Interrupts auszulösen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die ADC/DAC Komponente in UCTRL kann über Register &#039;&#039;&#039;ADAC_CTRL&#039;&#039;&#039; ($38) konfiguriert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Die oberen 8 Bit des Datenworts bestimmen die Adresse, die unteren 8 Bit die Daten.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCTRL Audio Config:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name			address		876543210	comment&lt;br /&gt;
&lt;br /&gt;
nop			0		XXXXXXXXX	do nothing&lt;br /&gt;
ctrl			1		XXXXXXXXE	E = enable audio (default off)&lt;br /&gt;
set fifo read count	2		XXXXXXCCC	96KHz/C = fread [0..15]&lt;br /&gt;
set fifo write count	3		XXXXXXCCC	96KHz/C = fwrite [0..15]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Hier sollte vor der eigentlich Audio Ausgabe/Aufnahme, der jeweilige Counter für den ADC/DAC gesetzt werden (Counter der bei erreichen von 0 liest/schreibt). Z.B. den Wert 2 um eine 32 KHz Ausgabe einzustellen. Um die Queues zu lesen/schreiben muss noch unter Adresse 1 die Komponente aktiviert werden.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Audioausgabe von zwei 16 Bit Werten (links/rechts).&lt;br /&gt;
&amp;lt;br&amp;gt;	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	;r2 Audiobase $34&lt;br /&gt;
	;r1 = Wert für L, r4 = Wert für R&lt;br /&gt;
&lt;br /&gt;
	movei	r3,0&lt;br /&gt;
	stinc	r2,r1	;dac left high = value&lt;br /&gt;
	movei	r7,$1&lt;br /&gt;
	stinc	r2,r3	;dac left low = 0&lt;br /&gt;
	moveih	r7,$1&lt;br /&gt;
	stinc	r2,r4	;dac right high = value&lt;br /&gt;
	nop&lt;br /&gt;
	stinc	r2,r3	;dac right low = 0&lt;br /&gt;
	nop&lt;br /&gt;
	st	r2,r7	;dac address/ctrl = $0101	;ctrl = enable audio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Audio Tools ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Um eine einfache Handhabung der Audioausgabe zu ermöglichen, gibt es unter dem Verzeichnis &#039;&#039;assembler_files\ucore\components&#039;&#039; Funktionen, die eine einfache Audioausgabe (Sample) und das Abspielen von MOD (Musik-Module) ermöglichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PS/2 im Detail==&lt;br /&gt;
Mit den Registern &#039;&#039;&#039;PS2_PORT_A/B&#039;&#039;&#039; kann auf die PS/2 Schnittstelle des DE2-115 zugegriffen werden. Um alle Scancodes zu verarbeiten, ist ein Eingangsqueue (von PS/2) mit 16 Einträgen und einen Ausgangsqueue (zu PS/2) mit 8 Einträgen implementiert worden &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Zum Schreiben eines 8 Bit breiten Wertes zum PS/2-Device kann/sollte vor dem eigentlichen Transfer geprüft werden, ob der Ausgangsqueue voll ist (Bit 9 = &#039;&#039;&#039;W&#039;&#039;&#039; in &#039;&#039;&#039;PS2_PORT_A/B&#039;&#039;&#039;).&amp;lt;br&amp;gt;&lt;br /&gt;
Der zu sendende Datenwert muss in den unteren 8 Bit des Registers (&#039;&#039;&#039;PS2_PORT_A/B&#039;&#039;&#039;) geschrieben werden. Mit Bit 9 (&#039;&#039;&#039;W&#039;&#039;&#039; = write) wird er dann schließlich in den Ausgangsqueue übertragen.&amp;lt;br&amp;gt;&lt;br /&gt;
Mit Bit 10 (&#039;&#039;&#039;F&#039;&#039;&#039; = writes finish) kann, je nach Bedarf, überprüft werden ob alle Daten übermittelt wurden.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Beim Lesen eine Wertes von dem PS/2-Device, muss mittels Bit 8 (&#039;&#039;&#039;V&#039;&#039;&#039; = data valid (lesen)) geprüft werden, ob Daten im Eingangsqueue vorhanden sind, wenn dies zutrifft, wird mit setzen von Bit 8 (&#039;&#039;&#039;A&#039;&#039;&#039; = ACK (schreiben)) das Datenwort in die unteren 8 Bit des Register übertragen (zwei Cycles delay).&amp;lt;br&amp;gt;&lt;br /&gt;
Um die Handhabung mit einer PS/2 Tastatur zu vereinfachen, sind unter &#039;&#039;components/ps2keyboards.s&#039;&#039; Funktionen implementiert, welche die Steuerung und Auswertung (zu Ascii etc.) übernehmen.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel: testen auf Taste &#039;Escape&#039;:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	;process keys (read from PS/2 Device and process)&lt;br /&gt;
	&lt;br /&gt;
	gpci	r7,2		;lr&lt;br /&gt;
	br	PS2Process&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	&lt;br /&gt;
	;key test (ESC)&lt;br /&gt;
	&lt;br /&gt;
	gpci	r7,2		;lr&lt;br /&gt;
	br	PS2TestKey&lt;br /&gt;
	movei	r0,118		;test again &#039;ESC&#039; 	delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	&lt;br /&gt;
	;&lt;br /&gt;
	&lt;br /&gt;
	cmpeqi	r0,0		;r0 = 0 no key pressed&lt;br /&gt;
	brtc	escIsPressed	;jump &lt;br /&gt;
	&lt;br /&gt;
	.&lt;br /&gt;
	.&lt;br /&gt;
	.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==I2C Ports im Detail==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Auf dem Altera DE2-115 befinden sich mehrere Komponenten (Audio-Codec, Video-In, EEPROM)  die mittels des I2C-Protokolls konfiguriert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Um diese Komponenten ansteuern zu können, besitzt UCtrl zwei Ports welche die jeweiligen Pins (SDA/SCK) der Komponenten bedienen können. Das eigentliche I2C-Protokoll ist in Software umgesetzt, d.h. mit den &#039;&#039;&#039;I2C_PORT_A/B&#039;&#039;&#039; Registern können nur Pins gesetzt bzw. ihr Zustand gelesen werden.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Zum Daten lesen (SDA) wird Bit 3 (&#039;&#039;&#039;D&#039;&#039;&#039;) von Register &#039;&#039;&#039;I2C_PORT_A/B&#039;&#039;&#039; benutzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Zum Konfigurieren des Daten-Pins (Datenrichtung) wird Bit 2 (&#039;&#039;&#039;I&#039;&#039;&#039;) verwendet. Hierbei ist zu beachten, dass beim Schreiben immer das zugehörige Enable gesetzt werden muss (Bit 11-9). Also beim setzen des CLK-Pins (z.B.: $22 = Enable CLK, setze CLK = &#039;1&#039;).&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Wie schon erwähnt, ist das eigentliche I2C Protokoll in Software umgesetzt. Unter &#039;&#039;components/i2c.s&#039;&#039; sind die benötigten Funktionen implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Timer im Detail==&lt;br /&gt;
UCtrl besitzt zwei integrierte 32 Bit große Timer/Counter.&amp;lt;br&amp;gt;&lt;br /&gt;
Konfiguriert werden kann jeder Timer über Register &#039;&#039;&#039;TIMER_1/2_CTRL&#039;&#039;&#039;.&amp;lt;br&amp;gt;&lt;br /&gt;
Um den Startwert bzw. den aktuellen Wert des Timers/Counters zu lesen (bzw. zu schreiben) werden die Register &#039;&#039;&#039;TIMER_1/2_LOW/HIGH&#039;&#039;&#039; benutzt.&amp;lt;br&amp;gt; &lt;br /&gt;
Beim Schreiben ist zu beachten, dass &#039;&#039;&#039;TIMER_1/2_HIGH&#039;&#039;&#039; nach &#039;&#039;&#039;TIMER_1/2_LOW&#039;&#039;&#039; geschrieben werden muss.&amp;lt;br&amp;gt;&lt;br /&gt;
Beim Lesen muss das Bit 3 (&#039;&#039;&#039;C&#039;&#039;&#039; = Capture Counter) einmalig gesetzt werden um den aktuellen Wert in die Register &#039;&#039;&#039;TIMER_1/2_HIGH/LOW&#039;&#039;&#039; (Lesezugriff) zu laden.&amp;lt;br&amp;gt;&lt;br /&gt;
Gestartet und gestoppt wird jeder Timer mit Bit 1/0 (&#039;&#039;&#039;S&#039;&#039;&#039; = Stop, &#039;&#039;&#039;R&#039;&#039;&#039; = Start) im Register &#039;&#039;&#039;TIMER_1/2_CTRL&#039;&#039;&#039;.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Timer übernimmt beim Start den 32 Bit großen/breiten Wert aus Register &#039;&#039;&#039;TIMER_1/2_LOW/HIGH&#039;&#039;&#039; und dekrementiert (-1) diesen solange bis er den Wert 0 erreicht.&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn der Wert 0 erreicht ist, wird ein &amp;quot;Timer-Hit&amp;quot; ausgelöst. Dieser kann je nach Bedarf einen Interrupt auslösen (siehe Register &#039;&#039;&#039;IRQ_MSK/MEMORY&#039;&#039;&#039;).&amp;lt;br&amp;gt;&lt;br /&gt;
Um einen kontinuierlichen Lauf zu ermöglichen, kann Bit 2 (&#039;&#039;&#039;L&#039;&#039;&#039; = Auto Reload) aktiviert werden, in diesem Fall wird bei dem Erreichen von Wert 0, der Wert aus &#039;&#039;&#039;TIMER_1/2_LOW/HIGH&#039;&#039;&#039; geladen und der Timer startet erneut.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel vom Setzen und Starten des Timers 2:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti	&amp;gt;UcTimer2LowValue&lt;br /&gt;
	movei	r2,UcTimer2LowValue	;timer 2 base&lt;br /&gt;
		&lt;br /&gt;
	move	r0,240		;low value&lt;br /&gt;
	move	r1,0		;high value&lt;br /&gt;
	&lt;br /&gt;
	stinc	r2,r0		;low&lt;br /&gt;
	movei	r0,5		;start with auto reload&lt;br /&gt;
	stinc	r2,r1		;high		&lt;br /&gt;
	nop&lt;br /&gt;
	stinc	r2,r0		;write config (lets go)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== SD-Zugriff im Detail ==&lt;br /&gt;
Über die Implementierung der SD-Karten Schnittstelle möchte ich hier nicht im Detail eingehen (es sei denn, es wird gewünscht).&amp;lt;br&amp;gt;&lt;br /&gt;
Zum benutzen der SD-Karte sind unter &#039;&#039;components/sdCardLoader.s&#039;&#039; Funktionen vorhanden.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Software (Block-IO) unterstützt SD-SC/HC/XC Karten, als Ziel für die zu lesenden Daten kann der SRAM/DRAM benutzt werden. Die maximale Transfergeschwindigkeit beträgt 100Mbit.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel, nachladen von 16384 Blöcken (a 256 Bytes):&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ;read sdcard to s/sdram&lt;br /&gt;
	&lt;br /&gt;
        dexti	&amp;gt;startBlock&lt;br /&gt;
	movei	r0,startBlock&lt;br /&gt;
	nop&lt;br /&gt;
	rqldi	r0,0	;low&lt;br /&gt;
	rqldi	r0,1	;high&lt;br /&gt;
	nop&lt;br /&gt;
	ld	r2&lt;br /&gt;
	ld	r3&lt;br /&gt;
	&lt;br /&gt;
	addi	r2,64	;64 blocks offset (ucore code/data)&lt;br /&gt;
	addtqi	r3,r3,0&lt;br /&gt;
	&lt;br /&gt;
	;set destination address&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,$10&lt;br /&gt;
	movei	r1,$02&lt;br /&gt;
	moveih	r0,$b1&lt;br /&gt;
	moveih	r1,$d0		;r1:r0 = $d002 b110 (dest start)&lt;br /&gt;
	&lt;br /&gt;
	dexti	&amp;gt;sdCardReadBlocks&lt;br /&gt;
	movei	r6,sdCardReadBlocks&lt;br /&gt;
	gpci	r7,2		;lr&lt;br /&gt;
	jmpi	r6,0&lt;br /&gt;
	movei	r4,$ff		;16384 blocks-1	delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	moveih	r4,$2f		;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Emulator ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:Ucore emulator4 info.png|miniatur]]&lt;br /&gt;
[[Datei:Ucore emulator3 info.png|miniatur]]&lt;br /&gt;
&lt;br /&gt;
Um den Test von Software zu vereinfachen, habe ich einen Emulator entwickelt, welcher das System auf einen ‚Windows‘ – System  (als Host) emuliert.  Der Emulator emuliert, in vielen Bereichen, Zyklen genau. &lt;br /&gt;
d.h. das Verhalten zwischen der Hardwareimplementierung und den Emulator ist identisch (nicht die Geschwindigkeit des Systems).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Um ein Sammelsurium von Tools beim Entwickelt zu vermeiden, sind mehre Tools im Emulator integriert (können aber auch einzeln ausgeführt werden):&lt;br /&gt;
&lt;br /&gt;
*Assembler (UCore, HCore)&lt;br /&gt;
*Grafikkonverter&lt;br /&gt;
*SD-Karten RAW IO (lesen/schreiben)&lt;br /&gt;
&lt;br /&gt;
Um den Status der Hardware zu überprüfen, wurden Hardware-Views implementiert:&lt;br /&gt;
&lt;br /&gt;
*UCore (Disassembler, Register, Status, Pipeline, …)&lt;br /&gt;
*HCore (Disassembler,…)&lt;br /&gt;
*Video Registerübersicht&lt;br /&gt;
*Audio Registerübersicht&lt;br /&gt;
*SD-Karten IO-Übersicht&lt;br /&gt;
*Speicheransicht (IRAM,SRAM,SDRAM, …)&lt;br /&gt;
&lt;br /&gt;
Die Geschwindigkeit der Emulation ist ungefähr 10-20 mal langsamer als auf der eigentlich Hardware. Um das Debuggen /Testen zu beschleunigen, kann die Software erkennen (wenn gewünscht) ob sie in einer Emulation läuft und so diverse Wartefunktionnen überspringen (z.B. warten auf VBlank).&lt;br /&gt;
&lt;br /&gt;
=== Starten des Emulators ===&lt;br /&gt;
&lt;br /&gt;
Unter dem Verzeichnis &#039;&#039;&#039;cross_development\binaries&#039;&#039;&#039; die Dateien &#039;&#039;&#039;ucore_emulator.exe&#039;&#039;&#039; ausführen. Unter Windows 8 kann es vorkommen, dass diese Datei als von einem unbekannten Hersteller angezeigt wird und das Ausführen extra bestätigt werden muss. Administratorrechte etc. werden nicht benötigt.&lt;br /&gt;
&lt;br /&gt;
=== Laden eines Packages ===&lt;br /&gt;
&lt;br /&gt;
Packages sind generierte Archive in denen sich alle benötigten Daten (IRAM, Flash, SDData,…) für einen Testlauf befinden. Sie sind mit wenigen Aufwand ladbar und vereinfachen die Handbarkeit des Emulators (wenn kein Debuggen erwünscht ist).&amp;lt;br&amp;gt;&lt;br /&gt;
Um ein Packages zu laden, muss unter dem Reiter &#039;&#039;&#039;io&#039;&#039;&#039; im Bereich &#039;&#039;&#039;package&#039;&#039;&#039; das gewollte Package ausgewählt werden ‚&#039;&#039;&#039;…&#039;&#039;&#039;. (Alle generierten Packages sind unter dem Verzeichnis &#039;&#039;&#039;packages &#039;&#039;&#039; verfügbar). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Ucore emulator2 info.png|miniatur|zentriert]]&lt;br /&gt;
&lt;br /&gt;
Danach mittels des Buttons &#039;&#039;&#039;Load&#039;&#039;&#039; kann das Package geladen werden. Wenn das erfolgt ist, kann das Programm mittels &#039;&#039;&#039;Start&#039;&#039;&#039; (Play-Knopf in der Toolleiste) gestartet werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Ucore emulator1 info.png|miniatur|zentriert]]&lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/310121&lt;br /&gt;
&lt;br /&gt;
= Homepage =&lt;br /&gt;
&lt;br /&gt;
http://www.goldmomo.de&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Ucore_emulator4_info.png&amp;diff=85080</id>
		<title>Datei:Ucore emulator4 info.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Ucore_emulator4_info.png&amp;diff=85080"/>
		<updated>2014-10-03T11:20:10Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Ucore_emulator3_info.png&amp;diff=85079</id>
		<title>Datei:Ucore emulator3 info.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Ucore_emulator3_info.png&amp;diff=85079"/>
		<updated>2014-10-03T11:19:54Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Ucore_emulator2_info.png&amp;diff=85078</id>
		<title>Datei:Ucore emulator2 info.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Ucore_emulator2_info.png&amp;diff=85078"/>
		<updated>2014-10-03T11:19:39Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Ucore_emulator1_info.png&amp;diff=85077</id>
		<title>Datei:Ucore emulator1 info.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Ucore_emulator1_info.png&amp;diff=85077"/>
		<updated>2014-10-03T11:19:23Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=83286</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=83286"/>
		<updated>2014-06-07T15:16:20Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: fix links, Format update&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein &#039;Computer&#039;system, welches nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses nachbildet.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen, welches vollständig&#039;&#039;&#039;*&#039;&#039;&#039; selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (&#039;&#039;&#039;*&#039;&#039;&#039;FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL verwendet, für Emulation und Tools (Assembler etc.) wird C# mit .NET benutzt.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 zur Verfügung gestellt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE = Utility Core), welcher über einen memorymapped UCTRL-Komponente vollständigen Zugriff auf alle Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* Programmierbares Audio Interface&lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Zwei Timer/Counter&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCORE) ist der &#039;&#039;&#039;zentrale&#039;&#039;&#039; Prozessor im System, d.h. er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist dazu gedacht, eine einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn, für alle meine Demos/Spiele, als Hauptprozessor benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In einen experimentellen Zustand befindet sich noch der HCORE Block. Dieser Block enthält mehre (konfigurierbar) 32 Bit Prozessoren die über spezielle Techniken (Hardwaresemaphoren, parallele Sprünge, … ) eine parallele Verarbeitung von Software vereinfachen sollen und Latenzprobleme bei Multithreading vermeiden. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Momentane Charakteristiken eines HCOREs sind:&lt;br /&gt;
&lt;br /&gt;
*9 Stufen Pipeline mit &#039;in order&#039; und &#039;out of order&#039; Pfad&lt;br /&gt;
*Instruction Cache (konfigurierbar (momentan 8 Wege mit 64 Worten))&lt;br /&gt;
*32 Bit ALU (Hold to Last Pfad, …) &lt;br /&gt;
*128 GP Register&lt;br /&gt;
*UCtrl/Memory/Semaphoren/… &#039;out of order&#039; Zugriff&lt;br /&gt;
*…&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
[[Datei:Goldmomo emulator.png|miniatur|rechts|Emulator]]&lt;br /&gt;
Um die Softwareentwicklung (Debuggen etc.) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Registerstatus, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (in Emulator integriert). Ein Compiler (z.B.: für C) existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/8i5pzlncr77cl1v/AADt708pu8p6irXm-YO-1so2a/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo endlos Sheriff2213.png|miniatur|Sheriff 2213]]&lt;br /&gt;
[[Datei:Goldmomo endlos SpacePilotOfDeath.png|miniatur|SpacePilotOfDeath]]&lt;br /&gt;
[[Datei:Goldmomo endlos ModPlayer.png|miniatur|MOD Player]]&lt;br /&gt;
[[Datei:Goldmomo endlos GfxExtension.png|miniatur|GFX Extension]]&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= UCORE Programmierung =&lt;br /&gt;
&lt;br /&gt;
UCORE unterscheidet sich einigen Teilen von einem &#039;&#039;normalen&#039;&#039; Prozessordesign.&lt;br /&gt;
Die Gründe bzw. Ziele welche verfolgt wurden, waren eine möglichst hohe Taktrate und ein möglichst geringe Benutzung von Hardwareressourcen, aber dennoch eine hohe Verarbeitungsgeschwindigkeit.&lt;br /&gt;
Dadurch ergeben sich einige Besonderheiten, welche bei der Programmierung beachtet werden &#039;&#039;&#039;müssen&#039;&#039;&#039; (siehe Registerzugriffe, Branch/Jump Delayslots, Request/Load Zugriffe).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pipeline ===&lt;br /&gt;
&lt;br /&gt;
Wie gesagt hat dieser Core eine sechsstufige Pipeline:&lt;br /&gt;
&lt;br /&gt;
# 1 Prepare Fetch (adressiere Daten)&lt;br /&gt;
# 2 Fetch (hole Daten)&lt;br /&gt;
# 3 Decode (dekodiere Daten)&lt;br /&gt;
# 4 Read Register (lese Register)&lt;br /&gt;
# 5 Execute (ausführen)&lt;br /&gt;
# 6 Write Register (schreibe Register (hat einen Bypass zu Stufe 4, somit keine extra Delay) &lt;br /&gt;
&lt;br /&gt;
Jede Instruktion wird in einem Cycle ausgeführt, nur der externe Speicherzugriff (nur Daten) kann einen Stall (Stillstand) der Pipeline verursachen.&lt;br /&gt;
&lt;br /&gt;
== Interne Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
In meinem System wird die folgende interne Speichermap verwendet (16 Bit interner Adressraum).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$0000 code / data memory&lt;br /&gt;
*     16384 * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$3fff&lt;br /&gt;
$4000 code / data memory MIRROR&lt;br /&gt;
*     &lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$7fff&lt;br /&gt;
$8000 uctrl / memory			StackPointer start at $8000 on reset&lt;br /&gt;
*     XXXX * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$XXXX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Reset-Vektor befindet sich an Adresse $0000, der Stackpointer an Adresse $8000 (am Ende des internen RAMs).&amp;lt;br&amp;gt; &lt;br /&gt;
Der Interruptvektor zeigt nach dem Reset auf Adresse $0010 (sollte nach dem Reset an die benötigte Position verschoben werden).&amp;lt;br&amp;gt; &lt;br /&gt;
Ab Adresse $8000 wird die Komponente UCtrl in den Adressraum &#039;gemappt&#039; (diese Komponente enthält Register für externe Hardware Peripherie etc.).&lt;br /&gt;
&lt;br /&gt;
== externe Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
Über den &#039;externen&#039; Datenbus (32 Bit Adressraum) kann auf folgende Komponenten zugegriffen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$a000 0000 - $a000 001f SDCard-Controller&lt;br /&gt;
$d000 0000 - $d3ff ffff SDRAM&lt;br /&gt;
$e000 0000 - $e03f ffff FLASH&lt;br /&gt;
$f000 0000 - $f00f ffff SRAM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei den meisten meiner Programme wird ein Boot-Programm aus dem FLASH-Speicher gelesen, welches einen Speichertest ausführt und auf das Einlegen einer SD-Karte, mit dem zu ladenden Programm, wartet.&lt;br /&gt;
&lt;br /&gt;
== Opcodes/Operanten ==&lt;br /&gt;
&lt;br /&gt;
UCore hat keine &#039;RISC&#039;-Typischen Befehlssatz (viele Befehle, aber geringe Komplexität).&lt;br /&gt;
 &lt;br /&gt;
Da ein Instruktions-Wort nur eine Breite von 16 Bit hat, können nur bedingte Mengen an Operanden verwendet werden. Um jedoch die Programmierung flexibler zu gestalten, haben viele Opcodes mehrere Arten von Operanden. &lt;br /&gt;
Für die Ausführungseinheit (ALU) ergibt sich dadurch keine Ressourcenveränderung, da der Decoder nur die Opcodes/Operanden in ein internes einheitliches Format auflöst.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Operanden Formate ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dc,imm8       Register, 8 Bit Wert&lt;br /&gt;
 dc,db,da      Register, Register , Register&lt;br /&gt;
 dc,db,imm3    Register, Register, 3 Bit Wert&lt;br /&gt;
 imm12         12 Bit Wert&lt;br /&gt;
 db,da         Register, Register&lt;br /&gt;
 imm6          6 Bit wert&lt;br /&gt;
 da            Register&lt;br /&gt;
 kein Operant&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Opcode / Operand(en) / Beschreibung ==== &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
movei     	dc,imm8		dc = imm&lt;br /&gt;
moveih    	dc,imm8		dc[15..8] = imm &amp;lt;&amp;lt; 8 | dc[7..0]&lt;br /&gt;
addi      	dc,imm8		dc = dc + imm&lt;br /&gt;
subi      	dc,imm8		dc = dc - imm&lt;br /&gt;
lsri      	dc,imm8		dc = dc &amp;gt;&amp;gt; imm&lt;br /&gt;
asri      	dc,imm8		dc = ((signed)dc) &amp;gt;&amp;gt; imm&lt;br /&gt;
muli      	dc,imm8		dc = dc * imm&lt;br /&gt;
cmpeqi    	dc,imm8		t = set if dc == imm else cleared&lt;br /&gt;
cmploi    	dc,imm8		t = set if dc &amp;lt; imm else cleared&lt;br /&gt;
cmplosi   	dc,imm8		t = set if  (signed)dc &amp;lt; (signed) imm else cleared&lt;br /&gt;
gpci      	dc,imm8		dc = pc + imm&lt;br /&gt;
jmpi      	dc,imm8		pc = dc + imm&lt;br /&gt;
extri     	dc,imm8		t = bit #imm of dc&lt;br /&gt;
rqldi     	dc,imm8		request (internal) mem; address = dc + imm&lt;br /&gt;
getsp     	dc,imm8		dc = sp + imm&lt;br /&gt;
dexti     	imm11		store imm as extension for next instruction&lt;br /&gt;
&lt;br /&gt;
add		dc,db,da	dc = db + da&lt;br /&gt;
sub     	dc,db,da	dc = db - da&lt;br /&gt;
lsr     	dc,db,da	dc = db &amp;gt;&amp;gt; da&lt;br /&gt;
asr     	dc,db,da	dc = ((signed)db) &amp;gt;&amp;gt; da&lt;br /&gt;
mul     	dc,db,da	dc = db * da&lt;br /&gt;
addt    	dc,db,da	dc = db + da + t&lt;br /&gt;
subt    	dc,db,da	dc = db - da - t&lt;br /&gt;
muls    	dc,db,da	dc = db * da&lt;br /&gt;
movets  	dc,db,da	dc = db if t = set else da&lt;br /&gt;
and     	dc,db,da	dc = db &amp;amp; da&lt;br /&gt;
or      	dc,db,da	dc = db | da&lt;br /&gt;
xor     	dc,db,da	dc = db ^ da&lt;br /&gt;
bic     	dc,db,da	dc = db &amp;amp; ~da&lt;br /&gt;
&lt;br /&gt;
addqi		dc,db,imm3	dc = db + imm&lt;br /&gt;
subqi   	dc,db,imm3	dc = db - imm&lt;br /&gt;
lsrqi   	dc,db,imm3	dc = db &amp;gt;&amp;gt; imm&lt;br /&gt;
asrqi   	dc,db,imm3	dc = ((signed)db) &amp;gt;&amp;gt; imm&lt;br /&gt;
mulqi   	dc,db,imm3	dc = db * imm3&lt;br /&gt;
addtqi  	dc,db,imm3	dc = db + imm + t&lt;br /&gt;
subtqi  	dc,db,imm3	dc = db - imm - t&lt;br /&gt;
edrqldi 	db,da,imm3	request (external) mem; address = (db:da) + imm3&lt;br /&gt;
&lt;br /&gt;
br		imm12		pc = pc + signed(imm)&lt;br /&gt;
brts		imm12		pc = pc + signed(imm) if t is set&lt;br /&gt;
brtc		imm12		pc = pc + signed(imm) if t is cleared&lt;br /&gt;
	             &lt;br /&gt;
cmpeq		db,da		t = set if db == da else cleared		&lt;br /&gt;
cmplo   	db,da           t = set if db &amp;lt; da else cleared&lt;br /&gt;
cmplos  	db,da           t = set if  (signed)db &amp;lt; (signed) da else cleared&lt;br /&gt;
esadr   	db,da		esadr = db:da&lt;br /&gt;
swp     	db,da		db = da[7..0]:da[15..8] &lt;br /&gt;
swptc   	db,da		db = da[7..0]:da[15..8] if t = set else da&lt;br /&gt;
st      	db,da		imem[db] = da&lt;br /&gt;
stinc   	db,da		imem[db] = da; db = db + 1&lt;br /&gt;
bffo    	db,da		db is first bit that is 1 found in da (from MSB to LSB)&lt;br /&gt;
bset    	db,da		db = db | 1 &amp;lt;&amp;lt; da&lt;br /&gt;
bclr    	db,da		db = db &amp;amp; ~ (1 &amp;lt;&amp;lt; da)&lt;br /&gt;
cmple   	db,da		t = set if db &amp;lt;= da else cleared&lt;br /&gt;
cmples  	db,da		t = set if  (signed)db &amp;lt;= (signed) da else cleared&lt;br /&gt;
rqld    	db,da		request (internal) mem; address = db + da&lt;br /&gt;
extb    	db,da		db = da byte to word singed extended&lt;br /&gt;
stwo    	db,da		imem[db + STORE_OFFSET] = da&lt;br /&gt;
andts   	db,da		db = db &amp;amp; da if t = set else da&lt;br /&gt;
orts    	db,da           db = db | da if t = set else da&lt;br /&gt;
xorts   	db,da           db = db ^ da if t = set else da&lt;br /&gt;
bicts   	db,da           db = db &amp;amp; ~da if t = set else da&lt;br /&gt;
lsrts   	db,da		db = db &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
asrts   	db,da           db = ((signed)db) &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
mults   	db,da           db = db * da if t = set else da&lt;br /&gt;
mulsts  	db,da		db = (signed)db * (signed)da if t = set else da&lt;br /&gt;
&lt;br /&gt;
erqldi		imm6		request (external) mem; address = esadr + imm	&lt;br /&gt;
ssto		imm6		STORE_OFFSET = imm&lt;br /&gt;
udivinit	imm6		udivqoutient = 0; udivrest = 0; udivbitcounter = imm&lt;br /&gt;
&lt;br /&gt;
eld		da		da = requested value from external memory&lt;br /&gt;
push            da		sp = sp – 1; imem[sp] = da&lt;br /&gt;
gmulhi          da		da = multiply result [31..15] from last multiplication&lt;br /&gt;
ld/pop          da		da = requested value from internal memory&lt;br /&gt;
poparqp         da		da = requested value from internal memory; request in internal memory adr = sp; sp = sp + 1&lt;br /&gt;
neg             da		da = 0 - da&lt;br /&gt;
udivgq          da		get division qoutinent&lt;br /&gt;
udivgr          da		get division remainder&lt;br /&gt;
udivgqh         da		get division qoutinent high [31 ..16]&lt;br /&gt;
udivgrh         da              get division remainder high [31 ..16]&lt;br /&gt;
udivsdd         da		set division divident &lt;br /&gt;
udivsdv         da		set division divider&lt;br /&gt;
udivsddh        da		set division divident high [31 ..16]&lt;br /&gt;
udivsdvh        da		set division divider  high [31 ..16]&lt;br /&gt;
erqld           da		request (external) mem; address = esadr + da&lt;br /&gt;
setsp           da		sp = da&lt;br /&gt;
erqldb          da		request (external) mem; address = esadr + da / 2&lt;br /&gt;
jmpts           da		pc = da if t = set&lt;br /&gt;
jmptc           da		pc = da if t = cleared&lt;br /&gt;
negts           da		da = 0 - da if t = set else da&lt;br /&gt;
&lt;br /&gt;
rqpop				internal memory request address = sp; sp = sp + 1&lt;br /&gt;
cli				disable interrupts&lt;br /&gt;
sei				enable interrupts&lt;br /&gt;
rti				pc = pc_before interrput&lt;br /&gt;
tnt				t = not t&lt;br /&gt;
vtt				t = v (overflow/underflow wrom add/sub)			&lt;br /&gt;
epushsadrl			sp = sp – 1; imem[sp] = esadr[15..0]&lt;br /&gt;
epushsadrh			sp = sp – 1; imem[sp] = esadr[31..16]&lt;br /&gt;
epopsadrl			esadr[15..0] = requested value from internal memory&lt;br /&gt;
epopsadrh			esadr[31..16] = requested value from internal memory&lt;br /&gt;
udivstep			performe one division step &lt;br /&gt;
nop				do nothing&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Registerzugriffe ==&lt;br /&gt;
&lt;br /&gt;
Da Register vor der Ausführungseinheit (ALU) gelesen werden und nach der Ausführungseinheit geschrieben werden, ergibt sich eine Latenz zwischen Register Zugriffen. Der Grund für diese Implementierungsart ist, schlicht und einfach, die Performanz zu erhöhen (weniger Logik pro Takt). Als Nebeneffekt entsteht eine Latenz zwischen den Zugriffen. Es bieten sich mehrere Möglichkeiten an, diese Register-&#039;Hazards&#039; in Hardware zu vermeiden (Registerscoring, Renaming etc.). Um den Hardwareimplementierung klein und schnell zu halten, wird in UCore auf einen Hardwaretest verzichtet. Als Resultat, &#039;&#039;&#039;muss&#039;&#039;&#039; der Anwender Registerabhängigkeiten im Programm-Code behandeln/beachten.&lt;br /&gt;
Der einzige Nachteil (der durch eine Latenz entsteht) ergibt sich in einer RAW (Read after Write) Abhängigkeit (da die Latenz hier eine Cycle beträgt). In diesem Fall sollte/muss eine andere Instruktion (z.B. nop) eingefügt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreiben eines Registers und späteres Lesen): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae	; &lt;br /&gt;
	nop		;write r0 = ae wird ausgeführt&lt;br /&gt;
	addi	r0,1	;r0 = r0 ($ae) + 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Im einfachsten Fall sollte eine &#039;&#039;nop&#039;&#039; Operation bei solchen Abhängigkeit verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (nicht optimiert mit nop - 6 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	nop&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	nop&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In den meisten Fällen kann aber eine andere Operationen als &#039;Füllung&#039; bei Registerabhängigkeiten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (optimiert - 4 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um versehentlich programmierte RAW-&#039;Hazards&#039; zu erkennen, erzeugt der Assembler Warnungen, ebenfalls kann der Emulator diese zur Laufzeit erkennen.&lt;br /&gt;
Prinzipiell ist es möglich, in gewissen Situationen, RAW-&#039;Hazards&#039; absichtlich zuzulassen (z.B. Optimierungen um Register zu sparen), wovon aber im Normalfall abzuraten ist.&lt;br /&gt;
&lt;br /&gt;
== Bedingungen ==&lt;br /&gt;
&lt;br /&gt;
UCore benutzt ein T-Bit (true/wahr Bit) um Bedingungen zu beschreiben/verarbeiten. Normalerweise (nicht ausschließlich) wird dieses Bit von Vergleichsoperationen gesetzt und kann nachfolgend von Operationen benutzt werden welche das T-Bit abfragen (z.B. bedingte Sprünge).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel:====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	cmpeqi	r0,0		;vergleiche auf r0 gleich 0, wenn wahr da (t=1) ansonsten (t=0)&lt;br /&gt;
	brts	r0IstNull	;springe zum &#039;r0IstNull&#039; Label wenn t set (t=1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist notwendig Register nur dann zu setzen, wenn bestimmte Bedingungen eintreten. In solchen Fällen ist es ärgerlich bedingte Sprünge auszuführen, da sie etwas Zeit benötigen (siehe Delay Slots) und den Programmcode unübersichtlich machen (Spaghetticode).&amp;lt;br&amp;gt;&lt;br /&gt;
Aus diesem Grund, unterstützen einige Befehle eine bedingte Ausführung.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	move	r1,123&lt;br /&gt;
	move 	r2,23&lt;br /&gt;
	…&lt;br /&gt;
	cmplo	r0,r1		;r0 &amp;lt; r1&lt;br /&gt;
	movets	r0,r2,r0	;wenn wahr/true r0 = r2 (23) ansonsten r0 = r0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sprünge ==&lt;br /&gt;
&lt;br /&gt;
Ein (bedingter) Sprung benötigt, wie jede andere Instruktion, einen Cycle um ausgeführt zu werden.&lt;br /&gt;
Da UCore keine Branchprediction bzw. keine spekulative Ausführung etc. unterstützt und es auch nicht gewollt ist Opcodes in der Pipeline zu verwerfen (wie z.B. bei MC68020), entstehen nach Sprungbefehlen sogenannte &#039;Delay Slots&#039;. Die Anzahl dieser &#039;Delay Slots&#039; ergeben sich aus der Anzahl der Pipelinestufen vor der Ausführungseinheit (da sie den Programmcounter verändert).&lt;br /&gt;
Kurzum programlauftechnisch werden Instruktionen in diesen &#039;Delay Slots&#039; ausgeführt bevor der Sprung in Wirklichkeit ausgeführt wird (bzw. &#039;gefetched&#039; werden).&lt;br /&gt;
Die kleinst mögliche Schleife benötigt deshalb fünf Instruktionen für einen Durchlauf.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loop	br	loop		;branch zu loop&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In vielen Fällen können &#039;Delay Slots&#039; sinnvoll genutzt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 1 (nicht optimiert - 8 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,1	;r1 = x Parameter&lt;br /&gt;
	movei	r1,7	;r2 = y Parameter&lt;br /&gt;
	gpci	r7,2	;r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 1 (optimiert - 6 Cycles): ====&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	gpci	r7,2	r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	movei	r0,1	;delay slot	r1 = x Parameter&lt;br /&gt;
	movei	r1,7	;delay slot     r2 = y Parameter&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 2 (nicht optimiert - 8 * n + 3 Cycles -&amp;gt; if n 128 -&amp;gt; total 1027 Cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127	;r0 = loop counter - 1&lt;br /&gt;
	movei	r1,0	;r1 = Füllwert&lt;br /&gt;
	nop&lt;br /&gt;
	&lt;br /&gt;
loop	st	r1,r6	;imem[r1] = r6&lt;br /&gt;
	addi	r1,1	;r1++&lt;br /&gt;
	subi	r0,1	;r0-- (t clear bei &amp;lt; 0)&lt;br /&gt;
	brts	loop	;branch loop solange t set&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 2 (optimiert - 6 * n + 2 Cycles -&amp;gt; if n 128 -&amp;gt; total 770 Cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127&lt;br /&gt;
	movei	r1,0&lt;br /&gt;
	&lt;br /&gt;
loop	subi	r0,1	;da t später verwendet wird nicht in delay slot benutzen (siehe Interruptverarbeitung)&lt;br /&gt;
	brts	loop&lt;br /&gt;
	st	r1,r6	;delay slot&lt;br /&gt;
	addi	r1,1	;delay slot	&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Speicherzugriffe ==&lt;br /&gt;
&lt;br /&gt;
UCore besitzt keine &#039;gewöhnlichen&#039; Lesebefehle für interne/externe Speicherzugriffe.&lt;br /&gt;
Um Pipeline-Stalls beim Lesen von Daten zu vermeiden (Latenz zum Speicher), wird eine Lesebefehl in zwei Operationen aufgeteilt.&lt;br /&gt;
Der erste Befehl ist ein &#039;Request&#039;, er teilt dem Core mit von welcher Adresse er etwas lesen soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Der zweite Befehl ist dann der &#039;Load&#039;, er holt sich die angekommenen Daten ab und speichert sie in einem Register.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== interner Speicherzugriff ====&lt;br /&gt;
&lt;br /&gt;
Bei internen Speicherzugriffen ist die Latenz zwischen Request und Load statisch (3 Cycles), bei externen Zugriff variable (hier wird im Fall eines Load ohne vorhandene Daten ein Stall ausgelöst).&lt;br /&gt;
&lt;br /&gt;
Mit den Opcode &#039;&#039;rqld&#039;&#039; (request load) und &#039;&#039;ld&#039;&#039; (load) kann vom internen Speicher gelesen werden.&lt;br /&gt;
Da die Daten erst zwei Operationen nach dem Request verfügbar sind, muss hier eine andere Instruktion ausgeführt werde (z.B. &#039;&#039;nop&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0	;send load to address (r0+0)&lt;br /&gt;
	nop		;data send to memory&lt;br /&gt;
	nop		;data will read&lt;br /&gt;
	ld	r1	;readed data to r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Da der interne Speicher immer innerhalb von einem Cycles antwortet und die Latenz durch Pipelinestufen entsteht, können internen Speicherzugriff bis zu drei Request hintereinander verwenden.&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0&lt;br /&gt;
	rqld	r0,1&lt;br /&gt;
	rqld	r0,2&lt;br /&gt;
	ld	r1	;r1 &amp;lt;- internal_mem[r0+0]&lt;br /&gt;
	ld	r2	;r2 &amp;lt;- internal_mem[r0+1]&lt;br /&gt;
	ld	r3	;r3 &amp;lt;- internal_mem[r0+2]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Bei Schreibzugriffen wird, wie bei anderen Prozessoren, ein &#039;&#039;st&#039;&#039; (Store-Kommando) verwendet.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti	$80	;imm extend&lt;br /&gt;
	move	r4,$01	;r4 = $8001&lt;br /&gt;
	move	r0,12	;r0 = 12&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	st	r0,r4	;imem[r4] = r0; $8001 = 12&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
Da ein &#039;&#039;st&#039;&#039;ore Befehl nur einen Register als Zieladresse benutzt, ist es vielen Fällen ärgerlich, diesen bei mehrfachen Schreiben zu verändern. Um in diesem Fall Abhilfe zu schaffen, wurde der Befehl &#039;&#039;ssto&#039;&#039; (Set Store Offset) und &#039;&#039;stwo&#039;&#039; (Store with Offset) implementiert. Mit &#039;&#039;ssto&#039;&#039; kann ein Offset für &#039;&#039;stwo&#039;&#039; gesetzt werden, d.h. der Wert der mit &#039;&#039;ssto&#039;&#039; gesetzt wird auf die Zieladresse von &#039;&#039;stwo&#039;&#039; addiert.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	stwo 1&lt;br /&gt;
	ssto r0,r7 ;imem[r7+1] = r0&lt;br /&gt;
	stwo 2&lt;br /&gt;
	ssto r1,r7 ;imem[r7+2] = r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist es leider etwas unangenehm mit der statischen Latenz bei internen Lesezugriffen, da man hier etwas mehr schreiben muss als man es von anderen Prozessoren gewöhnt ist.&lt;br /&gt;
&lt;br /&gt;
==== externe Speicherzugriffe ====&lt;br /&gt;
&lt;br /&gt;
Externe Speicherzugriffe verhalten sich ähnlich wie interne Zugriff.&lt;br /&gt;
Unterschiede gibt es in der Adressbreite (extern 32 Bit) und in der variablen Latenz (bestimmt durch mehre Faktoren).&lt;br /&gt;
Es gibt eine externe Hauptadresse (Base) die mit &#039;&#039;&#039;allen&#039;&#039;&#039; (bis auf edrqldi) externen Speicherzugriffsinstruktionen verwendet wird.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel Hauptadresse setzen: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel schreibe in externen Speicher: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r4,$af&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	esadr	r1,r0	;Hauptadresse (esadr) is r1:r0&lt;br /&gt;
	est	r4,0	;externSpeicher[esadr + 0] = r4&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
Beim Lesen vom externen Speicher werden ebenfalls Request/Load Befehle verwendet um Latenzen, wenn möglich, zu vermeiden. Da die Latenz (meist) nicht vorhersehbar ist, wird bei nicht vorhandenen Daten solange gewartet bis sie vorhanden sind (Stall).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
	erqld	0	;load from [r0:r1 + 0]&lt;br /&gt;
	eld	r7	;get external data (Stall solange bis Daten vorhanden)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um Lade/Schreiblatenzen zu vermeiden bzw. zu reduzieren, können mehre Stores oder Request hintereinander ausgeführt werden (maximal 256 Requestzugriffe, keine Begrenzung bei Stores).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreibe 8 Worte in externen Speicher, kein Stall solange Schreibpuffer nicht voll): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,0&lt;br /&gt;
	esadr	r7,r6	;external address is r7:r6 &lt;br /&gt;
	est	r0,0&lt;br /&gt;
	est	r0,1&lt;br /&gt;
	est	r0,2&lt;br /&gt;
	est	r0,3&lt;br /&gt;
	est	r0,4&lt;br /&gt;
	est	r0,5&lt;br /&gt;
	est	r0,6&lt;br /&gt;
	est	r0,7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (vermeiden von Leselatenzen) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r7,r6&lt;br /&gt;
	erqld	0&lt;br /&gt;
	erqld	1&lt;br /&gt;
	erqld	2&lt;br /&gt;
	erqld	3	;request 4 Worte&lt;br /&gt;
	&lt;br /&gt;
	....		;mach irgendwas&lt;br /&gt;
	&lt;br /&gt;
	eld	r0	&lt;br /&gt;
	eld	r1&lt;br /&gt;
	eld	r2&lt;br /&gt;
	eld	r3	;bekomme Daten (evtl. kein Stall, da Daten schnell genug vorhanden)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Stack ==&lt;br /&gt;
&lt;br /&gt;
Der Stackpointer zeigt nach dem Reset auf Adresse $8000 (also am oberen Ende des internen Speichers).&lt;br /&gt;
Das Verhalten von &#039;&#039;push&#039;&#039;, &#039;&#039;request pops&#039;&#039; und &#039;&#039;pops&#039;&#039; sind gleich dem internen Speicherzugriffsverhalten (3 Cycles Latenz, Pipelined).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (1 pop): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r4	;sp--; imem[sp] = r4&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop		;request imem[sp], sp++&lt;br /&gt;
	nop&lt;br /&gt;
	nop&lt;br /&gt;
	pop	r4	;r4 = imem[sp]&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel (3 Werte auf Stack und wieder herunter) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r1&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r3&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop		;durch Latenz maximal 3 rqpop dann Daten (ansonsten &#039;poparqp&#039; benutzen (kann Request und Load gleichzeitig))&lt;br /&gt;
	push	r3&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Decoder extend ==&lt;br /&gt;
&lt;br /&gt;
Da viele Operationen konstante Werte (in Operand kodiert) benutzen können, aber diese aus Gründen der Befehlsbreite (16 Bit) je nach Befehl/Operanden nur eine teilweise unzureichende Größe/Breite verwenden können, wurde eine Dekoder Instruktion &#039;&#039;dexti&#039;&#039; (decoder extend immediate) eingeführt.&amp;lt;br&amp;gt;&lt;br /&gt;
Dieser Befehl wird vom Dekoder ausgeführt und wird in der eigentlichen Ausführungseinheit ignoriert (&#039;&#039;nop&#039;&#039;).&lt;br /&gt;
Sinn dieses Befehls ist es, konstante Werte um einen 8 Bit breiten Wert zu erweitern. Um Fehler zu vermeiden ist dieser Wert nur einen Cycle nach &#039;&#039;dexti&#039;&#039; verfügbar.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (16 Bit immediate Addition) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti     $12&lt;br /&gt;
	addi	  r0,$34	;r0 = r0 + $1234&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interrupts ==&lt;br /&gt;
&lt;br /&gt;
Interrupts sind in einem Pipeline basierenden Design immer ärgerlich (IMHO) zu handhaben. Da UCore nicht, wie viele Mikrokontroller, möglichst kurze Interrupt-Latenzen ermöglichen muss, gibt es in diesem Design auch keine garantierten Zeiten in welchen der Interrupt ausgeführt wird.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Um den Hardwareaufwand gering wie möglich zu halten, habe ich eine sogenannte &#039;&#039;Branch-Injektion&#039;&#039; implementiert. Der Hintergedanke ist, dass Sprünge sehr oft im Code ausgeführt werden und diese, im Fall eines Interrupts, dazu &#039;&#039;missbraucht&#039;&#039; werden können, direkt zum Interrupt-Service-Vector zu springen, anstatt ihren eigentlichen definierten Sprung auszuführen (dieser wird gespeichert und später ausgeführt).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Der Vorteil dieser Implementierung ist, ein sehr geringer Hardwareaufwand, der Nachteil ist, dass die Interrupt-Latenz variiert (Delta zwischen zwei Sprüngen) und sich Verhaltensregeln für &#039;Delay-Slots&#039; ergeben.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;	&lt;br /&gt;
	sei			;irq enable&lt;br /&gt;
	br	anySubroutine	;if irq is enabled and occure a branch is taken to irq vector and after irq is finished (rte) the give branch will taken&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In &#039;Delay-Slots&#039; sollten kein T-Bit gesetzt werden, welches für spätere Verwendungen gebraucht wird.&amp;lt;br&amp;gt; Außerdem sollten keine Speicher-Request (ohne Loads) an diesen Stellen ausgeführt werden.&lt;br /&gt;
Um Fehler zu vermeiden warnt der Assembler bei solchen Konstrukten.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
	sei&lt;br /&gt;
	br	anySubroutine&lt;br /&gt;
	addt	r0,r1	;delay slot	(t is not save in delay slot if irq is enabled, because t is only store at br instruction)&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dividieren ==&lt;br /&gt;
&lt;br /&gt;
Viele Prozessoren die auf geringen &#039;Platzverbrauch&#039; optimiert sind, versuchen wenn möglich Divisions-Operationen zu vermeiden oder führen diesen nicht in einer Pipeline-Implementierung aus.&amp;lt;br&amp;gt;&lt;br /&gt;
Auf der Softwareseite sind Divisionen in vielen Fällen vermeidbar oder durch bestimmte Methoden ersetzbar. Prinzipiell ist eine Division einfach in Software zu implementieren, in diesem Fall ist die Geschwindigkeit einer Hardwareimplementierung meist nicht annähernd zu erreichen.&amp;lt;br&amp;gt;&lt;br /&gt;
UCore bietet spezielle Befehle an, um einen Kompromiss aus Geschwindigkeit und Hardwareaufwand zu ermöglichen.&lt;br /&gt;
Wie bei einer normalen Division wird der Divisor und Dividend gesetzt, zusätzlich muss noch die Divsions-Bitbreite angegeben werden (max. 32 Bit). Durch den Befehl &#039;&#039;udivstep&#039;&#039; wird eine &#039;1-Bit Division&#039; ausgeführt, d.h. &#039;&#039;udivstep&#039;&#039; muss/kann sooft ausgeführt werden wie die Divisionsbreite gewählt ist. Als Resultat der Division ergeben sich der Quotient und der Rest.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* udiv16&lt;br /&gt;
;* &lt;br /&gt;
;* r0 	 	divident&lt;br /&gt;
;* r1		divisor&lt;br /&gt;
;*&lt;br /&gt;
;* return&lt;br /&gt;
;*&lt;br /&gt;
;* r2		qoutient&lt;br /&gt;
;* r3		remainder&lt;br /&gt;
;*&lt;br /&gt;
;* needs 34 cycles&lt;br /&gt;
;*&lt;br /&gt;
	&lt;br /&gt;
udiv16	&lt;br /&gt;
	udivinit	15&lt;br /&gt;
	udivsdd		r0&lt;br /&gt;
	udivsdv		r1&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,3	;(3+1)*4 = 16&lt;br /&gt;
	cli		;disable irq&lt;br /&gt;
udiv16Loop	&lt;br /&gt;
	subi	r0,1&lt;br /&gt;
	brts	udiv16Loop&lt;br /&gt;
	udivstep	;delay slot	!!!! note udivstep is not irq save, so use cli/sei lock&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	udivgq		r2	;delay slot		get qoutient&lt;br /&gt;
	udivgr		r3	;delay slot		get remainder&lt;br /&gt;
	sei			;delay slot		enable irqs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== weiter Beispiele ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
= UCtrl =&lt;br /&gt;
&lt;br /&gt;
UCtrl ist eine Abstraktionsschicht für einen Großteil der externen (Altera-DE2-115) Peripherien und stellt zusätzlich hilfreiche Element (Timer,…) zur Verfügung.&amp;lt;br&amp;gt;&lt;br /&gt;
Direkten Zugriff auf diese Komponente hat nur UCore (siehe Memorymap).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCtrl bietet dem Benutzer zugriff auf:&lt;br /&gt;
*LEDS &lt;br /&gt;
*SWITCHES&lt;br /&gt;
*7-Segment Anzeige&lt;br /&gt;
*LCD (zweizeilig auf DE2-115)&lt;br /&gt;
*Interrupt Kontrolle (für UCore)&lt;br /&gt;
*Timer/Counter&lt;br /&gt;
*Video Setup (inkl. Counter und Vertikal-‚Hit‘-Erkennung)&lt;br /&gt;
*PS/2 Port (in/out, zwei Ports)&lt;br /&gt;
*I2C (zwei Ports)&lt;br /&gt;
*Audio (DAC/ADC)&lt;br /&gt;
*HCore Setup und Daten (beschreibe ich später)&lt;br /&gt;
&lt;br /&gt;
== Register ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8000&lt;br /&gt;
name = LEDG_SW&lt;br /&gt;
read            fedcba9876543210&lt;br /&gt;
                SSSSSSSSSSSSSSSS&lt;br /&gt;
                &lt;br /&gt;
                S = switches on DE2-115&lt;br /&gt;
                &lt;br /&gt;
write           fedcba9876543210&lt;br /&gt;
                -------GGGGGGGGG&lt;br /&gt;
                &lt;br /&gt;
                G = LED Green (&#039;1&#039; is ON)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8001&lt;br /&gt;
name = LEDR&lt;br /&gt;
read            fedcba9876543210&lt;br /&gt;
                --------------ME&lt;br /&gt;
        &lt;br /&gt;
                M = &#039;1&#039; if running in modelsim&lt;br /&gt;
                E = &#039;1&#039; if running in emulator&lt;br /&gt;
                &lt;br /&gt;
write                fedcba9876543210&lt;br /&gt;
                -------RRRRRRRRR&lt;br /&gt;
                &lt;br /&gt;
                R = LED Red (&#039;1&#039; is ON)&lt;br /&gt;
&lt;br /&gt;
                 &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8002 - $8005&lt;br /&gt;
name = 7SEG&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                2 ----------------&lt;br /&gt;
                3 ----------------&lt;br /&gt;
                4 ----------------&lt;br /&gt;
                5 ----------------&lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                2 -6543210-6543210&lt;br /&gt;
                3 -6543210-6543210&lt;br /&gt;
                4 -6543210-6543210&lt;br /&gt;
                5 -6543210-6543210&lt;br /&gt;
                &lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 1 / 0 (&#039;1&#039; is ON)                &lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 3 / 2 (&#039;1&#039; is ON)&lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 4 / 4 (&#039;1&#039; is ON)&lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 5 / 6 (&#039;1&#039; is ON)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8006 - $8007&lt;br /&gt;
name = LCD&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                6 -------BDDDDDDDD&lt;br /&gt;
                7 ----------------&lt;br /&gt;
                &lt;br /&gt;
                B = &#039;1&#039; if read/write request is busy&lt;br /&gt;
                D = Data after request&lt;br /&gt;
                &lt;br /&gt;
                note: wait 1 cycle after read/write request before read&lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                6 ------WRDDDDDDDD&lt;br /&gt;
                7 ----------------&lt;br /&gt;
                &lt;br /&gt;
                W = &#039;0&#039; is request write, &#039;1&#039; is request read&lt;br /&gt;
                R = LCS RS&lt;br /&gt;
                D = data to write&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8008 - $8009&lt;br /&gt;
name = IRQ&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                8 -----------HADTT IRQ MSK&lt;br /&gt;
                9 -----------HADTT IRQ MEMORY&lt;br /&gt;
                &lt;br /&gt;
                TT = Timer 2/1 IRQ&lt;br /&gt;
                D  = Audio DAC FIFO run low&lt;br /&gt;
                A  = Audio ADC FIFO run full&lt;br /&gt;
                H  = HCORE has data&lt;br /&gt;
                &lt;br /&gt;
write                  fedcba9876543210&lt;br /&gt;
                8 -----------HADTT IRQ MSK&lt;br /&gt;
                9 -----------HADTT IRQ MEMORY&lt;br /&gt;
                &lt;br /&gt;
                TT = Timer 2/1 IRQ&lt;br /&gt;
                D  = Audio DAC FIFO run low&lt;br /&gt;
                A  = Audio ADC FIFO run full&lt;br /&gt;
                H  = HCORE has data&lt;br /&gt;
                &lt;br /&gt;
description:&lt;br /&gt;
&lt;br /&gt;
                IRQ MSK is used to enable given interrupts (for example D = &#039;1&#039; then Audio DAC irq will be used)&lt;br /&gt;
                IRQ MEMORY reflect after interrupt which interrupt is the source (for example TT = &#039;01&#039; then Timer 1 made this interrupt)&lt;br /&gt;
                &lt;br /&gt;
                You should/have to clear the given interrupt bit in IRQ MEMORY before leaving interrupt service routine.&lt;br /&gt;
                        &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $800A - $800F&lt;br /&gt;
name = TIMERS&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                A DDDDDDDDDDDDDDDD TIMER_1_LOW  (Timer 1 value low)&lt;br /&gt;
                B DDDDDDDDDDDDDDDD TIMER_1_HIGH (Timer 1 value high, note: low/high needs capture first to be updated)&lt;br /&gt;
                C ----------------&lt;br /&gt;
                D DDDDDDDDDDDDDDDD TIMER_2_LOW  (Timer 2 value low)&lt;br /&gt;
                E DDDDDDDDDDDDDDDD TIMER_2_HIGH (Timer 2 value high, note: low/high needs capture first to be updated)&lt;br /&gt;
                F ----------------&lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                A DDDDDDDDDDDDDDDD TIMER_1_LOW  (Timer 1 value low)&lt;br /&gt;
                B DDDDDDDDDDDDDDDD TIMER_1_HIGH (Timer 1 value high, write to high will update)&lt;br /&gt;
                C ------------CLSR TIMER_1_CTRL&lt;br /&gt;
                D DDDDDDDDDDDDDDDD TIMER_2_LOW  (Timer 1 value low)&lt;br /&gt;
                E DDDDDDDDDDDDDDDD TIMER_2_HIGH (Timer 1 value high, write to high will update)&lt;br /&gt;
                F ------------CLSR TIMER_2_CTRL&lt;br /&gt;
                &lt;br /&gt;
                C = Capture counter value for read (copy current counter value to $A/B $D/E)&lt;br /&gt;
                L = Enable Auto Reload Value (after counter value runs to 0 next value is $A/B $D/E)&lt;br /&gt;
                S = Stop timer&lt;br /&gt;
                R = Start timer (will do a Autoreload from $A/B $D/E)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8010 - $802F&lt;br /&gt;
name = VIDEO&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                10 00000DDDDDDDDDDD current HCount (11..0)&lt;br /&gt;
                11 000000DDDDDDDDDD current VCount (10..0)&lt;br /&gt;
                12 ---------------H Hit of programmed VCOUNT&lt;br /&gt;
                13 ---------------- &lt;br /&gt;
                14 ---------------- &lt;br /&gt;
                15 ----------------&lt;br /&gt;
                16 ----------------&lt;br /&gt;
                17 ---------------- &lt;br /&gt;
                18 ---------------- &lt;br /&gt;
                19 ----------------&lt;br /&gt;
                1a ----------------&lt;br /&gt;
                1b ---------------- &lt;br /&gt;
                1c ---------------- &lt;br /&gt;
                1d ----------------&lt;br /&gt;
                1e ----------------&lt;br /&gt;
                1f ---------------- &lt;br /&gt;
                20 ---------------- &lt;br /&gt;
                21 ----------------                &lt;br /&gt;
                22 ----------------&lt;br /&gt;
                23 ---------------- &lt;br /&gt;
                24 ---------------- &lt;br /&gt;
                25 ----------------&lt;br /&gt;
                26 ----------------&lt;br /&gt;
                27 ---------------- &lt;br /&gt;
                28 ---------------- &lt;br /&gt;
                29 ----------------&lt;br /&gt;
                2a ----------------&lt;br /&gt;
                2b ---------------- &lt;br /&gt;
                2c ---------------- &lt;br /&gt;
                2d ----------------&lt;br /&gt;
                2e ----------------&lt;br /&gt;
                2f ---------------- &lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                10 ---------------D VIDEO ON if &#039;1&#039;&lt;br /&gt;
                11 ------DDDDDDDDDD HSYNC&lt;br /&gt;
                12 ------DDDDDDDDDD HSTART&lt;br /&gt;
                13 ------DDDDDDDDDD HMEMSTART&lt;br /&gt;
                14 ------DDDDDDDDDD HSTOP &lt;br /&gt;
                15 ------DDDDDDDDDD HTOTAL&lt;br /&gt;
                16 -------DDDDDDDDD VSYNC&lt;br /&gt;
                17 -------DDDDDDDDD VSTART&lt;br /&gt;
                18 -------DDDDDDDDD VSTOP&lt;br /&gt;
                19 -------DDDDDDDDD VTOTAL&lt;br /&gt;
                1a DDDDDDDDDDDDDDDD LINE CACHE ADDRESS ADD LOW&lt;br /&gt;
                1b DDDDDDDDDDDDDDDD LINE CACHE ADDRESS ADD HIGH &lt;br /&gt;
                1c ---------------- LINE CACHE LATCH VALUE&lt;br /&gt;
                1d -------DDDDDDDDD LINE CACHE START ADDRESS (Pixel offset)&lt;br /&gt;
                1e --------DDDDDDDD HITVCOUNT (see description)&lt;br /&gt;
                1f ---------------- &lt;br /&gt;
                20 ------DDDDDDDDDD HLOADSTART&lt;br /&gt;
                21 ------DDDDDDDDDD HLOADSTOP                &lt;br /&gt;
                22 -------DDDDDDDDD VLOADSTART&lt;br /&gt;
                23 -------DDDDDDDDD VLOADSTOP&lt;br /&gt;
                24 -------DDDDDDDDD VLOADNEXT&lt;br /&gt;
                25 DDDDDDDDDDDDDDDD EXTERNAL MEMORY START ADDRESS (low)&lt;br /&gt;
                26 DDDDDDDDDDDDDDDD EXTERNAL MEMORY START ADDRESS (high)&lt;br /&gt;
                27 DDDDDDDDDDDDDDDD EXTERNAL MEMORY LINE OFFSET (low)&lt;br /&gt;
                28 DDDDDDDDDDDDDDDD EXTERNAL MEMORY LINE OFFSET (high)&lt;br /&gt;
                29 --------------DD MEMORY Convertion MODE&lt;br /&gt;
                2a ---------------- LATCH MEMORY CONFIG&lt;br /&gt;
                2b ---------------- &lt;br /&gt;
                2c ---------------- &lt;br /&gt;
                2d ----------------&lt;br /&gt;
                2e ----------------&lt;br /&gt;
                2f ----------------                                 &lt;br /&gt;
                &lt;br /&gt;
        HITVCOUNT = Programmable VCOUNT if this Value is written $12 bit 0 is set to &#039;1&#039; if VCOUNT is equal to this value&lt;br /&gt;
                  $12 bit 0 is cleared at write to this register&lt;br /&gt;
&lt;br /&gt;
        EXTERNAL MEMORY LINE OFFSET = will be add after every loaded line (for non interleaved video setup)&lt;br /&gt;
        &lt;br /&gt;
        MEMORY Convertion MODE = defines the format of data converted from external memory (ever 32Bit fetch) to line cache&lt;br /&gt;
        &lt;br /&gt;
                00 = X8 R8 G8 B8                       (32 Bit = (8 Bit for Red/Gree/Blue))&lt;br /&gt;
                01 = R5 R6 R5 R5 R6 R5                 (2 * 16 Bit = (5 Bit for Red/Blue and 6 Bit for Green))&lt;br /&gt;
                10 = X1 R5 R5 X1 R5 R5 R5 R5         (2 * 16 Bit = (5 Bit for Red/Gree/Blue))&lt;br /&gt;
                11 = X4 R4 R4 R4 X4 R4 R4 R4          (2 * 16 Bit = (4 Bit for Red/Gree/Blue))&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8030 - $8031&lt;br /&gt;
name = PS/2 port a/b&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                30 -----FWVDDDDDDDD        PS2_PORT_A (port A)&lt;br /&gt;
                31 -----FWVDDDDDDDD        PS2_PORT_B (port B)&lt;br /&gt;
                &lt;br /&gt;
                D = PS/2 DATA (Scan Code) valid if A = &#039;1&#039;&lt;br /&gt;
                V = Data valid&lt;br /&gt;
                W = Write FIFO not full&lt;br /&gt;
                F = all writes finished (Fifo with 16 entries)&lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
                note: wait 1 cycle after read/write request before read&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                30 ------WADDDDDDDD        PS2_PORT_A (port A)&lt;br /&gt;
                31 ------WADDDDDDDD        PS2_PORT_B (port B)&lt;br /&gt;
                &lt;br /&gt;
                D = PS/2 DATA to write&lt;br /&gt;
                A = get next scan code (read 2 cycles after this from $30/$31)&lt;br /&gt;
                W = Write data to PS/2 device&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8032 - $8033&lt;br /&gt;
name = I2C port a/b&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                30 ------------D---       I2C_PORT_A (port A (eeprom on DE2-115))&lt;br /&gt;
                31 ------------D---       I2C_PORT_B (port B (audio/video in on DE2-115))&lt;br /&gt;
                &lt;br /&gt;
                D = data in from port A/B&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                30 ----EEE------ICD       I2C_PORT_A&lt;br /&gt;
                31 ----EEE------ICD       I2C_PORT_B&lt;br /&gt;
                &lt;br /&gt;
                D = data out value&lt;br /&gt;
                C = clock out value&lt;br /&gt;
                I = direction of data (&#039;0&#039; = in / &#039;1&#039; = out)&lt;br /&gt;
                &lt;br /&gt;
                EEE = is write enable for ICD&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8034 - $803b&lt;br /&gt;
name = AUDIO&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                34 DDDDDDDDDDDDDDDD ADC_DATA_LEFT_HIGH       &lt;br /&gt;
                35 --------DDDDDDDD ADC_DATA_LEFT_LOW                 &lt;br /&gt;
                36 DDDDDDDDDDDDDDDD ADC_DATA_RIGHT_HIGH                  &lt;br /&gt;
                37 --------DDDDDDDD ADC_DATA_RIGHT_LOW       &lt;br /&gt;
                38 ----------------&lt;br /&gt;
                39 ----------------&lt;br /&gt;
                3a ----------------&lt;br /&gt;
                3b ----------------&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                   fedcba9876543210&lt;br /&gt;
                34 DDDDDDDDDDDDDDDD DAC_DATA_LEFT_HIGH       &lt;br /&gt;
                35 --------DDDDDDDD DAC_DATA_LEFT_LOW            &lt;br /&gt;
                36 DDDDDDDDDDDDDDDD DAC_DATA_RIGHT_HIGH               &lt;br /&gt;
                37 --------DDDDDDDD DAC_DATA_RIGHT_LOW         &lt;br /&gt;
                38 AAAAAAAADDDDDDDD ADAC_CTRL (Data)&lt;br /&gt;
                39 --------DDDDDDDD DAC_IRQ_GEN (interrupt generate if lower) &lt;br /&gt;
                3a --------DDDDDDDD ADC_IRQ_GEN (interrupt generate if higher)&lt;br /&gt;
                3b ---------------- ADC_NEXT (recive values (after 2 cycles available in ADC_DATA ($34-$37)))&lt;br /&gt;
                &lt;br /&gt;
                ADAC_CTRL (Data) = configure internal ADC/DAC controller&lt;br /&gt;
                &lt;br /&gt;
                Adr 76543210&lt;br /&gt;
                0   -------- ignore&lt;br /&gt;
                1   -------E enable DAC&lt;br /&gt;
                2   ----CCCC DAC push counter (96KHz at 0, 48KHz at 1, 32KHz at 2 ....)&lt;br /&gt;
                3   -------E enable ADC&lt;br /&gt;
                4   ----CCCC ADC pull counter (96KHz at 0, 48KHz at 1, 32KHz at 2 ....)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $803c - $8044&lt;br /&gt;
name = HCORE CTRL/IO (in experimental state)                                &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Videosetup im Detail ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:16 32Bit Computer Konsole Uctrl video setup.png|miniatur|Video Setup]]&lt;br /&gt;
&lt;br /&gt;
UCore und UCtrl (also auch der Videokontoller) haben eine Taktfrequenz von 106,481 MHz, mit dieser Frequenz ist es möglich eine maximale Auflösung von 1440 x 900 Bildpunkten bei 60 Hz zu programmieren.&amp;lt;br&amp;gt;&lt;br /&gt;
Da diese Auflösung in vielen Fällen zu hoch ist, bzw. die Performance für eine flüssige Bildberechnung nicht immer ausreicht, kann ein interner Zeilen-Cache so programmiert werden, dass er nur eine bestimmte Anzahl an Pixeln pro Zeile ausgibt (H-Skaliert) und nur eine definierte Anzahl von Zeilen neu geladen wird (V-Skaliert).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Wie üblich können (siehe Bild), HSYNC, HSTART etc. frei programmiert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Als Quelle für die Bilddaten kann der SDRAM oder SRAM benutzt werden (siehe EXTERNAL_MEMORY_START_ADDRESS).&lt;br /&gt;
Das Farbformat kann zwischen einem 32 Bit Format (8Bit für R/G/B) und drei 16 Bit Formaten gewählt werden (siehe MEMORY Convertion MODE).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Support von Bitplanes oder Tiled-Grafiken gibt es nicht.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Video setup 360x225 4X4R4G4B Mode ($d0000000 ist Quelle (SDRAM)):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* setupVideo&lt;br /&gt;
;*&lt;br /&gt;
&lt;br /&gt;
setupVideo&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,videoDefault		;source&lt;br /&gt;
	movei	r1,UcTimer2Ctrl		;dest-1&lt;br /&gt;
	moveih	r0,&amp;gt;videoDefault&lt;br /&gt;
	moveih	r1,&amp;gt;UcTimer2Ctrl			&lt;br /&gt;
	movei	r2,26			;27-1&lt;br /&gt;
	&lt;br /&gt;
setupVideoLoop&lt;br /&gt;
&lt;br /&gt;
	rqldi	r0,0&lt;br /&gt;
	addi	r0,1&lt;br /&gt;
	addi	r1,1&lt;br /&gt;
	ld	r3&lt;br /&gt;
	subi	r2,1&lt;br /&gt;
	brts	setupVideoLoop&lt;br /&gt;
	st	r1,r3	;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
		&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
	&lt;br /&gt;
;*********************************************************************&lt;br /&gt;
;* data&lt;br /&gt;
;*********************************************************************&lt;br /&gt;
	&lt;br /&gt;
videoDefault		;AD NAME					&lt;br /&gt;
	&lt;br /&gt;
	word	$0001	;10 VIDEO_ON					&lt;br /&gt;
	word	$0097	;11 HSYNC (D = 11 .. 0)				&lt;br /&gt;
	word	$017f	;12 HSTART (D = 11 .. 0)			&lt;br /&gt;
	word	$017d	;13 HMEMSTART (D = 11 .. 0)			&lt;br /&gt;
	word	$071f	;14 HSTOP (D = 11 .. 0)				&lt;br /&gt;
	word	$076f	;15 HTOTAL (D = 11 .. 0)			&lt;br /&gt;
	word	$0002	;16 VSYNC (D = 10 .. 0)				&lt;br /&gt;
	word	$001e	;17 VSTART (D = 10 .. 0)			&lt;br /&gt;
	word	$03a2	;18 VSTOP  (D = 10 .. 0)			&lt;br /&gt;
	word	$03a3	;19 VTOTAL  (D = 10 .. 0)			&lt;br /&gt;
	word	$0000	;1a LC ADDER LOW				&lt;br /&gt;
	word	$0040	;1b LC ADDER HIGH				&lt;br /&gt;
	word	$0000	;1c LC ADDER LATCH				&lt;br /&gt;
	word	$0000	;1d LC START (10 .. 0) Pixeloffset		&lt;br /&gt;
	word	$0000	;1e						&lt;br /&gt;
	word	$0000	;1f						&lt;br /&gt;
	word	$0008	;20 HLOADSTART 					&lt;br /&gt;
	word	$00bc	;21 HLOADSTOP					&lt;br /&gt;
	word	$001e	;22 VLOADSTART 					&lt;br /&gt;
	word	$03a2	;23 VLOADSTOP 					&lt;br /&gt;
	word	$0004	;24 VLOADNEXT					&lt;br /&gt;
	word	$0000	;25 MEM_STARTADR_store low			&lt;br /&gt;
	word	$d000	;26 MEM_STARTADR_store high			&lt;br /&gt;
	word	$0000	;27 MEM_LINEOFFSET_store low			&lt;br /&gt;
	word	$0000	;28 MEM_LINEOFFSET_store high			&lt;br /&gt;
	word	$0002	;29 MEM_MODE_store 				&lt;br /&gt;
	word	$0000	;2a LATCH MEM_STARTADR/LINEOFFSET/MODE		&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Audiosetup im Detail ==&lt;br /&gt;
[[Datei:Uctrl audio overview.png|miniatur|rechts|audio simple]]&lt;br /&gt;
Da das DE-115 einen Wolfson WM8731 besitzt, unterteilt sich die Ansteuerung für die Audio-Ein/Ausgabe in zwei Teile.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Erste, ist die Konfiguration des WM8731, hierfür wird I2C Port B von UCTRL verwendet.&amp;lt;br&amp;gt;&lt;br /&gt;
Um die Konfiguration einfach zu halten sind Komponenten zur Initialisierung über I2C vorhanden (initAudio), es muss nur eine Tabelle mit den gewünschten Einstellungen übergeben werden (Register, Wert siehe WM8731 Registerbeschreibung).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Setup:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
audioDefault&lt;br /&gt;
	&lt;br /&gt;
	;&lt;br /&gt;
				;A =  8 7654 3210&lt;br /&gt;
	.data   $9,$0000	;9 =  0 0000 0000 	(inactivate interface)&lt;br /&gt;
	.data	$0,$0097	;0 =  0 1001 0111	;left line in mute&lt;br /&gt;
	.data	$1,$0097	;1 =  0 1001 0111	;right line in mute&lt;br /&gt;
	.data	$2,$006e	;2 =  0 0111 1001	;+6db left out&lt;br /&gt;
	.data	$3,$006e	;3 =  0 0111 1001	;0db right out&lt;br /&gt;
	.data	$4,$0012	;4 =  0 0001 0010	;0=0 mic boost off;&lt;br /&gt;
							;1=1 enable line input mute&lt;br /&gt;
							;2=1 line input to adc&lt;br /&gt;
							;3=0 disable bypass&lt;br /&gt;
							;4=1 DAC select&lt;br /&gt;
							;5=0 side tone disable&lt;br /&gt;
							;76=0 -6db sidetone						&lt;br /&gt;
	.data	$5,$0000	;5 =  0 0000 0000	;DAC soft Mute off, no Filer&lt;br /&gt;
	.data	$6,$0067	;6 =  0 0110 0111 	;DAC Power, Output Power, Device Power on&lt;br /&gt;
	.data	$7,$0009	;7 =  0 0000 1001 	;left justified, 24 bit&lt;br /&gt;
	.data	$8,$001e	;8 =  0 0001 1110	;0=0 normal mode&lt;br /&gt;
							;1=1 bosr (384/192)&lt;br /&gt;
							;5432=0111 96khz&lt;br /&gt;
							;78=00 no clk dividing	&lt;br /&gt;
	.data   $9,$0001	;9 =  0 0000 0001 	(activate interface)&lt;br /&gt;
	.data	$ff,$0000	;stop&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der zweite Teil, das Senden und Empfangen der Audio Daten wird über UCTRL Register $34 bis $3b ermöglicht(&#039;&#039;&#039;ADC&#039;&#039;&#039;/&#039;&#039;&#039;DAC_DATA&#039;&#039;&#039;, &#039;&#039;&#039;ADAC_CTRL&#039;&#039;&#039;, &#039;&#039;&#039;ADC&#039;&#039;&#039;/&#039;&#039;&#039;DAC_IRQ_GEN&#039;&#039;&#039;, &#039;&#039;&#039;ADC_NEXT&#039;&#039;&#039;).&amp;lt;br&amp;gt;&lt;br /&gt;
Für ADC und DAC gibt es jeweils für den linken &amp;amp; rechten Kanal je 24 Bit Daten zu empfangen/senden. &amp;lt;br&amp;gt;&lt;br /&gt;
ADC/DAC besitzen je einen 256 Worte (2 * 24 Bit) großen Queue, im Register &#039;&#039;&#039;DAC_IRQ_GEN&#039;&#039;&#039; ($39) bzw. &#039;&#039;&#039;ADC_IRQ_GEN&#039;&#039;&#039; ($3a) können die die Unter/Überlaufwerte, welche zu einem Interrupt führen, konfiguriert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
D.h. für einen Audioausgabe, konfiguriert man z.B. den DAC Queue auf den Wert 128 um beim Erreichen (kleiner als) einen Interrupt auszulösen (in welchen der Queue befüllt wird).&amp;lt;br&amp;gt;&lt;br /&gt;
Dadurch ist eine unterbrechungsfreie Wiedergabe/Aufnahme möglich ohne (je nach Einstellung) zu viele Interrupts auszulösen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die ADC/DAC Komponente in UCTRL kann über Register &#039;&#039;&#039;ADAC_CTRL&#039;&#039;&#039; ($38) konfiguriert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Die oberen 8 Bit des Datenworts bestimmen die Adresse, die unteren 8 Bit die Daten.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCTRL Audio Config:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name			address		876543210	comment&lt;br /&gt;
&lt;br /&gt;
nop			0		XXXXXXXXX	do nothing&lt;br /&gt;
ctrl			1		XXXXXXXXE	E = enable audio (default off)&lt;br /&gt;
set fifo read count	2		XXXXXXCCC	96KHz/C = fread [0..15]&lt;br /&gt;
set fifo write count	3		XXXXXXCCC	96KHz/C = fwrite [0..15]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Hier sollte vor der eigentlich Audio Ausgabe/Aufnahme, der jeweilige Counter für den ADC/DAC gesetzt werden (Counter der bei erreichen von 0 liest/schreibt). Z.B. den Wert 2 um eine 32 KHz Ausgabe einzustellen. Um die Queues zu lesen/schreiben muss noch unter Adresse 1 die Komponente aktiviert werden.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Audioausgabe von zwei 16 Bit Werten (links/rechts).&lt;br /&gt;
&amp;lt;br&amp;gt;	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	;r2 Audiobase $34&lt;br /&gt;
	;r1 = Wert für L, r4 = Wert für R&lt;br /&gt;
&lt;br /&gt;
	movei	r3,0&lt;br /&gt;
	stinc	r2,r1	;dac left high = value&lt;br /&gt;
	movei	r7,$1&lt;br /&gt;
	stinc	r2,r3	;dac left low = 0&lt;br /&gt;
	moveih	r7,$1&lt;br /&gt;
	stinc	r2,r4	;dac right high = value&lt;br /&gt;
	nop&lt;br /&gt;
	stinc	r2,r3	;dac right low = 0&lt;br /&gt;
	nop&lt;br /&gt;
	st	r2,r7	;dac address/ctrl = $0101	;ctrl = enable audio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Audio Tools ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Um eine einfache Handhabung der Audioausgabe zu ermöglichen, gibt es unter dem Verzeichnis &#039;&#039;assembler_files\ucore\components&#039;&#039; Funktionen, die eine einfache Audioausgabe (Sample) und das Abspielen von MOD (Musik-Module) ermöglichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PS/2 im Detail==&lt;br /&gt;
Mit den Registern &#039;&#039;&#039;PS2_PORT_A/B&#039;&#039;&#039; kann auf die PS/2 Schnittstelle des DE2-115 zugegriffen werden. Um alle Scancodes zu verarbeiten, ist ein Eingangsqueue (von PS/2) mit 16 Einträgen und einen Ausgangsqueue (zu PS/2) mit 8 Einträgen implementiert worden &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Zum Schreiben eines 8 Bit breiten Wertes zum PS/2-Device kann/sollte vor dem eigentlichen Transfer geprüft werden, ob der Ausgangsqueue voll ist (Bit 9 = &#039;&#039;&#039;W&#039;&#039;&#039; in &#039;&#039;&#039;PS2_PORT_A/B&#039;&#039;&#039;).&amp;lt;br&amp;gt;&lt;br /&gt;
Der zu sendende Datenwert muss in den unteren 8 Bit des Registers (&#039;&#039;&#039;PS2_PORT_A/B&#039;&#039;&#039;) geschrieben werden. Mit Bit 9 (&#039;&#039;&#039;W&#039;&#039;&#039; = write) wird er dann schließlich in den Ausgangsqueue übertragen.&amp;lt;br&amp;gt;&lt;br /&gt;
Mit Bit 10 (&#039;&#039;&#039;F&#039;&#039;&#039; = writes finish) kann, je nach Bedarf, überprüft werden ob alle Daten übermittelt wurden.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Beim Lesen eine Wertes von dem PS/2-Device, muss mittels Bit 8 (&#039;&#039;&#039;V&#039;&#039;&#039; = data valid (lesen)) geprüft werden, ob Daten im Eingangsqueue vorhanden sind, wenn dies zutrifft, wird mit setzen von Bit 8 (&#039;&#039;&#039;A&#039;&#039;&#039; = ACK (schreiben)) das Datenwort in die unteren 8 Bit des Register übertragen (zwei Cycles delay).&amp;lt;br&amp;gt;&lt;br /&gt;
Um die Handhabung mit einer PS/2 Tastatur zu vereinfachen, sind unter &#039;&#039;components/ps2keyboards.s&#039;&#039; Funktionen implementiert, welche die Steuerung und Auswertung (zu Ascii etc.) übernehmen.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel: testen auf Taste &#039;Escape&#039;:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	;process keys (read from PS/2 Device and process)&lt;br /&gt;
	&lt;br /&gt;
	gpci	r7,2		;lr&lt;br /&gt;
	br	PS2Process&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	&lt;br /&gt;
	;key test (ESC)&lt;br /&gt;
	&lt;br /&gt;
	gpci	r7,2		;lr&lt;br /&gt;
	br	PS2TestKey&lt;br /&gt;
	movei	r0,118		;test again &#039;ESC&#039; 	delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	&lt;br /&gt;
	;&lt;br /&gt;
	&lt;br /&gt;
	cmpeqi	r0,0		;r0 = 0 no key pressed&lt;br /&gt;
	brtc	escIsPressed	;jump &lt;br /&gt;
	&lt;br /&gt;
	.&lt;br /&gt;
	.&lt;br /&gt;
	.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==I2C Ports im Detail==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Auf dem Altera DE2-115 befinden sich mehrere Komponenten (Audio-Codec, Video-In, EEPROM)  die mittels des I2C-Protokolls konfiguriert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Um diese Komponenten ansteuern zu können, besitzt UCtrl zwei Ports welche die jeweiligen Pins (SDA/SCK) der Komponenten bedienen können. Das eigentliche I2C-Protokoll ist in Software umgesetzt, d.h. mit den &#039;&#039;&#039;I2C_PORT_A/B&#039;&#039;&#039; Registern können nur Pins gesetzt bzw. ihr Zustand gelesen werden.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Zum Daten lesen (SDA) wird Bit 3 (&#039;&#039;&#039;D&#039;&#039;&#039;) von Register &#039;&#039;&#039;I2C_PORT_A/B&#039;&#039;&#039; benutzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Zum Konfigurieren des Daten-Pins (Datenrichtung) wird Bit 2 (&#039;&#039;&#039;I&#039;&#039;&#039;) verwendet. Hierbei ist zu beachten, dass beim Schreiben immer das zugehörige Enable gesetzt werden muss (Bit 11-9). Also beim setzen des CLK-Pins (z.B.: $22 = Enable CLK, setze CLK = &#039;1&#039;).&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Wie schon erwähnt, ist das eigentliche I2C Protokoll in Software umgesetzt. Unter &#039;&#039;components/i2c.s&#039;&#039; sind die benötigten Funktionen implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Timer im Detail==&lt;br /&gt;
UCtrl besitzt zwei integrierte 32 Bit große Timer/Counter.&amp;lt;br&amp;gt;&lt;br /&gt;
Konfiguriert werden kann jeder Timer über Register &#039;&#039;&#039;TIMER_1/2_CTRL&#039;&#039;&#039;.&amp;lt;br&amp;gt;&lt;br /&gt;
Um den Startwert bzw. den aktuellen Wert des Timers/Counters zu lesen (bzw. zu schreiben) werden die Register &#039;&#039;&#039;TIMER_1/2_LOW/HIGH&#039;&#039;&#039; benutzt.&amp;lt;br&amp;gt; &lt;br /&gt;
Beim Schreiben ist zu beachten, dass &#039;&#039;&#039;TIMER_1/2_HIGH&#039;&#039;&#039; nach &#039;&#039;&#039;TIMER_1/2_LOW&#039;&#039;&#039; geschrieben werden muss.&amp;lt;br&amp;gt;&lt;br /&gt;
Beim Lesen muss das Bit 3 (&#039;&#039;&#039;C&#039;&#039;&#039; = Capture Counter) einmalig gesetzt werden um den aktuellen Wert in die Register &#039;&#039;&#039;TIMER_1/2_HIGH/LOW&#039;&#039;&#039; (Lesezugriff) zu laden.&amp;lt;br&amp;gt;&lt;br /&gt;
Gestartet und gestoppt wird jeder Timer mit Bit 1/0 (&#039;&#039;&#039;S&#039;&#039;&#039; = Stop, &#039;&#039;&#039;R&#039;&#039;&#039; = Start) im Register &#039;&#039;&#039;TIMER_1/2_CTRL&#039;&#039;&#039;.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Timer übernimmt beim Start den 32 Bit großen/breiten Wert aus Register &#039;&#039;&#039;TIMER_1/2_LOW/HIGH&#039;&#039;&#039; und dekrementiert (-1) diesen solange bis er den Wert 0 erreicht.&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn der Wert 0 erreicht ist, wird ein &amp;quot;Timer-Hit&amp;quot; ausgelöst. Dieser kann je nach Bedarf einen Interrupt auslösen (siehe Register &#039;&#039;&#039;IRQ_MSK/MEMORY&#039;&#039;&#039;).&amp;lt;br&amp;gt;&lt;br /&gt;
Um einen kontinuierlichen Lauf zu ermöglichen, kann Bit 2 (&#039;&#039;&#039;L&#039;&#039;&#039; = Auto Reload) aktiviert werden, in diesem Fall wird bei dem Erreichen von Wert 0, der Wert aus &#039;&#039;&#039;TIMER_1/2_LOW/HIGH&#039;&#039;&#039; geladen und der Timer startet erneut.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel vom Setzen und Starten des Timers 2:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti	&amp;gt;UcTimer2LowValue&lt;br /&gt;
	movei	r2,UcTimer2LowValue	;timer 2 base&lt;br /&gt;
		&lt;br /&gt;
	move	r0,240		;low value&lt;br /&gt;
	move	r1,0		;high value&lt;br /&gt;
	&lt;br /&gt;
	stinc	r2,r0		;low&lt;br /&gt;
	movei	r0,5		;start with auto reload&lt;br /&gt;
	stinc	r2,r1		;high		&lt;br /&gt;
	nop&lt;br /&gt;
	stinc	r2,r0		;write config (lets go)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== SD-Zugriff im Detail ==&lt;br /&gt;
Über die Implementierung der SD-Karten Schnittstelle möchte ich hier nicht im Detail eingehen (es sei denn, es wird gewünscht).&amp;lt;br&amp;gt;&lt;br /&gt;
Zum benutzen der SD-Karte sind unter &#039;&#039;components/sdCardLoader.s&#039;&#039; Funktionen vorhanden.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Software (Block-IO) unterstützt SD-SC/HC/XC Karten, als Ziel für die zu lesenden Daten kann der SRAM/DRAM benutzt werden. Die maximale Transfergeschwindigkeit beträgt 100Mbit.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel, nachladen von 16384 Blöcken (a 256 Bytes):&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ;read sdcard to s/sdram&lt;br /&gt;
	&lt;br /&gt;
        dexti	&amp;gt;startBlock&lt;br /&gt;
	movei	r0,startBlock&lt;br /&gt;
	nop&lt;br /&gt;
	rqldi	r0,0	;low&lt;br /&gt;
	rqldi	r0,1	;high&lt;br /&gt;
	nop&lt;br /&gt;
	ld	r2&lt;br /&gt;
	ld	r3&lt;br /&gt;
	&lt;br /&gt;
	addi	r2,64	;64 blocks offset (ucore code/data)&lt;br /&gt;
	addtqi	r3,r3,0&lt;br /&gt;
	&lt;br /&gt;
	;set destination address&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,$10&lt;br /&gt;
	movei	r1,$02&lt;br /&gt;
	moveih	r0,$b1&lt;br /&gt;
	moveih	r1,$d0		;r1:r0 = $d002 b110 (dest start)&lt;br /&gt;
	&lt;br /&gt;
	dexti	&amp;gt;sdCardReadBlocks&lt;br /&gt;
	movei	r6,sdCardReadBlocks&lt;br /&gt;
	gpci	r7,2		;lr&lt;br /&gt;
	jmpi	r6,0&lt;br /&gt;
	movei	r4,$ff		;16384 blocks-1	delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	moveih	r4,$2f		;delay slot&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
[[http://www.mikrocontroller.net/topic/310121#new|Thread]]&lt;br /&gt;
&lt;br /&gt;
= Homepage =&lt;br /&gt;
&lt;br /&gt;
http://www.goldmomo.de&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=83199</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=83199"/>
		<updated>2014-05-29T17:16:14Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: nichts wichtiges&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein ‚Computer‘system, das nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses nachbildet. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen das vollständig* selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (*FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL benutzt, für Emulation und Tools (Assembler etc.) wird C# mit .NET verwendet.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 benutzt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE) der über einen Memorymapped UCTRL-Komponente vollständigen Zugriff auf die Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Audio Interface (Stereo mit max. 24Bit / 96 KHz) &lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Timer/Counter&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCore = Utility Core) ist der ‚zentrale‘ Prozessor im System, er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist gedacht um einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn für alle meine Demos/Spiele als ‚CPU‘ benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In einen experimentellen Zustand befindet sich noch der HCORE Block. Dieser Block enthält mehre (konfigurierbar) 32 Bit Prozessoren die über spezielle Techniken (Hardwaresemaphoren, parallele Sprünge, … ) eine parallele Verarbeitung der Software vereinfachen sollen und die Latenzprobleme bei Multithreading vermeiden. Ich habe bisher ein Demo mit 16 parallel laufenden HCOREs veröffentlicht, alle anderen Demos benutzen diese Cores nicht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Momentane Charakteristiken eines HCOREs sind:&lt;br /&gt;
&lt;br /&gt;
*9 Stufen Pipeline mit „in order“ und „out of order“ Pfad&lt;br /&gt;
*Instruction Cache (konfigurierbar (momentan 8 Wege mit 64 Worten))&lt;br /&gt;
*32 Bit ALU (Hold to Last Pfad, …) &lt;br /&gt;
*128 GP Register&lt;br /&gt;
*UCtrl/Memory/Semaphoren/… out of order Zugriff&lt;br /&gt;
*…&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
[[Datei:Goldmomo emulator.png|miniatur|rechts|Emulator]]&lt;br /&gt;
Um die Softwareentwicklung (und Debuggen) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Register, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (auch in Emulator integriert), ein Compiler existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/2n1o8dfium4bdgi/TK_Da_o4rx/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/310121#new&lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo endlos Sheriff2213.png|miniatur|Sheriff 2213]]&lt;br /&gt;
[[Datei:Goldmomo endlos SpacePilotOfDeath.png|miniatur|SpacePilotOfDeath]]&lt;br /&gt;
[[Datei:Goldmomo endlos ModPlayer.png|miniatur|MOD Player]]&lt;br /&gt;
[[Datei:Goldmomo endlos GfxExtension.png|miniatur|GFX Extension]]&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= UCORE Programmierung =&lt;br /&gt;
&lt;br /&gt;
UCore (Utility Core) ist ein Eigenimplementierung  eines 16 Bit Prozessor. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Grundlegende Charakteristiken:&lt;br /&gt;
&lt;br /&gt;
* sechsstufige Pipeline&lt;br /&gt;
* 8 Generalpurpose Registern&lt;br /&gt;
* 32 Bit Register für externe Adressen&lt;br /&gt;
* T-Bit um Bedingungen zu verarbeiten&lt;br /&gt;
* Status Register&lt;br /&gt;
* Vector Base Register&lt;br /&gt;
* 32 Bit Multiplikation Register (High-Result)&lt;br /&gt;
* separater Stackpointer&lt;br /&gt;
* interne Speicher in dem Code/Daten liegen&lt;br /&gt;
* externer Speicherzugriff (32Bit-Adressraum) möglich&lt;br /&gt;
* die Datenwortbreite beträgt immer 16 Bit (es gibt keine Bytes)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCore unterscheidet sich einigen Teilen von einem &#039;normalen&#039; Prozessor (RISC-)Design.&lt;br /&gt;
Die Gründe bzw. Ziele welche verfolgt wurden, waren eine möglichst hohe Taktrate und ein möglichst geringer Benutzung von Hardwareressourcen, aber dennoch eine hohe Verarbeitungsgeschwindigkeit.&lt;br /&gt;
Dadurch ergeben sich einige Besonderheiten die bei der Programmierung beachtet werden müssen (siehe Registerzugriffe, Branch/Jump Delayslots, Request/Load Zugriffe).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pipeline ===&lt;br /&gt;
&lt;br /&gt;
Wie gesagt hat dieser Core eine sechsstufige Pipeline:&lt;br /&gt;
&lt;br /&gt;
# 1 Prepare Fetch (adressiere Daten)&lt;br /&gt;
# 2 Fetch (hole Daten)&lt;br /&gt;
# 3 Decode (dekodiere Daten)&lt;br /&gt;
# 4 Read Register (lese Register)&lt;br /&gt;
# 5 Execute (ausführen)&lt;br /&gt;
# 6 Write Register (schreibe Register (hat einen Bypass zu Stufe 4, somit keine extra Delay) &lt;br /&gt;
&lt;br /&gt;
Jede Instruktion wird in einem Cycle ausgeführt, nur der externe Speicherzugriff (nur Daten) kann einen Stall (Stillstand) der Pipeline verursachen.&lt;br /&gt;
&lt;br /&gt;
== Interne Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
In meinem System wird die folgende interne Speichermap verwendet (16 Bit interner Adressraum).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$0000 code / data memory&lt;br /&gt;
*     16384 * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$3fff&lt;br /&gt;
$4000 code / data memory MIRROR&lt;br /&gt;
*     &lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$7fff&lt;br /&gt;
$8000 ctrl / memory			StackPointer start at $8000 on reset&lt;br /&gt;
*     XXXX * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$XXXX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Reset-Vektor befindet sich an Adresse 0, der Stackpointer an Adresse $8000.&amp;lt;br&amp;gt; &lt;br /&gt;
Der Interruptvektor an Adresse $10 (sollte nach dem Reset an die benötigte Position verschoben werden).&amp;lt;br&amp;gt; &lt;br /&gt;
Ab Adresse $8000 wird die Komponente UCtrl in den Adressraum ‚gemappt‘ (diese Komponente enthält Register für externe Hardware Peripherie etc.).&lt;br /&gt;
&lt;br /&gt;
== externe Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
Über den &#039;externen&#039; Datenbus (32 Bit Adressraum) kann auf folgende Komponenten zugegriffen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$a000 0000 - $a000 001f SDCard-Controller&lt;br /&gt;
$d000 0000 - $d3ff ffff SDRAM&lt;br /&gt;
$e000 0000 - $e03f ffff FLASH&lt;br /&gt;
$f000 0000 - $f00f ffff SRAM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei den meisten meiner Programme wird ein Standard-Programm aus dem FLASH-Speicher gelesen, welches einen Speichertest ausführt und auf das Einlegen einer SD-Karte mit dem zuladenden Programm wartet (&#039;Boot-ROM&#039;).&lt;br /&gt;
&lt;br /&gt;
== Opcodes/Operanten ==&lt;br /&gt;
&lt;br /&gt;
UCore hat keine &#039;RISC&#039;-Typischen Befehlssatz (viele Befehle, aber geringe Komplexität).&lt;br /&gt;
 &lt;br /&gt;
Da ein Instruktions-Wort nur eine Breite von 16 Bit hat, können nur bedingte Mengen an Operanten verwendet werden. Um jedoch die Programmierung flexibler zu gestalten, haben viele Opcodes mehrere Arten von Operanten. &lt;br /&gt;
Für die Ausführungseinheit ergibt sich dadurch keine Ressourcenveränderung, da der Decoder nur die Opcodes/Operanten in ein internes einheitliches Format auflöst.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Operanten Formate ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dc,imm8       Register, 8 Bit Wert&lt;br /&gt;
 dc,db,da      Register, Register , Register&lt;br /&gt;
 dc,db,imm3    Register, Register, 3 Bit Wert&lt;br /&gt;
 imm12         12 Bit Wert&lt;br /&gt;
 db,da         Register, Register&lt;br /&gt;
 imm6          6 Bit wert&lt;br /&gt;
 da            Register&lt;br /&gt;
 kein Operant&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Opcode / Operante(n) / Beschreibung ==== &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
movei     	dc,imm8		dc = imm&lt;br /&gt;
moveih    	dc,imm8		dc[15..8] = imm &amp;lt;&amp;lt; 8 | dc[7..0]&lt;br /&gt;
addi      	dc,imm8		dc = dc + imm&lt;br /&gt;
subi      	dc,imm8		dc = dc - imm&lt;br /&gt;
lsri      	dc,imm8		dc = dc &amp;gt;&amp;gt; imm&lt;br /&gt;
asri      	dc,imm8		dc = ((signed)dc) &amp;gt;&amp;gt; imm&lt;br /&gt;
muli      	dc,imm8		dc = dc * imm&lt;br /&gt;
cmpeqi    	dc,imm8		t = set if dc == imm else cleared&lt;br /&gt;
cmploi    	dc,imm8		t = set if dc &amp;lt; imm else cleared&lt;br /&gt;
cmplosi   	dc,imm8		t = set if  (signed)dc &amp;lt; (signed) imm else cleared&lt;br /&gt;
gpci      	dc,imm8		dc = pc + imm&lt;br /&gt;
jmpi      	dc,imm8		pc = dc + imm&lt;br /&gt;
extri     	dc,imm8		t = bit #imm of dc&lt;br /&gt;
rqldi     	dc,imm8		request (internal) mem; address = dc + imm&lt;br /&gt;
getsp     	dc,imm8		dc = sp + imm&lt;br /&gt;
dexti     	imm11		store imm as extension for next instruction&lt;br /&gt;
&lt;br /&gt;
add		dc,db,da	dc = db + da&lt;br /&gt;
sub     	dc,db,da	dc = db - da&lt;br /&gt;
lsr     	dc,db,da	dc = db &amp;gt;&amp;gt; da&lt;br /&gt;
asr     	dc,db,da	dc = ((signed)db) &amp;gt;&amp;gt; da&lt;br /&gt;
mul     	dc,db,da	dc = db * da&lt;br /&gt;
addt    	dc,db,da	dc = db + da + t&lt;br /&gt;
subt    	dc,db,da	dc = db - da - t&lt;br /&gt;
muls    	dc,db,da	dc = db * da&lt;br /&gt;
movets  	dc,db,da	dc = db if t = set else da&lt;br /&gt;
and     	dc,db,da	dc = db &amp;amp; da&lt;br /&gt;
or      	dc,db,da	dc = db | da&lt;br /&gt;
xor     	dc,db,da	dc = db ^ da&lt;br /&gt;
bic     	dc,db,da	dc = db &amp;amp; ~da&lt;br /&gt;
&lt;br /&gt;
addqi		dc,db,imm3	dc = db + imm&lt;br /&gt;
subqi   	dc,db,imm3	dc = db - imm&lt;br /&gt;
lsrqi   	dc,db,imm3	dc = db &amp;gt;&amp;gt; imm&lt;br /&gt;
asrqi   	dc,db,imm3	dc = ((signed)db) &amp;gt;&amp;gt; imm&lt;br /&gt;
mulqi   	dc,db,imm3	dc = db * imm3&lt;br /&gt;
addtqi  	dc,db,imm3	dc = db + imm + t&lt;br /&gt;
subtqi  	dc,db,imm3	dc = db - imm - t&lt;br /&gt;
edrqldi 	db,da,imm3	request (external) mem; address = (db:da) + imm3&lt;br /&gt;
&lt;br /&gt;
br		imm12		pc = pc + signed(imm)&lt;br /&gt;
brts		imm12		pc = pc + signed(imm) if t is set&lt;br /&gt;
brtc		imm12		pc = pc + signed(imm) if t is cleared&lt;br /&gt;
	             &lt;br /&gt;
cmpeq		db,da		t = set if db == da else cleared		&lt;br /&gt;
cmplo   	db,da           t = set if db &amp;lt; da else cleared&lt;br /&gt;
cmplos  	db,da           t = set if  (signed)db &amp;lt; (signed) da else cleared&lt;br /&gt;
esadr   	db,da		esadr = db:da&lt;br /&gt;
swp     	db,da		db = da[7..0]:da[15..8] &lt;br /&gt;
swptc   	db,da		db = da[7..0]:da[15..8] if t = set else da&lt;br /&gt;
st      	db,da		imem[db] = da&lt;br /&gt;
stinc   	db,da		imem[db] = da; db = db + 1&lt;br /&gt;
bffo    	db,da		db is first bit that is 1 found in da (from MSB to LSB)&lt;br /&gt;
bset    	db,da		db = db | 1 &amp;lt;&amp;lt; da&lt;br /&gt;
bclr    	db,da		db = db &amp;amp; ~ (1 &amp;lt;&amp;lt; da)&lt;br /&gt;
cmple   	db,da		t = set if db &amp;lt;= da else cleared&lt;br /&gt;
cmples  	db,da		t = set if  (signed)db &amp;lt;= (signed) da else cleared&lt;br /&gt;
rqld    	db,da		request (internal) mem; address = db + da&lt;br /&gt;
extb    	db,da		db = da byte to word singed extended&lt;br /&gt;
stwo    	db,da		imem[db + STORE_OFFSET] = da&lt;br /&gt;
andts   	db,da		db = db &amp;amp; da if t = set else da&lt;br /&gt;
orts    	db,da           db = db | da if t = set else da&lt;br /&gt;
xorts   	db,da           db = db ^ da if t = set else da&lt;br /&gt;
bicts   	db,da           db = db &amp;amp; ~da if t = set else da&lt;br /&gt;
lsrts   	db,da		db = db &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
asrts   	db,da           db = ((signed)db) &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
mults   	db,da           db = db * da if t = set else da&lt;br /&gt;
mulsts  	db,da		db = (signed)db * (signed)da if t = set else da&lt;br /&gt;
&lt;br /&gt;
erqldi		imm6		request (external) mem; address = esadr + imm	&lt;br /&gt;
ssto		imm6		STORE_OFFSET = imm&lt;br /&gt;
udivinit	imm6		udivqoutient = 0; udivrest = 0; udivbitcounter = imm&lt;br /&gt;
&lt;br /&gt;
eld		da		da = requested value from external memory&lt;br /&gt;
push            da		sp = sp – 1; imem[sp] = da&lt;br /&gt;
gmulhi          da		da = multiply result [31..15] from last multiplication&lt;br /&gt;
ld/pop          da		da = requested value from internal memory&lt;br /&gt;
poparqp         da		da = requested value from internal memory; request in internal memory adr = sp; sp = sp + 1&lt;br /&gt;
neg             da		da = 0 - da&lt;br /&gt;
udivgq          da		get division qoutinent&lt;br /&gt;
udivgr          da		get division remainder&lt;br /&gt;
udivgqh         da		get division qoutinent high [31 ..16]&lt;br /&gt;
udivgrh         da              get division remainder high [31 ..16]&lt;br /&gt;
udivsdd         da		set division divident &lt;br /&gt;
udivsdv         da		set division divider&lt;br /&gt;
udivsddh        da		set division divident high [31 ..16]&lt;br /&gt;
udivsdvh        da		set division divider  high [31 ..16]&lt;br /&gt;
erqld           da		request (external) mem; address = esadr + da&lt;br /&gt;
setsp           da		sp = da&lt;br /&gt;
erqldb          da		request (external) mem; address = esadr + da / 2&lt;br /&gt;
jmpts           da		pc = da if t = set&lt;br /&gt;
jmptc           da		pc = da if t = cleared&lt;br /&gt;
negts           da		da = 0 - da if t = set else da&lt;br /&gt;
&lt;br /&gt;
rqpop				internal memory request address = sp; sp = sp + 1&lt;br /&gt;
cli				disable interrupts&lt;br /&gt;
sei				enable interrupts&lt;br /&gt;
rti				pc = pc_before interrput&lt;br /&gt;
tnt				t = not t&lt;br /&gt;
vtt				t = v (overflow/underflow wrom add/sub)			&lt;br /&gt;
epushsadrl			sp = sp – 1; imem[sp] = esadr[15..0]&lt;br /&gt;
epushsadrh			sp = sp – 1; imem[sp] = esadr[31..16]&lt;br /&gt;
epopsadrl			esadr[15..0] = requested value from internal memory&lt;br /&gt;
epopsadrh			esadr[31..16] = requested value from internal memory&lt;br /&gt;
udivstep			performe one division step &lt;br /&gt;
nop				do nothing&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Registerzugriffe ==&lt;br /&gt;
&lt;br /&gt;
Da Register vor der Ausführungseinheit gelesen werden und nach der Ausführungseinheit geschrieben werden, ergibt sich eine Latenz zwischen Register Zugriffen. Der Grund für diese Implementierungsart ist schlicht und einfach um die Performanz zu erhöhen. Als Nebeneffekt entsteht, wie gesagt, eine Latenz. Es bieten sich mehrere Möglichkeiten an, diese Register-‚Hazards‘ in Hardware zu vermeiden (Registerscoring, Renaming, …). Um den Hardware-Implementierung klein und schnell zu halten wird in UCore auf einen Hardwaretest verzichtet. Als Resultat muss der Anwender Registerabhängigkeiten im Programm-Code behandeln.&lt;br /&gt;
Der einzige logische sinnvolle Nachteil ergibt sich in einer RAW (Read after Write) Abhängikeit, da die Latenz hier eine Cycle beträgt. In diesem Fall sollte/muss eine andere Instruktion (z.B. nop) eingefügt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreiben eines Registers und späteres lesen): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae	; &lt;br /&gt;
	nop		;write r0 = ae wird ausgeführt&lt;br /&gt;
	addi	r0,1	;r0 = r0 ($ae) + 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Im einfachsten Fall, sollte eine nop Operation bei solchen Abhängigkeit verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (nicht optimiert mit nop - 6 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	nop&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	nop&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In den meisten Fällen kann man aber andere Operationen als ‚Füllung‘ bei Registerabhängikeiten verwenden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (Optimiert - 4 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um versehentlich programmierte RAW-&#039;Hazards&#039; zu erkennen erzeugt der Assembler Warnungen, ebenfalls kann der Emulator zur Laufzeit diese &#039;Probleme&#039; erkennen.&lt;br /&gt;
Prinzipiell ist es möglich, in gewissen Situationen, RAW-&#039;Hazards&#039; absichtlich zuzulassen (Optimierungen um Register zu sparen), wovon aber im Normalfall abzuraten ist.&lt;br /&gt;
&lt;br /&gt;
== Bedingungen ==&lt;br /&gt;
&lt;br /&gt;
UCore benutzt ein T-Bit (true Bit) um Bedingungen zu beschreiben/verarbeiten. Normalerweise wird dieses Bit von Vergleichsoperationen gesetzt und kann dann von Operationen benutzt werden welche das T-Bit intern verwenden (z.B. bedingte Sprünge).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel:====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	cmpeqi	r0,0		;vergleiche auf r0 gleich 0 wenn wahr da (t=1) ansonsten (t=0)&lt;br /&gt;
	brts	r0IstNull	;springe zu ‚r0IstNull‘ label wenn t set (t=1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist notwendig Register nur dann zu setzen wenn bestimmte Bedingungen eintreten. In diesen Fällen ist es ärgerlich bedingte Sprünge auszuführen, da sie etwas Zeit brauchen (Delay Slots) und den Programmcode unübersichtlich machen.&lt;br /&gt;
Aus diesem Grund, unterstützen einige Befehle eine Bedingte Ausführung (nicht jeder).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	move	r1,123&lt;br /&gt;
	move 	r2,23&lt;br /&gt;
	…&lt;br /&gt;
	cmplo	r0,r1		;r0 &amp;lt; r1&lt;br /&gt;
	movets	r0,r2,r0	;wenn ja r0 = r2 (23) ansonsten r0 = r0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sprünge ==&lt;br /&gt;
&lt;br /&gt;
Ein (bedingter) Sprung benötigt, wie jede andere Instruktion, einen Cycle um ausgeführt zu werden.&lt;br /&gt;
Da UCore keine Branchprediction bzw. keine spekulative Ausführung etc. unterstützt und es auch nicht gewollt ist Opcodes in der Pipeline zu verwerfen, entstehen nach Sprungbefehlen sogenannte &#039;Delay Slots&#039;. Die Anzahl dieser Delay Slots ergeben sich aus der Anzahl der Pipelinestufen vor der Ausführungseinheit (da sie den Programmcounter verändert).&lt;br /&gt;
Kurzum Programlauftechnisch werden Instruktionen in diesen Delay Slots ausgeführt bevor der Sprung in Wirklichkeit ausgeführt wird.&lt;br /&gt;
Die kleinste mögliche Schleife benötigt deshalb fünf Instruktionen für einen Durchlauf.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loop	br	loop		;branch zu loop&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In vielen Fällen können diese Delay Slots sinnvoll genutzt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 1 (nicht optimiert - 8 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,1	;r1 = x parameter&lt;br /&gt;
	movei	r1,7	;r2 = y parameter&lt;br /&gt;
	gpci	r7,2	;r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 1 (optimiert - 6 cycles): ====&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	gpci	r7,2	r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	movei	r0,1	;delay slot	r1 = x parameter&lt;br /&gt;
	movei	r1,7	;delay slot     r2 = y parameter&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 2 (nicht optimiert - 8 * n + 3 cycles -&amp;gt; if n 128 -&amp;gt; total 1027 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127	;r0 = loop counter - 1&lt;br /&gt;
	movei	r1,0	;r1 = Füllwert&lt;br /&gt;
	nop&lt;br /&gt;
	&lt;br /&gt;
loop	st	r1,r6	;imem[r1] = r6&lt;br /&gt;
	addi	r1,1	;r1++&lt;br /&gt;
	subi	r0,1	;r0-- (t clear bei &amp;lt; 0)&lt;br /&gt;
	brts	loop	;branch loop solange t set&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 2 (optimiert - 6 * n + 2 cycles -&amp;gt; if n 128 -&amp;gt; total 770 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127&lt;br /&gt;
	movei	r1,0&lt;br /&gt;
	&lt;br /&gt;
loop	subi	r0,1	;da t später verwendet wird nicht in delay slot benutzen (siehe  Interruptbenutzung)&lt;br /&gt;
	brts	loop&lt;br /&gt;
	st	r1,r6	;delay slot&lt;br /&gt;
	addi	r1,1	;delay slot	&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Speicherzugriffe ==&lt;br /&gt;
&lt;br /&gt;
UCore besitzt keine ‚gewöhnlichen‘ Lesebefehle für interne/externe Speicherzugriffe.&lt;br /&gt;
Um Pipeline-Stalls beim Lesen von Daten zu vermeiden (Latenz zum Speicher), wird eine Lesebefehl in zwei Operationen aufgeteilt.&lt;br /&gt;
Der erste Befehl ist ein &#039;Request&#039;, er teilt dem Core mit von welcher Adresse er etwas lesen soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Der zweite Befehl ist dann der &#039;Load&#039;, er holt sich die angekommenen Daten ab und speichert sie in einem Register.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== interner Speicherzugriff ====&lt;br /&gt;
&lt;br /&gt;
Bei internen Speicherzugriffen ist die Latenz zwischen Request und Load statisch (3 Cycles), bei externen Zugriff variable (hier wird im Fall eines Load ohne vorhandene Daten ein Stall ausgelöst).&lt;br /&gt;
&lt;br /&gt;
Mit den Opcodes rqld (request load) und ld (load) kann vom internen Speicher gelesen werden.&lt;br /&gt;
Da die Daten erst zwei Operationen nach dem Request verfügbar sind, muss hier etwas anderes ausgeführt werde (z.B. nop).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0	;send load to address (r0+0)&lt;br /&gt;
	nop		;data send to memory&lt;br /&gt;
	nop		;data will read&lt;br /&gt;
	ld	r1	;readed data to r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Da der interne Speicher immer innerhalb von einem Cycles antwortet und die Latenz durch Pipelinestufen entsteht, kann man bei internen Speicherzugriff bis zu drei Request hintereinander verwenden.&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0&lt;br /&gt;
	rqld	r0,1&lt;br /&gt;
	rqld	r0,2&lt;br /&gt;
	ld	r1	;r1 &amp;lt;- internal_mem[r0+0]&lt;br /&gt;
	ld	r2	;r2 &amp;lt;- internal_mem[r0+1]&lt;br /&gt;
	ld	r3	;r3 &amp;lt;- internal_mem[r0+2]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Bei Schreibzugriffen wird wie bei anderen Prozessoren ein Store-Kommando verwendet.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti	$80	;imm exted&lt;br /&gt;
	move	r4,$01	;r4 = $8001&lt;br /&gt;
	move	r0,12	;r0 = 12&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	st	r0,r4	;imem[r4] = r0; $8001 = 12&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
Da ein &#039;st&#039;ore Befehl nur einen Register als Zieladresse benutzt, ist es vielen Fällen ärgerlich diesen bei mehrfachen Schreiben zu verändern. Um bei diesem Fall Abhilfe zu verschaffen wurde der Befehl ssto (Set Store Offset) und stwo (Store with Offset) eingeführt. Mit ssto kann ein Offset für stwo gesetzt werden, d.h. der Wert der mit ssto gesetzt wird auf die Zieladresse von stwo addiert.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	stwo 1&lt;br /&gt;
	ssto r0,r7 ;imem[r7+1] = r0&lt;br /&gt;
	stwo 2&lt;br /&gt;
	ssto r1,r7 ;imem[r7+2] = r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist es leider etwas unangenehm mit der statischen Latenz bei internen Lesezugriffen, da man hier etwas mehr schreiben muss als man es von anderen Prozessoren gewöhnt ist.&lt;br /&gt;
&lt;br /&gt;
==== externe Speicherzugriffe ====&lt;br /&gt;
&lt;br /&gt;
Externe Speicherzugriffe verhalten sich ähnlich wie interne Zugriff.&lt;br /&gt;
Unterschiede gibt es in der Adressbreite (extern 32Bit) und in der variablen Latenz (bestimmt durch mehre Faktoren).&lt;br /&gt;
Es gibt eine externe Hauptadresse (Base) die mit &#039;allen&#039; (bis auf edrqldi) externen Speicherzugriffsinstruktionen verwendet wird.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel Hauptadresse setzen: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel schreibe in externen Speicher: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r4,$af&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	esadr	r1,r0	;Hauptadresse (esadr) is r1:r0&lt;br /&gt;
	est	r4,0	;externSpeicher[esadr + 0] = r4&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
Beim Lesen vom externen Speicher werden auch Request/Load Befehle verwendet um Latenzen, wenn möglich, zu vermeiden. Da die Latenz nicht vorhersehbar ist, wird bei nicht vorhandenen Daten solange gewartet bis sie vorhanden sind (Stall).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
	erqld	0	;load from [r0:r1 + 0]&lt;br /&gt;
	eld	r7	;get external data (Stall solange bis Daten vorhanden)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um Lade/Schreiblatenzen zu vermeiden, können mehre Stores oder Request (laden) hintereinander ausgeführt werden (maximal 256 Requestzugriffe, keine Begrenzung bei Stores).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreibe 8 Worte in externen Speicher, kein Stall solange Schreibpuffer nicht voll): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,0&lt;br /&gt;
	esadr	r7,r6	;external address is r1:r0 &lt;br /&gt;
	est	r0,0&lt;br /&gt;
	est	r0,1&lt;br /&gt;
	est	r0,2&lt;br /&gt;
	est	r0,3&lt;br /&gt;
	est	r0,4&lt;br /&gt;
	est	r0,5&lt;br /&gt;
	est	r0,6&lt;br /&gt;
	est	r0,7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (vermeiden von Leselatenzen) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r7,r6&lt;br /&gt;
	erqld	0&lt;br /&gt;
	erqld	1&lt;br /&gt;
	erqld	2&lt;br /&gt;
	erqld	3	;request 4 Worte&lt;br /&gt;
	&lt;br /&gt;
	....		;mach irgendwas&lt;br /&gt;
	&lt;br /&gt;
	eld	r0	&lt;br /&gt;
	eld	r1&lt;br /&gt;
	eld	r2&lt;br /&gt;
	eld	r3	;bekomme Daten (evtl. kein Stall, da Daten schnellgenug da)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Stack ==&lt;br /&gt;
&lt;br /&gt;
Der Stackpointer zeigt nach dem Reset auf Adresse $8000 (also am oberen Ende des internen Speichers).&lt;br /&gt;
Das Verhalten von push und request pops and pops sind gleich dem internen Speicherzugriffsverhalten (3 Cycles Latenz, Pipelined).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (1 pop): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r4	;sp--; imem[sp] = r4&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop		;request imem[sp], sp++&lt;br /&gt;
	nop&lt;br /&gt;
	nop&lt;br /&gt;
	pop	r4	;r4 = imem[sp]&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel (3 Werte auf Stack und wieder herunter) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r1&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r3&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop		;durch Latenz maximal 3 rqpop dann Daten (ansonsten &#039;poparqp&#039; benutzen (kann Request und Load gleichzeitig))&lt;br /&gt;
	push	r3&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Decoder extend ==&lt;br /&gt;
&lt;br /&gt;
Da viele Operationen konstante Werte benutzen können, aber diese aus Gründen der Befehlsbreite (16 Bit) je nach Befehl/Operanten nur eine teilweise unzureichende Größe/Breite verwenden können wurde eine Dekoder Instruktion (dexti = decoder extend immediate) eingeführt. Dieser Befehl wird vom Dekoder ausgeführt und wird in der eigentlichen Ausführungseinheit ignoriert.&lt;br /&gt;
Sinn dieses Befehls ist es, konstante Werte um einen 8 Bit breiten Wert zu erweitern. Um Fehler zu vermeiden ist dieser Wert nur einen Cycle nach ‚dexti‘ verfügbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (16 Bit Immediate Addition) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti     $12&lt;br /&gt;
	addi	  r0,$34	;r0 = r0 + $1234&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interrupts ==&lt;br /&gt;
&lt;br /&gt;
Interrupts sind in einem Pipeline basierenden Design immer ärgerlich zu handhaben. Da UCore nicht, wie viele Mikrokontroller, möglichst kurze Interrupt-Latenzen ermöglichen muss, gibt es in diesem Design auch keine garantierten Zeiten in welchen der Interrupt ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
Um den Hardwareaufwand gering wie möglich zu halten, habe ich eine sogenannte Branch-Injektion implementiert. Der Hintergedanke ist, dass Sprünge sehr oft im Code ausgeführt werden und diese, im Fall eines Interrupts , dazu ‚missbraucht‘ werden können direkt zum Interrupt-Service-Vector zu springen anstatt ihren eigentlichen definierten Sprung auszuführen (dieser wird gespeichert und später ausgeführt).&lt;br /&gt;
&lt;br /&gt;
Der Vorteil dieser Implementierung ist ein sehr geringer Hardwareaufwand, der Nachteil ist, dass die Interrupt-Latenz variiert (Delta zwischen zwei Sprüngen) und sich Verhaltensregeln für ‚Delay-Slots‘ ergeben.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;	&lt;br /&gt;
	sei			;irq enable&lt;br /&gt;
	br	anySubroutine	;if irq is enabled and occure a branch is take to irq vector and after irq is finished (rte) the give branch will take&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In ‘Delay-Slots’ sollten kein T-Bit gesetzt werden, welches für spätere Verwendungen gebraucht wird. Außerdem sollten keine Speicher-Request an diesen Stellen ausgeführt werden.&lt;br /&gt;
Um Fehler zu vermeiden warnt der Assembler bei solchen Konstrukten.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
	sei&lt;br /&gt;
	br	anySubroutine&lt;br /&gt;
	addt	r0,r1	;delay slot	(t is not save in delay slot if irq is enabled, because t is only store at br instruction)&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dividieren ==&lt;br /&gt;
&lt;br /&gt;
Viele Prozessoren die auf geringen ‚Platzverbrauch‘ optimiert sind, versuchen wenn möglich Divisions-Operationen zu vermeiden oder führen diesen nicht in einer Pipeline-Implementierung aus. Auf der Softwareseite sind Divisionen in vielen Fällen vermeidbar oder durch bestimmte Methoden ersetzbar. Prinzipiell ist eine Division einfach in Software zu implementieren, in diesem Fall ist die Geschwindigkeit einer Hardwareimplementierung meist nicht annähernd zu erreichen. UCore bietet spezielle Befehle an um einen Kompromiss aus Geschwindigkeit und Hardwareaufwand  zu erreichen.&lt;br /&gt;
Wie bei einer normalen Division wird in hier Divisor und Dividend gesetzt zusätzlich muss noch die Divsions-Bitbreite angegeben werden (max. 32 Bit). Durch den Befehl udivstep wird eine ‚1-Bit Division‚ ausgeführt, d.h. udivstep muss/kann sooft ausgeführt werden wie die Divisionsbreite gewählt ist. Als Resultat der Division ergeben sich der Quotient und der Rest.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* udiv16&lt;br /&gt;
;* &lt;br /&gt;
;* r0 	 	divident&lt;br /&gt;
;* r1		divisor&lt;br /&gt;
;*&lt;br /&gt;
;* return&lt;br /&gt;
;*&lt;br /&gt;
;* r2		qoutient&lt;br /&gt;
;* r3		remainder&lt;br /&gt;
;*&lt;br /&gt;
;* needs 34 cycles&lt;br /&gt;
;*&lt;br /&gt;
	&lt;br /&gt;
udiv16	&lt;br /&gt;
	udivinit	15&lt;br /&gt;
	udivsdd		r0&lt;br /&gt;
	udivsdv		r1&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,3	;(3+1)*4 = 16&lt;br /&gt;
	cli		;disable irq&lt;br /&gt;
udiv16Loop	&lt;br /&gt;
	subi	r0,1&lt;br /&gt;
	brts	udiv16Loop&lt;br /&gt;
	udivstep	;delay slot	!!!! note udivstep is not irq save, so use cli/sei lock&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	udivgq		r2	;delay slot		get qoutient&lt;br /&gt;
	udivgr		r3	;delay slot		get remainder&lt;br /&gt;
	sei			;delay slot		enable irqs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== weiter Beispiele ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
= UCtrl =&lt;br /&gt;
&lt;br /&gt;
UCtrl ist eine Abstraktionsschicht für einen Großteil der externen (DE2-115) Peripherien und stellt zusätzlich hilfreiche Element (Timer,…) zur Verfügung. &lt;br /&gt;
Direkten Zugriff auf diese Komponente hat nur UCore (siehe Memorymap).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCtrl bietet dem Benutzer zugriff auf:&lt;br /&gt;
*LEDS &lt;br /&gt;
*SWITCHES&lt;br /&gt;
*7-Segment Anzeige&lt;br /&gt;
*LCD (zweizeilig auf DE2-115)&lt;br /&gt;
*Interrupt Kontrolle (für UCore)&lt;br /&gt;
*Timer/Counter&lt;br /&gt;
*Video Setup (inkl. Counter und Vertikal-‚Hit‘-Erkennung)&lt;br /&gt;
*PS/2 Port (in/out, zwei Ports)&lt;br /&gt;
*I2C (zwei Ports)&lt;br /&gt;
*Audio (DAC/ADC)&lt;br /&gt;
*HCore Setup und Daten (beschreibe ich später)&lt;br /&gt;
&lt;br /&gt;
== Register ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8000&lt;br /&gt;
name = LEDG_SW&lt;br /&gt;
read            fedcba9876543210&lt;br /&gt;
                SSSSSSSSSSSSSSSS&lt;br /&gt;
                &lt;br /&gt;
                S = switches on DE2-115&lt;br /&gt;
                &lt;br /&gt;
write           fedcba9876543210&lt;br /&gt;
                -------GGGGGGGGG&lt;br /&gt;
                &lt;br /&gt;
                G = LED Green (&#039;1&#039; is ON)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8001&lt;br /&gt;
name = LEDR&lt;br /&gt;
read            fedcba9876543210&lt;br /&gt;
                --------------ME&lt;br /&gt;
        &lt;br /&gt;
                M = &#039;1&#039; if running in modelsim&lt;br /&gt;
                E = &#039;1&#039; if running in emulator&lt;br /&gt;
                &lt;br /&gt;
write                fedcba9876543210&lt;br /&gt;
                -------RRRRRRRRR&lt;br /&gt;
                &lt;br /&gt;
                R = LED Red (&#039;1&#039; is ON)&lt;br /&gt;
&lt;br /&gt;
                 &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8002 - $8005&lt;br /&gt;
name = 7SEG&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                2 ----------------&lt;br /&gt;
                3 ----------------&lt;br /&gt;
                4 ----------------&lt;br /&gt;
                5 ----------------&lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                2 -6543210-6543210&lt;br /&gt;
                3 -6543210-6543210&lt;br /&gt;
                4 -6543210-6543210&lt;br /&gt;
                5 -6543210-6543210&lt;br /&gt;
                &lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 1 / 0 (&#039;1&#039; is ON)                &lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 3 / 2 (&#039;1&#039; is ON)&lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 4 / 4 (&#039;1&#039; is ON)&lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 5 / 6 (&#039;1&#039; is ON)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8006 - $8007&lt;br /&gt;
name = LCD&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                6 -------BDDDDDDDD&lt;br /&gt;
                7 ----------------&lt;br /&gt;
                &lt;br /&gt;
                B = &#039;1&#039; if read/write request is busy&lt;br /&gt;
                D = Data after request&lt;br /&gt;
                &lt;br /&gt;
                note: wait 1 cycle after read/write request before read&lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                6 ------WRDDDDDDDD&lt;br /&gt;
                7 ----------------&lt;br /&gt;
                &lt;br /&gt;
                W = &#039;0&#039; is request write, &#039;1&#039; is request read&lt;br /&gt;
                R = LCS RS&lt;br /&gt;
                D = data to write&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8008 - $8009&lt;br /&gt;
name = IRQ&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                8 -----------HADTT IRQ MSK&lt;br /&gt;
                9 -----------HADTT IRQ MEMORY&lt;br /&gt;
                &lt;br /&gt;
                TT = Timer 2/1 IRQ&lt;br /&gt;
                D  = Audio DAC FIFO run low&lt;br /&gt;
                A  = Audio ADC FIFO run full&lt;br /&gt;
                H  = HCORE has data&lt;br /&gt;
                &lt;br /&gt;
write                  fedcba9876543210&lt;br /&gt;
                8 -----------HADTT IRQ MSK&lt;br /&gt;
                9 -----------HADTT IRQ MEMORY&lt;br /&gt;
                &lt;br /&gt;
                TT = Timer 2/1 IRQ&lt;br /&gt;
                D  = Audio DAC FIFO run low&lt;br /&gt;
                A  = Audio ADC FIFO run full&lt;br /&gt;
                H  = HCORE has data&lt;br /&gt;
                &lt;br /&gt;
description:&lt;br /&gt;
&lt;br /&gt;
                IRQ MSK is used to enable given interrupts (for example D = &#039;1&#039; then Audio DAC irq will be used)&lt;br /&gt;
                IRQ MEMORY reflect after interrupt which interrupt is the source (for example TT = &#039;01&#039; then Timer 1 made this interrupt)&lt;br /&gt;
                &lt;br /&gt;
                You should/have to clear the given interrupt bit in IRQ MEMORY before leaving interrupt service routine.&lt;br /&gt;
                        &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $800A - $800F&lt;br /&gt;
name = TIMERS&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                A DDDDDDDDDDDDDDDD Timer 1 low&lt;br /&gt;
                B DDDDDDDDDDDDDDDD Timer 1 high&lt;br /&gt;
                C ----------------&lt;br /&gt;
                D DDDDDDDDDDDDDDDD Timer 2 low&lt;br /&gt;
                E DDDDDDDDDDDDDDDD Timer 2 high&lt;br /&gt;
                F ----------------&lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                A DDDDDDDDDDDDDDDD Timer 1 low  (set before timer 1 high)&lt;br /&gt;
                B DDDDDDDDDDDDDDDD Timer 1 high &lt;br /&gt;
                C ------------CLSR&lt;br /&gt;
                D DDDDDDDDDDDDDDDD Timer 2 low  (set before timer 2 high)&lt;br /&gt;
                E DDDDDDDDDDDDDDDD Timer 2 high&lt;br /&gt;
                F ------------CLSR&lt;br /&gt;
                &lt;br /&gt;
                C = Capture counter value for read (copy current counter value to $A/B $D/E)&lt;br /&gt;
                L = Enable Auto Reload Value (after counter value runs to 0 next value is $A/B $D/E)&lt;br /&gt;
                S = Stop timer&lt;br /&gt;
                R = Start timer (will do a Autoreload from $A/B $D/E)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8010 - $802F&lt;br /&gt;
name = VIDEO&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                10 00000DDDDDDDDDDD current HCount (11..0)&lt;br /&gt;
                11 000000DDDDDDDDDD current VCount (10..0)&lt;br /&gt;
                12 ---------------H Hit of programmed VCOUNT&lt;br /&gt;
                13 ---------------- &lt;br /&gt;
                14 ---------------- &lt;br /&gt;
                15 ----------------&lt;br /&gt;
                16 ----------------&lt;br /&gt;
                17 ---------------- &lt;br /&gt;
                18 ---------------- &lt;br /&gt;
                19 ----------------&lt;br /&gt;
                1a ----------------&lt;br /&gt;
                1b ---------------- &lt;br /&gt;
                1c ---------------- &lt;br /&gt;
                1d ----------------&lt;br /&gt;
                1e ----------------&lt;br /&gt;
                1f ---------------- &lt;br /&gt;
                20 ---------------- &lt;br /&gt;
                21 ----------------                &lt;br /&gt;
                22 ----------------&lt;br /&gt;
                23 ---------------- &lt;br /&gt;
                24 ---------------- &lt;br /&gt;
                25 ----------------&lt;br /&gt;
                26 ----------------&lt;br /&gt;
                27 ---------------- &lt;br /&gt;
                28 ---------------- &lt;br /&gt;
                29 ----------------&lt;br /&gt;
                2a ----------------&lt;br /&gt;
                2b ---------------- &lt;br /&gt;
                2c ---------------- &lt;br /&gt;
                2d ----------------&lt;br /&gt;
                2e ----------------&lt;br /&gt;
                2f ---------------- &lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                10 ---------------D VIDEO ON if &#039;1&#039;&lt;br /&gt;
                11 ------DDDDDDDDDD HSYNC&lt;br /&gt;
                12 ------DDDDDDDDDD HSTART&lt;br /&gt;
                13 ------DDDDDDDDDD HMEMSTART&lt;br /&gt;
                14 ------DDDDDDDDDD HSTOP &lt;br /&gt;
                15 ------DDDDDDDDDD HTOTAL&lt;br /&gt;
                16 -------DDDDDDDDD VSYNC&lt;br /&gt;
                17 -------DDDDDDDDD VSTART&lt;br /&gt;
                18 -------DDDDDDDDD VSTOP&lt;br /&gt;
                19 -------DDDDDDDDD VTOTAL&lt;br /&gt;
                1a DDDDDDDDDDDDDDDD LINE CACHE ADDRESS ADD LOW&lt;br /&gt;
                1b DDDDDDDDDDDDDDDD LINE CACHE ADDRESS ADD HIGH &lt;br /&gt;
                1c ---------------- LINE CACHE LATCH VALUE&lt;br /&gt;
                1d -------DDDDDDDDD LINE CACHE START ADDRESS (Pixel offset)&lt;br /&gt;
                1e --------DDDDDDDD HITVCOUNT (see description)&lt;br /&gt;
                1f ---------------- &lt;br /&gt;
                20 ------DDDDDDDDDD HLOADSTART&lt;br /&gt;
                21 ------DDDDDDDDDD HLOADSTOP                &lt;br /&gt;
                22 -------DDDDDDDDD VLOADSTART&lt;br /&gt;
                23 -------DDDDDDDDD VLOADSTOP&lt;br /&gt;
                24 -------DDDDDDDDD VLOADNEXT&lt;br /&gt;
                25 DDDDDDDDDDDDDDDD EXTERNAL MEMORY START ADDRESS (low)&lt;br /&gt;
                26 DDDDDDDDDDDDDDDD EXTERNAL MEMORY START ADDRESS (high)&lt;br /&gt;
                27 DDDDDDDDDDDDDDDD EXTERNAL MEMORY LINE OFFSET (low)&lt;br /&gt;
                28 DDDDDDDDDDDDDDDD EXTERNAL MEMORY LINE OFFSET (high)&lt;br /&gt;
                29 --------------DD MEMORY Convertion MODE&lt;br /&gt;
                2a ---------------- LATCH MEMORY CONFIG&lt;br /&gt;
                2b ---------------- &lt;br /&gt;
                2c ---------------- &lt;br /&gt;
                2d ----------------&lt;br /&gt;
                2e ----------------&lt;br /&gt;
                2f ----------------                                 &lt;br /&gt;
                &lt;br /&gt;
        HITVCOUNT = Programmable VCOUNT if this Value is written $12 bit 0 is set to &#039;1&#039; if VCOUNT is equal to this value&lt;br /&gt;
                  $12 bit 0 is cleared at write to this register&lt;br /&gt;
&lt;br /&gt;
        EXTERNAL MEMORY LINE OFFSET = will be add after every loaded line (for non interleaved video setup)&lt;br /&gt;
        &lt;br /&gt;
        MEMORY Convertion MODE = defines the format of data converted from external memory (ever 32Bit fetch) to line cache&lt;br /&gt;
        &lt;br /&gt;
                00 = X8 R8 G8 B8                       (32 Bit = (8 Bit for Red/Gree/Blue))&lt;br /&gt;
                01 = R5 R6 R5 R5 R6 R5                 (2 * 16 Bit = (5 Bit for Red/Blue and 6 Bit for Green))&lt;br /&gt;
                10 = X1 R5 R5 X1 R5 R5 R5 R5         (2 * 16 Bit = (5 Bit for Red/Gree/Blue))&lt;br /&gt;
                11 = X4 R4 R4 R4 X4 R4 R4 R4          (2 * 16 Bit = (4 Bit for Red/Gree/Blue))&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8030 - $8031&lt;br /&gt;
name = PS/2 port a/b&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                30 -----FWVDDDDDDDD        port A&lt;br /&gt;
                31 -----FWVDDDDDDDD        port B&lt;br /&gt;
                &lt;br /&gt;
                D = PS/2 DATA (Scan Code) valid if A = &#039;1&#039;&lt;br /&gt;
                V = Data valid&lt;br /&gt;
                W = Write FIFO not full&lt;br /&gt;
                F = all writes finished (Fifo with 16 entries)&lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
                note: wait 1 cycle after read/write request before read&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                30 ------WADDDDDDDD        port A&lt;br /&gt;
                31 ------WADDDDDDDD        port B&lt;br /&gt;
                &lt;br /&gt;
                D = PS/2 DATA to write&lt;br /&gt;
                A = get next scan code (read 2 cycles after this from $30/$31)&lt;br /&gt;
                W = Write data to PS/2 device&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8032 - $8033&lt;br /&gt;
name = I2C port a/b&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                30 ------------D---        port A (eeprom on DE2-115)&lt;br /&gt;
                31 ------------D---        port B (audio/video in on DE2-115)&lt;br /&gt;
                &lt;br /&gt;
                D = data in from port A/B&lt;br /&gt;
                &lt;br /&gt;
write                   fedcba9876543210&lt;br /&gt;
                30 ----EEE------ICD        port A&lt;br /&gt;
                31 ----EEE------ICD        port B&lt;br /&gt;
                &lt;br /&gt;
                D = data out value&lt;br /&gt;
                C = clock out value&lt;br /&gt;
                I = direction of data (&#039;0&#039; = in / &#039;1&#039; = out)&lt;br /&gt;
                &lt;br /&gt;
                EEE = is write enable for ICD&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8034 - $803b&lt;br /&gt;
name = AUDIO&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                34 DDDDDDDDDDDDDDDD ADC_DATA_LEFT_HIGH       &lt;br /&gt;
                35 --------DDDDDDDD ADC_DATA_LEFT_LOW                 &lt;br /&gt;
                36 DDDDDDDDDDDDDDDD ADC_DATA_RIGHT_HIGH                  &lt;br /&gt;
                37 --------DDDDDDDD ADC_DATA_RIGHT_LOW       &lt;br /&gt;
                38 ----------------&lt;br /&gt;
                39 ----------------&lt;br /&gt;
                3a ----------------&lt;br /&gt;
                3b ----------------&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                   fedcba9876543210&lt;br /&gt;
                34 DDDDDDDDDDDDDDDD DAC_DATA_LEFT_HIGH       &lt;br /&gt;
                35 --------DDDDDDDD DAC_DATA_LEFT_LOW            &lt;br /&gt;
                36 DDDDDDDDDDDDDDDD DAC_DATA_RIGHT_HIGH               &lt;br /&gt;
                37 --------DDDDDDDD DAC_DATA_RIGHT_LOW         &lt;br /&gt;
                38 AAAAAAAADDDDDDDD ADAC_CTRL (Data)&lt;br /&gt;
                39 --------DDDDDDDD DAC_IRQ_GEN (interrupt generate if lower) &lt;br /&gt;
                3a --------DDDDDDDD ADC_IRQ_GEN (interrupt generate if higher)&lt;br /&gt;
                3b ---------------- ADC_NEXT (recive values (after 2 cycles available in ADC_DATA ($34-$37)))&lt;br /&gt;
                &lt;br /&gt;
                ADAC_CTRL (Data) = configure internal ADC/DAC controller&lt;br /&gt;
                &lt;br /&gt;
                Adr 76543210&lt;br /&gt;
                0   -------- ignore&lt;br /&gt;
                1   -------E enable DAC&lt;br /&gt;
                2   ----CCCC DAC push counter (96KHz at 0, 48KHz at 1, 32KHz at 2 ....)&lt;br /&gt;
                3   -------E enable ADC&lt;br /&gt;
                4   ----CCCC ADC pull counter (96KHz at 0, 48KHz at 1, 32KHz at 2 ....)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $803c - $8044&lt;br /&gt;
name = HCORE CTRL/IO (in experimental state)                                &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Videosetup im Detail ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:16 32Bit Computer Konsole Uctrl video setup.png|miniatur|Video Setup]]&lt;br /&gt;
&lt;br /&gt;
UCore und UCtrl (also auch der Videokontoller) haben eine Taktfrequenz von 106,481 MHz, mit dieser Frequenz ist es möglich eine maximale Auflösung von 1440 x 900 Bildpunkten bei 60 Hz zu programmieren. Da diese Auflösung in vielen Fällen zu hoch ist, bzw. die Performance für eine flüssige Bildberechnung nicht immer ausreicht, kann ein interner Zeilen-Cache so programmiert werden, dass er nur eine bestimmte Anzahl an Pixeln pro Zeile ausgibt (H-Skaliert) und nur eine definierte Anzahl von Zeilen neu geladen wird (V-Skaliert).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Wie üblich können (siehe Bild), HSYNC, HSTART etc. frei programmiert werden. Als Quelle für die Bilddaten kann der SDRAM oder SRAM benutzt werden (siehe EXTERNAL MEMORY START ADDRESS).&lt;br /&gt;
Das Farbformat kann zwischen einem 32 Bit Format (8Bit für R/G/B) und drei 16 Bit Formaten gewählt werden (siehe MEMORY Convertion MODE).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Support von Bitplanes oder Tiled-Grafiken gibt es nicht (da nicht notwendig, weil UCore/HCores schnell genug).&lt;br /&gt;
&lt;br /&gt;
Beispiel Video setup 360x225 4R4G4B Mode ($d0000000 ist Quelle (SDRAM)):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* setupVideo&lt;br /&gt;
;*&lt;br /&gt;
&lt;br /&gt;
setupVideo&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,videoDefault		;source&lt;br /&gt;
	movei	r1,UcTimer2Ctrl		;dest-1&lt;br /&gt;
	moveih	r0,&amp;gt;videoDefault&lt;br /&gt;
	moveih	r1,&amp;gt;UcTimer2Ctrl			&lt;br /&gt;
	movei	r2,26			;27-1&lt;br /&gt;
	&lt;br /&gt;
setupVideoLoop&lt;br /&gt;
&lt;br /&gt;
	rqldi	r0,0&lt;br /&gt;
	addi	r0,1&lt;br /&gt;
	addi	r1,1&lt;br /&gt;
	ld	r3&lt;br /&gt;
	subi	r2,1&lt;br /&gt;
	brts	setupVideoLoop&lt;br /&gt;
	st	r1,r3	;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
		&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
	&lt;br /&gt;
;*********************************************************************&lt;br /&gt;
;* data&lt;br /&gt;
;*********************************************************************&lt;br /&gt;
	&lt;br /&gt;
videoDefault		;AD NAME					&lt;br /&gt;
	&lt;br /&gt;
	word	$0001	;10 VIDEO_ON					&lt;br /&gt;
	word	$0097	;11 HSYNC (D = 11 .. 0)				&lt;br /&gt;
	word	$017f	;12 HSTART (D = 11 .. 0)			&lt;br /&gt;
	word	$017d	;13 HMEMSTART (D = 11 .. 0)			&lt;br /&gt;
	word	$071f	;14 HSTOP (D = 11 .. 0)				&lt;br /&gt;
	word	$076f	;15 HTOTAL (D = 11 .. 0)			&lt;br /&gt;
	word	$0002	;16 VSYNC (D = 10 .. 0)				&lt;br /&gt;
	word	$001e	;17 VSTART (D = 10 .. 0)			&lt;br /&gt;
	word	$03a2	;18 VSTOP  (D = 10 .. 0)			&lt;br /&gt;
	word	$03a3	;19 VTOTAL  (D = 10 .. 0)			&lt;br /&gt;
	word	$0000	;1a LC ADDER LOW				&lt;br /&gt;
	word	$0040	;1b LC ADDER HIGH				&lt;br /&gt;
	word	$0000	;1c LC ADDER LATCH				&lt;br /&gt;
	word	$0000	;1d LC START (10 .. 0) Pixeloffset		&lt;br /&gt;
	word	$0000	;1e						&lt;br /&gt;
	word	$0000	;1f						&lt;br /&gt;
	word	$0008	;20 HLOADSTART 					&lt;br /&gt;
	word	$00bc	;21 HLOADSTOP					&lt;br /&gt;
	word	$001e	;22 VLOADSTART 					&lt;br /&gt;
	word	$03a2	;23 VLOADSTOP 					&lt;br /&gt;
	word	$0004	;24 VLOADNEXT					&lt;br /&gt;
	word	$0000	;25 MEM_STARTADR_store low			&lt;br /&gt;
	word	$d000	;26 MEM_STARTADR_store high			&lt;br /&gt;
	word	$0000	;27 MEM_LINEOFFSET_store low			&lt;br /&gt;
	word	$0000	;28 MEM_LINEOFFSET_store high			&lt;br /&gt;
	word	$0002	;29 MEM_MODE_store 				&lt;br /&gt;
	word	$0000	;2a LATCH MEM_STARTADR/LINEOFFSET/MODE		&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Audiosetup im Detail ==&lt;br /&gt;
[[Datei:Uctrl audio overview.png|miniatur|rechts|audio simple]]&lt;br /&gt;
Da das DE-115 einen Wolfson WM8731 besitzt unterteilt sich die Ansteuerung für die Audio Ein/Ausgabe in zwei Teile.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Erste ist die Konfiguration der WM8731, hierfür wird I2C Port B von UCTRL verwendet.&amp;lt;br&amp;gt;&lt;br /&gt;
Um die Konfiguration einfach zu halten sind Komponenten zur Initialisierung über I2C vorhanden (initAudio), es muss nur eine Tabelle mit den gewünschten Einstellungen übergeben werden (Register, Wert siehe WM8731 Registerbeschreibung).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Setup:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
audioDefault&lt;br /&gt;
	&lt;br /&gt;
	;&lt;br /&gt;
				;A =  8 7654 3210&lt;br /&gt;
	.data   $9,$0000	;9 =  0 0000 0000 	(inactivate interface)&lt;br /&gt;
	.data	$0,$0097	;0 =  0 1001 0111	;left line in mute&lt;br /&gt;
	.data	$1,$0097	;1 =  0 1001 0111	;right line in mute&lt;br /&gt;
	.data	$2,$006e	;2 =  0 0111 1001	;+6db left out&lt;br /&gt;
	.data	$3,$006e	;3 =  0 0111 1001	;0db right out&lt;br /&gt;
	.data	$4,$0012	;4 =  0 0001 0010	;0=0 mic boost off;&lt;br /&gt;
							;1=1 enable line input mute&lt;br /&gt;
							;2=1 line input to adc&lt;br /&gt;
							;3=0 disable bypass&lt;br /&gt;
							;4=1 DAC select&lt;br /&gt;
							;5=0 side tone disable&lt;br /&gt;
							;76=0 -6db sidetone						&lt;br /&gt;
	.data	$5,$0000	;5 =  0 0000 0000	;DAC soft Mute off, no Filer&lt;br /&gt;
	.data	$6,$0067	;6 =  0 0110 0111 	;DAC Power, Output Power, Device Power on&lt;br /&gt;
	.data	$7,$0009	;7 =  0 0000 1001 	;left justified, 24 bit&lt;br /&gt;
	.data	$8,$001e	;8 =  0 0001 1110	;0=0 normal mode&lt;br /&gt;
							;1=1 bosr (384/192)&lt;br /&gt;
							;5432=0111 96khz&lt;br /&gt;
							;78=00 no clk dividing	&lt;br /&gt;
	.data   $9,$0001	;9 =  0 0000 0001 	(activate interface)&lt;br /&gt;
	.data	$ff,$0000	;stop&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Senden und Empfangen der Audio Daten wird über UCTRL Register $34 bis $3b bedient (ADC/DAC_DATA, ADAC_CTRL, ADC/DAC_IRQ_GEN, ADC_NEXT).&amp;lt;br&amp;gt;&lt;br /&gt;
Für ADC und DAC gibt es jeweils für den linken &amp;amp; rechten Kanal je 24 Bit Daten zum empfangen/senden. &amp;lt;br&amp;gt;&lt;br /&gt;
ADC/DAC besitzen je einen 256 Wort (2 * 24 Bit) großen Queue, im Register DAC_IRQ_GEN ($39) bzw. ADC_IRQ_GEN ($3a) können die die Unter/Überlaufwerte, welche zu einem Interrupt führen, konfiguriert werde.&amp;lt;br&amp;gt;&lt;br /&gt;
D.h. für einen Audioausgabe konfiguriert man z.B. den DAC Queue auf den Wert 128 um bei erreichen (kleiner als) einen Interrupt auszulösen (in welchen der Queue befüllt wird).&amp;lt;br&amp;gt;&lt;br /&gt;
Dadurch ist eine unterbrechungsfreie Wiedergabe/Aufnahme möglich ohne (je nach Einstellung) zu viele Interrupts auszulösen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die ADC/DAC Komponente in UCTRL kann über Register ADAC_CTRL ($38) konfiguriert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Die oberen 8 Bit des Datenworts bestimmen die Adresse, die unteren 8 Bit die Daten.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCTRL Audio Config:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name			address		876543210	comment&lt;br /&gt;
&lt;br /&gt;
nop			0		XXXXXXXXX	do nothing&lt;br /&gt;
ctrl			1		XXXXXXXXE	E = enable audio (default off)&lt;br /&gt;
set fifo read count	2		XXXXXXCCC	96KHz/C = fread [0..15]&lt;br /&gt;
set fifo write count	3		XXXXXXCCC	96KHz/C = fwrite [0..15]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Hier sollte vor der eigentlich Audio Ausgabe/Aufnahme, der jeweilige Counter für den ADC/DAC gesetzt werden (Counter der bei erreichen von 0 liest/schreibt). Z.B. den Wert 2 um eine 32 KHz Ausgabe einzustellen. Um die Queues zu lesen/schreiben muss noch unter Adresse 1 die Komponente aktiviert werden.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Audioausgabe von zwei 16 Bit Werten (links/rechts).&lt;br /&gt;
&amp;lt;br&amp;gt;	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	;r2 Audiobase $34&lt;br /&gt;
	;r1 = Wert für L, r4 = Wert für R&lt;br /&gt;
&lt;br /&gt;
	movei	r3,0&lt;br /&gt;
	stinc	r2,r1	;dac left high = value&lt;br /&gt;
	movei	r7,$1&lt;br /&gt;
	stinc	r2,r3	;dac left low = 0&lt;br /&gt;
	moveih	r7,$1&lt;br /&gt;
	stinc	r2,r4	;dac right high = value&lt;br /&gt;
	nop&lt;br /&gt;
	stinc	r2,r3	;dac right low = 0&lt;br /&gt;
	nop&lt;br /&gt;
	st	r2,r7	;dac address/ctrl = $0101	;ctrl = enable audio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Audio Tools ===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Um eine einfache Handhabung der Audioausgabe zu ermöglichen, gibt es unter dem Verzeichnis assembler_files\ucore\components Funktionen, die eine einfache Audioausgabe (Sample) und das Abspielen von MOD (Musik-Module) ermöglichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
= Homepage =&lt;br /&gt;
&lt;br /&gt;
http://www.goldmomo.de&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Uctrl_audio_overview.png&amp;diff=83198</id>
		<title>Datei:Uctrl audio overview.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Uctrl_audio_overview.png&amp;diff=83198"/>
		<updated>2014-05-29T16:51:10Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: uctrl audio simple overview&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;uctrl audio simple overview&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Benutzer:Goldmomo&amp;diff=83122</id>
		<title>Benutzer:Goldmomo</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Benutzer:Goldmomo&amp;diff=83122"/>
		<updated>2014-05-24T11:15:49Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: nicht wichtiges ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;My FPGA Project: http://www.mikrocontroller.net/articles/16/32Bit_Computer/Konsole &amp;lt;br&amp;gt;&lt;br /&gt;
My Homepage: http://www.goldmomo.org&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=83061</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=83061"/>
		<updated>2014-05-19T12:43:45Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: Screenshots hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein ‚Computer‘system, das nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses kopiert. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen das vollständig* selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (*FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL benutzt, für Emulation und Tools (Assembler etc.) wird C# mit .NET verwendet.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 benutzt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE) der über einen Memorymapped UCTRL-Komponente vollständigen Zugriff auf die Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Audio Interface (Stereo mit max. 24Bit / 96 KHz) &lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Timer/Counter&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCore = Utility Core) ist der ‚zentrale‘ Prozessor im System, er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist gedacht um einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn für alle meine Demos/Spiele als ‚CPU‘ benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* ‚RISC‘ Design&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In einen experimentellen Zustand befindet sich noch der HCORE Block. Dieser Block enthält mehre (konfigurierbar) 32 Bit Prozessoren die über spezielle Techniken (Hardwaresemaphoren, parallele Sprünge, … ) eine parallele Verarbeitung der Software vereinfachen sollen und die Latenzprobleme bei Multithreading vermeiden. Ich habe bisher ein Demo mit 16 parallel laufenden HCOREs veröffentlicht, alle anderen Demos benutzen diese Cores nicht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Momentane Charakteristiken eines HCOREs sind:&lt;br /&gt;
&lt;br /&gt;
*‚Risc‘ Design &lt;br /&gt;
*7 Stufen Pipeline mit „in order“ und „out of order“ Pfad&lt;br /&gt;
*Instruction Cache (konfigurierbar (momentan 8 Wege mit 64 Worten))&lt;br /&gt;
*32 Bit ALU (Hold to Last Pfad, …) &lt;br /&gt;
*128 GP Register&lt;br /&gt;
*UCtrl/Memory/Semaphoren/… out of order Zugriff&lt;br /&gt;
*…&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
[[Datei:Goldmomo emulator.png|miniatur|rechts|Emulator]]&lt;br /&gt;
Um die Softwareentwicklung (und Debuggen) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Register, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (auch in Emulator integriert), ein Compiler existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/2n1o8dfium4bdgi/TK_Da_o4rx/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/310121#new&lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo endlos Sheriff2213.png|miniatur|Sheriff 2213]]&lt;br /&gt;
[[Datei:Goldmomo endlos SpacePilotOfDeath.png|miniatur|SpacePilotOfDeath]]&lt;br /&gt;
[[Datei:Goldmomo endlos ModPlayer.png|miniatur|MOD Player]]&lt;br /&gt;
[[Datei:Goldmomo endlos GfxExtension.png|miniatur|GFX Extension]]&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= UCORE Programmierung =&lt;br /&gt;
&lt;br /&gt;
UCore (Utility Core) ist ein Eigenimplementierung  eines 16 Bit Prozessor. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Grundlegende Charakteristiken:&lt;br /&gt;
&lt;br /&gt;
* sechsstufige Pipeline&lt;br /&gt;
* 8 Generalpurpose Registern&lt;br /&gt;
* 32 Bit Register für externe Adressen&lt;br /&gt;
* T-Bit um Bedingungen zu verarbeiten&lt;br /&gt;
* Status Register&lt;br /&gt;
* Vector Base Register&lt;br /&gt;
* 32 Bit Multiplikation Register (High-Result)&lt;br /&gt;
* separater Stackpointer&lt;br /&gt;
* interne Speicher in dem Code/Daten liegen&lt;br /&gt;
* externer Speicherzugriff (32Bit-Adressraum) möglich&lt;br /&gt;
* die Datenwortbreite beträgt immer 16 Bit (es gibt keine Bytes)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCore unterscheidet sich einigen Teilen von einem &#039;normalen&#039; Prozessor (RISC-)Design.&lt;br /&gt;
Die Gründe bzw. Ziele welche verfolgt wurden, ware eine möglichst hohe Taktrate und ein möglichst geringer Benutzung von Hardwareressourcen, aber dennoch eine hohe Verarbeitungsgeschwindigkeit.&lt;br /&gt;
Dadurch ergeben sich einige Besonderheiten die bei der Programmierung beachtet werden müssen (siehe Registerzugriffe, Branch/Jump Delayslots, Request/Load Zugriffe).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pipeline ===&lt;br /&gt;
&lt;br /&gt;
Wie gesagt hat dieser Core eine sechsstufige Pipeline:&lt;br /&gt;
&lt;br /&gt;
# Prepare Fetch &lt;br /&gt;
# Fetch &lt;br /&gt;
# Decode &lt;br /&gt;
# Read Register &lt;br /&gt;
# Execute &lt;br /&gt;
# Write Register (hat einen Bypass zu Stufe 4) &lt;br /&gt;
&lt;br /&gt;
Jede Instruktion wird in einem Cycle ausgeführt, nur der externe Speicherzugriff (nur Daten) kann einen Stall (Stillstand) der Pipeline verursachen.&lt;br /&gt;
&lt;br /&gt;
== Interne Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
In meinem System wird die folgende interne Speichermap verwendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$0000 code / data memory&lt;br /&gt;
*     16384 * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$3fff&lt;br /&gt;
$4000 code / data memory MIRROR&lt;br /&gt;
*     &lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$7fff&lt;br /&gt;
$8000 ctrl / memory			StackPointer start at $8000 on reset&lt;br /&gt;
*     XXXX * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$XXXX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Reset-Vektor befindet sich an Adresse 0, der Stackpointer an Adresse $8000. &lt;br /&gt;
Der Interruptvektor an Adresse $10 (sollte nach dem Reset an die benötigte Position verschoben werden).&lt;br /&gt;
Ab Adresse $8000 wird die Komponente UCtrl in den Adressraum ‚gemappt‘ (diese Komponente enthält Register für externe Hardware Peripherie etc.).&lt;br /&gt;
&lt;br /&gt;
== externe Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
Über den &#039;externen&#039; Datenbus kann auf folgende Komponenten zugegriffen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$a000 0000 - $a000 001f SDCard-Controller&lt;br /&gt;
$d000 0000 - $d3ff ffff SDRAM&lt;br /&gt;
$e000 0000 - $e03f ffff FLASH&lt;br /&gt;
$f000 0000 - $f00f ffff SRAM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei den meisten meiner Programme wird ein Standard-Programm aus dem FLASH-Speicher gelesen, welches einen Speichertest ausführt und auf das Einlegen einer SD-Karte mit dem zuladenden Programm wartet.&lt;br /&gt;
&lt;br /&gt;
== Opcodes/Operanten ==&lt;br /&gt;
&lt;br /&gt;
UCore hat keine &#039;RISC&#039;-Typischen Befehlssatz (viele Befehle, aber geringe Komplexität).&lt;br /&gt;
 &lt;br /&gt;
Da ein Instruktions-Wort nur eine Breite von 16 Bit hat, können nur bedingte Mengen an Operanten verwendet werden. Um jedoch die Programmierung flexibler zu gestalten, haben viele Opcodes mehrere Arten von Operanten. &lt;br /&gt;
Für die Ausführungseinheit ergibt sich dadurch keine Ressourcenveränderung, da der Decoder nur die Opcodes/Operanten in ein internes einheitliches Format auflöst.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Operanten Formate ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dc,imm8&lt;br /&gt;
 dc,db,da&lt;br /&gt;
 dc,db,imm3&lt;br /&gt;
 imm12&lt;br /&gt;
 db,da&lt;br /&gt;
 imm6&lt;br /&gt;
 da&lt;br /&gt;
 kein Operant&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Opcode / Operante(n) / Beschreibung ==== &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
movei     	dc,imm8		dc = imm&lt;br /&gt;
moveih    	dc,imm8		dc[15..8] = imm &amp;lt;&amp;lt; 8 | dc[7..0]&lt;br /&gt;
addi      	dc,imm8		dc = dc + imm&lt;br /&gt;
subi      	dc,imm8		dc = dc - imm&lt;br /&gt;
lsri      	dc,imm8		dc = dc &amp;gt;&amp;gt; imm&lt;br /&gt;
asri      	dc,imm8		dc = ((signed)dc) &amp;gt;&amp;gt; imm&lt;br /&gt;
muli      	dc,imm8		dc = dc * imm&lt;br /&gt;
cmpeqi    	dc,imm8		t = set if dc == imm else cleared&lt;br /&gt;
cmploi    	dc,imm8		t = set if dc &amp;lt; imm else cleared&lt;br /&gt;
cmplosi   	dc,imm8		t = set if  (signed)dc &amp;lt; (signed) imm else cleared&lt;br /&gt;
gpci      	dc,imm8		dc = pc + imm&lt;br /&gt;
jmpi      	dc,imm8		pc = dc + imm&lt;br /&gt;
extri     	dc,imm8		t = bit #imm of dc&lt;br /&gt;
rqldi     	dc,imm8		request (internal) mem; address = dc + imm&lt;br /&gt;
getsp     	dc,imm8		dc = sp + imm&lt;br /&gt;
dexti     	imm11		store imm as extension for next instruction&lt;br /&gt;
&lt;br /&gt;
add		dc,db,da	dc = db + da&lt;br /&gt;
sub     	dc,db,da	dc = db - da&lt;br /&gt;
lsr     	dc,db,da	dc = db &amp;gt;&amp;gt; da&lt;br /&gt;
asr     	dc,db,da	dc = ((signed)db) &amp;gt;&amp;gt; da&lt;br /&gt;
mul     	dc,db,da	dc = db * da&lt;br /&gt;
addt    	dc,db,da	dc = db + da + t&lt;br /&gt;
subt    	dc,db,da	dc = db - da - t&lt;br /&gt;
muls    	dc,db,da	dc = db * da&lt;br /&gt;
movets  	dc,db,da	dc = db if t = set else da&lt;br /&gt;
and     	dc,db,da	dc = db &amp;amp; da&lt;br /&gt;
or      	dc,db,da	dc = db | da&lt;br /&gt;
xor     	dc,db,da	dc = db ^ da&lt;br /&gt;
bic     	dc,db,da	dc = db &amp;amp; ~da&lt;br /&gt;
&lt;br /&gt;
addqi		dc,db,imm3	dc = db + imm&lt;br /&gt;
subqi   	dc,db,imm3	dc = db - imm&lt;br /&gt;
lsrqi   	dc,db,imm3	dc = db &amp;gt;&amp;gt; imm&lt;br /&gt;
asrqi   	dc,db,imm3	dc = ((signed)db) &amp;gt;&amp;gt; imm&lt;br /&gt;
mulqi   	dc,db,imm3	dc = db * imm3&lt;br /&gt;
addtqi  	dc,db,imm3	dc = db + imm + t&lt;br /&gt;
subtqi  	dc,db,imm3	dc = db - imm - t&lt;br /&gt;
edrqldi 	db,da,imm3	request (external) mem; address = (db:da) + imm3&lt;br /&gt;
&lt;br /&gt;
br		imm12		pc = pc + signed(imm)&lt;br /&gt;
brts		imm12		pc = pc + signed(imm) if t is set&lt;br /&gt;
brtc		imm12		pc = pc + signed(imm) if t is cleared&lt;br /&gt;
	             &lt;br /&gt;
cmpeq		db,da		t = set if db == da else cleared		&lt;br /&gt;
cmplo   	db,da           t = set if db &amp;lt; da else cleared&lt;br /&gt;
cmplos  	db,da           t = set if  (signed)db &amp;lt; (signed) da else cleared&lt;br /&gt;
esadr   	db,da		esadr = db:da&lt;br /&gt;
swp     	db,da		db = da[7..0]:da[15..8] &lt;br /&gt;
swptc   	db,da		db = da[7..0]:da[15..8] if t = set else da&lt;br /&gt;
st      	db,da		imem[db] = da&lt;br /&gt;
stinc   	db,da		imem[db] = da; db = db + 1&lt;br /&gt;
bffo    	db,da		db is first bit that is 1 found in da (from MSB to LSB)&lt;br /&gt;
bset    	db,da		db = db | 1 &amp;lt;&amp;lt; da&lt;br /&gt;
bclr    	db,da		db = db &amp;amp; ~ (1 &amp;lt;&amp;lt; da)&lt;br /&gt;
cmple   	db,da		t = set if db &amp;lt;= da else cleared&lt;br /&gt;
cmples  	db,da		t = set if  (signed)db &amp;lt;= (signed) da else cleared&lt;br /&gt;
rqld    	db,da		request (internal) mem; address = db + da&lt;br /&gt;
extb    	db,da		db = da byte to word singed extended&lt;br /&gt;
stwo    	db,da		imem[db + STORE_OFFSET] = da&lt;br /&gt;
andts   	db,da		db = db &amp;amp; da if t = set else da&lt;br /&gt;
orts    	db,da           db = db | da if t = set else da&lt;br /&gt;
xorts   	db,da           db = db ^ da if t = set else da&lt;br /&gt;
bicts   	db,da           db = db &amp;amp; ~da if t = set else da&lt;br /&gt;
lsrts   	db,da		db = db &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
asrts   	db,da           db = ((signed)db) &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
mults   	db,da           db = db * da if t = set else da&lt;br /&gt;
mulsts  	db,da		db = (signed)db * (signed)da if t = set else da&lt;br /&gt;
&lt;br /&gt;
erqldi		imm6		request (external) mem; address = esadr + imm	&lt;br /&gt;
ssto		imm6		STORE_OFFSET = imm&lt;br /&gt;
udivinit	imm6		udivqoutient = 0; udivrest = 0; udivbitcounter = imm&lt;br /&gt;
&lt;br /&gt;
eld		da		da = requested value from external memory&lt;br /&gt;
push            da		sp = sp – 1; imem[sp] = da&lt;br /&gt;
gmulhi          da		da = multiply result [31..15] from last multiplication&lt;br /&gt;
ld/pop          da		da = requested value from internal memory&lt;br /&gt;
poparqp         da		da = requested value from internal memory; request in internal memory adr = sp; sp = sp + 1&lt;br /&gt;
neg             da		da = 0 - da&lt;br /&gt;
udivgq          da		get division qoutinent&lt;br /&gt;
udivgr          da		get division remainder&lt;br /&gt;
udivgqh         da		get division qoutinent high [31 ..16]&lt;br /&gt;
udivgrh         da              get division remainder high [31 ..16]&lt;br /&gt;
udivsdd         da		set division divident &lt;br /&gt;
udivsdv         da		set division divider&lt;br /&gt;
udivsddh        da		set division divident high [31 ..16]&lt;br /&gt;
udivsdvh        da		set division divider  high [31 ..16]&lt;br /&gt;
erqld           da		request (external) mem; address = esadr + da&lt;br /&gt;
setsp           da		sp = da&lt;br /&gt;
erqldb          da		request (external) mem; address = esadr + da / 2&lt;br /&gt;
jmpts           da		pc = da if t = set&lt;br /&gt;
jmptc           da		pc = da if t = cleared&lt;br /&gt;
negts           da		da = 0 - da if t = set else da&lt;br /&gt;
&lt;br /&gt;
rqpop				internal memory request address = sp; sp = sp + 1&lt;br /&gt;
cli				disable interrupts&lt;br /&gt;
sei				enable interrupts&lt;br /&gt;
rti				pc = pc_before interrput&lt;br /&gt;
tnt				t = not t&lt;br /&gt;
vtt				t = v (overflow/underflow wrom add/sub)			&lt;br /&gt;
epushsadrl			sp = sp – 1; imem[sp] = esadr[15..0]&lt;br /&gt;
epushsadrh			sp = sp – 1; imem[sp] = esadr[31..16]&lt;br /&gt;
epopsadrl			esadr[15..0] = requested value from internal memory&lt;br /&gt;
epopsadrh			esadr[31..16] = requested value from internal memory&lt;br /&gt;
udivstep			performe one division step &lt;br /&gt;
nop				do nothing&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Registerzugriffe ==&lt;br /&gt;
&lt;br /&gt;
Da Register vor der Ausführungseinheit gelesen werden und nach der Ausführungseinheit geschrieben werden, ergibt sich eine Latenz zwischen Register Zugriffen. Der Grund für diese Implementierungsart ist schlicht und einfach um die Performanz zu erhöhen. Als Nebeneffekt entsteht, wie gesagt, eine Latenz. Es bieten sich mehrere Möglichkeiten an, diese Register-‚Hazards‘ in Hardware zu vermeiden (Registerscoring, Renaming, …). Um den Hardware-Implementierung klein und schnell zu halten wird in UCore auf einen Hardwaretest verzichtet. Als Resultat muss der Anwender Registerabhängigkeiten im Programm-Code behandeln.&lt;br /&gt;
Der einzige logische sinnvolle Nachteil ergibt sich in einer RAW (Read after Write) Abhängikeit, da die Latenz hier eine Cycle beträgt. In diesem Fall sollte/muss eine andere Instruktion (z.B. nop) eingefügt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreiben eines Registers und späteres lesen): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae	; &lt;br /&gt;
	nop		;write r0 = ae wird ausgeführt&lt;br /&gt;
	addi	r0,1	;r0 = r0 ($ae) + 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Im einfachsten Fall, sollte eine nop Operation bei solchen Abhängigkeit verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (nicht optimiert mit nop - 6 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	nop&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	nop&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In den meisten Fällen kann man aber andere Operationen als ‚Füllung‘ bei Registerabhängikeiten verwenden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (Optimiert - 4 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um versehentlich programmierte RAW-&#039;Hazards&#039; zu erkennen erzeugt der Assembler Warnungen, ebenfalls kann der Emulator zur Laufzeit diese &#039;Probleme&#039; erkennen.&lt;br /&gt;
Prinzipiell ist es möglich, in gewissen Situationen, RAW-&#039;Hazards&#039; absichtlich zuzulassen (Optimierungen um Register zu sparen), wovon aber im Normalfall abzuraten ist.&lt;br /&gt;
&lt;br /&gt;
== Bedingungen ==&lt;br /&gt;
&lt;br /&gt;
UCore benutzt ein T-Bit (true Bit) um Bedingungen zu beschreiben/verarbeiten. Normalerweise wird dieses Bit von Vergleichsoperationen gesetzt und kann dann von Operationen benutzt werden welche das T-Bit intern verwenden (z.B. bedingte Sprünge).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel:====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	cmpeqi	r0,0		;vergleiche auf r0 gleich 0 wenn wahr da (t=1) ansonsten (t=0)&lt;br /&gt;
	brts	r0IstNull	;springe zu ‚r0IstNull‘ label wenn t set (t=1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist notwendig Register nur dann zu setzen wenn bestimmte Bedingungen eintreten. In diesen Fällen ist es ärgerlich bedingte Sprünge auszuführen, da sie etwas Zeit brauchen (Delay Slots) und den Programmcode unübersichtlich machen.&lt;br /&gt;
Aus diesem Grund, unterstützen einige Befehle eine Bedingte Ausführung (nicht jeder).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	move	r1,123&lt;br /&gt;
	move 	r2,23&lt;br /&gt;
	…&lt;br /&gt;
	cmplo	r0,r1		;r0 &amp;lt; r1&lt;br /&gt;
	movets	r0,r2,r0	;wenn ja r0 = r2 (23) ansonsten r0 = r0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sprünge ==&lt;br /&gt;
&lt;br /&gt;
Ein (bedingter) Sprung benötigt, wie jede andere Instruktion, einen Cycle um ausgeführt zu werden.&lt;br /&gt;
Da UCore keine Branchprediction bzw. keine spekulative Ausführung etc. unterstützt und es auch nicht gewollt ist Opcodes in der Pipeline zu verwerfen, entstehen nach Sprungbefehlen sogenannte &#039;Delay Slots&#039;. Die Anzahl dieser Delay Slots ergeben sich aus der Anzahl der Pipelinestufen vor der Ausführungseinheit (da sie den Programmcounter verändert).&lt;br /&gt;
Kurzum Programlauftechnisch werden Instruktionen in diesen Delay Slots ausgeführt bevor der Sprung in Wirklichkeit ausgeführt wird.&lt;br /&gt;
Die kleinste mögliche Schleife benötigt deshalb fünf Instruktionen für einen Durchlauf.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loop	br	loop		;branch zu loop&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In vielen Fällen können diese Delay Slots sinnvoll genutzt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 1 (nicht optimiert - 8 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,1	;r1 = x parameter&lt;br /&gt;
	movei	r1,7	;r2 = y parameter&lt;br /&gt;
	gpci	r7,2	;r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 1 (optimiert - 6 cycles): ====&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	gpci	r7,2	r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	movei	r0,1	;delay slot	r1 = x parameter&lt;br /&gt;
	movei	r1,7	;delay slot     r2 = y parameter&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 2 (nicht optimiert - 8 * n + 3 cycles -&amp;gt; if n 128 -&amp;gt; total 1027 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127	;r0 = loop counter - 1&lt;br /&gt;
	movei	r1,0	;r1 = Füllwert&lt;br /&gt;
	nop&lt;br /&gt;
	&lt;br /&gt;
loop	st	r1,r6	;imem[r1] = r6&lt;br /&gt;
	addi	r1,1	;r1++&lt;br /&gt;
	subi	r0,1	;r0-- (t clear bei &amp;lt; 0)&lt;br /&gt;
	brts	loop	;branch loop solange t set&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 2 (optimiert - 6 * n + 2 cycles -&amp;gt; if n 128 -&amp;gt; total 770 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127&lt;br /&gt;
	movei	r1,0&lt;br /&gt;
	&lt;br /&gt;
loop	subi	r0,1	;da t später verwendet wird nicht in delay slot benutzen (siehe  Interruptbenutzung)&lt;br /&gt;
	brts	loop&lt;br /&gt;
	st	r1,r6	;delay slot&lt;br /&gt;
	addi	r1,1	;delay slot	&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Speicherzugriffe ==&lt;br /&gt;
&lt;br /&gt;
UCore besitzt keine ‚gewöhnlichen‘ Lesebefehle für interne/externe Speicherzugriffe.&lt;br /&gt;
Um Pipeline-Stalls beim Lesen von Daten zu vermeiden (Latenz zum Speicher), wird eine Lesebefehl in zwei Operationen aufgeteilt.&lt;br /&gt;
Der erste Befehl ist ein &#039;Request&#039;, er teilt dem Core mit von welcher Adresse er etwas lesen soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Der zweite Befehl ist dann der &#039;Load&#039;, er holt sich die angekommenen Daten ab und speichert sie in einem Register.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== interner Speicherzugriff ====&lt;br /&gt;
&lt;br /&gt;
Bei internen Speicherzugriffen ist die Latenz zwischen Request und Load statisch (3 Cycles), bei externen Zugriff variable (hier wird im Fall eines Load ohne vorhandene Daten ein Stall ausgelöst).&lt;br /&gt;
&lt;br /&gt;
Mit den Opcodes rqld (request load) und ld (load) kann vom internen Speicher gelesen werden.&lt;br /&gt;
Da die Daten erst zwei Operationen nach dem Request verfügbar sind, muss hier etwas anderes ausgeführt werde (z.B. nop).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0	;send load to address (r0+0)&lt;br /&gt;
	nop		;data send to memory&lt;br /&gt;
	nop		;data will read&lt;br /&gt;
	ld	r1	;readed data to r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Da der interne Speicher immer innerhalb von einem Cycles antwortet und die Latenz durch Pipelinestufen entsteht, kann man bei internen Speicherzugriff bis zu drei Request hintereinander verwenden.&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0&lt;br /&gt;
	rqld	r0,1&lt;br /&gt;
	rqld	r0,2&lt;br /&gt;
	ld	r1	;r1 &amp;lt;- internal_mem[r0+0]&lt;br /&gt;
	ld	r2	;r2 &amp;lt;- internal_mem[r0+1]&lt;br /&gt;
	ld	r3	;r3 &amp;lt;- internal_mem[r0+2]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Bei Schreibzugriffen wird wie bei anderen Prozessoren ein Store-Kommando verwendet.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti	$80	;imm exted&lt;br /&gt;
	move	r4,$01	;r4 = $8001&lt;br /&gt;
	move	r0,12	;r0 = 12&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	st	r0,r4	;imem[r4] = r0; $8001 = 12&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
Da ein &#039;st&#039;ore Befehl nur einen Register als Zieladresse benutzt, ist es vielen Fällen ärgerlich diesen bei mehrfachen Schreiben zu verändern. Um bei diesem Fall Abhilfe zu verschaffen wurde der Befehl ssto (Set Store Offset) und stwo (Store with Offset) eingeführt. Mit ssto kann ein Offset für stwo gesetzt werden, d.h. der Wert der mit ssto gesetzt wird auf die Zieladresse von stwo addiert.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	stwo 1&lt;br /&gt;
	ssto r0,r7 ;imem[r7+1] = r0&lt;br /&gt;
	stwo 2&lt;br /&gt;
	ssto r1,r7 ;imem[r7+2] = r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist es leider etwas unangenehm mit der statischen Latenz bei internen Lesezugriffen, da man hier etwas mehr schreiben muss als man es von anderen Prozessoren gewöhnt ist.&lt;br /&gt;
&lt;br /&gt;
==== externe Speicherzugriffe ====&lt;br /&gt;
&lt;br /&gt;
Externe Speicherzugriffe verhalten sich ähnlich wie interne Zugriff.&lt;br /&gt;
Unterschiede gibt es in der Adressbreite (extern 32Bit) und in der variablen Latenz (bestimmt durch mehre Faktoren).&lt;br /&gt;
Es gibt eine externe Hauptadresse (Base) die mit &#039;allen&#039; (bis auf edrqldi) externen Speicherzugriffsinstruktionen verwendet wird.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel Hauptadresse setzen: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel schreibe in externen Speicher: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r4,$af&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	esadr	r1,r0	;Hauptadresse (esadr) is r1:r0&lt;br /&gt;
	est	r4,0	;externSpeicher[esadr + 0] = r4&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
Beim Lesen vom externen Speicher werden auch Request/Load Befehle verwendet um Latenzen, wenn möglich, zu vermeiden. Da die Latenz nicht vorhersehbar ist, wird bei nicht vorhandenen Daten solange gewartet bis sie vorhanden sind (Stall).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
	erqld	0	;load from [r0:r1 + 0]&lt;br /&gt;
	eld	r7	;get external data (Stall solange bis Daten vorhanden)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um Lade/Schreiblatenzen zu vermeiden, können mehre Stores oder Request (laden) hintereinander ausgeführt werden (maximal 256 Requestzugriffe, keine Begrenzung bei Stores).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreibe 8 Worte in externen Speicher, kein Stall solange Schreibpuffer nicht voll): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,0&lt;br /&gt;
	esadr	r7,r6	;external address is r1:r0 &lt;br /&gt;
	est	r0,0&lt;br /&gt;
	est	r0,1&lt;br /&gt;
	est	r0,2&lt;br /&gt;
	est	r0,3&lt;br /&gt;
	est	r0,4&lt;br /&gt;
	est	r0,5&lt;br /&gt;
	est	r0,6&lt;br /&gt;
	est	r0,7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (vermeiden von Leselatenzen) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r7,r6&lt;br /&gt;
	erqld	0&lt;br /&gt;
	erqld	1&lt;br /&gt;
	erqld	2&lt;br /&gt;
	erqld	3	;request 4 Worte&lt;br /&gt;
	&lt;br /&gt;
	....		;mach irgendwas&lt;br /&gt;
	&lt;br /&gt;
	eld	r0	&lt;br /&gt;
	eld	r1&lt;br /&gt;
	eld	r2&lt;br /&gt;
	eld	r3	;bekomme Daten (evtl. kein Stall, da Daten schnellgenug da)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Stack ==&lt;br /&gt;
&lt;br /&gt;
Der Stackpointer zeigt nach dem Reset auf Adresse $8000 (also am oberen Ende des internen Speichers).&lt;br /&gt;
Das Verhalten von push und request pops and pops sind gleich dem internen Speicherzugriffsverhalten (3 Cycles Latenz, Pipelined).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (1 pop): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r4	;sp--; imem[sp] = r4&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop		;request imem[sp], sp++&lt;br /&gt;
	nop&lt;br /&gt;
	nop&lt;br /&gt;
	pop	r4	;r4 = imem[sp]&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel (3 Werte auf Stack und wieder herunter) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r1&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r3&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop		;durch Latenz maximal 3 rqpop dann Daten (ansonsten &#039;poparqp&#039; benutzen (kann Request und Load gleichzeitig))&lt;br /&gt;
	push	r3&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Decoder extend ==&lt;br /&gt;
&lt;br /&gt;
Da viele Operationen konstante Werte benutzen können, aber diese aus Gründen der Befehlsbreite (16 Bit) je nach Befehl/Operanten nur eine teilweise unzureichende Größe/Breite verwenden können wurde eine Dekoder Instruktion (dexti = decoder extend immediate) eingeführt. Dieser Befehl wird vom Dekoder ausgeführt und wird in der eigentlichen Ausführungseinheit ignoriert.&lt;br /&gt;
Sinn dieses Befehls ist es, konstante Werte um einen 8 Bit breiten Wert zu erweitern. Um Fehler zu vermeiden ist dieser Wert nur einen Cycle nach ‚dexti‘ verfügbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (16 Bit Immediate Addition) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti     $12&lt;br /&gt;
	addi	  r0,$34	;r0 = r0 + $1234&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interrupts ==&lt;br /&gt;
&lt;br /&gt;
Interrupts sind in einem Pipeline basierenden Design immer ärgerlich zu handhaben. Da UCore nicht, wie viele Mikrokontroller, möglichst kurze Interrupt-Latenzen ermöglichen muss, gibt es in diesem Design auch keine garantierten Zeiten in welchen der Interrupt ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
Um den Hardwareaufwand gering wie möglich zu halten, habe ich eine sogenannte Branch-Injektion implementiert. Der Hintergedanke ist, dass Sprünge sehr oft im Code ausgeführt werden und diese, im Fall eines Interrupts , dazu ‚missbraucht‘ werden können direkt zum Interrupt-Service-Vector zu springen anstatt ihren eigentlichen definierten Sprung auszuführen (dieser wird gespeichert und später ausgeführt).&lt;br /&gt;
&lt;br /&gt;
Der Vorteil dieser Implementierung ist ein sehr geringer Hardwareaufwand, der Nachteil ist, dass die Interrupt-Latenz variiert (Delta zwischen zwei Sprüngen) und sich Verhaltensregeln für ‚Delay-Slots‘ ergeben.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;	&lt;br /&gt;
	sei			;irq enable&lt;br /&gt;
	br	anySubroutine	;if irq is enabled and occure a branch is take to irq vector and after irq is finished (rte) the give branch will take&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In ‘Delay-Slots’ sollten kein T-Bit gesetzt werden, welches für spätere Verwendungen gebraucht wird. Außerdem sollten keine Speicher-Request an diesen Stellen ausgeführt werden.&lt;br /&gt;
Um Fehler zu vermeiden warnt der Assembler bei solchen Konstrukten.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
	sei&lt;br /&gt;
	br	anySubroutine&lt;br /&gt;
	addt	r0,r1	;delay slot	(t is not save in delay slot if irq is enabled, because t is only store at br instruction)&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dividieren ==&lt;br /&gt;
&lt;br /&gt;
Viele Prozessoren die auf geringen ‚Platzverbrauch‘ optimiert sind, versuchen wenn möglich Divisions-Operationen zu vermeiden oder führen diesen nicht in einer Pipeline-Implementierung aus. Auf der Softwareseite sind Divisionen in vielen Fällen vermeidbar oder durch bestimmte Methoden ersetzbar. Prinzipiell ist eine Division einfach in Software zu implementieren, in diesem Fall ist die Geschwindigkeit einer Hardwareimplementierung meist nicht annähernd zu erreichen. UCore bietet spezielle Befehle an um einen Kompromiss aus Geschwindigkeit und Hardwareaufwand  zu erreichen.&lt;br /&gt;
Wie bei einer normalen Division wird in hier Divisor und Dividend gesetzt zusätzlich muss noch die Divsions-Bitbreite angegeben werden (max. 32 Bit). Durch den Befehl udivstep wird eine ‚1-Bit Division‚ ausgeführt, d.h. udivstep muss/kann sooft ausgeführt werden wie die Divisionsbreite gewählt ist. Als Resultat der Division ergeben sich der Quotient und der Rest.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* udiv16&lt;br /&gt;
;* &lt;br /&gt;
;* r0 	 	divident&lt;br /&gt;
;* r1		divisor&lt;br /&gt;
;*&lt;br /&gt;
;* return&lt;br /&gt;
;*&lt;br /&gt;
;* r2		qoutient&lt;br /&gt;
;* r3		remainder&lt;br /&gt;
;*&lt;br /&gt;
;* needs 34 cycles&lt;br /&gt;
;*&lt;br /&gt;
	&lt;br /&gt;
udiv16	&lt;br /&gt;
	udivinit	15&lt;br /&gt;
	udivsdd		r0&lt;br /&gt;
	udivsdv		r1&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,3	;(3+1)*4 = 16&lt;br /&gt;
	cli		;disable irq&lt;br /&gt;
udiv16Loop	&lt;br /&gt;
	subi	r0,1&lt;br /&gt;
	brts	udiv16Loop&lt;br /&gt;
	udivstep	;delay slot	!!!! note udivstep is not irq save, so use cli/sei lock&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	udivgq		r2	;delay slot		get qoutient&lt;br /&gt;
	udivgr		r3	;delay slot		get remainder&lt;br /&gt;
	sei			;delay slot		enable irqs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== weiter Beispiele ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
= UCtrl =&lt;br /&gt;
&lt;br /&gt;
UCtrl ist eine Abstraktionsschicht für einen Großteil der externen (DE2-115) Peripherien und stellt zusätzlich hilfreiche Element (Timer,…) zur Verfügung. &lt;br /&gt;
Direkten Zugriff auf diese Komponente hat nur UCore (siehe Memorymap).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCtrl bietet dem Benutzer zugriff auf:&lt;br /&gt;
*LEDS &lt;br /&gt;
*SWITCHES&lt;br /&gt;
*7-Segment Anzeige&lt;br /&gt;
*LCD (zweizeilig auf DE2-115)&lt;br /&gt;
*Interrupt Kontrolle (für UCore)&lt;br /&gt;
*Timer/Counter&lt;br /&gt;
*Video Setup (inkl. Counter und Vertikal-‚Hit‘-Erkennung)&lt;br /&gt;
*PS/2 Port (in/out, zwei Ports)&lt;br /&gt;
*I2C (zwei Ports)&lt;br /&gt;
*Audio (DAC/ADC)&lt;br /&gt;
*HCore Setup und Daten (beschreibe ich später)&lt;br /&gt;
&lt;br /&gt;
== Register ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8000&lt;br /&gt;
name = LEDG_SW&lt;br /&gt;
read            fedcba9876543210&lt;br /&gt;
                SSSSSSSSSSSSSSSS&lt;br /&gt;
                &lt;br /&gt;
                S = switches on DE2-115&lt;br /&gt;
                &lt;br /&gt;
write           fedcba9876543210&lt;br /&gt;
                -------GGGGGGGGG&lt;br /&gt;
                &lt;br /&gt;
                G = LED Green (&#039;1&#039; is ON)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8001&lt;br /&gt;
name = LEDR&lt;br /&gt;
read            fedcba9876543210&lt;br /&gt;
                --------------ME&lt;br /&gt;
        &lt;br /&gt;
                M = &#039;1&#039; if running in modelsim&lt;br /&gt;
                E = &#039;1&#039; if running in emulator&lt;br /&gt;
                &lt;br /&gt;
write                fedcba9876543210&lt;br /&gt;
                -------RRRRRRRRR&lt;br /&gt;
                &lt;br /&gt;
                R = LED Red (&#039;1&#039; is ON)&lt;br /&gt;
&lt;br /&gt;
                 &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8002 - $8005&lt;br /&gt;
name = 7SEG&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                2 ----------------&lt;br /&gt;
                3 ----------------&lt;br /&gt;
                4 ----------------&lt;br /&gt;
                5 ----------------&lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                2 -6543210-6543210&lt;br /&gt;
                3 -6543210-6543210&lt;br /&gt;
                4 -6543210-6543210&lt;br /&gt;
                5 -6543210-6543210&lt;br /&gt;
                &lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 1 / 0 (&#039;1&#039; is ON)                &lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 3 / 2 (&#039;1&#039; is ON)&lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 4 / 4 (&#039;1&#039; is ON)&lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 5 / 6 (&#039;1&#039; is ON)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8006 - $8007&lt;br /&gt;
name = LCD&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                6 -------BDDDDDDDD&lt;br /&gt;
                7 ----------------&lt;br /&gt;
                &lt;br /&gt;
                B = &#039;1&#039; if read/write request is busy&lt;br /&gt;
                D = Data after request&lt;br /&gt;
                &lt;br /&gt;
                note: wait 1 cycle after read/write request before read&lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                6 ------WRDDDDDDDD&lt;br /&gt;
                7 ----------------&lt;br /&gt;
                &lt;br /&gt;
                W = &#039;0&#039; is request write, &#039;1&#039; is request read&lt;br /&gt;
                R = LCS RS&lt;br /&gt;
                D = data to write&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8008 - $8009&lt;br /&gt;
name = IRQ&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                8 -----------HADTT IRQ MSK&lt;br /&gt;
                9 -----------HADTT IRQ MEMORY&lt;br /&gt;
                &lt;br /&gt;
                TT = Timer 2/1 IRQ&lt;br /&gt;
                D  = Audio DAC FIFO run low&lt;br /&gt;
                A  = Audio ADC FIFO run full&lt;br /&gt;
                H  = HCORE has data&lt;br /&gt;
                &lt;br /&gt;
write                  fedcba9876543210&lt;br /&gt;
                8 -----------HADTT IRQ MSK&lt;br /&gt;
                9 -----------HADTT IRQ MEMORY&lt;br /&gt;
                &lt;br /&gt;
                TT = Timer 2/1 IRQ&lt;br /&gt;
                D  = Audio DAC FIFO run low&lt;br /&gt;
                A  = Audio ADC FIFO run full&lt;br /&gt;
                H  = HCORE has data&lt;br /&gt;
                &lt;br /&gt;
description:&lt;br /&gt;
&lt;br /&gt;
                IRQ MSK is used to enable given interrupts (for example D = &#039;1&#039; then Audio DAC irq will be used)&lt;br /&gt;
                IRQ MEMORY reflect after interrupt which interrupt is the source (for example TT = &#039;01&#039; then Timer 1 made this interrupt)&lt;br /&gt;
                &lt;br /&gt;
                You should/have to clear the given interrupt bit in IRQ MEMORY before leaving interrupt service routine.&lt;br /&gt;
                        &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $800A - $800F&lt;br /&gt;
name = TIMERS&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                A DDDDDDDDDDDDDDDD Timer 1 low&lt;br /&gt;
                B DDDDDDDDDDDDDDDD Timer 1 high&lt;br /&gt;
                C ----------------&lt;br /&gt;
                D DDDDDDDDDDDDDDDD Timer 2 low&lt;br /&gt;
                E DDDDDDDDDDDDDDDD Timer 2 high&lt;br /&gt;
                F ----------------&lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                A DDDDDDDDDDDDDDDD Timer 1 low  (set before timer 1 high)&lt;br /&gt;
                B DDDDDDDDDDDDDDDD Timer 1 high &lt;br /&gt;
                C ------------CLSR&lt;br /&gt;
                D DDDDDDDDDDDDDDDD Timer 2 low  (set before timer 2 high)&lt;br /&gt;
                E DDDDDDDDDDDDDDDD Timer 2 high&lt;br /&gt;
                F ------------CLSR&lt;br /&gt;
                &lt;br /&gt;
                C = Capture counter value for read (copy current counter value to $A/B $D/E)&lt;br /&gt;
                L = Enable Auto Reload Value (after counter value runs to 0 next value is $A/B $D/E)&lt;br /&gt;
                S = Stop timer&lt;br /&gt;
                R = Start timer (will do a Autoreload from $A/B $D/E)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8010 - $802F&lt;br /&gt;
name = VIDEO&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                10 00000DDDDDDDDDDD current HCount (11..0)&lt;br /&gt;
                11 000000DDDDDDDDDD current VCount (10..0)&lt;br /&gt;
                12 ---------------H Hit of programmed VCOUNT&lt;br /&gt;
                13 ---------------- &lt;br /&gt;
                14 ---------------- &lt;br /&gt;
                15 ----------------&lt;br /&gt;
                16 ----------------&lt;br /&gt;
                17 ---------------- &lt;br /&gt;
                18 ---------------- &lt;br /&gt;
                19 ----------------&lt;br /&gt;
                1a ----------------&lt;br /&gt;
                1b ---------------- &lt;br /&gt;
                1c ---------------- &lt;br /&gt;
                1d ----------------&lt;br /&gt;
                1e ----------------&lt;br /&gt;
                1f ---------------- &lt;br /&gt;
                20 ---------------- &lt;br /&gt;
                21 ----------------                &lt;br /&gt;
                22 ----------------&lt;br /&gt;
                23 ---------------- &lt;br /&gt;
                24 ---------------- &lt;br /&gt;
                25 ----------------&lt;br /&gt;
                26 ----------------&lt;br /&gt;
                27 ---------------- &lt;br /&gt;
                28 ---------------- &lt;br /&gt;
                29 ----------------&lt;br /&gt;
                2a ----------------&lt;br /&gt;
                2b ---------------- &lt;br /&gt;
                2c ---------------- &lt;br /&gt;
                2d ----------------&lt;br /&gt;
                2e ----------------&lt;br /&gt;
                2f ---------------- &lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                10 ---------------D VIDEO ON if &#039;1&#039;&lt;br /&gt;
                11 ------DDDDDDDDDD HSYNC&lt;br /&gt;
                12 ------DDDDDDDDDD HSTART&lt;br /&gt;
                13 ------DDDDDDDDDD HMEMSTART&lt;br /&gt;
                14 ------DDDDDDDDDD HSTOP &lt;br /&gt;
                15 ------DDDDDDDDDD HTOTAL&lt;br /&gt;
                16 -------DDDDDDDDD VSYNC&lt;br /&gt;
                17 -------DDDDDDDDD VSTART&lt;br /&gt;
                18 -------DDDDDDDDD VSTOP&lt;br /&gt;
                19 -------DDDDDDDDD VTOTAL&lt;br /&gt;
                1a DDDDDDDDDDDDDDDD LINE CACHE ADDRESS ADD LOW&lt;br /&gt;
                1b DDDDDDDDDDDDDDDD LINE CACHE ADDRESS ADD HIGH &lt;br /&gt;
                1c ---------------- LINE CACHE LATCH VALUE&lt;br /&gt;
                1d -------DDDDDDDDD LINE CACHE START ADDRESS (Pixel offset)&lt;br /&gt;
                1e --------DDDDDDDD HITVCOUNT (see description)&lt;br /&gt;
                1f ---------------- &lt;br /&gt;
                20 ------DDDDDDDDDD HLOADSTART&lt;br /&gt;
                21 ------DDDDDDDDDD HLOADSTOP                &lt;br /&gt;
                22 -------DDDDDDDDD VLOADSTART&lt;br /&gt;
                23 -------DDDDDDDDD VLOADSTOP&lt;br /&gt;
                24 -------DDDDDDDDD VLOADNEXT&lt;br /&gt;
                25 DDDDDDDDDDDDDDDD EXTERNAL MEMORY START ADDRESS (low)&lt;br /&gt;
                26 DDDDDDDDDDDDDDDD EXTERNAL MEMORY START ADDRESS (high)&lt;br /&gt;
                27 DDDDDDDDDDDDDDDD EXTERNAL MEMORY LINE OFFSET (low)&lt;br /&gt;
                28 DDDDDDDDDDDDDDDD EXTERNAL MEMORY LINE OFFSET (high)&lt;br /&gt;
                29 --------------DD MEMORY Convertion MODE&lt;br /&gt;
                2a ---------------- LATCH MEMORY CONFIG&lt;br /&gt;
                2b ---------------- &lt;br /&gt;
                2c ---------------- &lt;br /&gt;
                2d ----------------&lt;br /&gt;
                2e ----------------&lt;br /&gt;
                2f ----------------                                 &lt;br /&gt;
                &lt;br /&gt;
        HITVCOUNT = Programmable VCOUNT if this Value is written $12 bit 0 is set to &#039;1&#039; if VCOUNT is equal to this value&lt;br /&gt;
                  $12 bit 0 is cleared at write to this register&lt;br /&gt;
&lt;br /&gt;
        EXTERNAL MEMORY LINE OFFSET = will be add after every loaded line (for non interleaved video setup)&lt;br /&gt;
        &lt;br /&gt;
        MEMORY Convertion MODE = defines the format of data converted from external memory (ever 32Bit fetch) to line cache&lt;br /&gt;
        &lt;br /&gt;
                00 = X8 R8 G8 B8                       (32 Bit = (8 Bit for Red/Gree/Blue))&lt;br /&gt;
                01 = R5 R6 R5 R5 R6 R5                 (2 * 16 Bit = (5 Bit for Red/Blue and 6 Bit for Green))&lt;br /&gt;
                10 = X1 R5 R5 X1 R5 R5 R5 R5         (2 * 16 Bit = (5 Bit for Red/Gree/Blue))&lt;br /&gt;
                11 = X4 R4 R4 R4 X4 R4 R4 R4          (2 * 16 Bit = (4 Bit for Red/Gree/Blue))&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8030 - $8031&lt;br /&gt;
name = PS/2 port a/b&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                30 -----FWVDDDDDDDD        port A&lt;br /&gt;
                31 -----FWVDDDDDDDD        port B&lt;br /&gt;
                &lt;br /&gt;
                D = PS/2 DATA (Scan Code) valid if A = &#039;1&#039;&lt;br /&gt;
                V = Data valid&lt;br /&gt;
                W = Write FIFO not full&lt;br /&gt;
                F = all writes finished (Fifo with 16 entries)&lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
                note: wait 1 cycle after read/write request before read&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                30 ------WADDDDDDDD        port A&lt;br /&gt;
                31 ------WADDDDDDDD        port B&lt;br /&gt;
                &lt;br /&gt;
                D = PS/2 DATA to write&lt;br /&gt;
                A = get next scan code (read 2 cycles after this from $30/$31)&lt;br /&gt;
                W = Write data to PS/2 device&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8032 - $8033&lt;br /&gt;
name = I2C port a/b&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                30 ------------D---        port A (eeprom on DE2-115)&lt;br /&gt;
                31 ------------D---        port B (audio/video in on DE2-115)&lt;br /&gt;
                &lt;br /&gt;
                D = data in from port A/B&lt;br /&gt;
                &lt;br /&gt;
write                   fedcba9876543210&lt;br /&gt;
                30 ----EEE------ICD        port A&lt;br /&gt;
                31 ----EEE------ICD        port B&lt;br /&gt;
                &lt;br /&gt;
                D = data out value&lt;br /&gt;
                C = clock out value&lt;br /&gt;
                I = direction of data (&#039;0&#039; = in / &#039;1&#039; = out)&lt;br /&gt;
                &lt;br /&gt;
                EEE = is write enable for ICD&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8034 - $803b&lt;br /&gt;
name = AUDIO&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                34 DDDDDDDDDDDDDDDD ADC data left high        &lt;br /&gt;
                35 --------DDDDDDDD ADC data left low                &lt;br /&gt;
                36 DDDDDDDDDDDDDDDD ADC data right high                &lt;br /&gt;
                37 --------DDDDDDDD ADC data right low        &lt;br /&gt;
                38 ----------------&lt;br /&gt;
                39 ----------------&lt;br /&gt;
                3a ----------------&lt;br /&gt;
                3b ----------------&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                   fedcba9876543210&lt;br /&gt;
                34 DDDDDDDDDDDDDDDD DAC data left high        &lt;br /&gt;
                35 --------DDDDDDDD DAC data left low                &lt;br /&gt;
                36 DDDDDDDDDDDDDDDD DAC data right high                &lt;br /&gt;
                37 --------DDDDDDDD DAC data right low        &lt;br /&gt;
                38 AAAAAAAADDDDDDDD ADAC Ctrl / Data&lt;br /&gt;
                39 --------DDDDDDDD DAC interrupt generate if lower &lt;br /&gt;
                3a --------DDDDDDDD ADC interrupt generate if higher&lt;br /&gt;
                3b ---------------- ADC recive values (after 2 cycles available in $34-$37)&lt;br /&gt;
                &lt;br /&gt;
                ADAC Ctrl / Data = configure internal ADC/DAC controller&lt;br /&gt;
                &lt;br /&gt;
                Adr 76543210&lt;br /&gt;
                0   -------- ignore&lt;br /&gt;
                1   -------E enable DAC&lt;br /&gt;
                2   ----CCCC DAC push counter (96KHz at 0, 48KHz at 1, 32KHz at 2 ....)&lt;br /&gt;
                3   -------E enable ADC&lt;br /&gt;
                4   ----CCCC ADC pull counter (96KHz at 0, 48KHz at 1, 32KHz at 2 ....)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $803c - $8044&lt;br /&gt;
name = HCORE CTRL/IO (in experimental state)                                &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Videosetup im Detail ===&lt;br /&gt;
&lt;br /&gt;
[[Datei:16 32Bit Computer Konsole Uctrl video setup.png|miniatur|Video Setup]]&lt;br /&gt;
&lt;br /&gt;
UCore und UCtrl (also auch der Videokontoller) haben eine Taktfrequenz von 106,481 MHz, mit dieser Frequenz ist es möglich eine maximale Auflösung von 1440 x 900 Bildpunkten bei 60 Hz zu programmieren. Da diese Auflösung in vielen Fällen zu hoch ist, bzw. die Performance für eine flüssige Bildberechnung nicht immer ausreicht, kann ein interner Zeilen-Cache so programmiert werden, dass er nur eine bestimmte Anzahl an Pixeln pro Zeile ausgibt (H-Skaliert) und nur eine definierte Anzahl von Zeilen neu geladen wird (V-Skaliert).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Wie üblich können (siehe Bild), HSYNC, HSTART etc. frei programmiert werden. Als Quelle für die Bilddaten kann der SDRAM oder SRAM benutzt werden (siehe EXTERNAL MEMORY START ADDRESS).&lt;br /&gt;
Das Farbformat kann zwischen einem 32 Bit Format (8Bit für R/G/B) und drei 16 Bit Formaten gewählt werden (siehe MEMORY Convertion MODE).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Support von Bitplanes oder Tiled-Grafiken gibt es nicht (da nicht notwendig, weil UCore/HCores schnell genug).&lt;br /&gt;
&lt;br /&gt;
Beispiel Video setup 360x225 4R4G4B Mode ($d0000000 ist Quelle (SDRAM)):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* setupVideo&lt;br /&gt;
;*&lt;br /&gt;
&lt;br /&gt;
setupVideo&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,videoDefault		;source&lt;br /&gt;
	movei	r1,UcTimer2Ctrl		;dest-1&lt;br /&gt;
	moveih	r0,&amp;gt;videoDefault&lt;br /&gt;
	moveih	r1,&amp;gt;UcTimer2Ctrl			&lt;br /&gt;
	movei	r2,26			;27-1&lt;br /&gt;
	&lt;br /&gt;
setupVideoLoop&lt;br /&gt;
&lt;br /&gt;
	rqldi	r0,0&lt;br /&gt;
	addi	r0,1&lt;br /&gt;
	addi	r1,1&lt;br /&gt;
	ld	r3&lt;br /&gt;
	subi	r2,1&lt;br /&gt;
	brts	setupVideoLoop&lt;br /&gt;
	st	r1,r3	;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
		&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
	&lt;br /&gt;
;*********************************************************************&lt;br /&gt;
;* data&lt;br /&gt;
;*********************************************************************&lt;br /&gt;
	&lt;br /&gt;
videoDefault		;AD NAME					&lt;br /&gt;
	&lt;br /&gt;
	word	$0001	;10 VIDEO_ON					&lt;br /&gt;
	word	$0097	;11 HSYNC (D = 11 .. 0)				&lt;br /&gt;
	word	$017f	;12 HSTART (D = 11 .. 0)			&lt;br /&gt;
	word	$017d	;13 HMEMSTART (D = 11 .. 0)			&lt;br /&gt;
	word	$071f	;14 HSTOP (D = 11 .. 0)				&lt;br /&gt;
	word	$076f	;15 HTOTAL (D = 11 .. 0)			&lt;br /&gt;
	word	$0002	;16 VSYNC (D = 10 .. 0)				&lt;br /&gt;
	word	$001e	;17 VSTART (D = 10 .. 0)			&lt;br /&gt;
	word	$03a2	;18 VSTOP  (D = 10 .. 0)			&lt;br /&gt;
	word	$03a3	;19 VTOTAL  (D = 10 .. 0)			&lt;br /&gt;
	word	$0000	;1a LC ADDER LOW				&lt;br /&gt;
	word	$0040	;1b LC ADDER HIGH				&lt;br /&gt;
	word	$0000	;1c LC ADDER LATCH				&lt;br /&gt;
	word	$0000	;1d LC START (10 .. 0) Pixeloffset		&lt;br /&gt;
	word	$0000	;1e						&lt;br /&gt;
	word	$0000	;1f						&lt;br /&gt;
	word	$0008	;20 HLOADSTART 					&lt;br /&gt;
	word	$00bc	;21 HLOADSTOP					&lt;br /&gt;
	word	$001e	;22 VLOADSTART 					&lt;br /&gt;
	word	$03a2	;23 VLOADSTOP 					&lt;br /&gt;
	word	$0004	;24 VLOADNEXT					&lt;br /&gt;
	word	$0000	;25 MEM_STARTADR_store low			&lt;br /&gt;
	word	$d000	;26 MEM_STARTADR_store high			&lt;br /&gt;
	word	$0000	;27 MEM_LINEOFFSET_store low			&lt;br /&gt;
	word	$0000	;28 MEM_LINEOFFSET_store high			&lt;br /&gt;
	word	$0002	;29 MEM_MODE_store 				&lt;br /&gt;
	word	$0000	;2a LATCH MEM_STARTADR/LINEOFFSET/MODE		&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Audiosetup im Detail ===&lt;br /&gt;
&lt;br /&gt;
Da das DE-115 einen Wolfson WM8731 besitzt unterteilt sich die Ansteuerung für die Audio Ein/Ausgabe in zwei Teile.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Erste ist die Konfiguration der WM8731, hierfür wird I2C Port B von UCTRL verwendet.&amp;lt;br&amp;gt;&lt;br /&gt;
Um die Konfiguration einfach zu halten sind Komponenten zur Initialisierung über I2C vorhanden (initAudio), es muss nur eine Tabelle mit den gewünschten Einstellungen übergeben werden (Register, Wert siehe WM8731 Registerbeschreibung).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Setup:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
audioDefault&lt;br /&gt;
	&lt;br /&gt;
	;&lt;br /&gt;
				;A =  8 7654 3210&lt;br /&gt;
	.data   $9,$0000	;9 =  0 0000 0000 	(inactivate interface)&lt;br /&gt;
	.data	$0,$0097	;0 =  0 1001 0111	;left line in mute&lt;br /&gt;
	.data	$1,$0097	;1 =  0 1001 0111	;right line in mute&lt;br /&gt;
	.data	$2,$006e	;2 =  0 0111 1001	;+6db left out&lt;br /&gt;
	.data	$3,$006e	;3 =  0 0111 1001	;0db right out&lt;br /&gt;
	.data	$4,$0012	;4 =  0 0001 0010	;0=0 mic boost off;&lt;br /&gt;
							;1=1 enable line input mute&lt;br /&gt;
							;2=1 line input to adc&lt;br /&gt;
							;3=0 disable bypass&lt;br /&gt;
							;4=1 DAC select&lt;br /&gt;
							;5=0 side tone disable&lt;br /&gt;
							;76=0 -6db sidetone						&lt;br /&gt;
	.data	$5,$0000	;5 =  0 0000 0000	;DAC soft Mute off, no Filer&lt;br /&gt;
	.data	$6,$0067	;6 =  0 0110 0111 	;DAC Power, Output Power, Device Power on&lt;br /&gt;
	.data	$7,$0009	;7 =  0 0000 1001 	;left justified, 24 bit&lt;br /&gt;
	.data	$8,$001e	;8 =  0 0001 1110	;0=0 normal mode&lt;br /&gt;
							;1=1 bosr (384/192)&lt;br /&gt;
							;5432=0111 96khz&lt;br /&gt;
							;78=00 no clk dividing	&lt;br /&gt;
	.data   $9,$0001	;9 =  0 0000 0001 	(activate interface)&lt;br /&gt;
	.data	$ff,$0000	;stop&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Senden und Empfangen der Audio Daten wird über UCTRL Register $34 bis $3b bedient.&amp;lt;br&amp;gt;&lt;br /&gt;
Für ADC und DAC gibt es jeweils für den linken &amp;amp; rechten Kanal je 24 Bit Daten zum empfangen/senden. &amp;lt;br&amp;gt;&lt;br /&gt;
ADC/DAC besitzen je einen 256 Wort (2 * 24 Bit) großen Queue, im Register $39 bzw. $3a können die die Unter/Überlaufwerte, welche zu einem Interrupt führen, konfiguriert werde.&amp;lt;br&amp;gt;&lt;br /&gt;
D.h. für einen Audioausgabe konfiguriert man z.B. den DAC Queue auf den Wert 128 um bei erreichen (kleiner als) einen Interrupt auszulösen (in welchen der Queue befüllt wird).&amp;lt;br&amp;gt;&lt;br /&gt;
Dadurch ist eine unterbrechungsfreie Wiedergabe/Aufnahme möglich ohne (je nach Einstellung) zu viele Interrupts auszulösen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die ADC/DAC Komponente in UCTRL kann über Register $38 (ADAC Ctrl) konfiguriert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Die oberen 8 Bit des Datenworts bestimmen die Adresse, die unteren 8 Bit die Daten.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCTRL Audio Config:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name			address		876543210	comment&lt;br /&gt;
&lt;br /&gt;
nop			0		XXXXXXXXX	do nothing&lt;br /&gt;
ctrl			1		XXXXXXXXE	E = enable audio (default off)&lt;br /&gt;
set fifo read count	2		XXXXXXCCC	96KHz/C = fread [0..15]&lt;br /&gt;
set fifo write count	3		XXXXXXCCC	96KHz/C = fwrite [0..15]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Hier sollte vor der eigentlich Audio Ausgabe/Aufnahme, der jeweilige Counter für den ADC/DAC gesetzt werden (Counter der bei erreichen von 0 liest/schreibt). Z.B. den Wert 2 um eine 32 KHz Ausgabe einzustellen. Um die Queues zu lesen/schreiben muss noch unter Adresse 1 die Komponente aktiviert werden.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Audioausgabe von zwei 16 Bit Werten (links/rechts).&lt;br /&gt;
&amp;lt;br&amp;gt;	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	;r2 Audiobase $34&lt;br /&gt;
	;r1 = Wert für L, r4 = Wert für R&lt;br /&gt;
&lt;br /&gt;
	movei	r3,0&lt;br /&gt;
	stinc	r2,r1	;dac left high = value&lt;br /&gt;
	movei	r7,$1&lt;br /&gt;
	stinc	r2,r3	;dac left low = 0&lt;br /&gt;
	moveih	r7,$1&lt;br /&gt;
	stinc	r2,r4	;dac right high = value&lt;br /&gt;
	nop&lt;br /&gt;
	stinc	r2,r3	;dac right low = 0&lt;br /&gt;
	nop&lt;br /&gt;
	st	r2,r7	;dac address/ctrl = $0101	;ctrl = enable audio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Homepage ==&lt;br /&gt;
&lt;br /&gt;
http://www.goldmomo.de&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Goldmomo_endlos_GfxExtension.png&amp;diff=83060</id>
		<title>Datei:Goldmomo endlos GfxExtension.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Goldmomo_endlos_GfxExtension.png&amp;diff=83060"/>
		<updated>2014-05-19T12:38:14Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Goldmomo_endlos_ModPlayer.png&amp;diff=83059</id>
		<title>Datei:Goldmomo endlos ModPlayer.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Goldmomo_endlos_ModPlayer.png&amp;diff=83059"/>
		<updated>2014-05-19T12:37:59Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Goldmomo_endlos_SpacePilotOfDeath.png&amp;diff=83058</id>
		<title>Datei:Goldmomo endlos SpacePilotOfDeath.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Goldmomo_endlos_SpacePilotOfDeath.png&amp;diff=83058"/>
		<updated>2014-05-19T12:37:37Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Goldmomo_endlos_Sheriff2213.png&amp;diff=83057</id>
		<title>Datei:Goldmomo endlos Sheriff2213.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Goldmomo_endlos_Sheriff2213.png&amp;diff=83057"/>
		<updated>2014-05-19T12:37:11Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: Sheriff2213 auf goldmomo_endlos&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Sheriff2213 auf goldmomo_endlos&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=83055</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=83055"/>
		<updated>2014-05-19T12:29:09Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: /* Videosetup im Detail */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein ‚Computer‘system, das nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses kopiert. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen das vollständig* selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (*FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL benutzt, für Emulation und Tools (Assembler etc.) wird C# mit .NET verwendet.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 benutzt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE) der über einen Memorymapped UCTRL-Komponente vollständigen Zugriff auf die Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Audio Interface (Stereo mit max. 24Bit / 96 KHz) &lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Timer/Counter&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCore = Utility Core) ist der ‚zentrale‘ Prozessor im System, er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist gedacht um einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn für alle meine Demos/Spiele als ‚CPU‘ benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* ‚RISC‘ Design&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In einen experimentellen Zustand befindet sich noch der HCORE Block. Dieser Block enthält mehre (konfigurierbar) 32 Bit Prozessoren die über spezielle Techniken (Hardwaresemaphoren, parallele Sprünge, … ) eine parallele Verarbeitung der Software vereinfachen sollen und die Latenzprobleme bei Multithreading vermeiden. Ich habe bisher ein Demo mit 16 parallel laufenden HCOREs veröffentlicht, alle anderen Demos benutzen diese Cores nicht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Momentane Charakteristiken eines HCOREs sind:&lt;br /&gt;
&lt;br /&gt;
*‚Risc‘ Design &lt;br /&gt;
*7 Stufen Pipeline mit „in order“ und „out of order“ Pfad&lt;br /&gt;
*Instruction Cache (konfigurierbar (momentan 8 Wege mit 64 Worten))&lt;br /&gt;
*32 Bit ALU (Hold to Last Pfad, …) &lt;br /&gt;
*128 GP Register&lt;br /&gt;
*UCtrl/Memory/Semaphoren/… out of order Zugriff&lt;br /&gt;
*…&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
[[Datei:Goldmomo emulator.png|miniatur|rechts|Emulator]]&lt;br /&gt;
Um die Softwareentwicklung (und Debuggen) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Register, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (auch in Emulator integriert), ein Compiler existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/2n1o8dfium4bdgi/TK_Da_o4rx/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/310121#new&lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= UCORE Programmierung =&lt;br /&gt;
&lt;br /&gt;
UCore (Utility Core) ist ein Eigenimplementierung  eines 16 Bit Prozessor. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Grundlegende Charakteristiken:&lt;br /&gt;
&lt;br /&gt;
* sechsstufige Pipeline&lt;br /&gt;
* 8 Generalpurpose Registern&lt;br /&gt;
* 32 Bit Register für externe Adressen&lt;br /&gt;
* T-Bit um Bedingungen zu verarbeiten&lt;br /&gt;
* Status Register&lt;br /&gt;
* Vector Base Register&lt;br /&gt;
* 32 Bit Multiplikation Register (High-Result)&lt;br /&gt;
* separater Stackpointer&lt;br /&gt;
* interne Speicher in dem Code/Daten liegen&lt;br /&gt;
* externer Speicherzugriff (32Bit-Adressraum) möglich&lt;br /&gt;
* die Datenwortbreite beträgt immer 16 Bit (es gibt keine Bytes)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCore unterscheidet sich einigen Teilen von einem &#039;normalen&#039; Prozessor (RISC-)Design.&lt;br /&gt;
Die Gründe bzw. Ziele welche verfolgt wurden, ware eine möglichst hohe Taktrate und ein möglichst geringer Benutzung von Hardwareressourcen, aber dennoch eine hohe Verarbeitungsgeschwindigkeit.&lt;br /&gt;
Dadurch ergeben sich einige Besonderheiten die bei der Programmierung beachtet werden müssen (siehe Registerzugriffe, Branch/Jump Delayslots, Request/Load Zugriffe).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pipeline ===&lt;br /&gt;
&lt;br /&gt;
Wie gesagt hat dieser Core eine sechsstufige Pipeline:&lt;br /&gt;
&lt;br /&gt;
# Prepare Fetch &lt;br /&gt;
# Fetch &lt;br /&gt;
# Decode &lt;br /&gt;
# Read Register &lt;br /&gt;
# Execute &lt;br /&gt;
# Write Register (hat einen Bypass zu Stufe 4) &lt;br /&gt;
&lt;br /&gt;
Jede Instruktion wird in einem Cycle ausgeführt, nur der externe Speicherzugriff (nur Daten) kann einen Stall (Stillstand) der Pipeline verursachen.&lt;br /&gt;
&lt;br /&gt;
== Interne Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
In meinem System wird die folgende interne Speichermap verwendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$0000 code / data memory&lt;br /&gt;
*     16384 * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$3fff&lt;br /&gt;
$4000 code / data memory MIRROR&lt;br /&gt;
*     &lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$7fff&lt;br /&gt;
$8000 ctrl / memory			StackPointer start at $8000 on reset&lt;br /&gt;
*     XXXX * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$XXXX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Reset-Vektor befindet sich an Adresse 0, der Stackpointer an Adresse $8000. &lt;br /&gt;
Der Interruptvektor an Adresse $10 (sollte nach dem Reset an die benötigte Position verschoben werden).&lt;br /&gt;
Ab Adresse $8000 wird die Komponente UCtrl in den Adressraum ‚gemappt‘ (diese Komponente enthält Register für externe Hardware Peripherie etc.).&lt;br /&gt;
&lt;br /&gt;
== externe Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
Über den &#039;externen&#039; Datenbus kann auf folgende Komponenten zugegriffen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$a000 0000 - $a000 001f SDCard-Controller&lt;br /&gt;
$d000 0000 - $d3ff ffff SDRAM&lt;br /&gt;
$e000 0000 - $e03f ffff FLASH&lt;br /&gt;
$f000 0000 - $f00f ffff SRAM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei den meisten meiner Programme wird ein Standard-Programm aus dem FLASH-Speicher gelesen, welches einen Speichertest ausführt und auf das Einlegen einer SD-Karte mit dem zuladenden Programm wartet.&lt;br /&gt;
&lt;br /&gt;
== Opcodes/Operanten ==&lt;br /&gt;
&lt;br /&gt;
UCore hat keine &#039;RISC&#039;-Typischen Befehlssatz (viele Befehle, aber geringe Komplexität).&lt;br /&gt;
 &lt;br /&gt;
Da ein Instruktions-Wort nur eine Breite von 16 Bit hat, können nur bedingte Mengen an Operanten verwendet werden. Um jedoch die Programmierung flexibler zu gestalten, haben viele Opcodes mehrere Arten von Operanten. &lt;br /&gt;
Für die Ausführungseinheit ergibt sich dadurch keine Ressourcenveränderung, da der Decoder nur die Opcodes/Operanten in ein internes einheitliches Format auflöst.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Operanten Formate ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dc,imm8&lt;br /&gt;
 dc,db,da&lt;br /&gt;
 dc,db,imm3&lt;br /&gt;
 imm12&lt;br /&gt;
 db,da&lt;br /&gt;
 imm6&lt;br /&gt;
 da&lt;br /&gt;
 kein Operant&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Opcode / Operante(n) / Beschreibung ==== &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
movei     	dc,imm8		dc = imm&lt;br /&gt;
moveih    	dc,imm8		dc[15..8] = imm &amp;lt;&amp;lt; 8 | dc[7..0]&lt;br /&gt;
addi      	dc,imm8		dc = dc + imm&lt;br /&gt;
subi      	dc,imm8		dc = dc - imm&lt;br /&gt;
lsri      	dc,imm8		dc = dc &amp;gt;&amp;gt; imm&lt;br /&gt;
asri      	dc,imm8		dc = ((signed)dc) &amp;gt;&amp;gt; imm&lt;br /&gt;
muli      	dc,imm8		dc = dc * imm&lt;br /&gt;
cmpeqi    	dc,imm8		t = set if dc == imm else cleared&lt;br /&gt;
cmploi    	dc,imm8		t = set if dc &amp;lt; imm else cleared&lt;br /&gt;
cmplosi   	dc,imm8		t = set if  (signed)dc &amp;lt; (signed) imm else cleared&lt;br /&gt;
gpci      	dc,imm8		dc = pc + imm&lt;br /&gt;
jmpi      	dc,imm8		pc = dc + imm&lt;br /&gt;
extri     	dc,imm8		t = bit #imm of dc&lt;br /&gt;
rqldi     	dc,imm8		request (internal) mem; address = dc + imm&lt;br /&gt;
getsp     	dc,imm8		dc = sp + imm&lt;br /&gt;
dexti     	imm11		store imm as extension for next instruction&lt;br /&gt;
&lt;br /&gt;
add		dc,db,da	dc = db + da&lt;br /&gt;
sub     	dc,db,da	dc = db - da&lt;br /&gt;
lsr     	dc,db,da	dc = db &amp;gt;&amp;gt; da&lt;br /&gt;
asr     	dc,db,da	dc = ((signed)db) &amp;gt;&amp;gt; da&lt;br /&gt;
mul     	dc,db,da	dc = db * da&lt;br /&gt;
addt    	dc,db,da	dc = db + da + t&lt;br /&gt;
subt    	dc,db,da	dc = db - da - t&lt;br /&gt;
muls    	dc,db,da	dc = db * da&lt;br /&gt;
movets  	dc,db,da	dc = db if t = set else da&lt;br /&gt;
and     	dc,db,da	dc = db &amp;amp; da&lt;br /&gt;
or      	dc,db,da	dc = db | da&lt;br /&gt;
xor     	dc,db,da	dc = db ^ da&lt;br /&gt;
bic     	dc,db,da	dc = db &amp;amp; ~da&lt;br /&gt;
&lt;br /&gt;
addqi		dc,db,imm3	dc = db + imm&lt;br /&gt;
subqi   	dc,db,imm3	dc = db - imm&lt;br /&gt;
lsrqi   	dc,db,imm3	dc = db &amp;gt;&amp;gt; imm&lt;br /&gt;
asrqi   	dc,db,imm3	dc = ((signed)db) &amp;gt;&amp;gt; imm&lt;br /&gt;
mulqi   	dc,db,imm3	dc = db * imm3&lt;br /&gt;
addtqi  	dc,db,imm3	dc = db + imm + t&lt;br /&gt;
subtqi  	dc,db,imm3	dc = db - imm - t&lt;br /&gt;
edrqldi 	db,da,imm3	request (external) mem; address = (db:da) + imm3&lt;br /&gt;
&lt;br /&gt;
br		imm12		pc = pc + signed(imm)&lt;br /&gt;
brts		imm12		pc = pc + signed(imm) if t is set&lt;br /&gt;
brtc		imm12		pc = pc + signed(imm) if t is cleared&lt;br /&gt;
	             &lt;br /&gt;
cmpeq		db,da		t = set if db == da else cleared		&lt;br /&gt;
cmplo   	db,da           t = set if db &amp;lt; da else cleared&lt;br /&gt;
cmplos  	db,da           t = set if  (signed)db &amp;lt; (signed) da else cleared&lt;br /&gt;
esadr   	db,da		esadr = db:da&lt;br /&gt;
swp     	db,da		db = da[7..0]:da[15..8] &lt;br /&gt;
swptc   	db,da		db = da[7..0]:da[15..8] if t = set else da&lt;br /&gt;
st      	db,da		imem[db] = da&lt;br /&gt;
stinc   	db,da		imem[db] = da; db = db + 1&lt;br /&gt;
bffo    	db,da		db is first bit that is 1 found in da (from MSB to LSB)&lt;br /&gt;
bset    	db,da		db = db | 1 &amp;lt;&amp;lt; da&lt;br /&gt;
bclr    	db,da		db = db &amp;amp; ~ (1 &amp;lt;&amp;lt; da)&lt;br /&gt;
cmple   	db,da		t = set if db &amp;lt;= da else cleared&lt;br /&gt;
cmples  	db,da		t = set if  (signed)db &amp;lt;= (signed) da else cleared&lt;br /&gt;
rqld    	db,da		request (internal) mem; address = db + da&lt;br /&gt;
extb    	db,da		db = da byte to word singed extended&lt;br /&gt;
stwo    	db,da		imem[db + STORE_OFFSET] = da&lt;br /&gt;
andts   	db,da		db = db &amp;amp; da if t = set else da&lt;br /&gt;
orts    	db,da           db = db | da if t = set else da&lt;br /&gt;
xorts   	db,da           db = db ^ da if t = set else da&lt;br /&gt;
bicts   	db,da           db = db &amp;amp; ~da if t = set else da&lt;br /&gt;
lsrts   	db,da		db = db &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
asrts   	db,da           db = ((signed)db) &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
mults   	db,da           db = db * da if t = set else da&lt;br /&gt;
mulsts  	db,da		db = (signed)db * (signed)da if t = set else da&lt;br /&gt;
&lt;br /&gt;
erqldi		imm6		request (external) mem; address = esadr + imm	&lt;br /&gt;
ssto		imm6		STORE_OFFSET = imm&lt;br /&gt;
udivinit	imm6		udivqoutient = 0; udivrest = 0; udivbitcounter = imm&lt;br /&gt;
&lt;br /&gt;
eld		da		da = requested value from external memory&lt;br /&gt;
push            da		sp = sp – 1; imem[sp] = da&lt;br /&gt;
gmulhi          da		da = multiply result [31..15] from last multiplication&lt;br /&gt;
ld/pop          da		da = requested value from internal memory&lt;br /&gt;
poparqp         da		da = requested value from internal memory; request in internal memory adr = sp; sp = sp + 1&lt;br /&gt;
neg             da		da = 0 - da&lt;br /&gt;
udivgq          da		get division qoutinent&lt;br /&gt;
udivgr          da		get division remainder&lt;br /&gt;
udivgqh         da		get division qoutinent high [31 ..16]&lt;br /&gt;
udivgrh         da              get division remainder high [31 ..16]&lt;br /&gt;
udivsdd         da		set division divident &lt;br /&gt;
udivsdv         da		set division divider&lt;br /&gt;
udivsddh        da		set division divident high [31 ..16]&lt;br /&gt;
udivsdvh        da		set division divider  high [31 ..16]&lt;br /&gt;
erqld           da		request (external) mem; address = esadr + da&lt;br /&gt;
setsp           da		sp = da&lt;br /&gt;
erqldb          da		request (external) mem; address = esadr + da / 2&lt;br /&gt;
jmpts           da		pc = da if t = set&lt;br /&gt;
jmptc           da		pc = da if t = cleared&lt;br /&gt;
negts           da		da = 0 - da if t = set else da&lt;br /&gt;
&lt;br /&gt;
rqpop				internal memory request address = sp; sp = sp + 1&lt;br /&gt;
cli				disable interrupts&lt;br /&gt;
sei				enable interrupts&lt;br /&gt;
rti				pc = pc_before interrput&lt;br /&gt;
tnt				t = not t&lt;br /&gt;
vtt				t = v (overflow/underflow wrom add/sub)			&lt;br /&gt;
epushsadrl			sp = sp – 1; imem[sp] = esadr[15..0]&lt;br /&gt;
epushsadrh			sp = sp – 1; imem[sp] = esadr[31..16]&lt;br /&gt;
epopsadrl			esadr[15..0] = requested value from internal memory&lt;br /&gt;
epopsadrh			esadr[31..16] = requested value from internal memory&lt;br /&gt;
udivstep			performe one division step &lt;br /&gt;
nop				do nothing&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Registerzugriffe ==&lt;br /&gt;
&lt;br /&gt;
Da Register vor der Ausführungseinheit gelesen werden und nach der Ausführungseinheit geschrieben werden, ergibt sich eine Latenz zwischen Register Zugriffen. Der Grund für diese Implementierungsart ist schlicht und einfach um die Performanz zu erhöhen. Als Nebeneffekt entsteht, wie gesagt, eine Latenz. Es bieten sich mehrere Möglichkeiten an, diese Register-‚Hazards‘ in Hardware zu vermeiden (Registerscoring, Renaming, …). Um den Hardware-Implementierung klein und schnell zu halten wird in UCore auf einen Hardwaretest verzichtet. Als Resultat muss der Anwender Registerabhängigkeiten im Programm-Code behandeln.&lt;br /&gt;
Der einzige logische sinnvolle Nachteil ergibt sich in einer RAW (Read after Write) Abhängikeit, da die Latenz hier eine Cycle beträgt. In diesem Fall sollte/muss eine andere Instruktion (z.B. nop) eingefügt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreiben eines Registers und späteres lesen): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae	; &lt;br /&gt;
	nop		;write r0 = ae wird ausgeführt&lt;br /&gt;
	addi	r0,1	;r0 = r0 ($ae) + 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Im einfachsten Fall, sollte eine nop Operation bei solchen Abhängigkeit verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (nicht optimiert mit nop - 6 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	nop&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	nop&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In den meisten Fällen kann man aber andere Operationen als ‚Füllung‘ bei Registerabhängikeiten verwenden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (Optimiert - 4 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um versehentlich programmierte RAW-&#039;Hazards&#039; zu erkennen erzeugt der Assembler Warnungen, ebenfalls kann der Emulator zur Laufzeit diese &#039;Probleme&#039; erkennen.&lt;br /&gt;
Prinzipiell ist es möglich, in gewissen Situationen, RAW-&#039;Hazards&#039; absichtlich zuzulassen (Optimierungen um Register zu sparen), wovon aber im Normalfall abzuraten ist.&lt;br /&gt;
&lt;br /&gt;
== Bedingungen ==&lt;br /&gt;
&lt;br /&gt;
UCore benutzt ein T-Bit (true Bit) um Bedingungen zu beschreiben/verarbeiten. Normalerweise wird dieses Bit von Vergleichsoperationen gesetzt und kann dann von Operationen benutzt werden welche das T-Bit intern verwenden (z.B. bedingte Sprünge).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel:====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	cmpeqi	r0,0		;vergleiche auf r0 gleich 0 wenn wahr da (t=1) ansonsten (t=0)&lt;br /&gt;
	brts	r0IstNull	;springe zu ‚r0IstNull‘ label wenn t set (t=1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist notwendig Register nur dann zu setzen wenn bestimmte Bedingungen eintreten. In diesen Fällen ist es ärgerlich bedingte Sprünge auszuführen, da sie etwas Zeit brauchen (Delay Slots) und den Programmcode unübersichtlich machen.&lt;br /&gt;
Aus diesem Grund, unterstützen einige Befehle eine Bedingte Ausführung (nicht jeder).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	move	r1,123&lt;br /&gt;
	move 	r2,23&lt;br /&gt;
	…&lt;br /&gt;
	cmplo	r0,r1		;r0 &amp;lt; r1&lt;br /&gt;
	movets	r0,r2,r0	;wenn ja r0 = r2 (23) ansonsten r0 = r0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sprünge ==&lt;br /&gt;
&lt;br /&gt;
Ein (bedingter) Sprung benötigt, wie jede andere Instruktion, einen Cycle um ausgeführt zu werden.&lt;br /&gt;
Da UCore keine Branchprediction bzw. keine spekulative Ausführung etc. unterstützt und es auch nicht gewollt ist Opcodes in der Pipeline zu verwerfen, entstehen nach Sprungbefehlen sogenannte &#039;Delay Slots&#039;. Die Anzahl dieser Delay Slots ergeben sich aus der Anzahl der Pipelinestufen vor der Ausführungseinheit (da sie den Programmcounter verändert).&lt;br /&gt;
Kurzum Programlauftechnisch werden Instruktionen in diesen Delay Slots ausgeführt bevor der Sprung in Wirklichkeit ausgeführt wird.&lt;br /&gt;
Die kleinste mögliche Schleife benötigt deshalb fünf Instruktionen für einen Durchlauf.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loop	br	loop		;branch zu loop&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In vielen Fällen können diese Delay Slots sinnvoll genutzt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 1 (nicht optimiert - 8 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,1	;r1 = x parameter&lt;br /&gt;
	movei	r1,7	;r2 = y parameter&lt;br /&gt;
	gpci	r7,2	;r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 1 (optimiert - 6 cycles): ====&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	gpci	r7,2	r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	movei	r0,1	;delay slot	r1 = x parameter&lt;br /&gt;
	movei	r1,7	;delay slot     r2 = y parameter&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 2 (nicht optimiert - 8 * n + 3 cycles -&amp;gt; if n 128 -&amp;gt; total 1027 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127	;r0 = loop counter - 1&lt;br /&gt;
	movei	r1,0	;r1 = Füllwert&lt;br /&gt;
	nop&lt;br /&gt;
	&lt;br /&gt;
loop	st	r1,r6	;imem[r1] = r6&lt;br /&gt;
	addi	r1,1	;r1++&lt;br /&gt;
	subi	r0,1	;r0-- (t clear bei &amp;lt; 0)&lt;br /&gt;
	brts	loop	;branch loop solange t set&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 2 (optimiert - 6 * n + 2 cycles -&amp;gt; if n 128 -&amp;gt; total 770 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127&lt;br /&gt;
	movei	r1,0&lt;br /&gt;
	&lt;br /&gt;
loop	subi	r0,1	;da t später verwendet wird nicht in delay slot benutzen (siehe  Interruptbenutzung)&lt;br /&gt;
	brts	loop&lt;br /&gt;
	st	r1,r6	;delay slot&lt;br /&gt;
	addi	r1,1	;delay slot	&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Speicherzugriffe ==&lt;br /&gt;
&lt;br /&gt;
UCore besitzt keine ‚gewöhnlichen‘ Lesebefehle für interne/externe Speicherzugriffe.&lt;br /&gt;
Um Pipeline-Stalls beim Lesen von Daten zu vermeiden (Latenz zum Speicher), wird eine Lesebefehl in zwei Operationen aufgeteilt.&lt;br /&gt;
Der erste Befehl ist ein &#039;Request&#039;, er teilt dem Core mit von welcher Adresse er etwas lesen soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Der zweite Befehl ist dann der &#039;Load&#039;, er holt sich die angekommenen Daten ab und speichert sie in einem Register.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== interner Speicherzugriff ====&lt;br /&gt;
&lt;br /&gt;
Bei internen Speicherzugriffen ist die Latenz zwischen Request und Load statisch (3 Cycles), bei externen Zugriff variable (hier wird im Fall eines Load ohne vorhandene Daten ein Stall ausgelöst).&lt;br /&gt;
&lt;br /&gt;
Mit den Opcodes rqld (request load) und ld (load) kann vom internen Speicher gelesen werden.&lt;br /&gt;
Da die Daten erst zwei Operationen nach dem Request verfügbar sind, muss hier etwas anderes ausgeführt werde (z.B. nop).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0	;send load to address (r0+0)&lt;br /&gt;
	nop		;data send to memory&lt;br /&gt;
	nop		;data will read&lt;br /&gt;
	ld	r1	;readed data to r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Da der interne Speicher immer innerhalb von einem Cycles antwortet und die Latenz durch Pipelinestufen entsteht, kann man bei internen Speicherzugriff bis zu drei Request hintereinander verwenden.&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0&lt;br /&gt;
	rqld	r0,1&lt;br /&gt;
	rqld	r0,2&lt;br /&gt;
	ld	r1	;r1 &amp;lt;- internal_mem[r0+0]&lt;br /&gt;
	ld	r2	;r2 &amp;lt;- internal_mem[r0+1]&lt;br /&gt;
	ld	r3	;r3 &amp;lt;- internal_mem[r0+2]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Bei Schreibzugriffen wird wie bei anderen Prozessoren ein Store-Kommando verwendet.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti	$80	;imm exted&lt;br /&gt;
	move	r4,$01	;r4 = $8001&lt;br /&gt;
	move	r0,12	;r0 = 12&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	st	r0,r4	;imem[r4] = r0; $8001 = 12&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
Da ein &#039;st&#039;ore Befehl nur einen Register als Zieladresse benutzt, ist es vielen Fällen ärgerlich diesen bei mehrfachen Schreiben zu verändern. Um bei diesem Fall Abhilfe zu verschaffen wurde der Befehl ssto (Set Store Offset) und stwo (Store with Offset) eingeführt. Mit ssto kann ein Offset für stwo gesetzt werden, d.h. der Wert der mit ssto gesetzt wird auf die Zieladresse von stwo addiert.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	stwo 1&lt;br /&gt;
	ssto r0,r7 ;imem[r7+1] = r0&lt;br /&gt;
	stwo 2&lt;br /&gt;
	ssto r1,r7 ;imem[r7+2] = r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist es leider etwas unangenehm mit der statischen Latenz bei internen Lesezugriffen, da man hier etwas mehr schreiben muss als man es von anderen Prozessoren gewöhnt ist.&lt;br /&gt;
&lt;br /&gt;
==== externe Speicherzugriffe ====&lt;br /&gt;
&lt;br /&gt;
Externe Speicherzugriffe verhalten sich ähnlich wie interne Zugriff.&lt;br /&gt;
Unterschiede gibt es in der Adressbreite (extern 32Bit) und in der variablen Latenz (bestimmt durch mehre Faktoren).&lt;br /&gt;
Es gibt eine externe Hauptadresse (Base) die mit &#039;allen&#039; (bis auf edrqldi) externen Speicherzugriffsinstruktionen verwendet wird.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel Hauptadresse setzen: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel schreibe in externen Speicher: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r4,$af&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	esadr	r1,r0	;Hauptadresse (esadr) is r1:r0&lt;br /&gt;
	est	r4,0	;externSpeicher[esadr + 0] = r4&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
Beim Lesen vom externen Speicher werden auch Request/Load Befehle verwendet um Latenzen, wenn möglich, zu vermeiden. Da die Latenz nicht vorhersehbar ist, wird bei nicht vorhandenen Daten solange gewartet bis sie vorhanden sind (Stall).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
	erqld	0	;load from [r0:r1 + 0]&lt;br /&gt;
	eld	r7	;get external data (Stall solange bis Daten vorhanden)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um Lade/Schreiblatenzen zu vermeiden, können mehre Stores oder Request (laden) hintereinander ausgeführt werden (maximal 256 Requestzugriffe, keine Begrenzung bei Stores).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreibe 8 Worte in externen Speicher, kein Stall solange Schreibpuffer nicht voll): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,0&lt;br /&gt;
	esadr	r7,r6	;external address is r1:r0 &lt;br /&gt;
	est	r0,0&lt;br /&gt;
	est	r0,1&lt;br /&gt;
	est	r0,2&lt;br /&gt;
	est	r0,3&lt;br /&gt;
	est	r0,4&lt;br /&gt;
	est	r0,5&lt;br /&gt;
	est	r0,6&lt;br /&gt;
	est	r0,7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (vermeiden von Leselatenzen) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r7,r6&lt;br /&gt;
	erqld	0&lt;br /&gt;
	erqld	1&lt;br /&gt;
	erqld	2&lt;br /&gt;
	erqld	3	;request 4 Worte&lt;br /&gt;
	&lt;br /&gt;
	....		;mach irgendwas&lt;br /&gt;
	&lt;br /&gt;
	eld	r0	&lt;br /&gt;
	eld	r1&lt;br /&gt;
	eld	r2&lt;br /&gt;
	eld	r3	;bekomme Daten (evtl. kein Stall, da Daten schnellgenug da)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Stack ==&lt;br /&gt;
&lt;br /&gt;
Der Stackpointer zeigt nach dem Reset auf Adresse $8000 (also am oberen Ende des internen Speichers).&lt;br /&gt;
Das Verhalten von push und request pops and pops sind gleich dem internen Speicherzugriffsverhalten (3 Cycles Latenz, Pipelined).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (1 pop): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r4	;sp--; imem[sp] = r4&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop		;request imem[sp], sp++&lt;br /&gt;
	nop&lt;br /&gt;
	nop&lt;br /&gt;
	pop	r4	;r4 = imem[sp]&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel (3 Werte auf Stack und wieder herunter) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r1&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r3&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop		;durch Latenz maximal 3 rqpop dann Daten (ansonsten &#039;poparqp&#039; benutzen (kann Request und Load gleichzeitig))&lt;br /&gt;
	push	r3&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Decoder extend ==&lt;br /&gt;
&lt;br /&gt;
Da viele Operationen konstante Werte benutzen können, aber diese aus Gründen der Befehlsbreite (16 Bit) je nach Befehl/Operanten nur eine teilweise unzureichende Größe/Breite verwenden können wurde eine Dekoder Instruktion (dexti = decoder extend immediate) eingeführt. Dieser Befehl wird vom Dekoder ausgeführt und wird in der eigentlichen Ausführungseinheit ignoriert.&lt;br /&gt;
Sinn dieses Befehls ist es, konstante Werte um einen 8 Bit breiten Wert zu erweitern. Um Fehler zu vermeiden ist dieser Wert nur einen Cycle nach ‚dexti‘ verfügbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (16 Bit Immediate Addition) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti     $12&lt;br /&gt;
	addi	  r0,$34	;r0 = r0 + $1234&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interrupts ==&lt;br /&gt;
&lt;br /&gt;
Interrupts sind in einem Pipeline basierenden Design immer ärgerlich zu handhaben. Da UCore nicht, wie viele Mikrokontroller, möglichst kurze Interrupt-Latenzen ermöglichen muss, gibt es in diesem Design auch keine garantierten Zeiten in welchen der Interrupt ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
Um den Hardwareaufwand gering wie möglich zu halten, habe ich eine sogenannte Branch-Injektion implementiert. Der Hintergedanke ist, dass Sprünge sehr oft im Code ausgeführt werden und diese, im Fall eines Interrupts , dazu ‚missbraucht‘ werden können direkt zum Interrupt-Service-Vector zu springen anstatt ihren eigentlichen definierten Sprung auszuführen (dieser wird gespeichert und später ausgeführt).&lt;br /&gt;
&lt;br /&gt;
Der Vorteil dieser Implementierung ist ein sehr geringer Hardwareaufwand, der Nachteil ist, dass die Interrupt-Latenz variiert (Delta zwischen zwei Sprüngen) und sich Verhaltensregeln für ‚Delay-Slots‘ ergeben.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;	&lt;br /&gt;
	sei			;irq enable&lt;br /&gt;
	br	anySubroutine	;if irq is enabled and occure a branch is take to irq vector and after irq is finished (rte) the give branch will take&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In ‘Delay-Slots’ sollten kein T-Bit gesetzt werden, welches für spätere Verwendungen gebraucht wird. Außerdem sollten keine Speicher-Request an diesen Stellen ausgeführt werden.&lt;br /&gt;
Um Fehler zu vermeiden warnt der Assembler bei solchen Konstrukten.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
	sei&lt;br /&gt;
	br	anySubroutine&lt;br /&gt;
	addt	r0,r1	;delay slot	(t is not save in delay slot if irq is enabled, because t is only store at br instruction)&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dividieren ==&lt;br /&gt;
&lt;br /&gt;
Viele Prozessoren die auf geringen ‚Platzverbrauch‘ optimiert sind, versuchen wenn möglich Divisions-Operationen zu vermeiden oder führen diesen nicht in einer Pipeline-Implementierung aus. Auf der Softwareseite sind Divisionen in vielen Fällen vermeidbar oder durch bestimmte Methoden ersetzbar. Prinzipiell ist eine Division einfach in Software zu implementieren, in diesem Fall ist die Geschwindigkeit einer Hardwareimplementierung meist nicht annähernd zu erreichen. UCore bietet spezielle Befehle an um einen Kompromiss aus Geschwindigkeit und Hardwareaufwand  zu erreichen.&lt;br /&gt;
Wie bei einer normalen Division wird in hier Divisor und Dividend gesetzt zusätzlich muss noch die Divsions-Bitbreite angegeben werden (max. 32 Bit). Durch den Befehl udivstep wird eine ‚1-Bit Division‚ ausgeführt, d.h. udivstep muss/kann sooft ausgeführt werden wie die Divisionsbreite gewählt ist. Als Resultat der Division ergeben sich der Quotient und der Rest.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* udiv16&lt;br /&gt;
;* &lt;br /&gt;
;* r0 	 	divident&lt;br /&gt;
;* r1		divisor&lt;br /&gt;
;*&lt;br /&gt;
;* return&lt;br /&gt;
;*&lt;br /&gt;
;* r2		qoutient&lt;br /&gt;
;* r3		remainder&lt;br /&gt;
;*&lt;br /&gt;
;* needs 34 cycles&lt;br /&gt;
;*&lt;br /&gt;
	&lt;br /&gt;
udiv16	&lt;br /&gt;
	udivinit	15&lt;br /&gt;
	udivsdd		r0&lt;br /&gt;
	udivsdv		r1&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,3	;(3+1)*4 = 16&lt;br /&gt;
	cli		;disable irq&lt;br /&gt;
udiv16Loop	&lt;br /&gt;
	subi	r0,1&lt;br /&gt;
	brts	udiv16Loop&lt;br /&gt;
	udivstep	;delay slot	!!!! note udivstep is not irq save, so use cli/sei lock&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	udivgq		r2	;delay slot		get qoutient&lt;br /&gt;
	udivgr		r3	;delay slot		get remainder&lt;br /&gt;
	sei			;delay slot		enable irqs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== weiter Beispiele ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
= UCtrl =&lt;br /&gt;
&lt;br /&gt;
UCtrl ist eine Abstraktionsschicht für einen Großteil der externen (DE2-115) Peripherien und stellt zusätzlich hilfreiche Element (Timer,…) zur Verfügung. &lt;br /&gt;
Direkten Zugriff auf diese Komponente hat nur UCore (siehe Memorymap).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCtrl bietet dem Benutzer zugriff auf:&lt;br /&gt;
*LEDS &lt;br /&gt;
*SWITCHES&lt;br /&gt;
*7-Segment Anzeige&lt;br /&gt;
*LCD (zweizeilig auf DE2-115)&lt;br /&gt;
*Interrupt Kontrolle (für UCore)&lt;br /&gt;
*Timer/Counter&lt;br /&gt;
*Video Setup (inkl. Counter und Vertikal-‚Hit‘-Erkennung)&lt;br /&gt;
*PS/2 Port (in/out, zwei Ports)&lt;br /&gt;
*I2C (zwei Ports)&lt;br /&gt;
*Audio (DAC/ADC)&lt;br /&gt;
*HCore Setup und Daten (beschreibe ich später)&lt;br /&gt;
&lt;br /&gt;
== Register ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8000&lt;br /&gt;
name = LEDG_SW&lt;br /&gt;
read            fedcba9876543210&lt;br /&gt;
                SSSSSSSSSSSSSSSS&lt;br /&gt;
                &lt;br /&gt;
                S = switches on DE2-115&lt;br /&gt;
                &lt;br /&gt;
write           fedcba9876543210&lt;br /&gt;
                -------GGGGGGGGG&lt;br /&gt;
                &lt;br /&gt;
                G = LED Green (&#039;1&#039; is ON)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8001&lt;br /&gt;
name = LEDR&lt;br /&gt;
read            fedcba9876543210&lt;br /&gt;
                --------------ME&lt;br /&gt;
        &lt;br /&gt;
                M = &#039;1&#039; if running in modelsim&lt;br /&gt;
                E = &#039;1&#039; if running in emulator&lt;br /&gt;
                &lt;br /&gt;
write                fedcba9876543210&lt;br /&gt;
                -------RRRRRRRRR&lt;br /&gt;
                &lt;br /&gt;
                R = LED Red (&#039;1&#039; is ON)&lt;br /&gt;
&lt;br /&gt;
                 &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8002 - $8005&lt;br /&gt;
name = 7SEG&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                2 ----------------&lt;br /&gt;
                3 ----------------&lt;br /&gt;
                4 ----------------&lt;br /&gt;
                5 ----------------&lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                2 -6543210-6543210&lt;br /&gt;
                3 -6543210-6543210&lt;br /&gt;
                4 -6543210-6543210&lt;br /&gt;
                5 -6543210-6543210&lt;br /&gt;
                &lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 1 / 0 (&#039;1&#039; is ON)                &lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 3 / 2 (&#039;1&#039; is ON)&lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 4 / 4 (&#039;1&#039; is ON)&lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 5 / 6 (&#039;1&#039; is ON)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8006 - $8007&lt;br /&gt;
name = LCD&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                6 -------BDDDDDDDD&lt;br /&gt;
                7 ----------------&lt;br /&gt;
                &lt;br /&gt;
                B = &#039;1&#039; if read/write request is busy&lt;br /&gt;
                D = Data after request&lt;br /&gt;
                &lt;br /&gt;
                note: wait 1 cycle after read/write request before read&lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                6 ------WRDDDDDDDD&lt;br /&gt;
                7 ----------------&lt;br /&gt;
                &lt;br /&gt;
                W = &#039;0&#039; is request write, &#039;1&#039; is request read&lt;br /&gt;
                R = LCS RS&lt;br /&gt;
                D = data to write&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8008 - $8009&lt;br /&gt;
name = IRQ&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                8 -----------HADTT IRQ MSK&lt;br /&gt;
                9 -----------HADTT IRQ MEMORY&lt;br /&gt;
                &lt;br /&gt;
                TT = Timer 2/1 IRQ&lt;br /&gt;
                D  = Audio DAC FIFO run low&lt;br /&gt;
                A  = Audio ADC FIFO run full&lt;br /&gt;
                H  = HCORE has data&lt;br /&gt;
                &lt;br /&gt;
write                  fedcba9876543210&lt;br /&gt;
                8 -----------HADTT IRQ MSK&lt;br /&gt;
                9 -----------HADTT IRQ MEMORY&lt;br /&gt;
                &lt;br /&gt;
                TT = Timer 2/1 IRQ&lt;br /&gt;
                D  = Audio DAC FIFO run low&lt;br /&gt;
                A  = Audio ADC FIFO run full&lt;br /&gt;
                H  = HCORE has data&lt;br /&gt;
                &lt;br /&gt;
description:&lt;br /&gt;
&lt;br /&gt;
                IRQ MSK is used to enable given interrupts (for example D = &#039;1&#039; then Audio DAC irq will be used)&lt;br /&gt;
                IRQ MEMORY reflect after interrupt which interrupt is the source (for example TT = &#039;01&#039; then Timer 1 made this interrupt)&lt;br /&gt;
                &lt;br /&gt;
                You should/have to clear the given interrupt bit in IRQ MEMORY before leaving interrupt service routine.&lt;br /&gt;
                        &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $800A - $800F&lt;br /&gt;
name = TIMERS&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                A DDDDDDDDDDDDDDDD Timer 1 low&lt;br /&gt;
                B DDDDDDDDDDDDDDDD Timer 1 high&lt;br /&gt;
                C ----------------&lt;br /&gt;
                D DDDDDDDDDDDDDDDD Timer 2 low&lt;br /&gt;
                E DDDDDDDDDDDDDDDD Timer 2 high&lt;br /&gt;
                F ----------------&lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                A DDDDDDDDDDDDDDDD Timer 1 low  (set before timer 1 high)&lt;br /&gt;
                B DDDDDDDDDDDDDDDD Timer 1 high &lt;br /&gt;
                C ------------CLSR&lt;br /&gt;
                D DDDDDDDDDDDDDDDD Timer 2 low  (set before timer 2 high)&lt;br /&gt;
                E DDDDDDDDDDDDDDDD Timer 2 high&lt;br /&gt;
                F ------------CLSR&lt;br /&gt;
                &lt;br /&gt;
                C = Capture counter value for read (copy current counter value to $A/B $D/E)&lt;br /&gt;
                L = Enable Auto Reload Value (after counter value runs to 0 next value is $A/B $D/E)&lt;br /&gt;
                S = Stop timer&lt;br /&gt;
                R = Start timer (will do a Autoreload from $A/B $D/E)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8010 - $802F&lt;br /&gt;
name = VIDEO&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                10 00000DDDDDDDDDDD current HCount (11..0)&lt;br /&gt;
                11 000000DDDDDDDDDD current VCount (10..0)&lt;br /&gt;
                12 ---------------H Hit of programmed VCOUNT&lt;br /&gt;
                13 ---------------- &lt;br /&gt;
                14 ---------------- &lt;br /&gt;
                15 ----------------&lt;br /&gt;
                16 ----------------&lt;br /&gt;
                17 ---------------- &lt;br /&gt;
                18 ---------------- &lt;br /&gt;
                19 ----------------&lt;br /&gt;
                1a ----------------&lt;br /&gt;
                1b ---------------- &lt;br /&gt;
                1c ---------------- &lt;br /&gt;
                1d ----------------&lt;br /&gt;
                1e ----------------&lt;br /&gt;
                1f ---------------- &lt;br /&gt;
                20 ---------------- &lt;br /&gt;
                21 ----------------                &lt;br /&gt;
                22 ----------------&lt;br /&gt;
                23 ---------------- &lt;br /&gt;
                24 ---------------- &lt;br /&gt;
                25 ----------------&lt;br /&gt;
                26 ----------------&lt;br /&gt;
                27 ---------------- &lt;br /&gt;
                28 ---------------- &lt;br /&gt;
                29 ----------------&lt;br /&gt;
                2a ----------------&lt;br /&gt;
                2b ---------------- &lt;br /&gt;
                2c ---------------- &lt;br /&gt;
                2d ----------------&lt;br /&gt;
                2e ----------------&lt;br /&gt;
                2f ---------------- &lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                10 ---------------D VIDEO ON if &#039;1&#039;&lt;br /&gt;
                11 ------DDDDDDDDDD HSYNC&lt;br /&gt;
                12 ------DDDDDDDDDD HSTART&lt;br /&gt;
                13 ------DDDDDDDDDD HMEMSTART&lt;br /&gt;
                14 ------DDDDDDDDDD HSTOP &lt;br /&gt;
                15 ------DDDDDDDDDD HTOTAL&lt;br /&gt;
                16 -------DDDDDDDDD VSYNC&lt;br /&gt;
                17 -------DDDDDDDDD VSTART&lt;br /&gt;
                18 -------DDDDDDDDD VSTOP&lt;br /&gt;
                19 -------DDDDDDDDD VTOTAL&lt;br /&gt;
                1a DDDDDDDDDDDDDDDD LINE CACHE ADDRESS ADD LOW&lt;br /&gt;
                1b DDDDDDDDDDDDDDDD LINE CACHE ADDRESS ADD HIGH &lt;br /&gt;
                1c ---------------- LINE CACHE LATCH VALUE&lt;br /&gt;
                1d -------DDDDDDDDD LINE CACHE START ADDRESS (Pixel offset)&lt;br /&gt;
                1e --------DDDDDDDD HITVCOUNT (see description)&lt;br /&gt;
                1f ---------------- &lt;br /&gt;
                20 ------DDDDDDDDDD HLOADSTART&lt;br /&gt;
                21 ------DDDDDDDDDD HLOADSTOP                &lt;br /&gt;
                22 -------DDDDDDDDD VLOADSTART&lt;br /&gt;
                23 -------DDDDDDDDD VLOADSTOP&lt;br /&gt;
                24 -------DDDDDDDDD VLOADNEXT&lt;br /&gt;
                25 DDDDDDDDDDDDDDDD EXTERNAL MEMORY START ADDRESS (low)&lt;br /&gt;
                26 DDDDDDDDDDDDDDDD EXTERNAL MEMORY START ADDRESS (high)&lt;br /&gt;
                27 DDDDDDDDDDDDDDDD EXTERNAL MEMORY LINE OFFSET (low)&lt;br /&gt;
                28 DDDDDDDDDDDDDDDD EXTERNAL MEMORY LINE OFFSET (high)&lt;br /&gt;
                29 --------------DD MEMORY Convertion MODE&lt;br /&gt;
                2a ---------------- LATCH MEMORY CONFIG&lt;br /&gt;
                2b ---------------- &lt;br /&gt;
                2c ---------------- &lt;br /&gt;
                2d ----------------&lt;br /&gt;
                2e ----------------&lt;br /&gt;
                2f ----------------                                 &lt;br /&gt;
                &lt;br /&gt;
        HITVCOUNT = Programmable VCOUNT if this Value is written $12 bit 0 is set to &#039;1&#039; if VCOUNT is equal to this value&lt;br /&gt;
                  $12 bit 0 is cleared at write to this register&lt;br /&gt;
&lt;br /&gt;
        EXTERNAL MEMORY LINE OFFSET = will be add after every loaded line (for non interleaved video setup)&lt;br /&gt;
        &lt;br /&gt;
        MEMORY Convertion MODE = defines the format of data converted from external memory (ever 32Bit fetch) to line cache&lt;br /&gt;
        &lt;br /&gt;
                00 = X8 R8 G8 B8                       (32 Bit = (8 Bit for Red/Gree/Blue))&lt;br /&gt;
                01 = R5 R6 R5 R5 R6 R5                 (2 * 16 Bit = (5 Bit for Red/Blue and 6 Bit for Green))&lt;br /&gt;
                10 = X1 R5 R5 X1 R5 R5 R5 R5         (2 * 16 Bit = (5 Bit for Red/Gree/Blue))&lt;br /&gt;
                11 = X4 R4 R4 R4 X4 R4 R4 R4          (2 * 16 Bit = (4 Bit for Red/Gree/Blue))&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8030 - $8031&lt;br /&gt;
name = PS/2 port a/b&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                30 -----FWVDDDDDDDD        port A&lt;br /&gt;
                31 -----FWVDDDDDDDD        port B&lt;br /&gt;
                &lt;br /&gt;
                D = PS/2 DATA (Scan Code) valid if A = &#039;1&#039;&lt;br /&gt;
                V = Data valid&lt;br /&gt;
                W = Write FIFO not full&lt;br /&gt;
                F = all writes finished (Fifo with 16 entries)&lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
                note: wait 1 cycle after read/write request before read&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                30 ------WADDDDDDDD        port A&lt;br /&gt;
                31 ------WADDDDDDDD        port B&lt;br /&gt;
                &lt;br /&gt;
                D = PS/2 DATA to write&lt;br /&gt;
                A = get next scan code (read 2 cycles after this from $30/$31)&lt;br /&gt;
                W = Write data to PS/2 device&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8032 - $8033&lt;br /&gt;
name = I2C port a/b&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                30 ------------D---        port A (eeprom on DE2-115)&lt;br /&gt;
                31 ------------D---        port B (audio/video in on DE2-115)&lt;br /&gt;
                &lt;br /&gt;
                D = data in from port A/B&lt;br /&gt;
                &lt;br /&gt;
write                   fedcba9876543210&lt;br /&gt;
                30 ----EEE------ICD        port A&lt;br /&gt;
                31 ----EEE------ICD        port B&lt;br /&gt;
                &lt;br /&gt;
                D = data out value&lt;br /&gt;
                C = clock out value&lt;br /&gt;
                I = direction of data (&#039;0&#039; = in / &#039;1&#039; = out)&lt;br /&gt;
                &lt;br /&gt;
                EEE = is write enable for ICD&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8034 - $803b&lt;br /&gt;
name = AUDIO&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                34 DDDDDDDDDDDDDDDD ADC data left high        &lt;br /&gt;
                35 --------DDDDDDDD ADC data left low                &lt;br /&gt;
                36 DDDDDDDDDDDDDDDD ADC data right high                &lt;br /&gt;
                37 --------DDDDDDDD ADC data right low        &lt;br /&gt;
                38 ----------------&lt;br /&gt;
                39 ----------------&lt;br /&gt;
                3a ----------------&lt;br /&gt;
                3b ----------------&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                   fedcba9876543210&lt;br /&gt;
                34 DDDDDDDDDDDDDDDD DAC data left high        &lt;br /&gt;
                35 --------DDDDDDDD DAC data left low                &lt;br /&gt;
                36 DDDDDDDDDDDDDDDD DAC data right high                &lt;br /&gt;
                37 --------DDDDDDDD DAC data right low        &lt;br /&gt;
                38 AAAAAAAADDDDDDDD ADAC Ctrl / Data&lt;br /&gt;
                39 --------DDDDDDDD DAC interrupt generate if lower &lt;br /&gt;
                3a --------DDDDDDDD ADC interrupt generate if higher&lt;br /&gt;
                3b ---------------- ADC recive values (after 2 cycles available in $34-$37)&lt;br /&gt;
                &lt;br /&gt;
                ADAC Ctrl / Data = configure internal ADC/DAC controller&lt;br /&gt;
                &lt;br /&gt;
                Adr 76543210&lt;br /&gt;
                0   -------- ignore&lt;br /&gt;
                1   -------E enable DAC&lt;br /&gt;
                2   ----CCCC DAC push counter (96KHz at 0, 48KHz at 1, 32KHz at 2 ....)&lt;br /&gt;
                3   -------E enable ADC&lt;br /&gt;
                4   ----CCCC ADC pull counter (96KHz at 0, 48KHz at 1, 32KHz at 2 ....)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $803c - $8044&lt;br /&gt;
name = HCORE CTRL/IO (in experimental state)                                &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Videosetup im Detail ===&lt;br /&gt;
&lt;br /&gt;
[[Datei:16 32Bit Computer Konsole Uctrl video setup.png|miniatur|Video Setup]]&lt;br /&gt;
&lt;br /&gt;
UCore und UCtrl (also auch der Videokontoller) haben eine Taktfrequenz von 106,481 MHz, mit dieser Frequenz ist es möglich eine maximale Auflösung von 1440 x 900 Bildpunkten bei 60 Hz zu programmieren. Da diese Auflösung in vielen Fällen zu hoch ist, bzw. die Performance für eine flüssige Bildberechnung nicht immer ausreicht, kann ein interner Zeilen-Cache so programmiert werden, dass er nur eine bestimmte Anzahl an Pixeln pro Zeile ausgibt (H-Skaliert) und nur eine definierte Anzahl von Zeilen neu geladen wird (V-Skaliert).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Wie üblich können (siehe Bild), HSYNC, HSTART etc. frei programmiert werden. Als Quelle für die Bilddaten kann der SDRAM oder SRAM benutzt werden (siehe EXTERNAL MEMORY START ADDRESS).&lt;br /&gt;
Das Farbformat kann zwischen einem 32 Bit Format (8Bit für R/G/B) und drei 16 Bit Formaten gewählt werden (siehe MEMORY Convertion MODE).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Support von Bitplanes oder Tiled-Grafiken gibt es nicht (da nicht notwendig, weil UCore/HCores schnell genug).&lt;br /&gt;
&lt;br /&gt;
Beispiel Video setup 360x225 4R4G4B Mode ($d0000000 ist Quelle (SDRAM)):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* setupVideo&lt;br /&gt;
;*&lt;br /&gt;
&lt;br /&gt;
setupVideo&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,videoDefault		;source&lt;br /&gt;
	movei	r1,UcTimer2Ctrl		;dest-1&lt;br /&gt;
	moveih	r0,&amp;gt;videoDefault&lt;br /&gt;
	moveih	r1,&amp;gt;UcTimer2Ctrl			&lt;br /&gt;
	movei	r2,26			;27-1&lt;br /&gt;
	&lt;br /&gt;
setupVideoLoop&lt;br /&gt;
&lt;br /&gt;
	rqldi	r0,0&lt;br /&gt;
	addi	r0,1&lt;br /&gt;
	addi	r1,1&lt;br /&gt;
	ld	r3&lt;br /&gt;
	subi	r2,1&lt;br /&gt;
	brts	setupVideoLoop&lt;br /&gt;
	st	r1,r3	;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
		&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
	&lt;br /&gt;
;*********************************************************************&lt;br /&gt;
;* data&lt;br /&gt;
;*********************************************************************&lt;br /&gt;
	&lt;br /&gt;
videoDefault		;AD NAME					&lt;br /&gt;
	&lt;br /&gt;
	word	$0001	;10 VIDEO_ON					&lt;br /&gt;
	word	$0097	;11 HSYNC (D = 11 .. 0)				&lt;br /&gt;
	word	$017f	;12 HSTART (D = 11 .. 0)			&lt;br /&gt;
	word	$017d	;13 HMEMSTART (D = 11 .. 0)			&lt;br /&gt;
	word	$071f	;14 HSTOP (D = 11 .. 0)				&lt;br /&gt;
	word	$076f	;15 HTOTAL (D = 11 .. 0)			&lt;br /&gt;
	word	$0002	;16 VSYNC (D = 10 .. 0)				&lt;br /&gt;
	word	$001e	;17 VSTART (D = 10 .. 0)			&lt;br /&gt;
	word	$03a2	;18 VSTOP  (D = 10 .. 0)			&lt;br /&gt;
	word	$03a3	;19 VTOTAL  (D = 10 .. 0)			&lt;br /&gt;
	word	$0000	;1a LC ADDER LOW				&lt;br /&gt;
	word	$0040	;1b LC ADDER HIGH				&lt;br /&gt;
	word	$0000	;1c LC ADDER LATCH				&lt;br /&gt;
	word	$0000	;1d LC START (10 .. 0) Pixeloffset		&lt;br /&gt;
	word	$0000	;1e						&lt;br /&gt;
	word	$0000	;1f						&lt;br /&gt;
	word	$0008	;20 HLOADSTART 					&lt;br /&gt;
	word	$00bc	;21 HLOADSTOP					&lt;br /&gt;
	word	$001e	;22 VLOADSTART 					&lt;br /&gt;
	word	$03a2	;23 VLOADSTOP 					&lt;br /&gt;
	word	$0004	;24 VLOADNEXT					&lt;br /&gt;
	word	$0000	;25 MEM_STARTADR_store low			&lt;br /&gt;
	word	$d000	;26 MEM_STARTADR_store high			&lt;br /&gt;
	word	$0000	;27 MEM_LINEOFFSET_store low			&lt;br /&gt;
	word	$0000	;28 MEM_LINEOFFSET_store high			&lt;br /&gt;
	word	$0002	;29 MEM_MODE_store 				&lt;br /&gt;
	word	$0000	;2a LATCH MEM_STARTADR/LINEOFFSET/MODE		&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Audiosetup im Detail ===&lt;br /&gt;
&lt;br /&gt;
Da das DE-115 einen Wolfson WM8731 besitzt unterteilt sich die Ansteuerung für die Audio Ein/Ausgabe in zwei Teile.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Erste ist die Konfiguration der WM8731, hierfür wird I2C Port B von UCTRL verwendet.&amp;lt;br&amp;gt;&lt;br /&gt;
Um die Konfiguration einfach zu halten sind Komponenten zur Initialisierung über I2C vorhanden (initAudio), es muss nur eine Tabelle mit den gewünschten Einstellungen übergeben werden (Register, Wert siehe WM8731 Registerbeschreibung).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Setup:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
audioDefault&lt;br /&gt;
	&lt;br /&gt;
	;&lt;br /&gt;
				;A =  8 7654 3210&lt;br /&gt;
	.data   $9,$0000	;9 =  0 0000 0000 	(inactivate interface)&lt;br /&gt;
	.data	$0,$0097	;0 =  0 1001 0111	;left line in mute&lt;br /&gt;
	.data	$1,$0097	;1 =  0 1001 0111	;right line in mute&lt;br /&gt;
	.data	$2,$006e	;2 =  0 0111 1001	;+6db left out&lt;br /&gt;
	.data	$3,$006e	;3 =  0 0111 1001	;0db right out&lt;br /&gt;
	.data	$4,$0012	;4 =  0 0001 0010	;0=0 mic boost off;&lt;br /&gt;
							;1=1 enable line input mute&lt;br /&gt;
							;2=1 line input to adc&lt;br /&gt;
							;3=0 disable bypass&lt;br /&gt;
							;4=1 DAC select&lt;br /&gt;
							;5=0 side tone disable&lt;br /&gt;
							;76=0 -6db sidetone						&lt;br /&gt;
	.data	$5,$0000	;5 =  0 0000 0000	;DAC soft Mute off, no Filer&lt;br /&gt;
	.data	$6,$0067	;6 =  0 0110 0111 	;DAC Power, Output Power, Device Power on&lt;br /&gt;
	.data	$7,$0009	;7 =  0 0000 1001 	;left justified, 24 bit&lt;br /&gt;
	.data	$8,$001e	;8 =  0 0001 1110	;0=0 normal mode&lt;br /&gt;
							;1=1 bosr (384/192)&lt;br /&gt;
							;5432=0111 96khz&lt;br /&gt;
							;78=00 no clk dividing	&lt;br /&gt;
	.data   $9,$0001	;9 =  0 0000 0001 	(activate interface)&lt;br /&gt;
	.data	$ff,$0000	;stop&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Senden und Empfangen der Audio Daten wird über UCTRL Register $34 bis $3b bedient.&amp;lt;br&amp;gt;&lt;br /&gt;
Für ADC und DAC gibt es jeweils für den linken &amp;amp; rechten Kanal je 24 Bit Daten zum empfangen/senden. &amp;lt;br&amp;gt;&lt;br /&gt;
ADC/DAC besitzen je einen 256 Wort (2 * 24 Bit) großen Queue, im Register $39 bzw. $3a können die die Unter/Überlaufwerte, welche zu einem Interrupt führen, konfiguriert werde.&amp;lt;br&amp;gt;&lt;br /&gt;
D.h. für einen Audioausgabe konfiguriert man z.B. den DAC Queue auf den Wert 128 um bei erreichen (kleiner als) einen Interrupt auszulösen (in welchen der Queue befüllt wird).&amp;lt;br&amp;gt;&lt;br /&gt;
Dadurch ist eine unterbrechungsfreie Wiedergabe/Aufnahme möglich ohne (je nach Einstellung) zu viele Interrupts auszulösen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die ADC/DAC Komponente in UCTRL kann über Register $38 (ADAC Ctrl) konfiguriert werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Die oberen 8 Bit des Datenworts bestimmen die Adresse, die unteren 8 Bit die Daten.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCTRL Audio Config:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
name			address		876543210	comment&lt;br /&gt;
&lt;br /&gt;
nop			0		XXXXXXXXX	do nothing&lt;br /&gt;
ctrl			1		XXXXXXXXE	E = enable audio (default off)&lt;br /&gt;
set fifo read count	2		XXXXXXCCC	96KHz/C = fread [0..15]&lt;br /&gt;
set fifo write count	3		XXXXXXCCC	96KHz/C = fwrite [0..15]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Hier sollte vor der eigentlich Audio Ausgabe/Aufnahme, der jeweilige Counter für den ADC/DAC gesetzt werden (Counter der bei erreichen von 0 liest/schreibt). Z.B. den Wert 2 um eine 32 KHz Ausgabe einzustellen. Um die Queues zu lesen/schreiben muss noch unter Adresse 1 die Komponente aktiviert werden.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel Audioausgabe von zwei 16 Bit Werten (links/rechts).&lt;br /&gt;
&amp;lt;br&amp;gt;	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	;r2 Audiobase $34&lt;br /&gt;
	;r1 = Wert für L, r4 = Wert für R&lt;br /&gt;
&lt;br /&gt;
	movei	r3,0&lt;br /&gt;
	stinc	r2,r1	;dac left high = value&lt;br /&gt;
	movei	r7,$1&lt;br /&gt;
	stinc	r2,r3	;dac left low = 0&lt;br /&gt;
	moveih	r7,$1&lt;br /&gt;
	stinc	r2,r4	;dac right high = value&lt;br /&gt;
	nop&lt;br /&gt;
	stinc	r2,r3	;dac right low = 0&lt;br /&gt;
	nop&lt;br /&gt;
	st	r2,r7	;dac address/ctrl = $0101	;ctrl = enable audio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Homepage ==&lt;br /&gt;
&lt;br /&gt;
http://www.goldmomo.de&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82474</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82474"/>
		<updated>2014-04-03T12:57:10Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: UCtrl Register, Video Setup Beschreibung  (minimal)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein ‚Computer‘system, das nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses kopiert. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen das vollständig* selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (*FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL benutzt, für Emulation und Tools (Assembler etc.) wird C# mit .NET verwendet.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 benutzt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE) der über einen Memorymapped UCTRL-Komponente vollständigen Zugriff auf die Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Audio Interface (Stereo mit max. 24Bit / 96 KHz) &lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Timer/Counter&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCore = Utility Core) ist der ‚zentrale‘ Prozessor im System, er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist gedacht um einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn für alle meine Demos/Spiele als ‚CPU‘ benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* ‚RISC‘ Design&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In einen experimentellen Zustand befindet sich noch der HCORE Block. Dieser Block enthält mehre (konfigurierbar) 32 Bit Prozessoren die über spezielle Techniken (Hardwaresemaphoren, parallele Sprünge, … ) eine parallele Verarbeitung der Software vereinfachen sollen und die Latenzprobleme bei Multithreading vermeiden. Ich habe bisher ein Demo mit 16 parallel laufenden HCOREs veröffentlicht, alle anderen Demos benutzen diese Cores nicht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Momentane Charakteristiken eines HCOREs sind:&lt;br /&gt;
&lt;br /&gt;
*‚Risc‘ Design &lt;br /&gt;
*7 Stufen Pipeline mit „in order“ und „out of order“ Pfad&lt;br /&gt;
*Instruction Cache (konfigurierbar (momentan 8 Wege mit 64 Worten))&lt;br /&gt;
*32 Bit ALU (Hold to Last Pfad, …) &lt;br /&gt;
*128 GP Register&lt;br /&gt;
*UCtrl/Memory/Semaphoren/… out of order Zugriff&lt;br /&gt;
*…&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
[[Datei:Goldmomo emulator.png|miniatur|rechts|Emulator]]&lt;br /&gt;
Um die Softwareentwicklung (und Debuggen) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Register, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (auch in Emulator integriert), ein Compiler existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/2n1o8dfium4bdgi/TK_Da_o4rx/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/310121#new&lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= UCORE Programmierung =&lt;br /&gt;
&lt;br /&gt;
UCore (Utility Core) ist ein Eigenimplementierung  eines 16 Bit Prozessor. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Grundlegende Charakteristiken:&lt;br /&gt;
&lt;br /&gt;
* sechsstufige Pipeline&lt;br /&gt;
* 8 Generalpurpose Registern&lt;br /&gt;
* 32 Bit Register für externe Adressen&lt;br /&gt;
* T-Bit um Bedingungen zu verarbeiten&lt;br /&gt;
* Status Register&lt;br /&gt;
* Vector Base Register&lt;br /&gt;
* 32 Bit Multiplikation Register (High-Result)&lt;br /&gt;
* separater Stackpointer&lt;br /&gt;
* interne Speicher in dem Code/Daten liegen&lt;br /&gt;
* externer Speicherzugriff (32Bit-Adressraum) möglich&lt;br /&gt;
* die Datenwortbreite beträgt immer 16 Bit (es gibt keine Bytes)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCore unterscheidet sich einigen Teilen von einem &#039;normalen&#039; Prozessor (RISC-)Design.&lt;br /&gt;
Die Gründe bzw. Ziele welche verfolgt wurden, ware eine möglichst hohe Taktrate und ein möglichst geringer Benutzung von Hardwareressourcen, aber dennoch eine hohe Verarbeitungsgeschwindigkeit.&lt;br /&gt;
Dadurch ergeben sich einige Besonderheiten die bei der Programmierung beachtet werden müssen (siehe Registerzugriffe, Branch/Jump Delayslots, Request/Load Zugriffe).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pipeline ===&lt;br /&gt;
&lt;br /&gt;
Wie gesagt hat dieser Core eine sechsstufige Pipeline:&lt;br /&gt;
&lt;br /&gt;
# Prepare Fetch &lt;br /&gt;
# Fetch &lt;br /&gt;
# Decode &lt;br /&gt;
# Read Register &lt;br /&gt;
# Execute &lt;br /&gt;
# Write Register (hat einen Bypass zu Stufe 4) &lt;br /&gt;
&lt;br /&gt;
Jede Instruktion wird in einem Cycle ausgeführt, nur der externe Speicherzugriff (nur Daten) kann einen Stall (Stillstand) der Pipeline verursachen.&lt;br /&gt;
&lt;br /&gt;
== Interne Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
In meinem System wird die folgende interne Speichermap verwendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$0000 code / data memory&lt;br /&gt;
*     16384 * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$3fff&lt;br /&gt;
$4000 code / data memory MIRROR&lt;br /&gt;
*     &lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$7fff&lt;br /&gt;
$8000 ctrl / memory			StackPointer start at $8000 on reset&lt;br /&gt;
*     XXXX * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$XXXX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Reset-Vektor befindet sich an Adresse 0, der Stackpointer an Adresse $8000. &lt;br /&gt;
Der Interruptvektor an Adresse $10 (sollte nach dem Reset an die benötigte Position verschoben werden).&lt;br /&gt;
Ab Adresse $8000 wird die Komponente UCtrl in den Adressraum ‚gemappt‘ (diese Komponente enthält Register für externe Hardware Peripherie etc.).&lt;br /&gt;
&lt;br /&gt;
== externe Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
Über den &#039;externen&#039; Datenbus kann auf folgende Komponenten zugegriffen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$a000 0000 - $a000 001f SDCard-Controller&lt;br /&gt;
$d000 0000 - $d3ff ffff SDRAM&lt;br /&gt;
$e000 0000 - $e03f ffff FLASH&lt;br /&gt;
$f000 0000 - $f00f ffff SRAM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei den meisten meiner Programme wird ein Standard-Programm aus dem FLASH-Speicher gelesen, welches einen Speichertest ausführt und auf das Einlegen einer SD-Karte mit dem zuladenden Programm wartet.&lt;br /&gt;
&lt;br /&gt;
== Opcodes/Operanten ==&lt;br /&gt;
&lt;br /&gt;
UCore hat keine &#039;RISC&#039;-Typischen Befehlssatz (viele Befehle, aber geringe Komplexität).&lt;br /&gt;
 &lt;br /&gt;
Da ein Instruktions-Wort nur eine Breite von 16 Bit hat, können nur bedingte Mengen an Operanten verwendet werden. Um jedoch die Programmierung flexibler zu gestalten, haben viele Opcodes mehrere Arten von Operanten. &lt;br /&gt;
Für die Ausführungseinheit ergibt sich dadurch keine Ressourcenveränderung, da der Decoder nur die Opcodes/Operanten in ein internes einheitliches Format auflöst.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Operanten Formate ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dc,imm8&lt;br /&gt;
 dc,db,da&lt;br /&gt;
 dc,db,imm3&lt;br /&gt;
 imm12&lt;br /&gt;
 db,da&lt;br /&gt;
 imm6&lt;br /&gt;
 da&lt;br /&gt;
 kein Operant&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Opcode / Operante(n) / Beschreibung ==== &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
movei     	dc,imm8		dc = imm&lt;br /&gt;
moveih    	dc,imm8		dc[15..8] = imm &amp;lt;&amp;lt; 8 | dc[7..0]&lt;br /&gt;
addi      	dc,imm8		dc = dc + imm&lt;br /&gt;
subi      	dc,imm8		dc = dc - imm&lt;br /&gt;
lsri      	dc,imm8		dc = dc &amp;gt;&amp;gt; imm&lt;br /&gt;
asri      	dc,imm8		dc = ((signed)dc) &amp;gt;&amp;gt; imm&lt;br /&gt;
muli      	dc,imm8		dc = dc * imm&lt;br /&gt;
cmpeqi    	dc,imm8		t = set if dc == imm else cleared&lt;br /&gt;
cmploi    	dc,imm8		t = set if dc &amp;lt; imm else cleared&lt;br /&gt;
cmplosi   	dc,imm8		t = set if  (signed)dc &amp;lt; (signed) imm else cleared&lt;br /&gt;
gpci      	dc,imm8		dc = pc + imm&lt;br /&gt;
jmpi      	dc,imm8		pc = dc + imm&lt;br /&gt;
extri     	dc,imm8		t = bit #imm of dc&lt;br /&gt;
rqldi     	dc,imm8		request (internal) mem; address = dc + imm&lt;br /&gt;
getsp     	dc,imm8		dc = sp + imm&lt;br /&gt;
dexti     	imm11		store imm as extension for next instruction&lt;br /&gt;
&lt;br /&gt;
add		dc,db,da	dc = db + da&lt;br /&gt;
sub     	dc,db,da	dc = db - da&lt;br /&gt;
lsr     	dc,db,da	dc = db &amp;gt;&amp;gt; da&lt;br /&gt;
asr     	dc,db,da	dc = ((signed)db) &amp;gt;&amp;gt; da&lt;br /&gt;
mul     	dc,db,da	dc = db * da&lt;br /&gt;
addt    	dc,db,da	dc = db + da + t&lt;br /&gt;
subt    	dc,db,da	dc = db - da - t&lt;br /&gt;
muls    	dc,db,da	dc = db * da&lt;br /&gt;
movets  	dc,db,da	dc = db if t = set else da&lt;br /&gt;
and     	dc,db,da	dc = db &amp;amp; da&lt;br /&gt;
or      	dc,db,da	dc = db | da&lt;br /&gt;
xor     	dc,db,da	dc = db ^ da&lt;br /&gt;
bic     	dc,db,da	dc = db &amp;amp; ~da&lt;br /&gt;
&lt;br /&gt;
addqi		dc,db,imm3	dc = db + imm&lt;br /&gt;
subqi   	dc,db,imm3	dc = db - imm&lt;br /&gt;
lsrqi   	dc,db,imm3	dc = db &amp;gt;&amp;gt; imm&lt;br /&gt;
asrqi   	dc,db,imm3	dc = ((signed)db) &amp;gt;&amp;gt; imm&lt;br /&gt;
mulqi   	dc,db,imm3	dc = db * imm3&lt;br /&gt;
addtqi  	dc,db,imm3	dc = db + imm + t&lt;br /&gt;
subtqi  	dc,db,imm3	dc = db - imm - t&lt;br /&gt;
edrqldi 	db,da,imm3	request (external) mem; address = (db:da) + imm3&lt;br /&gt;
&lt;br /&gt;
br		imm12		pc = pc + signed(imm)&lt;br /&gt;
brts		imm12		pc = pc + signed(imm) if t is set&lt;br /&gt;
brtc		imm12		pc = pc + signed(imm) if t is cleared&lt;br /&gt;
	             &lt;br /&gt;
cmpeq		db,da		t = set if db == da else cleared		&lt;br /&gt;
cmplo   	db,da           t = set if db &amp;lt; da else cleared&lt;br /&gt;
cmplos  	db,da           t = set if  (signed)db &amp;lt; (signed) da else cleared&lt;br /&gt;
esadr   	db,da		esadr = db:da&lt;br /&gt;
swp     	db,da		db = da[7..0]:da[15..8] &lt;br /&gt;
swptc   	db,da		db = da[7..0]:da[15..8] if t = set else da&lt;br /&gt;
st      	db,da		imem[db] = da&lt;br /&gt;
stinc   	db,da		imem[db] = da; db = db + 1&lt;br /&gt;
bffo    	db,da		db is first bit that is 1 found in da (from MSB to LSB)&lt;br /&gt;
bset    	db,da		db = db | 1 &amp;lt;&amp;lt; da&lt;br /&gt;
bclr    	db,da		db = db &amp;amp; ~ (1 &amp;lt;&amp;lt; da)&lt;br /&gt;
cmple   	db,da		t = set if db &amp;lt;= da else cleared&lt;br /&gt;
cmples  	db,da		t = set if  (signed)db &amp;lt;= (signed) da else cleared&lt;br /&gt;
rqld    	db,da		request (internal) mem; address = db + da&lt;br /&gt;
extb    	db,da		db = da byte to word singed extended&lt;br /&gt;
stwo    	db,da		imem[db + STORE_OFFSET] = da&lt;br /&gt;
andts   	db,da		db = db &amp;amp; da if t = set else da&lt;br /&gt;
orts    	db,da           db = db | da if t = set else da&lt;br /&gt;
xorts   	db,da           db = db ^ da if t = set else da&lt;br /&gt;
bicts   	db,da           db = db &amp;amp; ~da if t = set else da&lt;br /&gt;
lsrts   	db,da		db = db &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
asrts   	db,da           db = ((signed)db) &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
mults   	db,da           db = db * da if t = set else da&lt;br /&gt;
mulsts  	db,da		db = (signed)db * (signed)da if t = set else da&lt;br /&gt;
&lt;br /&gt;
erqldi		imm6		request (external) mem; address = esadr + imm	&lt;br /&gt;
ssto		imm6		STORE_OFFSET = imm&lt;br /&gt;
udivinit	imm6		udivqoutient = 0; udivrest = 0; udivbitcounter = imm&lt;br /&gt;
&lt;br /&gt;
eld		da		da = requested value from external memory&lt;br /&gt;
push            da		sp = sp – 1; imem[sp] = da&lt;br /&gt;
gmulhi          da		da = multiply result [31..15] from last multiplication&lt;br /&gt;
ld/pop          da		da = requested value from internal memory&lt;br /&gt;
poparqp         da		da = requested value from internal memory; request in internal memory adr = sp; sp = sp + 1&lt;br /&gt;
neg             da		da = 0 - da&lt;br /&gt;
udivgq          da		get division qoutinent&lt;br /&gt;
udivgr          da		get division remainder&lt;br /&gt;
udivgqh         da		get division qoutinent high [31 ..16]&lt;br /&gt;
udivgrh         da              get division remainder high [31 ..16]&lt;br /&gt;
udivsdd         da		set division divident &lt;br /&gt;
udivsdv         da		set division divider&lt;br /&gt;
udivsddh        da		set division divident high [31 ..16]&lt;br /&gt;
udivsdvh        da		set division divider  high [31 ..16]&lt;br /&gt;
erqld           da		request (external) mem; address = esadr + da&lt;br /&gt;
setsp           da		sp = da&lt;br /&gt;
erqldb          da		request (external) mem; address = esadr + da / 2&lt;br /&gt;
jmpts           da		pc = da if t = set&lt;br /&gt;
jmptc           da		pc = da if t = cleared&lt;br /&gt;
negts           da		da = 0 - da if t = set else da&lt;br /&gt;
&lt;br /&gt;
rqpop				internal memory request address = sp; sp = sp + 1&lt;br /&gt;
cli				disable interrupts&lt;br /&gt;
sei				enable interrupts&lt;br /&gt;
rti				pc = pc_before interrput&lt;br /&gt;
tnt				t = not t&lt;br /&gt;
vtt				t = v (overflow/underflow wrom add/sub)			&lt;br /&gt;
epushsadrl			sp = sp – 1; imem[sp] = esadr[15..0]&lt;br /&gt;
epushsadrh			sp = sp – 1; imem[sp] = esadr[31..16]&lt;br /&gt;
epopsadrl			esadr[15..0] = requested value from internal memory&lt;br /&gt;
epopsadrh			esadr[31..16] = requested value from internal memory&lt;br /&gt;
udivstep			performe one division step &lt;br /&gt;
nop				do nothing&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Registerzugriffe ==&lt;br /&gt;
&lt;br /&gt;
Da Register vor der Ausführungseinheit gelesen werden und nach der Ausführungseinheit geschrieben werden, ergibt sich eine Latenz zwischen Register Zugriffen. Der Grund für diese Implementierungsart ist schlicht und einfach um die Performanz zu erhöhen. Als Nebeneffekt entsteht, wie gesagt, eine Latenz. Es bieten sich mehrere Möglichkeiten an, diese Register-‚Hazards‘ in Hardware zu vermeiden (Registerscoring, Renaming, …). Um den Hardware-Implementierung klein und schnell zu halten wird in UCore auf einen Hardwaretest verzichtet. Als Resultat muss der Anwender Registerabhängigkeiten im Programm-Code behandeln.&lt;br /&gt;
Der einzige logische sinnvolle Nachteil ergibt sich in einer RAW (Read after Write) Abhängikeit, da die Latenz hier eine Cycle beträgt. In diesem Fall sollte/muss eine andere Instruktion (z.B. nop) eingefügt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreiben eines Registers und späteres lesen): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae	; &lt;br /&gt;
	nop		;write r0 = ae wird ausgeführt&lt;br /&gt;
	addi	r0,1	;r0 = r0 ($ae) + 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Im einfachsten Fall, sollte eine nop Operation bei solchen Abhängigkeit verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (nicht optimiert mit nop - 6 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	nop&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	nop&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In den meisten Fällen kann man aber andere Operationen als ‚Füllung‘ bei Registerabhängikeiten verwenden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (Optimiert - 4 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um versehentlich programmierte RAW-&#039;Hazards&#039; zu erkennen erzeugt der Assembler Warnungen, ebenfalls kann der Emulator zur Laufzeit diese &#039;Probleme&#039; erkennen.&lt;br /&gt;
Prinzipiell ist es möglich, in gewissen Situationen, RAW-&#039;Hazards&#039; absichtlich zuzulassen (Optimierungen um Register zu sparen), wovon aber im Normalfall abzuraten ist.&lt;br /&gt;
&lt;br /&gt;
== Bedingungen ==&lt;br /&gt;
&lt;br /&gt;
UCore benutzt ein T-Bit (true Bit) um Bedingungen zu beschreiben/verarbeiten. Normalerweise wird dieses Bit von Vergleichsoperationen gesetzt und kann dann von Operationen benutzt werden welche das T-Bit intern verwenden (z.B. bedingte Sprünge).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel:====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	cmpeqi	r0,0		;vergleiche auf r0 gleich 0 wenn wahr da (t=1) ansonsten (t=0)&lt;br /&gt;
	brts	r0IstNull	;springe zu ‚r0IstNull‘ label wenn t set (t=1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist notwendig Register nur dann zu setzen wenn bestimmte Bedingungen eintreten. In diesen Fällen ist es ärgerlich bedingte Sprünge auszuführen, da sie etwas Zeit brauchen (Delay Slots) und den Programmcode unübersichtlich machen.&lt;br /&gt;
Aus diesem Grund, unterstützen einige Befehle eine Bedingte Ausführung (nicht jeder).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	move	r1,123&lt;br /&gt;
	move 	r2,23&lt;br /&gt;
	…&lt;br /&gt;
	cmplo	r0,r1		;r0 &amp;lt; r1&lt;br /&gt;
	movets	r0,r2,r0	;wenn ja r0 = r2 (23) ansonsten r0 = r0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sprünge ==&lt;br /&gt;
&lt;br /&gt;
Ein (bedingter) Sprung benötigt, wie jede andere Instruktion, einen Cycle um ausgeführt zu werden.&lt;br /&gt;
Da UCore keine Branchprediction bzw. keine spekulative Ausführung etc. unterstützt und es auch nicht gewollt ist Opcodes in der Pipeline zu verwerfen, entstehen nach Sprungbefehlen sogenannte &#039;Delay Slots&#039;. Die Anzahl dieser Delay Slots ergeben sich aus der Anzahl der Pipelinestufen vor der Ausführungseinheit (da sie den Programmcounter verändert).&lt;br /&gt;
Kurzum Programlauftechnisch werden Instruktionen in diesen Delay Slots ausgeführt bevor der Sprung in Wirklichkeit ausgeführt wird.&lt;br /&gt;
Die kleinste mögliche Schleife benötigt deshalb fünf Instruktionen für einen Durchlauf.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loop	br	loop		;branch zu loop&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In vielen Fällen können diese Delay Slots sinnvoll genutzt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 1 (nicht optimiert - 8 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,1	;r1 = x parameter&lt;br /&gt;
	movei	r1,7	;r2 = y parameter&lt;br /&gt;
	gpci	r7,2	;r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 1 (optimiert - 6 cycles): ====&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	gpci	r7,2	r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	movei	r0,1	;delay slot	r1 = x parameter&lt;br /&gt;
	movei	r1,7	;delay slot     r2 = y parameter&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 2 (nicht optimiert - 8 * n + 3 cycles -&amp;gt; if n 128 -&amp;gt; total 1027 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127	;r0 = loop counter - 1&lt;br /&gt;
	movei	r1,0	;r1 = Füllwert&lt;br /&gt;
	nop&lt;br /&gt;
	&lt;br /&gt;
loop	st	r1,r6	;imem[r1] = r6&lt;br /&gt;
	addi	r1,1	;r1++&lt;br /&gt;
	subi	r0,1	;r0-- (t clear bei &amp;lt; 0)&lt;br /&gt;
	brts	loop	;branch loop solange t set&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 2 (optimiert - 6 * n + 2 cycles -&amp;gt; if n 128 -&amp;gt; total 770 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127&lt;br /&gt;
	movei	r1,0&lt;br /&gt;
	&lt;br /&gt;
loop	subi	r0,1	;da t später verwendet wird nicht in delay slot benutzen (siehe  Interruptbenutzung)&lt;br /&gt;
	brts	loop&lt;br /&gt;
	st	r1,r6	;delay slot&lt;br /&gt;
	addi	r1,1	;delay slot	&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Speicherzugriffe ==&lt;br /&gt;
&lt;br /&gt;
UCore besitzt keine ‚gewöhnlichen‘ Lesebefehle für interne/externe Speicherzugriffe.&lt;br /&gt;
Um Pipeline-Stalls beim Lesen von Daten zu vermeiden (Latenz zum Speicher), wird eine Lesebefehl in zwei Operationen aufgeteilt.&lt;br /&gt;
Der erste Befehl ist ein &#039;Request&#039;, er teilt dem Core mit von welcher Adresse er etwas lesen soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Der zweite Befehl ist dann der &#039;Load&#039;, er holt sich die angekommenen Daten ab und speichert sie in einem Register.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== interner Speicherzugriff ====&lt;br /&gt;
&lt;br /&gt;
Bei internen Speicherzugriffen ist die Latenz zwischen Request und Load statisch (3 Cycles), bei externen Zugriff variable (hier wird im Fall eines Load ohne vorhandene Daten ein Stall ausgelöst).&lt;br /&gt;
&lt;br /&gt;
Mit den Opcodes rqld (request load) und ld (load) kann vom internen Speicher gelesen werden.&lt;br /&gt;
Da die Daten erst zwei Operationen nach dem Request verfügbar sind, muss hier etwas anderes ausgeführt werde (z.B. nop).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0	;send load to address (r0+0)&lt;br /&gt;
	nop		;data send to memory&lt;br /&gt;
	nop		;data will read&lt;br /&gt;
	ld	r1	;readed data to r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Da der interne Speicher immer innerhalb von einem Cycles antwortet und die Latenz durch Pipelinestufen entsteht, kann man bei internen Speicherzugriff bis zu drei Request hintereinander verwenden.&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0&lt;br /&gt;
	rqld	r0,1&lt;br /&gt;
	rqld	r0,2&lt;br /&gt;
	ld	r1	;r1 &amp;lt;- internal_mem[r0+0]&lt;br /&gt;
	ld	r2	;r2 &amp;lt;- internal_mem[r0+1]&lt;br /&gt;
	ld	r3	;r3 &amp;lt;- internal_mem[r0+2]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Bei Schreibzugriffen wird wie bei anderen Prozessoren ein Store-Kommando verwendet.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti	$80	;imm exted&lt;br /&gt;
	move	r4,$01	;r4 = $8001&lt;br /&gt;
	move	r0,12	;r0 = 12&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	st	r0,r4	;imem[r4] = r0; $8001 = 12&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
Da ein &#039;st&#039;ore Befehl nur einen Register als Zieladresse benutzt, ist es vielen Fällen ärgerlich diesen bei mehrfachen Schreiben zu verändern. Um bei diesem Fall Abhilfe zu verschaffen wurde der Befehl ssto (Set Store Offset) und stwo (Store with Offset) eingeführt. Mit ssto kann ein Offset für stwo gesetzt werden, d.h. der Wert der mit ssto gesetzt wird auf die Zieladresse von stwo addiert.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	stwo 1&lt;br /&gt;
	ssto r0,r7 ;imem[r7+1] = r0&lt;br /&gt;
	stwo 2&lt;br /&gt;
	ssto r1,r7 ;imem[r7+2] = r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist es leider etwas unangenehm mit der statischen Latenz bei internen Lesezugriffen, da man hier etwas mehr schreiben muss als man es von anderen Prozessoren gewöhnt ist.&lt;br /&gt;
&lt;br /&gt;
==== externe Speicherzugriffe ====&lt;br /&gt;
&lt;br /&gt;
Externe Speicherzugriffe verhalten sich ähnlich wie interne Zugriff.&lt;br /&gt;
Unterschiede gibt es in der Adressbreite (extern 32Bit) und in der variablen Latenz (bestimmt durch mehre Faktoren).&lt;br /&gt;
Es gibt eine externe Hauptadresse (Base) die mit &#039;allen&#039; (bis auf edrqldi) externen Speicherzugriffsinstruktionen verwendet wird.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel Hauptadresse setzen: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel schreibe in externen Speicher: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r4,$af&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	esadr	r1,r0	;Hauptadresse (esadr) is r1:r0&lt;br /&gt;
	est	r4,0	;externSpeicher[esadr + 0] = r4&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
Beim Lesen vom externen Speicher werden auch Request/Load Befehle verwendet um Latenzen, wenn möglich, zu vermeiden. Da die Latenz nicht vorhersehbar ist, wird bei nicht vorhandenen Daten solange gewartet bis sie vorhanden sind (Stall).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
	erqld	0	;load from [r0:r1 + 0]&lt;br /&gt;
	eld	r7	;get external data (Stall solange bis Daten vorhanden)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um Lade/Schreiblatenzen zu vermeiden, können mehre Stores oder Request (laden) hintereinander ausgeführt werden (maximal 256 Requestzugriffe, keine Begrenzung bei Stores).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreibe 8 Worte in externen Speicher, kein Stall solange Schreibpuffer nicht voll): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,0&lt;br /&gt;
	esadr	r7,r6	;external address is r1:r0 &lt;br /&gt;
	est	r0,0&lt;br /&gt;
	est	r0,1&lt;br /&gt;
	est	r0,2&lt;br /&gt;
	est	r0,3&lt;br /&gt;
	est	r0,4&lt;br /&gt;
	est	r0,5&lt;br /&gt;
	est	r0,6&lt;br /&gt;
	est	r0,7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (vermeiden von Leselatenzen) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r7,r6&lt;br /&gt;
	erqld	0&lt;br /&gt;
	erqld	1&lt;br /&gt;
	erqld	2&lt;br /&gt;
	erqld	3	;request 4 Worte&lt;br /&gt;
	&lt;br /&gt;
	....		;mach irgendwas&lt;br /&gt;
	&lt;br /&gt;
	eld	r0	&lt;br /&gt;
	eld	r1&lt;br /&gt;
	eld	r2&lt;br /&gt;
	eld	r3	;bekomme Daten (evtl. kein Stall, da Daten schnellgenug da)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Stack ==&lt;br /&gt;
&lt;br /&gt;
Der Stackpointer zeigt nach dem Reset auf Adresse $8000 (also am oberen Ende des internen Speichers).&lt;br /&gt;
Das Verhalten von push und request pops and pops sind gleich dem internen Speicherzugriffsverhalten (3 Cycles Latenz, Pipelined).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (1 pop): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r4	;sp--; imem[sp] = r4&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop		;request imem[sp], sp++&lt;br /&gt;
	nop&lt;br /&gt;
	nop&lt;br /&gt;
	pop	r4	;r4 = imem[sp]&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel (3 Werte auf Stack und wieder herunter) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r1&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r3&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop		;durch Latenz maximal 3 rqpop dann Daten (ansonsten &#039;poparqp&#039; benutzen (kann Request und Load gleichzeitig))&lt;br /&gt;
	push	r3&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Decoder extend ==&lt;br /&gt;
&lt;br /&gt;
Da viele Operationen konstante Werte benutzen können, aber diese aus Gründen der Befehlsbreite (16 Bit) je nach Befehl/Operanten nur eine teilweise unzureichende Größe/Breite verwenden können wurde eine Dekoder Instruktion (dexti = decoder extend immediate) eingeführt. Dieser Befehl wird vom Dekoder ausgeführt und wird in der eigentlichen Ausführungseinheit ignoriert.&lt;br /&gt;
Sinn dieses Befehls ist es, konstante Werte um einen 8 Bit breiten Wert zu erweitern. Um Fehler zu vermeiden ist dieser Wert nur einen Cycle nach ‚dexti‘ verfügbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (16 Bit Immediate Addition) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti     $12&lt;br /&gt;
	addi	  r0,$34	;r0 = r0 + $1234&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interrupts ==&lt;br /&gt;
&lt;br /&gt;
Interrupts sind in einem Pipeline basierenden Design immer ärgerlich zu handhaben. Da UCore nicht, wie viele Mikrokontroller, möglichst kurze Interrupt-Latenzen ermöglichen muss, gibt es in diesem Design auch keine garantierten Zeiten in welchen der Interrupt ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
Um den Hardwareaufwand gering wie möglich zu halten, habe ich eine sogenannte Branch-Injektion implementiert. Der Hintergedanke ist, dass Sprünge sehr oft im Code ausgeführt werden und diese, im Fall eines Interrupts , dazu ‚missbraucht‘ werden können direkt zum Interrupt-Service-Vector zu springen anstatt ihren eigentlichen definierten Sprung auszuführen (dieser wird gespeichert und später ausgeführt).&lt;br /&gt;
&lt;br /&gt;
Der Vorteil dieser Implementierung ist ein sehr geringer Hardwareaufwand, der Nachteil ist, dass die Interrupt-Latenz variiert (Delta zwischen zwei Sprüngen) und sich Verhaltensregeln für ‚Delay-Slots‘ ergeben.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;	&lt;br /&gt;
	sei			;irq enable&lt;br /&gt;
	br	anySubroutine	;if irq is enabled and occure a branch is take to irq vector and after irq is finished (rte) the give branch will take&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In ‘Delay-Slots’ sollten kein T-Bit gesetzt werden, welches für spätere Verwendungen gebraucht wird. Außerdem sollten keine Speicher-Request an diesen Stellen ausgeführt werden.&lt;br /&gt;
Um Fehler zu vermeiden warnt der Assembler bei solchen Konstrukten.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
	sei&lt;br /&gt;
	br	anySubroutine&lt;br /&gt;
	addt	r0,r1	;delay slot	(t is not save in delay slot if irq is enabled, because t is only store at br instruction)&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dividieren ==&lt;br /&gt;
&lt;br /&gt;
Viele Prozessoren die auf geringen ‚Platzverbrauch‘ optimiert sind, versuchen wenn möglich Divisions-Operationen zu vermeiden oder führen diesen nicht in einer Pipeline-Implementierung aus. Auf der Softwareseite sind Divisionen in vielen Fällen vermeidbar oder durch bestimmte Methoden ersetzbar. Prinzipiell ist eine Division einfach in Software zu implementieren, in diesem Fall ist die Geschwindigkeit einer Hardwareimplementierung meist nicht annähernd zu erreichen. UCore bietet spezielle Befehle an um einen Kompromiss aus Geschwindigkeit und Hardwareaufwand  zu erreichen.&lt;br /&gt;
Wie bei einer normalen Division wird in hier Divisor und Dividend gesetzt zusätzlich muss noch die Divsions-Bitbreite angegeben werden (max. 32 Bit). Durch den Befehl udivstep wird eine ‚1-Bit Division‚ ausgeführt, d.h. udivstep muss/kann sooft ausgeführt werden wie die Divisionsbreite gewählt ist. Als Resultat der Division ergeben sich der Quotient und der Rest.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* udiv16&lt;br /&gt;
;* &lt;br /&gt;
;* r0 	 	divident&lt;br /&gt;
;* r1		divisor&lt;br /&gt;
;*&lt;br /&gt;
;* return&lt;br /&gt;
;*&lt;br /&gt;
;* r2		qoutient&lt;br /&gt;
;* r3		remainder&lt;br /&gt;
;*&lt;br /&gt;
;* needs 34 cycles&lt;br /&gt;
;*&lt;br /&gt;
	&lt;br /&gt;
udiv16	&lt;br /&gt;
	udivinit	15&lt;br /&gt;
	udivsdd		r0&lt;br /&gt;
	udivsdv		r1&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,3	;(3+1)*4 = 16&lt;br /&gt;
	cli		;disable irq&lt;br /&gt;
udiv16Loop	&lt;br /&gt;
	subi	r0,1&lt;br /&gt;
	brts	udiv16Loop&lt;br /&gt;
	udivstep	;delay slot	!!!! note udivstep is not irq save, so use cli/sei lock&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	udivgq		r2	;delay slot		get qoutient&lt;br /&gt;
	udivgr		r3	;delay slot		get remainder&lt;br /&gt;
	sei			;delay slot		enable irqs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== weiter Beispiele ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
= UCtrl =&lt;br /&gt;
&lt;br /&gt;
UCtrl ist eine Abstraktionsschicht für einen Großteil der externen (DE2-115) Peripherien und stellt zusätzlich hilfreiche Element (Timer,…) zur Verfügung. &lt;br /&gt;
Direkten Zugriff auf diese Komponente hat nur UCore (siehe Memorymap).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCtrl bietet dem Benutzer zugriff auf:&lt;br /&gt;
*LEDS &lt;br /&gt;
*SWITCHES&lt;br /&gt;
*7-Segment Anzeige&lt;br /&gt;
*LCD (zweizeilig auf DE2-115)&lt;br /&gt;
*Interrupt Kontrolle (für UCore)&lt;br /&gt;
*Timer/Counter&lt;br /&gt;
*Video Setup (inkl. Counter und Vertikal-‚Hit‘-Erkennung)&lt;br /&gt;
*PS/2 Port (in/out, zwei Ports)&lt;br /&gt;
*I2C (zwei Ports)&lt;br /&gt;
*Audio (DAC/ADC)&lt;br /&gt;
*HCore Setup und Daten (beschreibe ich später)&lt;br /&gt;
&lt;br /&gt;
== Register ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8000&lt;br /&gt;
name = LEDG_SW&lt;br /&gt;
read            fedcba9876543210&lt;br /&gt;
                SSSSSSSSSSSSSSSS&lt;br /&gt;
                &lt;br /&gt;
                S = switches on DE2-115&lt;br /&gt;
                &lt;br /&gt;
write           fedcba9876543210&lt;br /&gt;
                -------GGGGGGGGG&lt;br /&gt;
                &lt;br /&gt;
                G = LED Green (&#039;1&#039; is ON)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8001&lt;br /&gt;
name = LEDR&lt;br /&gt;
read            fedcba9876543210&lt;br /&gt;
                --------------ME&lt;br /&gt;
        &lt;br /&gt;
                M = &#039;1&#039; if running in modelsim&lt;br /&gt;
                E = &#039;1&#039; if running in emulator&lt;br /&gt;
                &lt;br /&gt;
write                fedcba9876543210&lt;br /&gt;
                -------RRRRRRRRR&lt;br /&gt;
                &lt;br /&gt;
                R = LED Red (&#039;1&#039; is ON)&lt;br /&gt;
&lt;br /&gt;
                 &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8002 - $8005&lt;br /&gt;
name = 7SEG&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                2 ----------------&lt;br /&gt;
                3 ----------------&lt;br /&gt;
                4 ----------------&lt;br /&gt;
                5 ----------------&lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                2 -6543210-6543210&lt;br /&gt;
                3 -6543210-6543210&lt;br /&gt;
                4 -6543210-6543210&lt;br /&gt;
                5 -6543210-6543210&lt;br /&gt;
                &lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 1 / 0 (&#039;1&#039; is ON)                &lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 3 / 2 (&#039;1&#039; is ON)&lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 4 / 4 (&#039;1&#039; is ON)&lt;br /&gt;
                -6543210-6543210 = Hex Segment of Hex 5 / 6 (&#039;1&#039; is ON)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8006 - $8007&lt;br /&gt;
name = LCD&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                6 -------BDDDDDDDD&lt;br /&gt;
                7 ----------------&lt;br /&gt;
                &lt;br /&gt;
                B = &#039;1&#039; if read/write request is busy&lt;br /&gt;
                D = Data after request&lt;br /&gt;
                &lt;br /&gt;
                note: wait 1 cycle after read/write request before read&lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                6 ------WRDDDDDDDD&lt;br /&gt;
                7 ----------------&lt;br /&gt;
                &lt;br /&gt;
                W = &#039;0&#039; is request write, &#039;1&#039; is request read&lt;br /&gt;
                R = LCS RS&lt;br /&gt;
                D = data to write&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8008 - $8009&lt;br /&gt;
name = IRQ&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                8 -----------HADTT IRQ MSK&lt;br /&gt;
                9 -----------HADTT IRQ MEMORY&lt;br /&gt;
                &lt;br /&gt;
                TT = Timer 2/1 IRQ&lt;br /&gt;
                D  = Audio DAC FIFO run low&lt;br /&gt;
                A  = Audio ADC FIFO run full&lt;br /&gt;
                H  = HCORE has data&lt;br /&gt;
                &lt;br /&gt;
write                  fedcba9876543210&lt;br /&gt;
                8 -----------HADTT IRQ MSK&lt;br /&gt;
                9 -----------HADTT IRQ MEMORY&lt;br /&gt;
                &lt;br /&gt;
                TT = Timer 2/1 IRQ&lt;br /&gt;
                D  = Audio DAC FIFO run low&lt;br /&gt;
                A  = Audio ADC FIFO run full&lt;br /&gt;
                H  = HCORE has data&lt;br /&gt;
                &lt;br /&gt;
description:&lt;br /&gt;
&lt;br /&gt;
                IRQ MSK is used to enable given interrupts (for example D = &#039;1&#039; then Audio DAC irq will be used)&lt;br /&gt;
                IRQ MEMORY reflect after interrupt which interrupt is the source (for example TT = &#039;01&#039; then Timer 1 made this interrupt)&lt;br /&gt;
                &lt;br /&gt;
                You should/have to clear the given interrupt bit in IRQ MEMORY before leaving interrupt service routine.&lt;br /&gt;
                        &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $800A - $800F&lt;br /&gt;
name = TIMERS&lt;br /&gt;
&lt;br /&gt;
read              fedcba9876543210&lt;br /&gt;
                A DDDDDDDDDDDDDDDD Timer 1 low&lt;br /&gt;
                B DDDDDDDDDDDDDDDD Timer 1 high&lt;br /&gt;
                C ----------------&lt;br /&gt;
                D DDDDDDDDDDDDDDDD Timer 2 low&lt;br /&gt;
                E DDDDDDDDDDDDDDDD Timer 2 high&lt;br /&gt;
                F ----------------&lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
write             fedcba9876543210&lt;br /&gt;
                A DDDDDDDDDDDDDDDD Timer 1 low  (set before timer 1 high)&lt;br /&gt;
                B DDDDDDDDDDDDDDDD Timer 1 high &lt;br /&gt;
                C ------------CLSR&lt;br /&gt;
                D DDDDDDDDDDDDDDDD Timer 2 low  (set before timer 2 high)&lt;br /&gt;
                E DDDDDDDDDDDDDDDD Timer 2 high&lt;br /&gt;
                F ------------CLSR&lt;br /&gt;
                &lt;br /&gt;
                C = Capture counter value for read (copy current counter value to $A/B $D/E)&lt;br /&gt;
                L = Enable Auto Reload Value (after counter value runs to 0 next value is $A/B $D/E)&lt;br /&gt;
                S = Stop timer&lt;br /&gt;
                R = Start timer (will do a Autoreload from $A/B $D/E)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8010 - $802F&lt;br /&gt;
name = VIDEO&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                10 00000DDDDDDDDDDD current HCount (11..0)&lt;br /&gt;
                11 000000DDDDDDDDDD current VCount (10..0)&lt;br /&gt;
                12 ---------------H Hit of programmed VCOUNT&lt;br /&gt;
                13 ---------------- &lt;br /&gt;
                14 ---------------- &lt;br /&gt;
                15 ----------------&lt;br /&gt;
                16 ----------------&lt;br /&gt;
                17 ---------------- &lt;br /&gt;
                18 ---------------- &lt;br /&gt;
                19 ----------------&lt;br /&gt;
                1a ----------------&lt;br /&gt;
                1b ---------------- &lt;br /&gt;
                1c ---------------- &lt;br /&gt;
                1d ----------------&lt;br /&gt;
                1e ----------------&lt;br /&gt;
                1f ---------------- &lt;br /&gt;
                20 ---------------- &lt;br /&gt;
                21 ----------------                &lt;br /&gt;
                22 ----------------&lt;br /&gt;
                23 ---------------- &lt;br /&gt;
                24 ---------------- &lt;br /&gt;
                25 ----------------&lt;br /&gt;
                26 ----------------&lt;br /&gt;
                27 ---------------- &lt;br /&gt;
                28 ---------------- &lt;br /&gt;
                29 ----------------&lt;br /&gt;
                2a ----------------&lt;br /&gt;
                2b ---------------- &lt;br /&gt;
                2c ---------------- &lt;br /&gt;
                2d ----------------&lt;br /&gt;
                2e ----------------&lt;br /&gt;
                2f ---------------- &lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                10 ---------------D VIDEO ON if &#039;1&#039;&lt;br /&gt;
                11 ------DDDDDDDDDD HSYNC&lt;br /&gt;
                12 ------DDDDDDDDDD HSTART&lt;br /&gt;
                13 ------DDDDDDDDDD HMEMSTART&lt;br /&gt;
                14 ------DDDDDDDDDD HSTOP &lt;br /&gt;
                15 ------DDDDDDDDDD HTOTAL&lt;br /&gt;
                16 -------DDDDDDDDD VSYNC&lt;br /&gt;
                17 -------DDDDDDDDD VSTART&lt;br /&gt;
                18 -------DDDDDDDDD VSTOP&lt;br /&gt;
                19 -------DDDDDDDDD VTOTAL&lt;br /&gt;
                1a DDDDDDDDDDDDDDDD LINE CACHE ADDRESS ADD LOW&lt;br /&gt;
                1b DDDDDDDDDDDDDDDD LINE CACHE ADDRESS ADD HIGH &lt;br /&gt;
                1c ---------------- LINE CACHE LATCH VALUE&lt;br /&gt;
                1d -------DDDDDDDDD LINE CACHE START ADDRESS (Pixel offset)&lt;br /&gt;
                1e --------DDDDDDDD HITVCOUNT (see description)&lt;br /&gt;
                1f ---------------- &lt;br /&gt;
                20 ------DDDDDDDDDD HLOADSTART&lt;br /&gt;
                21 ------DDDDDDDDDD HLOADSTOP                &lt;br /&gt;
                22 -------DDDDDDDDD VLOADSTART&lt;br /&gt;
                23 -------DDDDDDDDD VLOADSTOP&lt;br /&gt;
                24 -------DDDDDDDDD VLOADNEXT&lt;br /&gt;
                25 DDDDDDDDDDDDDDDD EXTERNAL MEMORY START ADDRESS (low)&lt;br /&gt;
                26 DDDDDDDDDDDDDDDD EXTERNAL MEMORY START ADDRESS (high)&lt;br /&gt;
                27 DDDDDDDDDDDDDDDD EXTERNAL MEMORY LINE OFFSET (low)&lt;br /&gt;
                28 DDDDDDDDDDDDDDDD EXTERNAL MEMORY LINE OFFSET (high)&lt;br /&gt;
                29 --------------DD MEMORY Convertion MODE&lt;br /&gt;
                2a ---------------- LATCH MEMORY CONFIG&lt;br /&gt;
                2b ---------------- &lt;br /&gt;
                2c ---------------- &lt;br /&gt;
                2d ----------------&lt;br /&gt;
                2e ----------------&lt;br /&gt;
                2f ----------------                                 &lt;br /&gt;
                &lt;br /&gt;
        HITVCOUNT = Programmable VCOUNT if this Value is written $12 bit 0 is set to &#039;1&#039; if VCOUNT is equal to this value&lt;br /&gt;
                  $12 bit 0 is cleared at write to this register&lt;br /&gt;
&lt;br /&gt;
        EXTERNAL MEMORY LINE OFFSET = will be add after every loaded line (for non interleaved video setup)&lt;br /&gt;
        &lt;br /&gt;
        MEMORY Convertion MODE = defines the format of data converted from external memory (ever 32Bit fetch) to line cache&lt;br /&gt;
        &lt;br /&gt;
                00 = X8 R8 G8 B8                       (32 Bit = (8 Bit for Red/Gree/Blue))&lt;br /&gt;
                01 = R5 R6 R5 R5 R6 R5                 (2 * 16 Bit = (5 Bit for Red/Blue and 6 Bit for Green))&lt;br /&gt;
                10 = X1 R5 R5 X1 R5 R5 R5 R5         (2 * 16 Bit = (5 Bit for Red/Gree/Blue))&lt;br /&gt;
                11 = X4 R4 R4 R4 X4 R4 R4 R4          (2 * 16 Bit = (4 Bit for Red/Gree/Blue))&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8030 - $8031&lt;br /&gt;
name = PS/2 port a/b&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                30 -----FWVDDDDDDDD        port A&lt;br /&gt;
                31 -----FWVDDDDDDDD        port B&lt;br /&gt;
                &lt;br /&gt;
                D = PS/2 DATA (Scan Code) valid if A = &#039;1&#039;&lt;br /&gt;
                V = Data valid&lt;br /&gt;
                W = Write FIFO not full&lt;br /&gt;
                F = all writes finished (Fifo with 16 entries)&lt;br /&gt;
                &lt;br /&gt;
                &lt;br /&gt;
                note: wait 1 cycle after read/write request before read&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                30 ------WADDDDDDDD        port A&lt;br /&gt;
                31 ------WADDDDDDDD        port B&lt;br /&gt;
                &lt;br /&gt;
                D = PS/2 DATA to write&lt;br /&gt;
                A = get next scan code (read 2 cycles after this from $30/$31)&lt;br /&gt;
                W = Write data to PS/2 device&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8032 - $8033&lt;br /&gt;
name = I2C port a/b&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                30 ------------D---        port A (eeprom on DE2-115)&lt;br /&gt;
                31 ------------D---        port B (audio/video in on DE2-115)&lt;br /&gt;
                &lt;br /&gt;
                D = data in from port A/B&lt;br /&gt;
                &lt;br /&gt;
write                   fedcba9876543210&lt;br /&gt;
                30 ----EEE------ICD        port A&lt;br /&gt;
                31 ----EEE------ICD        port B&lt;br /&gt;
                &lt;br /&gt;
                D = data out value&lt;br /&gt;
                C = clock out value&lt;br /&gt;
                I = direction of data (&#039;0&#039; = in / &#039;1&#039; = out)&lt;br /&gt;
                &lt;br /&gt;
                EEE = is write enable for ICD&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $8034 - $803b&lt;br /&gt;
name = AUDIO&lt;br /&gt;
&lt;br /&gt;
read               fedcba9876543210&lt;br /&gt;
                34 DDDDDDDDDDDDDDDD ADC data left high        &lt;br /&gt;
                35 --------DDDDDDDD ADC data left low                &lt;br /&gt;
                36 DDDDDDDDDDDDDDDD ADC data right high                &lt;br /&gt;
                37 --------DDDDDDDD ADC data right low        &lt;br /&gt;
                38 ----------------&lt;br /&gt;
                39 ----------------&lt;br /&gt;
                3a ----------------&lt;br /&gt;
                3b ----------------&lt;br /&gt;
                &lt;br /&gt;
write              fedcba9876543210&lt;br /&gt;
                   fedcba9876543210&lt;br /&gt;
                34 DDDDDDDDDDDDDDDD DAC data left high        &lt;br /&gt;
                35 --------DDDDDDDD DAC data left low                &lt;br /&gt;
                36 DDDDDDDDDDDDDDDD DAC data right high                &lt;br /&gt;
                37 --------DDDDDDDD DAC data right low        &lt;br /&gt;
                38 AAAAAAAADDDDDDDD ADAC Ctrl / Data&lt;br /&gt;
                39 --------DDDDDDDD DAC interrupt generate if lower &lt;br /&gt;
                3a --------DDDDDDDD ADC interrupt generate if higher&lt;br /&gt;
                3b ---------------- ADC recive values (after 2 cycles available in $34-$37)&lt;br /&gt;
                &lt;br /&gt;
                ADAC Ctrl / Data = configure internal ADC/DAC controller&lt;br /&gt;
                &lt;br /&gt;
                Adr 76543210&lt;br /&gt;
                0   -------- ignore&lt;br /&gt;
                1   -------E enable DAC&lt;br /&gt;
                2   ----CCCC DAC push counter (96KHz at 0, 48KHz at 1, 32KHz at 2 ....)&lt;br /&gt;
                3   -------E enable ADC&lt;br /&gt;
                4   ----CCCC ADC pull counter (96KHz at 0, 48KHz at 1, 32KHz at 2 ....)&lt;br /&gt;
                &lt;br /&gt;
-----------------------------------------------------------&lt;br /&gt;
address = $803c - $8044&lt;br /&gt;
name = HCORE CTRL/IO (in experimental state)                                &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Videosetup im Detail ===&lt;br /&gt;
&lt;br /&gt;
[[Datei:16 32Bit Computer Konsole Uctrl video setup.png|miniatur|Video Setup]]&lt;br /&gt;
&lt;br /&gt;
UCore und UCtrl (also auch der Videokontoller) haben eine Taktfrequenz von 106,481 MHz, mit dieser Frequenz ist es möglich eine maximale Auflösung von 1440 x 900 Bildpunkten bei 60 Hz zu programmieren. Da diese Auflösung in vielen Fällen zu hoch ist, bzw. die Performance für eine flüssige Bildberechnung nicht immer ausreicht, kann ein interner Zeilen-Cache so programmiert werden, dass er nur eine bestimmte Anzahl an Pixeln pro Zeile ausgibt (H-Skaliert) und nur eine definierte Anzahl von Zeilen neu geladen wird (V-Skaliert).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Wie üblich können (siehe Bild), HSYNC, HSTART etc. frei programmiert werden. Als Quelle für die Bilddaten kann der SDRAM oder SRAM benutzt werden (siehe EXTERNAL MEMORY START ADDRESS).&lt;br /&gt;
Das Farbformat kann zwischen einem 32 Bit Format (8Bit für R/G/B) und drei 16 Bit Formaten gewählt werden (siehe MEMORY Convertion MODE).&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Support von Bitplanes oder Tiled-Grafiken gibt es nicht (da nicht notwendig, weil UCore/HCores schnell genug).&lt;br /&gt;
&lt;br /&gt;
Beispiel Video setup 360x225 4R4G4B Mode ($d0000000 ist Quelle (SDRAM)):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* setupVideo&lt;br /&gt;
;*&lt;br /&gt;
&lt;br /&gt;
setupVideo&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,videoDefault		;source&lt;br /&gt;
	movei	r1,UcTimer2Ctrl		;dest-1&lt;br /&gt;
	moveih	r0,&amp;gt;videoDefault&lt;br /&gt;
	moveih	r1,&amp;gt;UcTimer2Ctrl			&lt;br /&gt;
	movei	r2,26			;27-1&lt;br /&gt;
	&lt;br /&gt;
setupVideoLoop&lt;br /&gt;
&lt;br /&gt;
	rqldi	r0,0&lt;br /&gt;
	addi	r0,1&lt;br /&gt;
	addi	r1,1&lt;br /&gt;
	ld	r3&lt;br /&gt;
	subi	r2,1&lt;br /&gt;
	brts	setupVideoLoop&lt;br /&gt;
	st	r1,r3	;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
		&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
	&lt;br /&gt;
;*********************************************************************&lt;br /&gt;
;* data&lt;br /&gt;
;*********************************************************************&lt;br /&gt;
	&lt;br /&gt;
videoDefault		;AD NAME					&lt;br /&gt;
	&lt;br /&gt;
	word	$0001	;10 VIDEO_ON					&lt;br /&gt;
	word	$0097	;11 HSYNC (D = 11 .. 0)				&lt;br /&gt;
	word	$017f	;12 HSTART (D = 11 .. 0)			&lt;br /&gt;
	word	$017d	;13 HMEMSTART (D = 11 .. 0)			&lt;br /&gt;
	word	$071f	;14 HSTOP (D = 11 .. 0)				&lt;br /&gt;
	word	$076f	;15 HTOTAL (D = 11 .. 0)			&lt;br /&gt;
	word	$0002	;16 VSYNC (D = 10 .. 0)				&lt;br /&gt;
	word	$001e	;17 VSTART (D = 10 .. 0)			&lt;br /&gt;
	word	$03a2	;18 VSTOP  (D = 10 .. 0)			&lt;br /&gt;
	word	$03a3	;19 VTOTAL  (D = 10 .. 0)			&lt;br /&gt;
	word	$0000	;1a LC ADDER LOW				&lt;br /&gt;
	word	$0040	;1b LC ADDER HIGH				&lt;br /&gt;
	word	$0000	;1c LC ADDER LATCH				&lt;br /&gt;
	word	$0000	;1d LC START (10 .. 0) Pixeloffset		&lt;br /&gt;
	word	$0000	;1e						&lt;br /&gt;
	word	$0000	;1f						&lt;br /&gt;
	word	$0008	;20 HLOADSTART 					&lt;br /&gt;
	word	$00bc	;21 HLOADSTOP					&lt;br /&gt;
	word	$001e	;22 VLOADSTART 					&lt;br /&gt;
	word	$03a2	;23 VLOADSTOP 					&lt;br /&gt;
	word	$0004	;24 VLOADNEXT					&lt;br /&gt;
	word	$0000	;25 MEM_STARTADR_store low			&lt;br /&gt;
	word	$d000	;26 MEM_STARTADR_store high			&lt;br /&gt;
	word	$0000	;27 MEM_LINEOFFSET_store low			&lt;br /&gt;
	word	$0000	;28 MEM_LINEOFFSET_store high			&lt;br /&gt;
	word	$0002	;29 MEM_MODE_store 				&lt;br /&gt;
	word	$0000	;2a LATCH MEM_STARTADR/LINEOFFSET/MODE		&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Homepage ==&lt;br /&gt;
&lt;br /&gt;
http://www.goldmomo.de&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:16_32Bit_Computer_Konsole_Uctrl_video_setup.png&amp;diff=82472</id>
		<title>Datei:16 32Bit Computer Konsole Uctrl video setup.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:16_32Bit_Computer_Konsole_Uctrl_video_setup.png&amp;diff=82472"/>
		<updated>2014-04-03T12:28:40Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: Details fürs Video-Setup&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Details fürs Video-Setup&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82441</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82441"/>
		<updated>2014-04-01T11:38:39Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein ‚Computer‘system, das nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses kopiert. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen das vollständig* selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (*FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL benutzt, für Emulation und Tools (Assembler etc.) wird C# mit .NET verwendet.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 benutzt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE) der über einen Memorymapped UCTRL-Komponente vollständigen Zugriff auf die Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Audio Interface (Stereo mit max. 24Bit / 96 KHz) &lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Timer/Counter&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCore = Utility Core) ist der ‚zentrale‘ Prozessor im System, er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist gedacht um einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn für alle meine Demos/Spiele als ‚CPU‘ benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* ‚RISC‘ Design&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In einen experimentellen Zustand befindet sich noch der HCORE Block. Dieser Block enthält mehre (konfigurierbar) 32 Bit Prozessoren die über spezielle Techniken (Hardwaresemaphoren, parallele Sprünge, … ) eine parallele Verarbeitung der Software vereinfachen sollen und die Latenzprobleme bei Multithreading vermeiden. Ich habe bisher ein Demo mit 16 parallel laufenden HCOREs veröffentlicht, alle anderen Demos benutzen diese Cores nicht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Momentane Charakteristiken eines HCOREs sind:&lt;br /&gt;
&lt;br /&gt;
*‚Risc‘ Design &lt;br /&gt;
*7 Stufen Pipeline mit „in order“ und „out of order“ Pfad&lt;br /&gt;
*Instruction Cache (konfigurierbar (momentan 8 Wege mit 64 Worten))&lt;br /&gt;
*32 Bit ALU (Hold to Last Pfad, …) &lt;br /&gt;
*128 GP Register&lt;br /&gt;
*UCtrl/Memory/Semaphoren/… out of order Zugriff&lt;br /&gt;
*…&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
[[Datei:Goldmomo emulator.png|miniatur|rechts|Emulator]]&lt;br /&gt;
Um die Softwareentwicklung (und Debuggen) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Register, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (auch in Emulator integriert), ein Compiler existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/2n1o8dfium4bdgi/TK_Da_o4rx/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/310121#new&lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= UCORE Programmierung =&lt;br /&gt;
&lt;br /&gt;
UCore (Utility Core) ist ein Eigenimplementierung  eines 16 Bit Prozessor. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Grundlegende Charakteristiken:&lt;br /&gt;
&lt;br /&gt;
* sechsstufige Pipeline&lt;br /&gt;
* 8 Generalpurpose Registern&lt;br /&gt;
* 32 Bit Register für externe Adressen&lt;br /&gt;
* T-Bit um Bedingungen zu verarbeiten&lt;br /&gt;
* Status Register&lt;br /&gt;
* Vector Base Register&lt;br /&gt;
* 32 Bit Multiplikation Register (High-Result)&lt;br /&gt;
* separater Stackpointer&lt;br /&gt;
* interne Speicher in dem Code/Daten liegen&lt;br /&gt;
* externer Speicherzugriff (32Bit-Adressraum) möglich&lt;br /&gt;
* die Datenwortbreite beträgt immer 16 Bit (es gibt keine Bytes)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCore unterscheidet sich einigen Teilen von einem &#039;normalen&#039; Prozessor (RISC-)Design.&lt;br /&gt;
Die Gründe bzw. Ziele welche verfolgt wurden, ware eine möglichst hohe Taktrate und ein möglichst geringer Benutzung von Hardwareressourcen, aber dennoch eine hohe Verarbeitungsgeschwindigkeit.&lt;br /&gt;
Dadurch ergeben sich einige Besonderheiten die bei der Programmierung beachtet werden müssen (siehe Registerzugriffe, Branch/Jump Delayslots, Request/Load Zugriffe).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pipeline ===&lt;br /&gt;
&lt;br /&gt;
Wie gesagt hat dieser Core eine sechsstufige Pipeline:&lt;br /&gt;
&lt;br /&gt;
# Prepare Fetch &lt;br /&gt;
# Fetch &lt;br /&gt;
# Decode &lt;br /&gt;
# Read Register &lt;br /&gt;
# Execute &lt;br /&gt;
# Write Register (hat einen Bypass zu Stufe 4) &lt;br /&gt;
&lt;br /&gt;
Jede Instruktion wird in einem Cycle ausgeführt, nur der externe Speicherzugriff (nur Daten) kann einen Stall (Stillstand) der Pipeline verursachen.&lt;br /&gt;
&lt;br /&gt;
== Interne Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
In meinem System wird die folgende interne Speichermap verwendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$0000 code / data memory&lt;br /&gt;
*     16384 * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$3fff&lt;br /&gt;
$4000 code / data memory MIRROR&lt;br /&gt;
*     &lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$7fff&lt;br /&gt;
$8000 ctrl / memory			StackPointer start at $8000 on reset&lt;br /&gt;
*     XXXX * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$XXXX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Reset-Vektor befindet sich an Adresse 0, der Stackpointer an Adresse $8000. &lt;br /&gt;
Der Interruptvektor an Adresse $10 (sollte nach dem Reset an die benötigte Position verschoben werden).&lt;br /&gt;
Ab Adresse $8000 wird die Komponente UCtrl in den Adressraum ‚gemappt‘ (diese Komponente enthält Register für externe Hardware Peripherie etc.).&lt;br /&gt;
&lt;br /&gt;
== externe Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
Über den &#039;externen&#039; Datenbus kann auf folgende Komponenten zugegriffen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$a000 0000 - $a000 001f SDCard-Controller&lt;br /&gt;
$d000 0000 - $d3ff ffff SDRAM&lt;br /&gt;
$e000 0000 - $e03f ffff FLASH&lt;br /&gt;
$f000 0000 - $f00f ffff SRAM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei den meisten meiner Programme wird ein Standard-Programm aus dem FLASH-Speicher gelesen, welches einen Speichertest ausführt und auf das Einlegen einer SD-Karte mit dem zuladenden Programm wartet.&lt;br /&gt;
&lt;br /&gt;
== Opcodes/Operanten ==&lt;br /&gt;
&lt;br /&gt;
UCore hat keine &#039;RISC&#039;-Typischen Befehlssatz (viele Befehle, aber geringe Komplexität).&lt;br /&gt;
 &lt;br /&gt;
Da ein Instruktions-Wort nur eine Breite von 16 Bit hat, können nur bedingte Mengen an Operanten verwendet werden. Um jedoch die Programmierung flexibler zu gestalten, haben viele Opcodes mehrere Arten von Operanten. &lt;br /&gt;
Für die Ausführungseinheit ergibt sich dadurch keine Ressourcenveränderung, da der Decoder nur die Opcodes/Operanten in ein internes einheitliches Format auflöst.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Operanten Formate ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dc,imm8&lt;br /&gt;
 dc,db,da&lt;br /&gt;
 dc,db,imm3&lt;br /&gt;
 imm12&lt;br /&gt;
 db,da&lt;br /&gt;
 imm6&lt;br /&gt;
 da&lt;br /&gt;
 kein Operant&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Opcode / Operante(n) / Beschreibung ==== &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
movei     	dc,imm8		dc = imm&lt;br /&gt;
moveih    	dc,imm8		dc[15..8] = imm &amp;lt;&amp;lt; 8 | dc[7..0]&lt;br /&gt;
addi      	dc,imm8		dc = dc + imm&lt;br /&gt;
subi      	dc,imm8		dc = dc - imm&lt;br /&gt;
lsri      	dc,imm8		dc = dc &amp;gt;&amp;gt; imm&lt;br /&gt;
asri      	dc,imm8		dc = ((signed)dc) &amp;gt;&amp;gt; imm&lt;br /&gt;
muli      	dc,imm8		dc = dc * imm&lt;br /&gt;
cmpeqi    	dc,imm8		t = set if dc == imm else cleared&lt;br /&gt;
cmploi    	dc,imm8		t = set if dc &amp;lt; imm else cleared&lt;br /&gt;
cmplosi   	dc,imm8		t = set if  (signed)dc &amp;lt; (signed) imm else cleared&lt;br /&gt;
gpci      	dc,imm8		dc = pc + imm&lt;br /&gt;
jmpi      	dc,imm8		pc = dc + imm&lt;br /&gt;
extri     	dc,imm8		t = bit #imm of dc&lt;br /&gt;
rqldi     	dc,imm8		request (internal) mem; address = dc + imm&lt;br /&gt;
getsp     	dc,imm8		dc = sp + imm&lt;br /&gt;
dexti     	imm11		store imm as extension for next instruction&lt;br /&gt;
&lt;br /&gt;
add		dc,db,da	dc = db + da&lt;br /&gt;
sub     	dc,db,da	dc = db - da&lt;br /&gt;
lsr     	dc,db,da	dc = db &amp;gt;&amp;gt; da&lt;br /&gt;
asr     	dc,db,da	dc = ((signed)db) &amp;gt;&amp;gt; da&lt;br /&gt;
mul     	dc,db,da	dc = db * da&lt;br /&gt;
addt    	dc,db,da	dc = db + da + t&lt;br /&gt;
subt    	dc,db,da	dc = db - da - t&lt;br /&gt;
muls    	dc,db,da	dc = db * da&lt;br /&gt;
movets  	dc,db,da	dc = db if t = set else da&lt;br /&gt;
and     	dc,db,da	dc = db &amp;amp; da&lt;br /&gt;
or      	dc,db,da	dc = db | da&lt;br /&gt;
xor     	dc,db,da	dc = db ^ da&lt;br /&gt;
bic     	dc,db,da	dc = db &amp;amp; ~da&lt;br /&gt;
&lt;br /&gt;
addqi		dc,db,imm3	dc = db + imm&lt;br /&gt;
subqi   	dc,db,imm3	dc = db - imm&lt;br /&gt;
lsrqi   	dc,db,imm3	dc = db &amp;gt;&amp;gt; imm&lt;br /&gt;
asrqi   	dc,db,imm3	dc = ((signed)db) &amp;gt;&amp;gt; imm&lt;br /&gt;
mulqi   	dc,db,imm3	dc = db * imm3&lt;br /&gt;
addtqi  	dc,db,imm3	dc = db + imm + t&lt;br /&gt;
subtqi  	dc,db,imm3	dc = db - imm - t&lt;br /&gt;
edrqldi 	db,da,imm3	request (external) mem; address = (db:da) + imm3&lt;br /&gt;
&lt;br /&gt;
br		imm12		pc = pc + signed(imm)&lt;br /&gt;
brts		imm12		pc = pc + signed(imm) if t is set&lt;br /&gt;
brtc		imm12		pc = pc + signed(imm) if t is cleared&lt;br /&gt;
	             &lt;br /&gt;
cmpeq		db,da		t = set if db == da else cleared		&lt;br /&gt;
cmplo   	db,da           t = set if db &amp;lt; da else cleared&lt;br /&gt;
cmplos  	db,da           t = set if  (signed)db &amp;lt; (signed) da else cleared&lt;br /&gt;
esadr   	db,da		esadr = db:da&lt;br /&gt;
swp     	db,da		db = da[7..0]:da[15..8] &lt;br /&gt;
swptc   	db,da		db = da[7..0]:da[15..8] if t = set else da&lt;br /&gt;
st      	db,da		imem[db] = da&lt;br /&gt;
stinc   	db,da		imem[db] = da; db = db + 1&lt;br /&gt;
bffo    	db,da		db is first bit that is 1 found in da (from MSB to LSB)&lt;br /&gt;
bset    	db,da		db = db | 1 &amp;lt;&amp;lt; da&lt;br /&gt;
bclr    	db,da		db = db &amp;amp; ~ (1 &amp;lt;&amp;lt; da)&lt;br /&gt;
cmple   	db,da		t = set if db &amp;lt;= da else cleared&lt;br /&gt;
cmples  	db,da		t = set if  (signed)db &amp;lt;= (signed) da else cleared&lt;br /&gt;
rqld    	db,da		request (internal) mem; address = db + da&lt;br /&gt;
extb    	db,da		db = da byte to word singed extended&lt;br /&gt;
stwo    	db,da		imem[db + STORE_OFFSET] = da&lt;br /&gt;
andts   	db,da		db = db &amp;amp; da if t = set else da&lt;br /&gt;
orts    	db,da           db = db | da if t = set else da&lt;br /&gt;
xorts   	db,da           db = db ^ da if t = set else da&lt;br /&gt;
bicts   	db,da           db = db &amp;amp; ~da if t = set else da&lt;br /&gt;
lsrts   	db,da		db = db &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
asrts   	db,da           db = ((signed)db) &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
mults   	db,da           db = db * da if t = set else da&lt;br /&gt;
mulsts  	db,da		db = (signed)db * (signed)da if t = set else da&lt;br /&gt;
&lt;br /&gt;
erqldi		imm6		request (external) mem; address = esadr + imm	&lt;br /&gt;
ssto		imm6		STORE_OFFSET = imm&lt;br /&gt;
udivinit	imm6		udivqoutient = 0; udivrest = 0; udivbitcounter = imm&lt;br /&gt;
&lt;br /&gt;
eld		da		da = requested value from external memory&lt;br /&gt;
push            da		sp = sp – 1; imem[sp] = da&lt;br /&gt;
gmulhi          da		da = multiply result [31..15] from last multiplication&lt;br /&gt;
ld/pop          da		da = requested value from internal memory&lt;br /&gt;
poparqp         da		da = requested value from internal memory; request in internal memory adr = sp; sp = sp + 1&lt;br /&gt;
neg             da		da = 0 - da&lt;br /&gt;
udivgq          da		get division qoutinent&lt;br /&gt;
udivgr          da		get division remainder&lt;br /&gt;
udivgqh         da		get division qoutinent high [31 ..16]&lt;br /&gt;
udivgrh         da              get division remainder high [31 ..16]&lt;br /&gt;
udivsdd         da		set division divident &lt;br /&gt;
udivsdv         da		set division divider&lt;br /&gt;
udivsddh        da		set division divident high [31 ..16]&lt;br /&gt;
udivsdvh        da		set division divider  high [31 ..16]&lt;br /&gt;
erqld           da		request (external) mem; address = esadr + da&lt;br /&gt;
setsp           da		sp = da&lt;br /&gt;
erqldb          da		request (external) mem; address = esadr + da / 2&lt;br /&gt;
jmpts           da		pc = da if t = set&lt;br /&gt;
jmptc           da		pc = da if t = cleared&lt;br /&gt;
negts           da		da = 0 - da if t = set else da&lt;br /&gt;
&lt;br /&gt;
rqpop				internal memory request address = sp; sp = sp + 1&lt;br /&gt;
cli				disable interrupts&lt;br /&gt;
sei				enable interrupts&lt;br /&gt;
rti				pc = pc_before interrput&lt;br /&gt;
tnt				t = not t&lt;br /&gt;
vtt				t = v (overflow/underflow wrom add/sub)			&lt;br /&gt;
epushsadrl			sp = sp – 1; imem[sp] = esadr[15..0]&lt;br /&gt;
epushsadrh			sp = sp – 1; imem[sp] = esadr[31..16]&lt;br /&gt;
epopsadrl			esadr[15..0] = requested value from internal memory&lt;br /&gt;
epopsadrh			esadr[31..16] = requested value from internal memory&lt;br /&gt;
udivstep			performe one division step &lt;br /&gt;
nop				do nothing&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Registerzugriffe ==&lt;br /&gt;
&lt;br /&gt;
Da Register vor der Ausführungseinheit gelesen werden und nach der Ausführungseinheit geschrieben werden, ergibt sich eine Latenz zwischen Register Zugriffen. Der Grund für diese Implementierungsart ist schlicht und einfach um die Performanz zu erhöhen. Als Nebeneffekt entsteht, wie gesagt, eine Latenz. Es bieten sich mehrere Möglichkeiten an, diese Register-‚Hazards‘ in Hardware zu vermeiden (Registerscoring, Renaming, …). Um den Hardware-Implementierung klein und schnell zu halten wird in UCore auf einen Hardwaretest verzichtet. Als Resultat muss der Anwender Registerabhängigkeiten im Programm-Code behandeln.&lt;br /&gt;
Der einzige logische sinnvolle Nachteil ergibt sich in einer RAW (Read after Write) Abhängikeit, da die Latenz hier eine Cycle beträgt. In diesem Fall sollte/muss eine andere Instruktion (z.B. nop) eingefügt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreiben eines Registers und späteres lesen): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae	; &lt;br /&gt;
	nop		;write r0 = ae wird ausgeführt&lt;br /&gt;
	addi	r0,1	;r0 = r0 ($ae) + 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Im einfachsten Fall, sollte eine nop Operation bei solchen Abhängigkeit verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (nicht optimiert mit nop - 6 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	nop&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	nop&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In den meisten Fällen kann man aber andere Operationen als ‚Füllung‘ bei Registerabhängikeiten verwenden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (Optimiert - 4 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um versehentlich programmierte RAW-&#039;Hazards&#039; zu erkennen erzeugt der Assembler Warnungen, ebenfalls kann der Emulator zur Laufzeit diese &#039;Probleme&#039; erkennen.&lt;br /&gt;
Prinzipiell ist es möglich, in gewissen Situationen, RAW-&#039;Hazards&#039; absichtlich zuzulassen (Optimierungen um Register zu sparen), wovon aber im Normalfall abzuraten ist.&lt;br /&gt;
&lt;br /&gt;
== Bedingungen ==&lt;br /&gt;
&lt;br /&gt;
UCore benutzt ein T-Bit (true Bit) um Bedingungen zu beschreiben/verarbeiten. Normalerweise wird dieses Bit von Vergleichsoperationen gesetzt und kann dann von Operationen benutzt werden welche das T-Bit intern verwenden (z.B. bedingte Sprünge).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel:====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	cmpeqi	r0,0		;vergleiche auf r0 gleich 0 wenn wahr da (t=1) ansonsten (t=0)&lt;br /&gt;
	brts	r0IstNull	;springe zu ‚r0IstNull‘ label wenn t set (t=1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist notwendig Register nur dann zu setzen wenn bestimmte Bedingungen eintreten. In diesen Fällen ist es ärgerlich bedingte Sprünge auszuführen, da sie etwas Zeit brauchen (Delay Slots) und den Programmcode unübersichtlich machen.&lt;br /&gt;
Aus diesem Grund, unterstützen einige Befehle eine Bedingte Ausführung (nicht jeder).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	move	r1,123&lt;br /&gt;
	move 	r2,23&lt;br /&gt;
	…&lt;br /&gt;
	cmplo	r0,r1		;r0 &amp;lt; r1&lt;br /&gt;
	movets	r0,r2,r0	;wenn ja r0 = r2 (23) ansonsten r0 = r0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sprünge ==&lt;br /&gt;
&lt;br /&gt;
Ein (bedingter) Sprung benötigt, wie jede andere Instruktion, einen Cycle um ausgeführt zu werden.&lt;br /&gt;
Da UCore keine Branchprediction bzw. keine spekulative Ausführung etc. unterstützt und es auch nicht gewollt ist Opcodes in der Pipeline zu verwerfen, entstehen nach Sprungbefehlen sogenannte &#039;Delay Slots&#039;. Die Anzahl dieser Delay Slots ergeben sich aus der Anzahl der Pipelinestufen vor der Ausführungseinheit (da sie den Programmcounter verändert).&lt;br /&gt;
Kurzum Programlauftechnisch werden Instruktionen in diesen Delay Slots ausgeführt bevor der Sprung in Wirklichkeit ausgeführt wird.&lt;br /&gt;
Die kleinste mögliche Schleife benötigt deshalb fünf Instruktionen für einen Durchlauf.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loop	br	loop		;branch zu loop&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In vielen Fällen können diese Delay Slots sinnvoll genutzt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 1 (nicht optimiert - 8 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,1	;r1 = x parameter&lt;br /&gt;
	movei	r1,7	;r2 = y parameter&lt;br /&gt;
	gpci	r7,2	;r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 1 (optimiert - 6 cycles): ====&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	gpci	r7,2	r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	movei	r0,1	;delay slot	r1 = x parameter&lt;br /&gt;
	movei	r1,7	;delay slot     r2 = y parameter&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 2 (nicht optimiert - 8 * n + 3 cycles -&amp;gt; if n 128 -&amp;gt; total 1027 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127	;r0 = loop counter - 1&lt;br /&gt;
	movei	r1,0	;r1 = Füllwert&lt;br /&gt;
	nop&lt;br /&gt;
	&lt;br /&gt;
loop	st	r1,r6	;imem[r1] = r6&lt;br /&gt;
	addi	r1,1	;r1++&lt;br /&gt;
	subi	r0,1	;r0-- (t clear bei &amp;lt; 0)&lt;br /&gt;
	brts	loop	;branch loop solange t set&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 2 (optimiert - 6 * n + 2 cycles -&amp;gt; if n 128 -&amp;gt; total 770 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127&lt;br /&gt;
	movei	r1,0&lt;br /&gt;
	&lt;br /&gt;
loop	subi	r0,1	;da t später verwendet wird nicht in delay slot benutzen (siehe  Interruptbenutzung)&lt;br /&gt;
	brts	loop&lt;br /&gt;
	st	r1,r6	;delay slot&lt;br /&gt;
	addi	r1,1	;delay slot	&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Speicherzugriffe ==&lt;br /&gt;
&lt;br /&gt;
UCore besitzt keine ‚gewöhnlichen‘ Lesebefehle für interne/externe Speicherzugriffe.&lt;br /&gt;
Um Pipeline-Stalls beim Lesen von Daten zu vermeiden (Latenz zum Speicher), wird eine Lesebefehl in zwei Operationen aufgeteilt.&lt;br /&gt;
Der erste Befehl ist ein &#039;Request&#039;, er teilt dem Core mit von welcher Adresse er etwas lesen soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Der zweite Befehl ist dann der &#039;Load&#039;, er holt sich die angekommenen Daten ab und speichert sie in einem Register.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== interner Speicherzugriff ====&lt;br /&gt;
&lt;br /&gt;
Bei internen Speicherzugriffen ist die Latenz zwischen Request und Load statisch (3 Cycles), bei externen Zugriff variable (hier wird im Fall eines Load ohne vorhandene Daten ein Stall ausgelöst).&lt;br /&gt;
&lt;br /&gt;
Mit den Opcodes rqld (request load) und ld (load) kann vom internen Speicher gelesen werden.&lt;br /&gt;
Da die Daten erst zwei Operationen nach dem Request verfügbar sind, muss hier etwas anderes ausgeführt werde (z.B. nop).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0	;send load to address (r0+0)&lt;br /&gt;
	nop		;data send to memory&lt;br /&gt;
	nop		;data will read&lt;br /&gt;
	ld	r1	;readed data to r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Da der interne Speicher immer innerhalb von einem Cycles antwortet und die Latenz durch Pipelinestufen entsteht, kann man bei internen Speicherzugriff bis zu drei Request hintereinander verwenden.&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0&lt;br /&gt;
	rqld	r0,1&lt;br /&gt;
	rqld	r0,2&lt;br /&gt;
	ld	r1	;r1 &amp;lt;- internal_mem[r0+0]&lt;br /&gt;
	ld	r2	;r2 &amp;lt;- internal_mem[r0+1]&lt;br /&gt;
	ld	r3	;r3 &amp;lt;- internal_mem[r0+2]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Bei Schreibzugriffen wird wie bei anderen Prozessoren ein Store-Kommando verwendet.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti	$80	;imm exted&lt;br /&gt;
	move	r4,$01	;r4 = $8001&lt;br /&gt;
	move	r0,12	;r0 = 12&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	st	r0,r4	;imem[r4] = r0; $8001 = 12&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
Da ein &#039;st&#039;ore Befehl nur einen Register als Zieladresse benutzt, ist es vielen Fällen ärgerlich diesen bei mehrfachen Schreiben zu verändern. Um bei diesem Fall Abhilfe zu verschaffen wurde der Befehl ssto (Set Store Offset) und stwo (Store with Offset) eingeführt. Mit ssto kann ein Offset für stwo gesetzt werden, d.h. der Wert der mit ssto gesetzt wird auf die Zieladresse von stwo addiert.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	stwo 1&lt;br /&gt;
	ssto r0,r7 ;imem[r7+1] = r0&lt;br /&gt;
	stwo 2&lt;br /&gt;
	ssto r1,r7 ;imem[r7+2] = r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist es leider etwas unangenehm mit der statischen Latenz bei internen Lesezugriffen, da man hier etwas mehr schreiben muss als man es von anderen Prozessoren gewöhnt ist.&lt;br /&gt;
&lt;br /&gt;
==== externe Speicherzugriffe ====&lt;br /&gt;
&lt;br /&gt;
Externe Speicherzugriffe verhalten sich ähnlich wie interne Zugriff.&lt;br /&gt;
Unterschiede gibt es in der Adressbreite (extern 32Bit) und in der variablen Latenz (bestimmt durch mehre Faktoren).&lt;br /&gt;
Es gibt eine externe Hauptadresse (Base) die mit &#039;allen&#039; (bis auf edrqldi) externen Speicherzugriffsinstruktionen verwendet wird.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel Hauptadresse setzen: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel schreibe in externen Speicher: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r4,$af&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	esadr	r1,r0	;Hauptadresse (esadr) is r1:r0&lt;br /&gt;
	est	r4,0	;externSpeicher[esadr + 0] = r4&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
Beim Lesen vom externen Speicher werden auch Request/Load Befehle verwendet um Latenzen, wenn möglich, zu vermeiden. Da die Latenz nicht vorhersehbar ist, wird bei nicht vorhandenen Daten solange gewartet bis sie vorhanden sind (Stall).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
	erqld	0	;load from [r0:r1 + 0]&lt;br /&gt;
	eld	r7	;get external data (Stall solange bis Daten vorhanden)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um Lade/Schreiblatenzen zu vermeiden, können mehre Stores oder Request (laden) hintereinander ausgeführt werden (maximal 256 Requestzugriffe, keine Begrenzung bei Stores).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreibe 8 Worte in externen Speicher, kein Stall solange Schreibpuffer nicht voll): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,0&lt;br /&gt;
	esadr	r7,r6	;external address is r1:r0 &lt;br /&gt;
	est	r0,0&lt;br /&gt;
	est	r0,1&lt;br /&gt;
	est	r0,2&lt;br /&gt;
	est	r0,3&lt;br /&gt;
	est	r0,4&lt;br /&gt;
	est	r0,5&lt;br /&gt;
	est	r0,6&lt;br /&gt;
	est	r0,7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (vermeiden von Leselatenzen) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r7,r6&lt;br /&gt;
	erqld	0&lt;br /&gt;
	erqld	1&lt;br /&gt;
	erqld	2&lt;br /&gt;
	erqld	3	;request 4 Worte&lt;br /&gt;
	&lt;br /&gt;
	....		;mach irgendwas&lt;br /&gt;
	&lt;br /&gt;
	eld	r0	&lt;br /&gt;
	eld	r1&lt;br /&gt;
	eld	r2&lt;br /&gt;
	eld	r3	;bekomme Daten (evtl. kein Stall, da Daten schnellgenug da)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Stack ==&lt;br /&gt;
&lt;br /&gt;
Der Stackpointer zeigt nach dem Reset auf Adresse $8000 (also am oberen Ende des internen Speichers).&lt;br /&gt;
Das Verhalten von push und request pops and pops sind gleich dem internen Speicherzugriffsverhalten (3 Cycles Latenz, Pipelined).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (1 pop): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r4	;sp--; imem[sp] = r4&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop		;request imem[sp], sp++&lt;br /&gt;
	nop&lt;br /&gt;
	nop&lt;br /&gt;
	pop	r4	;r4 = imem[sp]&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel (3 Werte auf Stack und wieder herunter) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r1&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r3&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop		;durch Latenz maximal 3 rqpop dann Daten (ansonsten &#039;poparqp&#039; benutzen (kann Request und Load gleichzeitig))&lt;br /&gt;
	push	r3&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
== Decoder extend ==&lt;br /&gt;
&lt;br /&gt;
Da viele Operationen konstante Werte benutzen können, aber diese aus Gründen der Befehlsbreite (16 Bit) je nach Befehl/Operanten nur eine teilweise unzureichende Größe/Breite verwenden können wurde eine Dekoder Instruktion (dexti = decoder extend immediate) eingeführt. Dieser Befehl wird vom Dekoder ausgeführt und wird in der eigentlichen Ausführungseinheit ignoriert.&lt;br /&gt;
Sinn dieses Befehls ist es, konstante Werte um einen 8 Bit breiten Wert zu erweitern. Um Fehler zu vermeiden ist dieser Wert nur einen Cycle nach ‚dexti‘ verfügbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (16 Bit Immediate Addition) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti     $12&lt;br /&gt;
	addi	  r0,$34	;r0 = r0 + $1234&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interrupts ==&lt;br /&gt;
&lt;br /&gt;
Interrupts sind in einem Pipeline basierenden Design immer ärgerlich zu handhaben. Da UCore nicht, wie viele Mikrokontroller, möglichst kurze Interrupt-Latenzen ermöglichen muss, gibt es in diesem Design auch keine garantierten Zeiten in welchen der Interrupt ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
Um den Hardwareaufwand gering wie möglich zu halten, habe ich eine sogenannte Branch-Injektion implementiert. Der Hintergedanke ist, dass Sprünge sehr oft im Code ausgeführt werden und diese, im Fall eines Interrupts , dazu ‚missbraucht‘ werden können direkt zum Interrupt-Service-Vector zu springen anstatt ihren eigentlichen definierten Sprung auszuführen (dieser wird gespeichert und später ausgeführt).&lt;br /&gt;
&lt;br /&gt;
Der Vorteil dieser Implementierung ist ein sehr geringer Hardwareaufwand, der Nachteil ist, dass die Interrupt-Latenz variiert (Delta zwischen zwei Sprüngen) und sich Verhaltensregeln für ‚Delay-Slots‘ ergeben.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;	&lt;br /&gt;
	sei			;irq enable&lt;br /&gt;
	br	anySubroutine	;if irq is enabled and occure a branch is take to irq vector and after irq is finished (rte) the give branch will take&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In ‘Delay-Slots’ sollten kein T-Bit gesetzt werden, welches für spätere Verwendungen gebraucht wird. Außerdem sollten keine Speicher-Request an diesen Stellen ausgeführt werden.&lt;br /&gt;
Um Fehler zu vermeiden warnt der Assembler bei solchen Konstrukten.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
	sei&lt;br /&gt;
	br	anySubroutine&lt;br /&gt;
	addt	r0,r1	;delay slot	(t is not save in delay slot if irq is enabled, because t is only store at br instruction)&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Divdieren ==&lt;br /&gt;
&lt;br /&gt;
Viele Prozessoren die auf geringen ‚Platzverbrauch‘ optimiert sind, versuchen wenn möglich Divisions-Operationen zu vermeiden oder führen diesen nicht in einer Pipeline-Implementierung aus. Auf der Softwareseite sind Divisionen in vielen Fällen vermeidbar oder durch bestimmte Methoden ersetzbar. Prinzipiell ist eine Division einfach in Software zu implementieren, in diesem Fall ist die Geschwindigkeit einer Hardwareimplementierung meist nicht annähernd zu erreichen. UCore bietet spezielle Befehle an um einen Kompromiss aus Geschwindigkeit und Hardwareaufwand  zu erreichen.&lt;br /&gt;
Wie bei einer normalen Division wird in hier Divisor und Dividend gesetzt zusätzlich muss noch die Divsions-Bitbreite angegeben werden (max. 32 Bit). Durch den Befehl udivstep wird eine ‚1-Bit Division‚ ausgeführt, d.h. udivstep muss/kann sooft ausgeführt werden wie die Divisionsbreite gewählt ist. Als Resultat der Division ergeben sich der Quotient und der Rest.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;******************************&lt;br /&gt;
;*&lt;br /&gt;
;* udiv16&lt;br /&gt;
;* &lt;br /&gt;
;* r0 	 	divident&lt;br /&gt;
;* r1		divisor&lt;br /&gt;
;*&lt;br /&gt;
;* return&lt;br /&gt;
;*&lt;br /&gt;
;* r2		qoutient&lt;br /&gt;
;* r3		remainder&lt;br /&gt;
;*&lt;br /&gt;
;* needs 34 cycles&lt;br /&gt;
;*&lt;br /&gt;
	&lt;br /&gt;
udiv16	&lt;br /&gt;
	udivinit	15&lt;br /&gt;
	udivsdd		r0&lt;br /&gt;
	udivsdv		r1&lt;br /&gt;
	&lt;br /&gt;
	movei	r0,3	;(3+1)*4 = 16&lt;br /&gt;
	cli		;disable irq&lt;br /&gt;
udiv16Loop	&lt;br /&gt;
	subi	r0,1&lt;br /&gt;
	brts	udiv16Loop&lt;br /&gt;
	udivstep	;delay slot	!!!! note udivstep is not irq save, so use cli/sei lock&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
	udivstep        ;delay slot&lt;br /&gt;
&lt;br /&gt;
	jmpi	r7,0&lt;br /&gt;
	nop			;delay slot&lt;br /&gt;
	udivgq		r2	;delay slot		get qoutient&lt;br /&gt;
	udivgr		r3	;delay slot		get remainder&lt;br /&gt;
	sei			;delay slot		enable irqs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== weiter Beispiele ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
=== UCtrl ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
== Homepage ==&lt;br /&gt;
&lt;br /&gt;
http://www.goldmomo.de&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82434</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82434"/>
		<updated>2014-04-01T10:53:48Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein ‚Computer‘system, das nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses kopiert. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen das vollständig* selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (*FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL benutzt, für Emulation und Tools (Assembler etc.) wird C# mit .NET verwendet.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 benutzt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE) der über einen Memorymapped UCTRL-Komponente vollständigen Zugriff auf die Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Audio Interface (Stereo mit max. 24Bit / 96 KHz) &lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Timer/Counter&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCore = Utility Core) ist der ‚zentrale‘ Prozessor im System, er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist gedacht um einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn für alle meine Demos/Spiele als ‚CPU‘ benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* ‚RISC‘ Design&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In einen experimentellen Zustand befindet sich noch der HCORE Block. Dieser Block enthält mehre (konfigurierbar) 32 Bit Prozessoren die über spezielle Techniken (Hardwaresemaphoren, parallele Sprünge, … ) eine parallele Verarbeitung der Software vereinfachen sollen und die Latenzprobleme bei Multithreading vermeiden. Ich habe bisher ein Demo mit 16 parallel laufenden HCOREs veröffentlicht, alle anderen Demos benutzen diese Cores nicht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Momentane Charakteristiken eines HCOREs sind:&lt;br /&gt;
&lt;br /&gt;
*‚Risc‘ Design &lt;br /&gt;
*7 Stufen Pipeline mit „in order“ und „out of order“ Pfad&lt;br /&gt;
*Instruction Cache (konfigurierbar (momentan 8 Wege mit 64 Worten))&lt;br /&gt;
*32 Bit ALU (Hold to Last Pfad, …) &lt;br /&gt;
*128 GP Register&lt;br /&gt;
*UCtrl/Memory/Semaphoren/… out of order Zugriff&lt;br /&gt;
*…&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
[[Datei:Goldmomo emulator.png|miniatur|rechts|Emulator]]&lt;br /&gt;
Um die Softwareentwicklung (und Debuggen) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Register, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (auch in Emulator integriert), ein Compiler existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/2n1o8dfium4bdgi/TK_Da_o4rx/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/310121#new&lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= UCORE Programmierung =&lt;br /&gt;
&lt;br /&gt;
UCore (Utility Core) ist ein Eigenimplementierung  eines 16 Bit Prozessor. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Grundlegende Charakteristiken:&lt;br /&gt;
&lt;br /&gt;
* sechsstufige Pipeline&lt;br /&gt;
* 8 Generalpurpose Registern&lt;br /&gt;
* 32 Bit Register für externe Adressen&lt;br /&gt;
* T-Bit um Bedingungen zu verarbeiten&lt;br /&gt;
* Status Register&lt;br /&gt;
* Vector Base Register&lt;br /&gt;
* 32 Bit Multiplikation Register (High-Result)&lt;br /&gt;
* separater Stackpointer&lt;br /&gt;
* interne Speicher in dem Code/Daten liegen&lt;br /&gt;
* externer Speicherzugriff (32Bit-Adressraum) möglich&lt;br /&gt;
* die Datenwortbreite beträgt immer 16 Bit (es gibt keine Bytes)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
UCore unterscheidet sich einigen Teilen von einem &#039;normalen&#039; Prozessor (RISC-)Design.&lt;br /&gt;
Die Gründe bzw. Ziele welche verfolgt wurden, ware eine möglichst hohe Taktrate und ein möglichst geringer Benutzung von Hardwareressourcen, aber dennoch eine hohe Verarbeitungsgeschwindigkeit.&lt;br /&gt;
Dadurch ergeben sich einige Besonderheiten die bei der Programmierung beachtet werden müssen (siehe Registerzugriffe, Branch/Jump Delayslots, Request/Load Zugriffe).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pipeline ===&lt;br /&gt;
&lt;br /&gt;
Wie gesagt hat dieser Core eine sechsstufige Pipeline:&lt;br /&gt;
&lt;br /&gt;
# Prepare Fetch &lt;br /&gt;
# Fetch &lt;br /&gt;
# Decode &lt;br /&gt;
# Read Register &lt;br /&gt;
# Execute &lt;br /&gt;
# Write Register (hat einen Bypass zu Stufe 4) &lt;br /&gt;
&lt;br /&gt;
Jede Instruktion wird in einem Cycle ausgeführt, nur der externe Speicherzugriff (nur Daten) kann einen Stall (Stillstand) der Pipeline verursachen.&lt;br /&gt;
&lt;br /&gt;
== Interne Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
In meinem System wird die folgende interne Speichermap verwendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$0000 code / data memory&lt;br /&gt;
*     16384 * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$3fff&lt;br /&gt;
$4000 code / data memory MIRROR&lt;br /&gt;
*     &lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$7fff&lt;br /&gt;
$8000 ctrl / memory			StackPointer start at $8000 on reset&lt;br /&gt;
*     XXXX * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$XXXX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Reset-Vektor befindet sich an Adresse 0, der Stackpointer an Adresse $8000. &lt;br /&gt;
Der Interruptvektor an Adresse $10 (sollte nach dem Reset an die benötigte Position verschoben werden).&lt;br /&gt;
Ab Adresse $8000 wird die Komponente UCtrl in den Adressraum ‚gemappt‘ (diese Komponente enthält Register für externe Hardware Peripherie etc.).&lt;br /&gt;
&lt;br /&gt;
== externe Memory Map (Standardkonfiguration) ==&lt;br /&gt;
&lt;br /&gt;
Über den &#039;externen&#039; Datenbus kann auf folgende Komponenten zugegriffen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$a000 0000 - $a000 001f SDCard-Controller&lt;br /&gt;
$d000 0000 - $d3ff ffff SDRAM&lt;br /&gt;
$e000 0000 - $e03f ffff FLASH&lt;br /&gt;
$f000 0000 - $f00f ffff SRAM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei den meisten meiner Programme wird ein Standard-Programm aus dem FLASH-Speicher gelesen, welches einen Speichertest ausführt und auf das Einlegen einer SD-Karte mit dem zuladenden Programm wartet.&lt;br /&gt;
&lt;br /&gt;
== Opcodes/Operanten ==&lt;br /&gt;
&lt;br /&gt;
UCore hat keine &#039;RISC&#039;-Typischen Befehlssatz (viele Befehle, aber geringe Komplexität).&lt;br /&gt;
 &lt;br /&gt;
Da ein Instruktions-Wort nur eine Breite von 16 Bit hat, können nur bedingte Mengen an Operanten verwendet werden. Um jedoch die Programmierung flexibler zu gestalten, haben viele Opcodes mehrere Arten von Operanten. &lt;br /&gt;
Für die Ausführungseinheit ergibt sich dadurch keine Ressourcenveränderung, da der Decoder nur die Opcodes/Operanten in ein internes einheitliches Format auflöst.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Operanten Formate ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dc,imm8&lt;br /&gt;
 dc,db,da&lt;br /&gt;
 dc,db,imm3&lt;br /&gt;
 imm12&lt;br /&gt;
 db,da&lt;br /&gt;
 imm6&lt;br /&gt;
 da&lt;br /&gt;
 kein Operant&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Opcode / Operante(n) / Beschreibung ==== &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
movei     	dc,imm8		dc = imm&lt;br /&gt;
moveih    	dc,imm8		dc[15..8] = imm &amp;lt;&amp;lt; 8 | dc[7..0]&lt;br /&gt;
addi      	dc,imm8		dc = dc + imm&lt;br /&gt;
subi      	dc,imm8		dc = dc - imm&lt;br /&gt;
lsri      	dc,imm8		dc = dc &amp;gt;&amp;gt; imm&lt;br /&gt;
asri      	dc,imm8		dc = ((signed)dc) &amp;gt;&amp;gt; imm&lt;br /&gt;
muli      	dc,imm8		dc = dc * imm&lt;br /&gt;
cmpeqi    	dc,imm8		t = set if dc == imm else cleared&lt;br /&gt;
cmploi    	dc,imm8		t = set if dc &amp;lt; imm else cleared&lt;br /&gt;
cmplosi   	dc,imm8		t = set if  (signed)dc &amp;lt; (signed) imm else cleared&lt;br /&gt;
gpci      	dc,imm8		dc = pc + imm&lt;br /&gt;
jmpi      	dc,imm8		pc = dc + imm&lt;br /&gt;
extri     	dc,imm8		t = bit #imm of dc&lt;br /&gt;
rqldi     	dc,imm8		request (internal) mem; address = dc + imm&lt;br /&gt;
getsp     	dc,imm8		dc = sp + imm&lt;br /&gt;
dexti     	imm11		store imm as extension for next instruction&lt;br /&gt;
&lt;br /&gt;
add		dc,db,da	dc = db + da&lt;br /&gt;
sub     	dc,db,da	dc = db - da&lt;br /&gt;
lsr     	dc,db,da	dc = db &amp;gt;&amp;gt; da&lt;br /&gt;
asr     	dc,db,da	dc = ((signed)db) &amp;gt;&amp;gt; da&lt;br /&gt;
mul     	dc,db,da	dc = db * da&lt;br /&gt;
addt    	dc,db,da	dc = db + da + t&lt;br /&gt;
subt    	dc,db,da	dc = db - da - t&lt;br /&gt;
muls    	dc,db,da	dc = db * da&lt;br /&gt;
movets  	dc,db,da	dc = db if t = set else da&lt;br /&gt;
and     	dc,db,da	dc = db &amp;amp; da&lt;br /&gt;
or      	dc,db,da	dc = db | da&lt;br /&gt;
xor     	dc,db,da	dc = db ^ da&lt;br /&gt;
bic     	dc,db,da	dc = db &amp;amp; ~da&lt;br /&gt;
&lt;br /&gt;
addqi		dc,db,imm3	dc = db + imm&lt;br /&gt;
subqi   	dc,db,imm3	dc = db - imm&lt;br /&gt;
lsrqi   	dc,db,imm3	dc = db &amp;gt;&amp;gt; imm&lt;br /&gt;
asrqi   	dc,db,imm3	dc = ((signed)db) &amp;gt;&amp;gt; imm&lt;br /&gt;
mulqi   	dc,db,imm3	dc = db * imm3&lt;br /&gt;
addtqi  	dc,db,imm3	dc = db + imm + t&lt;br /&gt;
subtqi  	dc,db,imm3	dc = db - imm - t&lt;br /&gt;
edrqldi 	db,da,imm3	request (external) mem; address = (db:da) + imm3&lt;br /&gt;
&lt;br /&gt;
br		imm12		pc = pc + signed(imm)&lt;br /&gt;
brts		imm12		pc = pc + signed(imm) if t is set&lt;br /&gt;
brtc		imm12		pc = pc + signed(imm) if t is cleared&lt;br /&gt;
	             &lt;br /&gt;
cmpeq		db,da		t = set if db == da else cleared		&lt;br /&gt;
cmplo   	db,da           t = set if db &amp;lt; da else cleared&lt;br /&gt;
cmplos  	db,da           t = set if  (signed)db &amp;lt; (signed) da else cleared&lt;br /&gt;
esadr   	db,da		esadr = db:da&lt;br /&gt;
swp     	db,da		db = da[7..0]:da[15..8] &lt;br /&gt;
swptc   	db,da		db = da[7..0]:da[15..8] if t = set else da&lt;br /&gt;
st      	db,da		imem[db] = da&lt;br /&gt;
stinc   	db,da		imem[db] = da; db = db + 1&lt;br /&gt;
bffo    	db,da		db is first bit that is 1 found in da (from MSB to LSB)&lt;br /&gt;
bset    	db,da		db = db | 1 &amp;lt;&amp;lt; da&lt;br /&gt;
bclr    	db,da		db = db &amp;amp; ~ (1 &amp;lt;&amp;lt; da)&lt;br /&gt;
cmple   	db,da		t = set if db &amp;lt;= da else cleared&lt;br /&gt;
cmples  	db,da		t = set if  (signed)db &amp;lt;= (signed) da else cleared&lt;br /&gt;
rqld    	db,da		request (internal) mem; address = db + da&lt;br /&gt;
extb    	db,da		db = da byte to word singed extended&lt;br /&gt;
stwo    	db,da		imem[db + STORE_OFFSET] = da&lt;br /&gt;
andts   	db,da		db = db &amp;amp; da if t = set else da&lt;br /&gt;
orts    	db,da           db = db | da if t = set else da&lt;br /&gt;
xorts   	db,da           db = db ^ da if t = set else da&lt;br /&gt;
bicts   	db,da           db = db &amp;amp; ~da if t = set else da&lt;br /&gt;
lsrts   	db,da		db = db &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
asrts   	db,da           db = ((signed)db) &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
mults   	db,da           db = db * da if t = set else da&lt;br /&gt;
mulsts  	db,da		db = (signed)db * (signed)da if t = set else da&lt;br /&gt;
&lt;br /&gt;
erqldi		imm6		request (external) mem; address = esadr + imm	&lt;br /&gt;
ssto		imm6		STORE_OFFSET = imm&lt;br /&gt;
udivinit	imm6		udivqoutient = 0; udivrest = 0; udivbitcounter = imm&lt;br /&gt;
&lt;br /&gt;
eld		da		da = requested value from external memory&lt;br /&gt;
push            da		sp = sp – 1; imem[sp] = da&lt;br /&gt;
gmulhi          da		da = multiply result [31..15] from last multiplication&lt;br /&gt;
ld/pop          da		da = requested value from internal memory&lt;br /&gt;
poparqp         da		da = requested value from internal memory; request in internal memory adr = sp; sp = sp + 1&lt;br /&gt;
neg             da		da = 0 - da&lt;br /&gt;
udivgq          da		get division qoutinent&lt;br /&gt;
udivgr          da		get division remainder&lt;br /&gt;
udivgqh         da		get division qoutinent high [31 ..16]&lt;br /&gt;
udivgrh         da              get division remainder high [31 ..16]&lt;br /&gt;
udivsdd         da		set division divident &lt;br /&gt;
udivsdv         da		set division divider&lt;br /&gt;
udivsddh        da		set division divident high [31 ..16]&lt;br /&gt;
udivsdvh        da		set division divider  high [31 ..16]&lt;br /&gt;
erqld           da		request (external) mem; address = esadr + da&lt;br /&gt;
setsp           da		sp = da&lt;br /&gt;
erqldb          da		request (external) mem; address = esadr + da / 2&lt;br /&gt;
jmpts           da		pc = da if t = set&lt;br /&gt;
jmptc           da		pc = da if t = cleared&lt;br /&gt;
negts           da		da = 0 - da if t = set else da&lt;br /&gt;
&lt;br /&gt;
rqpop				internal memory request address = sp; sp = sp + 1&lt;br /&gt;
cli				disable interrupts&lt;br /&gt;
sei				enable interrupts&lt;br /&gt;
rti				pc = pc_before interrput&lt;br /&gt;
tnt				t = not t&lt;br /&gt;
vtt				t = v (overflow/underflow wrom add/sub)			&lt;br /&gt;
epushsadrl			sp = sp – 1; imem[sp] = esadr[15..0]&lt;br /&gt;
epushsadrh			sp = sp – 1; imem[sp] = esadr[31..16]&lt;br /&gt;
epopsadrl			esadr[15..0] = requested value from internal memory&lt;br /&gt;
epopsadrh			esadr[31..16] = requested value from internal memory&lt;br /&gt;
udivstep			performe one division step &lt;br /&gt;
nop				do nothing&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registerzugriffe ===&lt;br /&gt;
&lt;br /&gt;
Da Register vor der Ausführungseinheit gelesen werden und nach der Ausführungseinheit geschrieben werden, ergibt sich eine Latenz zwischen Register Zugriffen. Der Grund für diese Implementierungsart ist schlicht und einfach um die Performanz zu erhöhen. Als Nebeneffekt entsteht, wie gesagt, eine Latenz. Es bieten sich mehrere Möglichkeiten an, diese Register-‚Hazards‘ in Hardware zu vermeiden (Registerscoring, Renaming, …). Um den Hardware-Implementierung klein und schnell zu halten wird in UCore auf einen Hardwaretest verzichtet. Als Resultat muss der Anwender Registerabhängigkeiten im Programm-Code behandeln.&lt;br /&gt;
Der einzige logische sinnvolle Nachteil ergibt sich in einer RAW (Read after Write) Abhängikeit, da die Latenz hier eine Cycle beträgt. In diesem Fall sollte/muss eine andere Instruktion (z.B. nop) eingefügt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreiben eines Registers und späteres lesen): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae	; &lt;br /&gt;
	nop		;write r0 = ae wird ausgeführt&lt;br /&gt;
	addi	r0,1	;r0 = r0 ($ae) + 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Im einfachsten Fall, sollte eine nop Operation bei solchen Abhängigkeit verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (nicht optimiert mit nop - 6 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	nop&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	nop&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In den meisten Fällen kann man aber andere Operationen als ‚Füllung‘ bei Registerabhängikeiten verwenden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (Optimiert - 4 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um versehentlich programmierte RAW-&#039;Hazards&#039; zu erkennen erzeugt der Assembler Warnungen, ebenfalls kann der Emulator zur Laufzeit diese &#039;Probleme&#039; erkennen.&lt;br /&gt;
Prinzipiell ist es möglich, in gewissen Situationen, RAW-&#039;Hazards&#039; absichtlich zuzulassen (Optimierungen um Register zu sparen), wovon aber im Normalfall abzuraten ist.&lt;br /&gt;
&lt;br /&gt;
=== Bedingungen ===&lt;br /&gt;
&lt;br /&gt;
UCore benutzt ein T-Bit (true Bit) um Bedingungen zu beschreiben/verarbeiten. Normalerweise wird dieses Bit von Vergleichsoperationen gesetzt und kann dann von Operationen benutzt werden welche das T-Bit intern verwenden (z.B. bedingte Sprünge).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel:====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	cmpeqi	r0,0		;vergleiche auf r0 gleich 0 wenn wahr da (t=1) ansonsten (t=0)&lt;br /&gt;
	brts	r0IstNull	;springe zu ‚r0IstNull‘ label wenn t set (t=1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist notwendig Register nur dann zu setzen wenn bestimmte Bedingungen eintreten. In diesen Fällen ist es ärgerlich bedingte Sprünge auszuführen, da sie etwas Zeit brauchen (Delay Slots) und den Programmcode unübersichtlich machen.&lt;br /&gt;
Aus diesem Grund, unterstützen einige Befehle eine Bedingte Ausführung (nicht jeder).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	move	r1,123&lt;br /&gt;
	move 	r2,23&lt;br /&gt;
	…&lt;br /&gt;
	cmplo	r0,r1		;r0 &amp;lt; r1&lt;br /&gt;
	movets	r0,r2,r0	;wenn ja r0 = r2 (23) ansonsten r0 = r0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sprünge ===&lt;br /&gt;
&lt;br /&gt;
Ein (bedingter) Sprung benötigt, wie jede andere Instruktion, einen Cycle um ausgeführt zu werden.&lt;br /&gt;
Da UCore keine Branchprediction bzw. keine spekulative Ausführung etc. unterstützt und es auch nicht gewollt ist Opcodes in der Pipeline zu verwerfen, entstehen nach Sprungbefehlen sogenannte &#039;Delay Slots&#039;. Die Anzahl dieser Delay Slots ergeben sich aus der Anzahl der Pipelinestufen vor der Ausführungseinheit (da sie den Programmcounter verändert).&lt;br /&gt;
Kurzum Programlauftechnisch werden Instruktionen in diesen Delay Slots ausgeführt bevor der Sprung in Wirklichkeit ausgeführt wird.&lt;br /&gt;
Die kleinste mögliche Schleife benötigt deshalb fünf Instruktionen für einen Durchlauf.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loop	br	loop		;branch zu loop&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In vielen Fällen können diese Delay Slots sinnvoll genutzt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 1 (nicht optimiert - 8 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,1	;r1 = x parameter&lt;br /&gt;
	movei	r1,7	;r2 = y parameter&lt;br /&gt;
	gpci	r7,2	;r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 1 (optimiert - 6 cycles): ====&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	gpci	r7,2	r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	movei	r0,1	;delay slot	r1 = x parameter&lt;br /&gt;
	movei	r1,7	;delay slot     r2 = y parameter&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 2 (nicht optimiert - 8 * n + 3 cycles -&amp;gt; if n 128 -&amp;gt; total 1027 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127	;r0 = loop counter - 1&lt;br /&gt;
	movei	r1,0	;r1 = Füllwert&lt;br /&gt;
	nop&lt;br /&gt;
	&lt;br /&gt;
loop	st	r1,r6	;imem[r1] = r6&lt;br /&gt;
	addi	r1,1	;r1++&lt;br /&gt;
	subi	r0,1	;r0-- (t clear bei &amp;lt; 0)&lt;br /&gt;
	brts	loop	;branch loop solange t set&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 2 (optimiert - 6 * n + 2 cycles -&amp;gt; if n 128 -&amp;gt; total 770 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127&lt;br /&gt;
	movei	r1,0&lt;br /&gt;
	&lt;br /&gt;
loop	subi	r0,1	;da t später verwendet wird nicht in delay slot benutzen (siehe  Interruptbenutzung)&lt;br /&gt;
	brts	loop&lt;br /&gt;
	st	r1,r6	;delay slot&lt;br /&gt;
	addi	r1,1	;delay slot	&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speicherzugriffe ===&lt;br /&gt;
&lt;br /&gt;
UCore besitzt keine ‚gewöhnlichen‘ Lesebefehle für interne/externe Speicherzugriffe.&lt;br /&gt;
Um Pipeline-Stalls beim Lesen von Daten zu vermeiden (Latenz zum Speicher), wird eine Lesebefehl in zwei Operationen aufgeteilt.&lt;br /&gt;
Der erste Befehl ist ein &#039;Request&#039;, er teilt dem Core mit von welcher Adresse er etwas lesen soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Der zweite Befehl ist dann der &#039;Load&#039;, er holt sich die angekommenen Daten ab und speichert sie in einem Register.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== interner Speicherzugriff ====&lt;br /&gt;
&lt;br /&gt;
Bei internen Speicherzugriffen ist die Latenz zwischen Request und Load statisch (3 Cycles), bei externen Zugriff variable (hier wird im Fall eines Load ohne vorhandene Daten ein Stall ausgelöst).&lt;br /&gt;
&lt;br /&gt;
Mit den Opcodes rqld (request load) und ld (load) kann vom internen Speicher gelesen werden.&lt;br /&gt;
Da die Daten erst zwei Operationen nach dem Request verfügbar sind, muss hier etwas anderes ausgeführt werde (z.B. nop).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0	;send load to address (r0+0)&lt;br /&gt;
	nop		;data send to memory&lt;br /&gt;
	nop		;data will read&lt;br /&gt;
	ld	r1	;readed data to r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Da der interne Speicher immer innerhalb von einem Cycles antwortet und die Latenz durch Pipelinestufen entsteht, kann man bei internen Speicherzugriff bis zu drei Request hintereinander verwenden.&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0&lt;br /&gt;
	rqld	r0,1&lt;br /&gt;
	rqld	r0,2&lt;br /&gt;
	ld	r1	;r1 &amp;lt;- internal_mem[r0+0]&lt;br /&gt;
	ld	r2	;r2 &amp;lt;- internal_mem[r0+1]&lt;br /&gt;
	ld	r3	;r3 &amp;lt;- internal_mem[r0+2]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Bei Schreibzugriffen wird wie bei anderen Prozessoren ein Store-Kommando verwendet.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti	$80	;imm exted&lt;br /&gt;
	move	r4,$01	;r4 = $8001&lt;br /&gt;
	move	r0,12	;r0 = 12&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	st	r0,r4	;imem[r4] = r0; $8001 = 12&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
Da ein &#039;st&#039;ore Befehl nur einen Register als Zieladresse benutzt, ist es vielen Fällen ärgerlich diesen bei mehrfachen Schreiben zu verändern. Um bei diesem Fall Abhilfe zu verschaffen wurde der Befehl ssto (Set Store Offset) und stwo (Store with Offset) eingeführt. Mit ssto kann ein Offset für stwo gesetzt werden, d.h. der Wert der mit ssto gesetzt wird auf die Zieladresse von stwo addiert.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	stwo 1&lt;br /&gt;
	ssto r0,r7 ;imem[r7+1] = r0&lt;br /&gt;
	stwo 2&lt;br /&gt;
	ssto r1,r7 ;imem[r7+2] = r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist es leider etwas unangenehm mit der statischen Latenz bei internen Lesezugriffen, da man hier etwas mehr schreiben muss als man es von anderen Prozessoren gewöhnt ist.&lt;br /&gt;
&lt;br /&gt;
==== externe Speicherzugriffe ====&lt;br /&gt;
&lt;br /&gt;
Externe Speicherzugriffe verhalten sich ähnlich wie interne Zugriff.&lt;br /&gt;
Unterschiede gibt es in der Adressbreite (extern 32Bit) und in der variablen Latenz (bestimmt durch mehre Faktoren).&lt;br /&gt;
Es gibt eine externe Hauptadresse (Base) die mit &#039;allen&#039; (bis auf edrqldi) externen Speicherzugriffsinstruktionen verwendet wird.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel Hauptadresse setzen: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel schreibe in externen Speicher: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r4,$af&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	esadr	r1,r0	;Hauptadresse (esadr) is r1:r0&lt;br /&gt;
	est	r4,0	;externSpeicher[esadr + 0] = r4&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
Beim Lesen vom externen Speicher werden auch Request/Load Befehle verwendet um Latenzen, wenn möglich, zu vermeiden. Da die Latenz nicht vorhersehbar ist, wird bei nicht vorhandenen Daten solange gewartet bis sie vorhanden sind (Stall).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
	erqld	0	;load from [r0:r1 + 0]&lt;br /&gt;
	eld	r7	;get external data (Stall solange bis Daten vorhanden)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um Lade/Schreiblatenzen zu vermeiden, können mehre Stores oder Request (laden) hintereinander ausgeführt werden (maximal 256 Requestzugriffe, keine Begrenzung bei Stores).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreibe 8 Worte in externen Speicher, kein Stall solange Schreibpuffer nicht voll): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,0&lt;br /&gt;
	esadr	r7,r6	;external address is r1:r0 &lt;br /&gt;
	est	r0,0&lt;br /&gt;
	est	r0,1&lt;br /&gt;
	est	r0,2&lt;br /&gt;
	est	r0,3&lt;br /&gt;
	est	r0,4&lt;br /&gt;
	est	r0,5&lt;br /&gt;
	est	r0,6&lt;br /&gt;
	est	r0,7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (vermeiden von Leselatenzen) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r7,r6&lt;br /&gt;
	erqld	0&lt;br /&gt;
	erqld	1&lt;br /&gt;
	erqld	2&lt;br /&gt;
	erqld	3	;request 4 Worte&lt;br /&gt;
	&lt;br /&gt;
	....		;mach irgendwas&lt;br /&gt;
	&lt;br /&gt;
	eld	r0	&lt;br /&gt;
	eld	r1&lt;br /&gt;
	eld	r2&lt;br /&gt;
	eld	r3	;bekomme Daten (evtl. kein Stall, da Daten schnellgenug da)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
=== Stack ===&lt;br /&gt;
&lt;br /&gt;
Der Stackpointer zeigt nach dem Reset auf Adresse $8000 (also am oberen Ende des internen Speichers).&lt;br /&gt;
Das Verhalten von push und request pops and pops sind gleich dem internen Speicherzugriffsverhalten (3 Cycles Latenz, Pipelined).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (1 pop): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r4	;sp--; imem[sp] = r4&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop		;request imem[sp], sp++&lt;br /&gt;
	nop&lt;br /&gt;
	nop&lt;br /&gt;
	pop	r4	;r4 = imem[sp]&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel (3 Werte auf Stack und wieder herunter) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r1&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r3&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop		;durch Latenz maximal 3 rqpop dann Daten (ansonsten &#039;poparqp&#039; benutzen (kann Request und Load gleichzeitig))&lt;br /&gt;
	push	r3&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
=== Decoder extend ===&lt;br /&gt;
&lt;br /&gt;
Da viele Operationen konstante Werte benutzen können, aber diese aus Gründen der Befehlsbreite (16 Bit) je nach Befehl/Operanten nur eine teilweise unzureichende Größe/Breite verwenden können wurde eine Dekoder Instruktion (dexti = decoder extend immediate) eingeführt. Dieser Befehl wird vom Dekoder ausgeführt und wird in der eigentlichen Ausführungseinheit ignoriert.&lt;br /&gt;
Sinn dieses Befehls ist es, konstante Werte um einen 8 Bit breiten Wert zu erweitern. Um Fehler zu vermeiden ist dieser Wert nur einen Cycle nach ‚dexti‘ verfügbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (16 Bit Immediate Addition) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti     $12&lt;br /&gt;
	addi	  r0,$34	;r0 = r0 + $1234&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interrupts ===&lt;br /&gt;
&lt;br /&gt;
Interrupts sind in einem Pipeline basierenden Design immer ärgerlich zu handhaben. Da UCore nicht, wie viele Mikrokontroller, möglichst kurze Interrupt-Latenzen ermöglichen muss, gibt es in diesem Design auch keine garantierten Zeiten in welchen der Interrupt ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
Um den Hardwareaufwand gering wie möglich zu halten, habe ich eine sogenannte Branch-Injektion implementiert. Der Hintergedanke ist, dass Sprünge sehr oft im Code ausgeführt werden und diese, im Fall eines Interrupts , dazu ‚missbraucht‘ werden können direkt zum Interrupt-Service-Vector zu springen anstatt ihren eigentlichen definierten Sprung auszuführen (dieser wird gespeichert und später ausgeführt).&lt;br /&gt;
&lt;br /&gt;
Der Vorteil dieser Implementierung ist ein sehr geringer Hardwareaufwand, der Nachteil ist, dass die Interrupt-Latenz variiert (Delta zwischen zwei Sprüngen) und sich Verhaltensregeln für ‚Delay-Slots‘ ergeben.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;	&lt;br /&gt;
	sei			;irq enable&lt;br /&gt;
	br	anySubroutine	;if irq is enabled and occure a branch is take to irq vector and after irq is finished (rte) the give branch will take&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In ‘Delay-Slots’ sollten kein T-Bit gesetzt werden, welches für spätere Verwendungen gebraucht wird. Außerdem sollten keine Speicher-Request an diesen Stellen ausgeführt werden.&lt;br /&gt;
Um Fehler zu vermeiden warnt der Assembler bei solchen Konstrukten.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
	sei&lt;br /&gt;
	br	anySubroutine&lt;br /&gt;
	addt	r0,r1	;delay slot	(t is not save in delay slot if irq is enabled, because t is only store at br instruction)&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Divdieren ===&lt;br /&gt;
&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
=== weiter Beispiele ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
=== UCtrl ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
== Homepage ==&lt;br /&gt;
&lt;br /&gt;
http://www.goldmomo.de&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82328</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82328"/>
		<updated>2014-03-27T17:34:20Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: /* Vergleiche */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein ‚Computer‘system, das nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses kopiert. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen das vollständig* selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (*FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL benutzt, für Emulation und Tools (Assembler etc.) wird C# mit .NET verwendet.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 benutzt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE) der über einen Memorymapped UCTRL-Komponente vollständigen Zugriff auf die Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Audio Interface (Stereo mit max. 24Bit / 96 KHz) &lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Timer/Counter&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCore = Utility Core) ist der ‚zentrale‘ Prozessor im System, er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist gedacht um einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn für alle meine Demos/Spiele als ‚CPU‘ benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* ‚RISC‘ Design&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In einen experimentellen Zustand befindet sich noch der HCORE Block. Dieser Block enthält mehre (konfigurierbar) 32 Bit Prozessoren die über spezielle Techniken (Hardwaresemaphoren, parallele Sprünge, … ) eine parallele Verarbeitung der Software vereinfachen sollen und die Latenzprobleme bei Multithreading vermeiden. Ich habe bisher ein Demo mit 16 parallel laufenden HCOREs veröffentlicht, alle anderen Demos benutzen diese Cores nicht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Momentane Charakteristiken eines HCOREs sind:&lt;br /&gt;
&lt;br /&gt;
*‚Risc‘ Design &lt;br /&gt;
*7 Stufen Pipeline mit „in order“ und „out of order“ Pfad&lt;br /&gt;
*Instruction Cache (konfigurierbar (momentan 8 Wege mit 64 Worten))&lt;br /&gt;
*32 Bit ALU (Hold to Last Pfad, …) &lt;br /&gt;
*128 GP Register&lt;br /&gt;
*UCtrl/Memory/Semaphoren/… out of order Zugriff&lt;br /&gt;
*…&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
[[Datei:Goldmomo emulator.png|miniatur|rechts|Emulator]]&lt;br /&gt;
Um die Softwareentwicklung (und Debuggen) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Register, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (auch in Emulator integriert), ein Compiler existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/2n1o8dfium4bdgi/TK_Da_o4rx/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/310121#new&lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= UCORE Programmierung =&lt;br /&gt;
&lt;br /&gt;
UCore (Utility Core) ist ein Eigenimplementierung  eines 16 Bit Prozessor. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Grundlegende Charakteristiken:&lt;br /&gt;
&lt;br /&gt;
* sechsstufige Pipeline&lt;br /&gt;
* 8 Generalpurpose Registern&lt;br /&gt;
* interne Speicher in dem Code/Daten liegen&lt;br /&gt;
* externen Speicher Zugriff (32Bit-Adressraum) möglich&lt;br /&gt;
* die Datenwortbreite beträgt immer 16 Bit (es gibt keine Bytes)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Weiterhin unterscheidet sich UCore einigen Dingen von einem &#039;normalen&#039; Prozessor (RISC-)Design, die Ziele die hier verfolgt wurden, waren eine möglichst hohe Taktrate und ein möglichst geringer Aufwand von Hardwareressourcen, aber dennoch eine hohe Verarbeitungsgeschwindigkeit zu erreichen.&lt;br /&gt;
Dadurch ergeben sich einige Besonderheiten die bei der Programmierung beachtet werden müssen (siehe Registerzugriffe, Branch/Jump Delayslots, Request/Load Zugriffe).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pipeline ===&lt;br /&gt;
&lt;br /&gt;
Wie gesagt hat dieser Core eine sechsstufige Pipeline:&lt;br /&gt;
&lt;br /&gt;
# Prepare Fetch  &lt;br /&gt;
# Fetch &lt;br /&gt;
# Decode &lt;br /&gt;
# Read Register &lt;br /&gt;
# Execute &lt;br /&gt;
# Write Register (hat einen Bypass zu Stufe 4) &lt;br /&gt;
&lt;br /&gt;
Jede Instruktion wird in einem Cycle ausgeführt, nur der externe Speicherzugriff (nur Daten) kann einen Stall (Stillstand) der Pipeline verursachen.&lt;br /&gt;
== Interne Memory Map (Standardkonfiguration) ==&lt;br /&gt;
In meinem System wird die folgende interne Speichermap verwendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$0000 code / data memory&lt;br /&gt;
*     16384 * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$3fff&lt;br /&gt;
$4000 code / data memory MIRROR&lt;br /&gt;
*     &lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$7fff&lt;br /&gt;
$8000 ctrl / memory			StackPointer start at $8000 on reset&lt;br /&gt;
*     XXXX * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$XXXX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Reset-Vektor befindet sich an Adresse 0, der Stackpointer an Adresse $8000. &lt;br /&gt;
Der Interruptvektor an Adresse $10 (sollte nach dem Reset an die benötigte Position verschoben werden).&lt;br /&gt;
Ab Adresse $8000 wird die Komponente UCtrl in den Adressraum ‚gemappt‘ (diese Komponente enthält Register für externe Hardware Peripherie etc.).&lt;br /&gt;
== externe Memory Map (Standardkonfiguration) ==&lt;br /&gt;
Über den &#039;externen&#039; Datenbus kann auf folgende Komponenten zugegriffen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$a000 0000 - $a000 001f SDCard-Controller&lt;br /&gt;
$d000 0000 - $d3ff ffff SDRAM&lt;br /&gt;
$e000 0000 - $e03f ffff FLASH&lt;br /&gt;
$f000 0000 - $f00f ffff SRAM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei den meisten meiner Programme wird ein Standard-Programm aus dem FLASH-Speicher gelesen, welches dann einen Speichertest ausführt und auf das Einlegen einer SD-Karte mit dem zuladenden Programm wartet.&lt;br /&gt;
&lt;br /&gt;
== Opcodes/Operanten ==&lt;br /&gt;
&lt;br /&gt;
UCore hat keine &#039;RISC&#039;-Typischen Befehlssatz.&lt;br /&gt;
Da ein Instruktions-Wort nur 16 Bit breit ist, können nur bedingte Mengen an Operanden verwendet werden. Um jedoch die Programmierung flexibler zu gestalten, haben viele Opcodes mehrere Arten von Operanden. Es ergibt sich keine nachteilige Auswirkung auf die Ausführungseinheit, nur der Decoder ist etwas komplexer als bei anderen RISC Designs.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Operanten Formate ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dc,imm8&lt;br /&gt;
 dc,db,da&lt;br /&gt;
 dc,db,imm3&lt;br /&gt;
 imm12&lt;br /&gt;
 db,da&lt;br /&gt;
 imm6&lt;br /&gt;
 da&lt;br /&gt;
 kein Operant&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Opcode / Operante(n) / Beschreibung ==== &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
movei     	dc,imm8		dc = imm&lt;br /&gt;
moveih    	dc,imm8		dc[15..8] = imm &amp;lt;&amp;lt; 8 | dc[7..0]&lt;br /&gt;
addi      	dc,imm8		dc = dc + imm&lt;br /&gt;
subi      	dc,imm8		dc = dc - imm&lt;br /&gt;
lsri      	dc,imm8		dc = dc &amp;gt;&amp;gt; imm&lt;br /&gt;
asri      	dc,imm8		dc = ((signed)dc) &amp;gt;&amp;gt; imm&lt;br /&gt;
muli      	dc,imm8		dc = dc * imm&lt;br /&gt;
cmpeqi    	dc,imm8		t = set if dc == imm else cleared&lt;br /&gt;
cmploi    	dc,imm8		t = set if dc &amp;lt; imm else cleared&lt;br /&gt;
cmplosi   	dc,imm8		t = set if  (signed)dc &amp;lt; (signed) imm else cleared&lt;br /&gt;
gpci      	dc,imm8		dc = pc + imm&lt;br /&gt;
jmpi      	dc,imm8		pc = dc + imm&lt;br /&gt;
extri     	dc,imm8		t = bit #imm of dc&lt;br /&gt;
rqldi     	dc,imm8		request (internal) mem; address = dc + imm&lt;br /&gt;
getsp     	dc,imm8		dc = sp + imm&lt;br /&gt;
dexti     	imm11		store imm as extension for next instruction&lt;br /&gt;
&lt;br /&gt;
add		dc,db,da	dc = db + da&lt;br /&gt;
sub     	dc,db,da	dc = db - da&lt;br /&gt;
lsr     	dc,db,da	dc = db &amp;gt;&amp;gt; da&lt;br /&gt;
asr     	dc,db,da	dc = ((signed)db) &amp;gt;&amp;gt; da&lt;br /&gt;
mul     	dc,db,da	dc = db * da&lt;br /&gt;
addt    	dc,db,da	dc = db + da + t&lt;br /&gt;
subt    	dc,db,da	dc = db - da - t&lt;br /&gt;
muls    	dc,db,da	dc = db * da&lt;br /&gt;
movets  	dc,db,da	dc = db if t = set else da&lt;br /&gt;
and     	dc,db,da	dc = db &amp;amp; da&lt;br /&gt;
or      	dc,db,da	dc = db | da&lt;br /&gt;
xor     	dc,db,da	dc = db ^ da&lt;br /&gt;
bic     	dc,db,da	dc = db &amp;amp; ~da&lt;br /&gt;
&lt;br /&gt;
addqi		dc,db,imm3	dc = db + imm&lt;br /&gt;
subqi   	dc,db,imm3	dc = db - imm&lt;br /&gt;
lsrqi   	dc,db,imm3	dc = db &amp;gt;&amp;gt; imm&lt;br /&gt;
asrqi   	dc,db,imm3	dc = ((signed)db) &amp;gt;&amp;gt; imm&lt;br /&gt;
mulqi   	dc,db,imm3	dc = db * imm3&lt;br /&gt;
addtqi  	dc,db,imm3	dc = db + imm + t&lt;br /&gt;
subtqi  	dc,db,imm3	dc = db - imm - t&lt;br /&gt;
edrqldi 	db,da,imm3	request (external) mem; address = (db:da) + imm3&lt;br /&gt;
&lt;br /&gt;
br		imm12		pc = pc + signed(imm)&lt;br /&gt;
brts		imm12		pc = pc + signed(imm) if t is set&lt;br /&gt;
brtc		imm12		pc = pc + signed(imm) if t is cleared&lt;br /&gt;
	             &lt;br /&gt;
cmpeq		db,da		t = set if db == da else cleared		&lt;br /&gt;
cmplo   	db,da           t = set if db &amp;lt; da else cleared&lt;br /&gt;
cmplos  	db,da           t = set if  (signed)db &amp;lt; (signed) da else cleared&lt;br /&gt;
esadr   	db,da		esadr = db:da&lt;br /&gt;
swp     	db,da		db = da[7..0]:da[15..8] &lt;br /&gt;
swptc   	db,da		db = da[7..0]:da[15..8] if t = set else da&lt;br /&gt;
st      	db,da		imem[db] = da&lt;br /&gt;
stinc   	db,da		imem[db] = da; db = db + 1&lt;br /&gt;
bffo    	db,da		db is first bit that is 1 found in da (from MSB to LSB)&lt;br /&gt;
bset    	db,da		db = db | 1 &amp;lt;&amp;lt; da&lt;br /&gt;
bclr    	db,da		db = db &amp;amp; ~ (1 &amp;lt;&amp;lt; da)&lt;br /&gt;
cmple   	db,da		t = set if db &amp;lt;= da else cleared&lt;br /&gt;
cmples  	db,da		t = set if  (signed)db &amp;lt;= (signed) da else cleared&lt;br /&gt;
rqld    	db,da		request (internal) mem; address = db + da&lt;br /&gt;
extb    	db,da		db = da byte to word singed extended&lt;br /&gt;
stwo    	db,da		imem[db + STORE_OFFSET] = da&lt;br /&gt;
andts   	db,da		db = db &amp;amp; da if t = set else da&lt;br /&gt;
orts    	db,da           db = db | da if t = set else da&lt;br /&gt;
xorts   	db,da           db = db ^ da if t = set else da&lt;br /&gt;
bicts   	db,da           db = db &amp;amp; ~da if t = set else da&lt;br /&gt;
lsrts   	db,da		db = db &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
asrts   	db,da           db = ((signed)db) &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
mults   	db,da           db = db * da if t = set else da&lt;br /&gt;
mulsts  	db,da		db = (signed)db * (signed)da if t = set else da&lt;br /&gt;
&lt;br /&gt;
erqldi		imm6		request (external) mem; address = esadr + imm	&lt;br /&gt;
ssto		imm6		STORE_OFFSET = imm&lt;br /&gt;
udivinit	imm6		udivqoutient = 0; udivrest = 0; udivbitcounter = imm&lt;br /&gt;
&lt;br /&gt;
eld		da		da = requested value from external memory&lt;br /&gt;
push            da		sp = sp – 1; imem[sp] = da&lt;br /&gt;
gmulhi          da		da = multiply result [31..15] from last multiplication&lt;br /&gt;
ld/pop          da		da = requested value from internal memory&lt;br /&gt;
poparqp         da		da = requested value from internal memory; request in internal memory adr = sp; sp = sp + 1&lt;br /&gt;
neg             da		da = 0 - da&lt;br /&gt;
udivgq          da		get division qoutinent&lt;br /&gt;
udivgr          da		get division remainder&lt;br /&gt;
udivgqh         da		get division qoutinent high [31 ..16]&lt;br /&gt;
udivgrh         da              get division remainder high [31 ..16]&lt;br /&gt;
udivsdd         da		set division divident &lt;br /&gt;
udivsdv         da		set division divider&lt;br /&gt;
udivsddh        da		set division divident high [31 ..16]&lt;br /&gt;
udivsdvh        da		set division divider  high [31 ..16]&lt;br /&gt;
erqld           da		request (external) mem; address = esadr + da&lt;br /&gt;
setsp           da		sp = da&lt;br /&gt;
erqldb          da		request (external) mem; address = esadr + da / 2&lt;br /&gt;
jmpts           da		pc = da if t = set&lt;br /&gt;
jmptc           da		pc = da if t = cleared&lt;br /&gt;
negts           da		da = 0 - da if t = set else da&lt;br /&gt;
&lt;br /&gt;
rqpop				internal memory request address = sp; sp = sp + 1&lt;br /&gt;
cli				disable interrupts&lt;br /&gt;
sei				enable interrupts&lt;br /&gt;
rti				pc = pc_before interrput&lt;br /&gt;
tnt				t = not t&lt;br /&gt;
vtt				t = v (overflow/underflow wrom add/sub)			&lt;br /&gt;
epushsadrl			sp = sp – 1; imem[sp] = esadr[15..0]&lt;br /&gt;
epushsadrh			sp = sp – 1; imem[sp] = esadr[31..16]&lt;br /&gt;
epopsadrl			esadr[15..0] = requested value from internal memory&lt;br /&gt;
epopsadrh			esadr[31..16] = requested value from internal memory&lt;br /&gt;
udivstep			performe one division step &lt;br /&gt;
nop				do nothing&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registerzugriffe ===&lt;br /&gt;
&lt;br /&gt;
Um ein ‚Registerscoring‘ und/oder extra Pipeline-Stalls zu vermeiden, muss man bei Registerabhängigkeiten (RAW = Read after Write) mindestens einen Cycle warten bzw. eine andere Operation ausführen.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreiben eines Registers und späteres lesen): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae	; &lt;br /&gt;
	nop		;write r0 = ae wird ausgeführt&lt;br /&gt;
	addi	r0,1	;r0 = r0 ($ae) + 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Im einfachsten Fall, sollte eine nop Operation bei solchen Abhängigkeit verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (nicht optimiert mit nop - 6 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	nop&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	nop&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In den meisten Fällen kann man aber andere Operationen als ‚Füllung‘ bei Registerabhängikeiten verwenden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (Optimiert - 4 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um versehentlich solche ‚Hazards‘ zu erkennen erzeugt der Assembler Warnungen, ebenfalls kann der Emulator zur Laufzeit solche Probleme erkennen.&lt;br /&gt;
Prinzipiell ist es möglich, in gewissen Situationen, Hazards absichtlich zuzulassen (Optimierungen um Register zu sparen), wovon aber im Normalfall abzuraten ist.&lt;br /&gt;
&lt;br /&gt;
=== Bedingungen ===&lt;br /&gt;
&lt;br /&gt;
UCore benutzt ein T-Bit (true Bit) um Bedingungen zu verarbeiten. Grundsätzlich wird dieses Bit von Vergleichsoperationen gesetzt und kann dann von Operationen benutzt werden welche das T-Bit intern verwenden (z.B. bedingte Sprünge).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel:====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	cmpeqi	r0,0		;vergleiche auf r0 gleich 0 wenn wahr da (t=1) ansonsten (t=0)&lt;br /&gt;
	brts	r0IstNull	;springe zu ‚r0IstNull‘ label wenn t set (t=1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist notwendig Register nur dann zu setzen wenn bestimmte Bedingungen eintreten. In diesen Fällen ist es ärgerlich bedingte Sprünge auszuführen, da sie etwas Zeit brauchen (Delay Slots) und den Programmcode unübersichtlich machen.&lt;br /&gt;
Aus diesem Grund unterstützen einige Befehle eine Bedingte Ausführung (nicht jeder).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	move	r1,123&lt;br /&gt;
	move 	r2,23&lt;br /&gt;
	…&lt;br /&gt;
	cmplo	r0,r1		;r0 &amp;lt; r1&lt;br /&gt;
	movets	r0,r2,r0	;wenn ja r0 = r2 (23) ansonsten r0 = r0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sprünge ===&lt;br /&gt;
&lt;br /&gt;
Ein (bedingter) Sprung benötigt, wie jede andere Instruktion, einen Cycle um ausgeführt zu werden.&lt;br /&gt;
Da UCore keine Branchprediction bzw. keine spekulative Ausführung unterstützt und es auch nicht gewollt ist Opcodes in der Pipeline zu verwerfen, entstehen nach Sprungbefehlen sogenannte &#039;Delay Slots&#039;. Die Anzahl dieser Delay Slots ergeben sich aus der Anzahl der Pipelinestufen vor der Ausführungseinheit (da sie den Programmcounter verändert).&lt;br /&gt;
Kurzum Programlauftechnisch werden Instruktionen in diesen Delay Slots ausgeführt bevor der Sprung in Wirklichkeit ausgeführt wird.&lt;br /&gt;
Die kleinste mögliche Schleife benötigt deshalb fünf Instruktionen für einen Durchlauf.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loop	br	loop		;branch zu loop&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In vielen Fällen können diese Delay Slots sinnvoll genutzt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 1 (nicht optimiert - 8 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,1	;r1 = x parameter&lt;br /&gt;
	movei	r1,7	;r2 = y parameter&lt;br /&gt;
	gpci	r7,2	;r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 1 (optimiert - 6 cycles): ====&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	gpci	r7,2	r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	movei	r0,1	;delay slot	r1 = x parameter&lt;br /&gt;
	movei	r1,7	;delay slot     r2 = y parameter&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 2 (nicht optimiert - 8 * n + 3 cycles -&amp;gt; if n 128 -&amp;gt; total 1027 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127	;r0 = loop counter - 1&lt;br /&gt;
	movei	r1,0	;r1 = Füllwert&lt;br /&gt;
	nop&lt;br /&gt;
	&lt;br /&gt;
loop	st	r1,r6	;imem[r1] = r6&lt;br /&gt;
	addi	r1,1	;r1++&lt;br /&gt;
	subi	r0,1	;r0-- (t clear bei &amp;lt; 0)&lt;br /&gt;
	brts	loop	;branch loop solange t set&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 2 (optimiert - 6 * n + 2 cycles -&amp;gt; if n 128 -&amp;gt; total 770 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127&lt;br /&gt;
	movei	r1,0&lt;br /&gt;
	&lt;br /&gt;
loop	subi	r0,1	;da t später verwendet wird nicht in delay slot benutzen (siehe  Interruptbenutzung)&lt;br /&gt;
	brts	loop&lt;br /&gt;
	st	r1,r6	;delay slot&lt;br /&gt;
	addi	r1,1	;delay slot	&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speicherzugriffe ===&lt;br /&gt;
&lt;br /&gt;
UCore besitzt keine ‚gewöhnlichen‘ Lesebefehle für interne/externe Speicherzugriffe.&lt;br /&gt;
Um Pipeline-Stalls beim Lesen von Daten zu vermeiden (Latenz zum Speicher), wird eine Lesebefehl in zwei Operationen aufgeteilt.&lt;br /&gt;
Der erste Befehl ist ein &#039;Request&#039;, er teilt dem Core mit von welcher Adresse er etwas lesen soll.&lt;br /&gt;
Der zweite Befehl ist dann der &#039;Load&#039;, er holt sich die angekommenen Daten ab und speichert sie in einem Register.&lt;br /&gt;
==== interner Speicherzugriff ====&lt;br /&gt;
Bei internen Speicherzugriffen ist die Latenz zwischen Request und Load statisch (3 Cycles), bei externen Zugriff variable (hier wird im Fall eines Load ohne vorhandene Daten ein Stall ausgelöst).&lt;br /&gt;
Mit den Opcodes rqld (request load) und ld (load) kann vom internen Speicher gelesen werden.&lt;br /&gt;
Da die Daten erst zwei Operationen nach dem Request verfügbar sind, muss hier etwas anderes ausgeführt werde (z.B. nop).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0	;send load to address (r0+0)&lt;br /&gt;
	nop		;data send to memory&lt;br /&gt;
	nop		;data will read&lt;br /&gt;
	ld	r1	;readed data to r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Da der interne Speicher immer innerhalb von einem Cycles antwortet und die Latenz durch Pipelinestufen entsteht, kann man bei internen Speicherzugriff bis zu drei Request hintereinander verwenden.&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0&lt;br /&gt;
	rqld	r0,1&lt;br /&gt;
	rqld	r0,2&lt;br /&gt;
	ld	r1	;r1 &amp;lt;- internal_mem[r0+0]&lt;br /&gt;
	ld	r2	;r2 &amp;lt;- internal_mem[r0+1]&lt;br /&gt;
	ld	r3	;r3 &amp;lt;- internal_mem[r0+2]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Bei Schreibzugriffen wird wie bei anderen Prozessoren ein Store-Kommando verwendet.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti	$80	;imm exted&lt;br /&gt;
	move	r4,$01	;r4 = $8001&lt;br /&gt;
	move	r0,12	;r0 = 12&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	st	r0,r4	;imem[r4] = r0; $8001 = 12&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist es leider etwas unangenehm mit der statischen Latenz bei internen Lesezugriffen, da man hier etwas mehr schreiben muss als man es von anderen Prozessoren gewöhnt ist.&lt;br /&gt;
&lt;br /&gt;
==== externe Speicherzugriffe ====&lt;br /&gt;
&lt;br /&gt;
Externe Speicherzugriffe verhalten sich ähnlich wie interne Zugriff.&lt;br /&gt;
Unterschiede gibt es in der Adressbreite (extern 32Bit) und in der variablen Latenz (bestimmt durch mehre Faktoren).&lt;br /&gt;
Es gibt eine externe Hauptadresse (Base) die mit &#039;allen&#039; (bis auf edrqldi) externen Speicherzugriffsinstruktionen verwendet wird.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel Hauptadresse setzen: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel schreibe in externen Speicher: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r4,$af&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	esadr	r1,r0	;Hauptadresse (esadr) is r1:r0&lt;br /&gt;
	est	r4,0	;externSpeicher[esadr + 0] = r4&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
Beim Lesen vom externen Speicher werden auch Request/Load Befehle verwendet um Latenzen, wenn möglich, zu vermeiden. Da die Latenz nicht vorhersehbar ist wird bei nicht vorhandenen Daten solange gewartet bis sie vorhanden sind (Stall).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
	erqld	0	;load from [r0:r1 + 0]&lt;br /&gt;
	eld	r7	;get external data (Stall solange bis Daten vorhanden)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um Lade/Schreiblatenzen zu vermeiden, können mehre Stores oder Request (laden) hintereinander ausgeführt werden (maximal 256 Requestzugriffe, keine Begrenzung bei Stores).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreibe 8 Worte in externen Speicher, kein Stall solange Schreibpuffer nicht voll): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,0&lt;br /&gt;
	esadr	r7,r6	;external address is r1:r0 &lt;br /&gt;
	est	r0,0&lt;br /&gt;
	est	r0,1&lt;br /&gt;
	est	r0,2&lt;br /&gt;
	est	r0,3&lt;br /&gt;
	est	r0,4&lt;br /&gt;
	est	r0,5&lt;br /&gt;
	est	r0,6&lt;br /&gt;
	est	r0,7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (vermeiden von Leselatenzen) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r7,r6&lt;br /&gt;
	erqld	0&lt;br /&gt;
	erqld	1&lt;br /&gt;
	erqld	2&lt;br /&gt;
	erqld	3	;request 4 Worte&lt;br /&gt;
	&lt;br /&gt;
	....		;mach irgendwas&lt;br /&gt;
	&lt;br /&gt;
	eld	r0	&lt;br /&gt;
	eld	r1&lt;br /&gt;
	eld	r2&lt;br /&gt;
	eld	r3	;bekomme Daten (evtl. kein Stall, da Daten schnellgenug da)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
=== Stack ===&lt;br /&gt;
&lt;br /&gt;
Der Stackpointer zeigt nach dem Reset auf Adresse $8000 (also am oberen Ende des internen Speichers).&lt;br /&gt;
Das Verhalten von push und request pops and pops sind gleich dem internen Speicherzugriffsverhalten (3 Cycles Latenz, Pipelined).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (1 pop): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r4	;sp--; imem[sp] = r4&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop		;request imem[sp], sp++&lt;br /&gt;
	nop&lt;br /&gt;
	nop&lt;br /&gt;
	pop	r4	;r4 = imem[sp]&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel (3 Werte auf Stack und wieder herunter) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r1&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r3&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop		;durch Latenz maximal 3 rqpop dann Daten (ansonsten &#039;poparqp&#039; benutzen (kann Request und Load gleichzeitig))&lt;br /&gt;
	push	r3&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
=== Decoder extend ===&lt;br /&gt;
später&lt;br /&gt;
=== Interrupts ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
=== Divdieren ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
=== weiter Beispiele ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
=== UCtrl ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
== Homepage ==&lt;br /&gt;
&lt;br /&gt;
http://www.goldmomo.de&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82327</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82327"/>
		<updated>2014-03-27T17:24:12Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: habe etwas über die Programmierung von meinem 16 Bit Core geschrieben&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein ‚Computer‘system, das nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses kopiert. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen das vollständig* selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (*FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL benutzt, für Emulation und Tools (Assembler etc.) wird C# mit .NET verwendet.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 benutzt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE) der über einen Memorymapped UCTRL-Komponente vollständigen Zugriff auf die Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Audio Interface (Stereo mit max. 24Bit / 96 KHz) &lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Timer/Counter&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCore = Utility Core) ist der ‚zentrale‘ Prozessor im System, er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist gedacht um einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn für alle meine Demos/Spiele als ‚CPU‘ benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* ‚RISC‘ Design&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In einen experimentellen Zustand befindet sich noch der HCORE Block. Dieser Block enthält mehre (konfigurierbar) 32 Bit Prozessoren die über spezielle Techniken (Hardwaresemaphoren, parallele Sprünge, … ) eine parallele Verarbeitung der Software vereinfachen sollen und die Latenzprobleme bei Multithreading vermeiden. Ich habe bisher ein Demo mit 16 parallel laufenden HCOREs veröffentlicht, alle anderen Demos benutzen diese Cores nicht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Momentane Charakteristiken eines HCOREs sind:&lt;br /&gt;
&lt;br /&gt;
*‚Risc‘ Design &lt;br /&gt;
*7 Stufen Pipeline mit „in order“ und „out of order“ Pfad&lt;br /&gt;
*Instruction Cache (konfigurierbar (momentan 8 Wege mit 64 Worten))&lt;br /&gt;
*32 Bit ALU (Hold to Last Pfad, …) &lt;br /&gt;
*128 GP Register&lt;br /&gt;
*UCtrl/Memory/Semaphoren/… out of order Zugriff&lt;br /&gt;
*…&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
[[Datei:Goldmomo emulator.png|miniatur|rechts|Emulator]]&lt;br /&gt;
Um die Softwareentwicklung (und Debuggen) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Register, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (auch in Emulator integriert), ein Compiler existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/2n1o8dfium4bdgi/TK_Da_o4rx/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/310121#new&lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= UCORE Programmierung =&lt;br /&gt;
&lt;br /&gt;
UCore (Utility Core) ist ein Eigenimplementierung  eines 16 Bit Prozessor. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Grundlegende Charakteristiken:&lt;br /&gt;
&lt;br /&gt;
* sechsstufige Pipeline&lt;br /&gt;
* 8 Generalpurpose Registern&lt;br /&gt;
* interne Speicher in dem Code/Daten liegen&lt;br /&gt;
* externen Speicher Zugriff (32Bit-Adressraum) möglich&lt;br /&gt;
* die Datenwortbreite beträgt immer 16 Bit (es gibt keine Bytes)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Weiterhin unterscheidet sich UCore einigen Dingen von einem &#039;normalen&#039; Prozessor (RISC-)Design, die Ziele die hier verfolgt wurden, waren eine möglichst hohe Taktrate und ein möglichst geringer Aufwand von Hardwareressourcen, aber dennoch eine hohe Verarbeitungsgeschwindigkeit zu erreichen.&lt;br /&gt;
Dadurch ergeben sich einige Besonderheiten die bei der Programmierung beachtet werden müssen (siehe Registerzugriffe, Branch/Jump Delayslots, Request/Load Zugriffe).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pipeline ===&lt;br /&gt;
&lt;br /&gt;
Wie gesagt hat dieser Core eine sechsstufige Pipeline:&lt;br /&gt;
&lt;br /&gt;
# Prepare Fetch  &lt;br /&gt;
# Fetch &lt;br /&gt;
# Decode &lt;br /&gt;
# Read Register &lt;br /&gt;
# Execute &lt;br /&gt;
# Write Register (hat einen Bypass zu Stufe 4) &lt;br /&gt;
&lt;br /&gt;
Jede Instruktion wird in einem Cycle ausgeführt, nur der externe Speicherzugriff (nur Daten) kann einen Stall (Stillstand) der Pipeline verursachen.&lt;br /&gt;
== Interne Memory Map (Standardkonfiguration) ==&lt;br /&gt;
In meinem System wird die folgende interne Speichermap verwendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$0000 code / data memory&lt;br /&gt;
*     16384 * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$3fff&lt;br /&gt;
$4000 code / data memory MIRROR&lt;br /&gt;
*     &lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$7fff&lt;br /&gt;
$8000 ctrl / memory			StackPointer start at $8000 on reset&lt;br /&gt;
*     XXXX * 16 bit&lt;br /&gt;
*&lt;br /&gt;
*&lt;br /&gt;
$XXXX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Reset-Vektor befindet sich an Adresse 0, der Stackpointer an Adresse $8000. &lt;br /&gt;
Der Interruptvektor an Adresse $10 (sollte nach dem Reset an die benötigte Position verschoben werden).&lt;br /&gt;
Ab Adresse $8000 wird die Komponente UCtrl in den Adressraum ‚gemappt‘ (diese Komponente enthält Register für externe Hardware Peripherie etc.).&lt;br /&gt;
== externe Memory Map (Standardkonfiguration) ==&lt;br /&gt;
Über den &#039;externen&#039; Datenbus kann auf folgende Komponenten zugegriffen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$a000 0000 - $a000 001f SDCard-Controller&lt;br /&gt;
$d000 0000 - $d3ff ffff SDRAM&lt;br /&gt;
$e000 0000 - $e03f ffff FLASH&lt;br /&gt;
$f000 0000 - $f00f ffff SRAM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei den meisten meiner Programme wird ein Standard-Programm aus dem FLASH-Speicher gelesen, welches dann einen Speichertest ausführt und auf das Einlegen einer SD-Karte mit dem zuladenden Programm wartet.&lt;br /&gt;
&lt;br /&gt;
== Opcodes/Operanten ==&lt;br /&gt;
&lt;br /&gt;
UCore hat keine &#039;RISC&#039;-Typischen Befehlssatz.&lt;br /&gt;
Da ein Instruktions-Wort nur 16 Bit breit ist, können nur bedingte Mengen an Operanden verwendet werden. Um jedoch die Programmierung flexibler zu gestalten, haben viele Opcodes mehrere Arten von Operanden. Es ergibt sich keine nachteilige Auswirkung auf die Ausführungseinheit, nur der Decoder ist etwas komplexer als bei anderen RISC Designs.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Operanten Formate ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dc,imm8&lt;br /&gt;
 dc,db,da&lt;br /&gt;
 dc,db,imm3&lt;br /&gt;
 imm12&lt;br /&gt;
 db,da&lt;br /&gt;
 imm6&lt;br /&gt;
 da&lt;br /&gt;
 kein Operant&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Opcode / Operante(n) / Beschreibung ==== &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
movei     	dc,imm8		dc = imm&lt;br /&gt;
moveih    	dc,imm8		dc[15..8] = imm &amp;lt;&amp;lt; 8 | dc[7..0]&lt;br /&gt;
addi      	dc,imm8		dc = dc + imm&lt;br /&gt;
subi      	dc,imm8		dc = dc - imm&lt;br /&gt;
lsri      	dc,imm8		dc = dc &amp;gt;&amp;gt; imm&lt;br /&gt;
asri      	dc,imm8		dc = ((signed)dc) &amp;gt;&amp;gt; imm&lt;br /&gt;
muli      	dc,imm8		dc = dc * imm&lt;br /&gt;
cmpeqi    	dc,imm8		t = set if dc == imm else cleared&lt;br /&gt;
cmploi    	dc,imm8		t = set if dc &amp;lt; imm else cleared&lt;br /&gt;
cmplosi   	dc,imm8		t = set if  (signed)dc &amp;lt; (signed) imm else cleared&lt;br /&gt;
gpci      	dc,imm8		dc = pc + imm&lt;br /&gt;
jmpi      	dc,imm8		pc = dc + imm&lt;br /&gt;
extri     	dc,imm8		t = bit #imm of dc&lt;br /&gt;
rqldi     	dc,imm8		request (internal) mem; address = dc + imm&lt;br /&gt;
getsp     	dc,imm8		dc = sp + imm&lt;br /&gt;
dexti     	imm11		store imm as extension for next instruction&lt;br /&gt;
&lt;br /&gt;
add		dc,db,da	dc = db + da&lt;br /&gt;
sub     	dc,db,da	dc = db - da&lt;br /&gt;
lsr     	dc,db,da	dc = db &amp;gt;&amp;gt; da&lt;br /&gt;
asr     	dc,db,da	dc = ((signed)db) &amp;gt;&amp;gt; da&lt;br /&gt;
mul     	dc,db,da	dc = db * da&lt;br /&gt;
addt    	dc,db,da	dc = db + da + t&lt;br /&gt;
subt    	dc,db,da	dc = db - da - t&lt;br /&gt;
muls    	dc,db,da	dc = db * da&lt;br /&gt;
movets  	dc,db,da	dc = db if t = set else da&lt;br /&gt;
and     	dc,db,da	dc = db &amp;amp; da&lt;br /&gt;
or      	dc,db,da	dc = db | da&lt;br /&gt;
xor     	dc,db,da	dc = db ^ da&lt;br /&gt;
bic     	dc,db,da	dc = db &amp;amp; ~da&lt;br /&gt;
&lt;br /&gt;
addqi		dc,db,imm3	dc = db + imm&lt;br /&gt;
subqi   	dc,db,imm3	dc = db - imm&lt;br /&gt;
lsrqi   	dc,db,imm3	dc = db &amp;gt;&amp;gt; imm&lt;br /&gt;
asrqi   	dc,db,imm3	dc = ((signed)db) &amp;gt;&amp;gt; imm&lt;br /&gt;
mulqi   	dc,db,imm3	dc = db * imm3&lt;br /&gt;
addtqi  	dc,db,imm3	dc = db + imm + t&lt;br /&gt;
subtqi  	dc,db,imm3	dc = db - imm - t&lt;br /&gt;
edrqldi 	db,da,imm3	request (external) mem; address = (db:da) + imm3&lt;br /&gt;
&lt;br /&gt;
br		imm12		pc = pc + signed(imm)&lt;br /&gt;
brts		imm12		pc = pc + signed(imm) if t is set&lt;br /&gt;
brtc		imm12		pc = pc + signed(imm) if t is cleared&lt;br /&gt;
	             &lt;br /&gt;
cmpeq		db,da		t = set if db == da else cleared		&lt;br /&gt;
cmplo   	db,da           t = set if db &amp;lt; da else cleared&lt;br /&gt;
cmplos  	db,da           t = set if  (signed)db &amp;lt; (signed) da else cleared&lt;br /&gt;
esadr   	db,da		esadr = db:da&lt;br /&gt;
swp     	db,da		db = da[7..0]:da[15..8] &lt;br /&gt;
swptc   	db,da		db = da[7..0]:da[15..8] if t = set else da&lt;br /&gt;
st      	db,da		imem[db] = da&lt;br /&gt;
stinc   	db,da		imem[db] = da; db = db + 1&lt;br /&gt;
bffo    	db,da		db is first bit that is 1 found in da (from MSB to LSB)&lt;br /&gt;
bset    	db,da		db = db | 1 &amp;lt;&amp;lt; da&lt;br /&gt;
bclr    	db,da		db = db &amp;amp; ~ (1 &amp;lt;&amp;lt; da)&lt;br /&gt;
cmple   	db,da		t = set if db &amp;lt;= da else cleared&lt;br /&gt;
cmples  	db,da		t = set if  (signed)db &amp;lt;= (signed) da else cleared&lt;br /&gt;
rqld    	db,da		request (internal) mem; address = db + da&lt;br /&gt;
extb    	db,da		db = da byte to word singed extended&lt;br /&gt;
stwo    	db,da		imem[db + STORE_OFFSET] = da&lt;br /&gt;
andts   	db,da		db = db &amp;amp; da if t = set else da&lt;br /&gt;
orts    	db,da           db = db | da if t = set else da&lt;br /&gt;
xorts   	db,da           db = db ^ da if t = set else da&lt;br /&gt;
bicts   	db,da           db = db &amp;amp; ~da if t = set else da&lt;br /&gt;
lsrts   	db,da		db = db &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
asrts   	db,da           db = ((signed)db) &amp;gt;&amp;gt; da if t = set else da&lt;br /&gt;
mults   	db,da           db = db * da if t = set else da&lt;br /&gt;
mulsts  	db,da		db = (signed)db * (signed)da if t = set else da&lt;br /&gt;
&lt;br /&gt;
erqldi		imm6		request (external) mem; address = esadr + imm	&lt;br /&gt;
ssto		imm6		STORE_OFFSET = imm&lt;br /&gt;
udivinit	imm6		udivqoutient = 0; udivrest = 0; udivbitcounter = imm&lt;br /&gt;
&lt;br /&gt;
eld		da		da = requested value from external memory&lt;br /&gt;
push            da		sp = sp – 1; imem[sp] = da&lt;br /&gt;
gmulhi          da		da = multiply result [31..15] from last multiplication&lt;br /&gt;
ld/pop          da		da = requested value from internal memory&lt;br /&gt;
poparqp         da		da = requested value from internal memory; request in internal memory adr = sp; sp = sp + 1&lt;br /&gt;
neg             da		da = 0 - da&lt;br /&gt;
udivgq          da		get division qoutinent&lt;br /&gt;
udivgr          da		get division remainder&lt;br /&gt;
udivgqh         da		get division qoutinent high [31 ..16]&lt;br /&gt;
udivgrh         da              get division remainder high [31 ..16]&lt;br /&gt;
udivsdd         da		set division divident &lt;br /&gt;
udivsdv         da		set division divider&lt;br /&gt;
udivsddh        da		set division divident high [31 ..16]&lt;br /&gt;
udivsdvh        da		set division divider  high [31 ..16]&lt;br /&gt;
erqld           da		request (external) mem; address = esadr + da&lt;br /&gt;
setsp           da		sp = da&lt;br /&gt;
erqldb          da		request (external) mem; address = esadr + da / 2&lt;br /&gt;
jmpts           da		pc = da if t = set&lt;br /&gt;
jmptc           da		pc = da if t = cleared&lt;br /&gt;
negts           da		da = 0 - da if t = set else da&lt;br /&gt;
&lt;br /&gt;
rqpop				internal memory request address = sp; sp = sp + 1&lt;br /&gt;
cli				disable interrupts&lt;br /&gt;
sei				enable interrupts&lt;br /&gt;
rti				pc = pc_before interrput&lt;br /&gt;
tnt				t = not t&lt;br /&gt;
vtt				t = v (overflow/underflow wrom add/sub)			&lt;br /&gt;
epushsadrl			sp = sp – 1; imem[sp] = esadr[15..0]&lt;br /&gt;
epushsadrh			sp = sp – 1; imem[sp] = esadr[31..16]&lt;br /&gt;
epopsadrl			esadr[15..0] = requested value from internal memory&lt;br /&gt;
epopsadrh			esadr[31..16] = requested value from internal memory&lt;br /&gt;
udivstep			performe one division step &lt;br /&gt;
nop				do nothing&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registerzugriffe ===&lt;br /&gt;
&lt;br /&gt;
Um ein ‚Registerscoring‘ und/oder extra Pipeline-Stalls zu vermeiden, muss man bei Registerabhängigkeiten (RAW = Read after Write) mindestens einen Cycle warten bzw. eine andere Operation ausführen.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreiben eines Registers und späteres lesen): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae	; &lt;br /&gt;
	nop		;write r0 = ae wird ausgeführt&lt;br /&gt;
	addi	r0,1	;r0 = r0 ($ae) + 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Im einfachsten Fall, sollte eine nop Operation bei solchen Abhängigkeit verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (nicht optimiert mit nop - 6 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	nop&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	nop&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In den meisten Fällen kann man aber andere Operationen als ‚Füllung‘ bei Registerabhängikeiten verwenden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (Optimiert - 4 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,$ae&lt;br /&gt;
	movei	r1,$ef&lt;br /&gt;
	add	r0,r5&lt;br /&gt;
	mul	r1,r6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um versehentlich solche ‚Hazards‘ zu erkennen erzeugt der Assembler Warnungen, ebenfalls kann der Emulator zur Laufzeit solche Probleme erkennen.&lt;br /&gt;
Prinzipiell ist es möglich, in gewissen Situationen, Hazards absichtlich zuzulassen (Optimierungen um Register zu sparen), wovon aber im Normalfall abzuraten ist.&lt;br /&gt;
&lt;br /&gt;
=== Vergleiche ===&lt;br /&gt;
&lt;br /&gt;
UCore benutzt ein T-Bit (true Bit) um Bedingungen zu verarbeiten. Grundsätzlich wird dieses Bit von Vergleichsoperationen gesetzt und kann dann von Operationen benutzt werden welche das T-Bit intern verwenden (z.B. bedingte Sprünge).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel:====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cmpeqi	r0,0		;vergleiche auf r0 gleich 0 wenn wahr da (t=1) ansonsten (t=0)&lt;br /&gt;
brts	r0IstNull	;springe zu ‚r0IstNull‘ label wenn t set (t=1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist notwendig Register nur dann zu setzen wenn bestimmte Bedingungen eintreten. In diesen Fällen ist es ärgerlich bedingte Sprünge auszuführen, da sie etwas Zeit brauchen (Delay Slots) und den Programmcode unübersichtlich machen.&lt;br /&gt;
Aus diesem Grund unterstützen einige Befehle eine Bedingte Ausführung (nicht jeder).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	move	r1,123&lt;br /&gt;
	move 	r2,23&lt;br /&gt;
	…&lt;br /&gt;
	cmplo	r0,r1		;r0 &amp;lt; r1&lt;br /&gt;
	movets	r0,r2,r0	;wenn ja r0 = r2 (23) ansonsten r0 = r0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sprünge ===&lt;br /&gt;
&lt;br /&gt;
Ein (bedingter) Sprung benötigt, wie jede andere Instruktion, einen Cycle um ausgeführt zu werden.&lt;br /&gt;
Da UCore keine Branchprediction bzw. keine spekulative Ausführung unterstützt und es auch nicht gewollt ist Opcodes in der Pipeline zu verwerfen, entstehen nach Sprungbefehlen sogenannte &#039;Delay Slots&#039;. Die Anzahl dieser Delay Slots ergeben sich aus der Anzahl der Pipelinestufen vor der Ausführungseinheit (da sie den Programmcounter verändert).&lt;br /&gt;
Kurzum Programlauftechnisch werden Instruktionen in diesen Delay Slots ausgeführt bevor der Sprung in Wirklichkeit ausgeführt wird.&lt;br /&gt;
Die kleinste mögliche Schleife benötigt deshalb fünf Instruktionen für einen Durchlauf.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
loop	br	loop		;branch zu loop&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
In vielen Fällen können diese Delay Slots sinnvoll genutzt werden.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 1 (nicht optimiert - 8 cycles): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,1	;r1 = x parameter&lt;br /&gt;
	movei	r1,7	;r2 = y parameter&lt;br /&gt;
	gpci	r7,2	;r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 1 (optimiert - 6 cycles): ====&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	gpci	r7,2	r7 = Rücksprungadresse für Unterfunktion&lt;br /&gt;
	br	drawPixel&lt;br /&gt;
	movei	r0,1	;delay slot	r1 = x parameter&lt;br /&gt;
	movei	r1,7	;delay slot     r2 = y parameter&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel 2 (nicht optimiert - 8 * n + 3 cycles -&amp;gt; if n 128 -&amp;gt; total 1027 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127	;r0 = loop counter - 1&lt;br /&gt;
	movei	r1,0	;r1 = Füllwert&lt;br /&gt;
	nop&lt;br /&gt;
	&lt;br /&gt;
loop	st	r1,r6	;imem[r1] = r6&lt;br /&gt;
	addi	r1,1	;r1++&lt;br /&gt;
	subi	r0,1	;r0-- (t clear bei &amp;lt; 0)&lt;br /&gt;
	brts	loop	;branch loop solange t set&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
	nop	;delay slot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel 2 (optimiert - 6 * n + 2 cycles -&amp;gt; if n 128 -&amp;gt; total 770 cycles) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,127&lt;br /&gt;
	movei	r1,0&lt;br /&gt;
	&lt;br /&gt;
loop	subi	r0,1	;da t später verwendet wird nicht in delay slot benutzen (siehe  Interruptbenutzung)&lt;br /&gt;
	brts	loop&lt;br /&gt;
	st	r1,r6	;delay slot&lt;br /&gt;
	addi	r1,1	;delay slot	&lt;br /&gt;
	nop		;delay slot&lt;br /&gt;
	nop		;delay slot	&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speicherzugriffe ===&lt;br /&gt;
&lt;br /&gt;
UCore besitzt keine ‚gewöhnlichen‘ Lesebefehle für interne/externe Speicherzugriffe.&lt;br /&gt;
Um Pipeline-Stalls beim Lesen von Daten zu vermeiden (Latenz zum Speicher), wird eine Lesebefehl in zwei Operationen aufgeteilt.&lt;br /&gt;
Der erste Befehl ist ein &#039;Request&#039;, er teilt dem Core mit von welcher Adresse er etwas lesen soll.&lt;br /&gt;
Der zweite Befehl ist dann der &#039;Load&#039;, er holt sich die angekommenen Daten ab und speichert sie in einem Register.&lt;br /&gt;
==== interner Speicherzugriff ====&lt;br /&gt;
Bei internen Speicherzugriffen ist die Latenz zwischen Request und Load statisch (3 Cycles), bei externen Zugriff variable (hier wird im Fall eines Load ohne vorhandene Daten ein Stall ausgelöst).&lt;br /&gt;
Mit den Opcodes rqld (request load) und ld (load) kann vom internen Speicher gelesen werden.&lt;br /&gt;
Da die Daten erst zwei Operationen nach dem Request verfügbar sind, muss hier etwas anderes ausgeführt werde (z.B. nop).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0	;send load to address (r0+0)&lt;br /&gt;
	nop		;data send to memory&lt;br /&gt;
	nop		;data will read&lt;br /&gt;
	ld	r1	;readed data to r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Da der interne Speicher immer innerhalb von einem Cycles antwortet und die Latenz durch Pipelinestufen entsteht, kann man bei internen Speicherzugriff bis zu drei Request hintereinander verwenden.&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	rqld	r0,0&lt;br /&gt;
	rqld	r0,1&lt;br /&gt;
	rqld	r0,2&lt;br /&gt;
	ld	r1	;r1 &amp;lt;- internal_mem[r0+0]&lt;br /&gt;
	ld	r2	;r2 &amp;lt;- internal_mem[r0+1]&lt;br /&gt;
	ld	r3	;r3 &amp;lt;- internal_mem[r0+2]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Bei Schreibzugriffen wird wie bei anderen Prozessoren ein Store-Kommando verwendet.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	dexti	$80	;imm exted&lt;br /&gt;
	move	r4,$01	;r4 = $8001&lt;br /&gt;
	move	r0,12	;r0 = 12&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	st	r0,r4	;imem[r4] = r0; $8001 = 12&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist es leider etwas unangenehm mit der statischen Latenz bei internen Lesezugriffen, da man hier etwas mehr schreiben muss als man es von anderen Prozessoren gewöhnt ist.&lt;br /&gt;
&lt;br /&gt;
==== externe Speicherzugriffe ====&lt;br /&gt;
&lt;br /&gt;
Externe Speicherzugriffe verhalten sich ähnlich wie interne Zugriff.&lt;br /&gt;
Unterschiede gibt es in der Adressbreite (extern 32Bit) und in der variablen Latenz (bestimmt durch mehre Faktoren).&lt;br /&gt;
Es gibt eine externe Hauptadresse (Base) die mit &#039;allen&#039; (bis auf edrqldi) externen Speicherzugriffsinstruktionen verwendet wird.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel Hauptadresse setzen: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel schreibe in externen Speicher: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r4,$af&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	esadr	r1,r0	;Hauptadresse (esadr) is r1:r0&lt;br /&gt;
	est	r4,0	;externSpeicher[esadr + 0] = r4&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
Beim Lesen vom externen Speicher werden auch Request/Load Befehle verwendet um Latenzen, wenn möglich, zu vermeiden. Da die Latenz nicht vorhersehbar ist wird bei nicht vorhandenen Daten solange gewartet bis sie vorhanden sind (Stall).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r1,r0	;external address is r1:r0 &lt;br /&gt;
	erqld	0	;load from [r0:r1 + 0]&lt;br /&gt;
	eld	r7	;get external data (Stall solange bis Daten vorhanden)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
Um Lade/Schreiblatenzen zu vermeiden, können mehre Stores oder Request (laden) hintereinander ausgeführt werden (maximal 256 Requestzugriffe, keine Begrenzung bei Stores).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (schreibe 8 Worte in externen Speicher, kein Stall solange Schreibpuffer nicht voll): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	movei	r0,0&lt;br /&gt;
	esadr	r7,r6	;external address is r1:r0 &lt;br /&gt;
	est	r0,0&lt;br /&gt;
	est	r0,1&lt;br /&gt;
	est	r0,2&lt;br /&gt;
	est	r0,3&lt;br /&gt;
	est	r0,4&lt;br /&gt;
	est	r0,5&lt;br /&gt;
	est	r0,6&lt;br /&gt;
	est	r0,7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (vermeiden von Leselatenzen) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	esadr	r7,r6&lt;br /&gt;
	erqld	0&lt;br /&gt;
	erqld	1&lt;br /&gt;
	erqld	2&lt;br /&gt;
	erqld	3	;request 4 Worte&lt;br /&gt;
	&lt;br /&gt;
	....		;mach irgendwas&lt;br /&gt;
	&lt;br /&gt;
	eld	r0	&lt;br /&gt;
	eld	r1&lt;br /&gt;
	eld	r2&lt;br /&gt;
	eld	r3	;bekomme Daten (evtl. kein Stall, da Daten schnellgenug da)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
=== Stack ===&lt;br /&gt;
&lt;br /&gt;
Der Stackpointer zeigt nach dem Reset auf Adresse $8000 (also am oberen Ende des internen Speichers).&lt;br /&gt;
Das Verhalten von push und request pops and pops sind gleich dem internen Speicherzugriffsverhalten (3 Cycles Latenz, Pipelined).&lt;br /&gt;
&lt;br /&gt;
==== Beispiel (1 pop): ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r4	;sp--; imem[sp] = r4&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop		;request imem[sp], sp++&lt;br /&gt;
	nop&lt;br /&gt;
	nop&lt;br /&gt;
	pop	r4	;r4 = imem[sp]&lt;br /&gt;
&amp;lt;/pre&amp;gt;	&lt;br /&gt;
	&lt;br /&gt;
==== Beispiel (3 Werte auf Stack und wieder herunter) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	push	r1&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r3&lt;br /&gt;
	&lt;br /&gt;
	....&lt;br /&gt;
	&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop&lt;br /&gt;
	rqpop		;durch Latenz maximal 3 rqpop dann Daten (ansonsten &#039;poparqp&#039; benutzen (kann Request und Load gleichzeitig))&lt;br /&gt;
	push	r3&lt;br /&gt;
	push	r2&lt;br /&gt;
	push	r1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
=== Decoder extend ===&lt;br /&gt;
später&lt;br /&gt;
=== Interrupts ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
=== Divdieren ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
=== weiter Beispiele ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
=== UCtrl ===&lt;br /&gt;
später&lt;br /&gt;
&lt;br /&gt;
== Homepage ==&lt;br /&gt;
&lt;br /&gt;
http://www.goldmomo.de&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82263</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82263"/>
		<updated>2014-03-25T16:25:38Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein ‚Computer‘system, das nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses kopiert. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen das vollständig* selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (*FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL benutzt, für Emulation und Tools (Assembler etc.) wird C# mit .NET verwendet.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 benutzt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE) der über einen Memorymapped UCTRL-Komponente vollständigen Zugriff auf die Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Audio Interface (Stereo mit max. 24Bit / 96 KHz) &lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Timer/Counter&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCore = Utility Core) ist der ‚zentrale‘ Prozessor im System, er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist gedacht um einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn für alle meine Demos/Spiele als ‚CPU‘ benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* ‚RISC‘ Design&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In einen experimentellen Zustand befindet sich noch der HCORE Block. Dieser Block enthält mehre (konfigurierbar) 32 Bit Prozessoren die über spezielle Techniken (Hardwaresemaphoren, parallele Sprünge, … ) eine parallele Verarbeitung der Software vereinfachen sollen und die Latenzprobleme bei Multithreading vermeiden. Ich habe bisher ein Demo mit 16 parallel laufenden HCOREs veröffentlicht, alle anderen Demos benutzen diese Cores nicht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Momentane Charakteristiken eines HCOREs sind:&lt;br /&gt;
&lt;br /&gt;
*‚Risc‘ Design &lt;br /&gt;
*7 Stufen Pipeline mit „in order“ und „out of order“ Pfad&lt;br /&gt;
*Instruction Cache (konfigurierbar (momentan 8 Wege mit 64 Worten))&lt;br /&gt;
*32 Bit ALU (Hold to Last Pfad, …) &lt;br /&gt;
*128 GP Register&lt;br /&gt;
*UCtrl/Memory/Semaphoren/… out of order Zugriff&lt;br /&gt;
*…&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
[[Datei:Goldmomo emulator.png|miniatur|rechts|Emulator]]&lt;br /&gt;
Um die Softwareentwicklung (und Debuggen) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Register, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (auch in Emulator integriert), ein Compiler existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/2n1o8dfium4bdgi/TK_Da_o4rx/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/310121#new&lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Homepage ==&lt;br /&gt;
&lt;br /&gt;
http://www.goldmomo.de&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82262</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82262"/>
		<updated>2014-03-25T16:24:17Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein ‚Computer‘system, das nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses kopiert. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen das vollständig* selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (*FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL benutzt, für Emulation und Tools (Assembler etc.) wird C# mit .NET verwendet.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 benutzt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE) der über einen Memorymapped UCTRL-Komponente vollständigen Zugriff auf die Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Audio Interface (Stereo mit max. 24Bit / 96 KHz) &lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Timer/Counter&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCore = Utility Core) ist der ‚zentrale‘ Prozessor im System, er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist gedacht um einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn für alle meine Demos/Spiele als ‚CPU‘ benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* ‚RISC‘ Design&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In einen experimentellen Zustand befindet sich noch der HCORE Block. Dieser Block enthält mehre (konfigurierbar) 32 Bit Prozessoren die über spezielle Techniken (Hardwaresemaphoren, parallele Sprünge, … ) eine parallele Verarbeitung der Software vereinfachen sollen und die Latenzprobleme bei Multithreading vermeiden. Ich habe bisher ein Demo mit 16 parallel laufenden HCOREs veröffentlicht, alle anderen Demos benutzen diese Cores nicht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Momentane Charakteristiken eines HCOREs sind:&lt;br /&gt;
&lt;br /&gt;
*‚Risc‘ Design &lt;br /&gt;
*7 Stufen Pipeline mit „in order“ und „out of order“ Pfad&lt;br /&gt;
*Instruction Cache (konfigurierbar (momentan 8 Wege mit 64 Worten))&lt;br /&gt;
*32 Bit ALU (Hold to Last Pfad, …) &lt;br /&gt;
*128 GP Register&lt;br /&gt;
*UCtrl/Memory/Semaphoren/… out of order Zugriff&lt;br /&gt;
*…&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
[[Datei:Goldmomo emulator.png|miniatur|rechts|Emulator]]&lt;br /&gt;
Um die Softwareentwicklung (und Debuggen) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Register, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (auch in Emulator integriert), ein Compiler existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/2n1o8dfium4bdgi/TK_Da_o4rx/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/310121#new&lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82260</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82260"/>
		<updated>2014-03-25T15:53:41Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: /* Software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein ‚Computer‘system, das nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses kopiert. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen das vollständig* selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (*FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL benutzt, für Emulation und Tools (Assembler etc.) wird C# mit .NET verwendet.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 benutzt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE) der über einen Memorymapped UCTRL-Komponente vollständigen Zugriff auf die Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Audio Interface (Stereo mit max. 24Bit / 96 KHz) &lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Timer/Counter&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCore = Utility Core) ist der ‚zentrale‘ Prozessor im System, er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist gedacht um einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn für alle meine Demos/Spiele als ‚CPU‘ benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* ‚RISC‘ Design&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
[[Datei:Goldmomo emulator.png|miniatur|rechts|Emulator]]&lt;br /&gt;
Um die Softwareentwicklung (und Debuggen) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Register, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (auch in Emulator integriert), ein Compiler existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/2n1o8dfium4bdgi/TK_Da_o4rx/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Goldmomo_emulator.png&amp;diff=82259</id>
		<title>Datei:Goldmomo emulator.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Goldmomo_emulator.png&amp;diff=82259"/>
		<updated>2014-03-25T15:52:49Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82258</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82258"/>
		<updated>2014-03-25T15:49:01Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: /* Beschreibung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein ‚Computer‘system, das nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses kopiert. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen das vollständig* selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (*FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL benutzt, für Emulation und Tools (Assembler etc.) wird C# mit .NET verwendet.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 benutzt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Goldmomo system simple view.png|miniatur|rechts|System Überblick]]&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE) der über einen Memorymapped UCTRL-Komponente vollständigen Zugriff auf die Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Audio Interface (Stereo mit max. 24Bit / 96 KHz) &lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Timer/Counter&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCore = Utility Core) ist der ‚zentrale‘ Prozessor im System, er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist gedacht um einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn für alle meine Demos/Spiele als ‚CPU‘ benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* ‚RISC‘ Design&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
Um die Softwareentwicklung (und Debuggen) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Register, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (auch in Emulator integriert), ein Compiler existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/2n1o8dfium4bdgi/TK_Da_o4rx/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Goldmomo_system_simple_view.png&amp;diff=82257</id>
		<title>Datei:Goldmomo system simple view.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Goldmomo_system_simple_view.png&amp;diff=82257"/>
		<updated>2014-03-25T15:47:24Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82256</id>
		<title>16/32Bit Computer/Konsole</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=16/32Bit_Computer/Konsole&amp;diff=82256"/>
		<updated>2014-03-25T15:42:18Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: 16/32 Bit Computer/Konsole&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;16/32 Bit Computer/Konsole&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt implementiert ein ‚Computer‘system, das nicht auf irgendeinem vorhandenen Design (CPU etc.) beruht bzw. dieses kopiert. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Idee ist/war ein System zu erstellen das vollständig* selbst geschrieben ist um in jeden Teil der Implementierung (Hardware/Software) flexibel zu sein und natürlich ein Verständnis für jede Komponente zu entwickeln. (*FIFO, PLLs, etc. wurden generiert).&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
&lt;br /&gt;
Als Hardwarebasis wird ein Altera DE2-115 Evaluations-Board benutzt. Zur Hardwarebeschreibung wird die Sprache VHDL benutzt, für Emulation und Tools (Assembler etc.) wird C# mit .NET verwendet.&lt;br /&gt;
Im Grundsystem wird ein Großteil der Peripherie des DE2-115 benutzt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(SRAM / SDRAM / FLASH / VGA / SDSLOT / HEX / LED / SW / LCD / AUDIO / EEPROM / PS/2)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Grundsystem implementiert einen 16 Bit Prozessor (UCORE) der über einen Memorymapped UCTRL-Komponente vollständigen Zugriff auf die Hardwarekomponenten hat.&lt;br /&gt;
&lt;br /&gt;
Diese UCTRL-Komponente enthält:&lt;br /&gt;
&lt;br /&gt;
* Programmierbares Audio Interface (Stereo mit max. 24Bit / 96 KHz) &lt;br /&gt;
* Zwei I2C Ports (für WM8731 und EEPROM)&lt;br /&gt;
* Zwei PS/2 Ports&lt;br /&gt;
* Timer/Counter&lt;br /&gt;
* Programmierbares Video Interface (Auflösung/Scale/Farbformat/… programmierbar, SRAM/DRAM Port, H/V Hit/Counter etc.)&lt;br /&gt;
* HCore Ctrl/Data Interface&lt;br /&gt;
* …&lt;br /&gt;
&lt;br /&gt;
Der 16 Bit Core (UCore = Utility Core) ist der ‚zentrale‘ Prozessor im System, er kann alle Hardwarekomponenten ansprechen (indirekt (UCTRL), direkt (SRAM/DRAM/…)) und ist gedacht um einfache Steuerungen durch eine Softwareimplementierung zu ermöglichen. Nichtsdestotrotz ist seine Verarbeitungsgeschwindigkeit recht hoch (ca. 106MIPS) und ich habe ihn für alle meine Demos/Spiele als ‚CPU‘ benutzt. In Zukunft sollen aber softwarelastige Aufgaben in den HCore Block verlagert werden (32 Bit Cores).&lt;br /&gt;
&lt;br /&gt;
Die Charakteristiken von UCORE sind:&lt;br /&gt;
&lt;br /&gt;
* ‚RISC‘ Design&lt;br /&gt;
* Interner Code / Daten Speicher&lt;br /&gt;
* 6 Stufige Pipeline (eine Cycle pro Instruktion) &lt;br /&gt;
* 16 Bit Ausführungseinheit (Arithmetisch, Logisch, Bitfeld, … Operationen)&lt;br /&gt;
* 32 Bit externer Port zu SRAM/DRAM/FLASH/SDCard/…&lt;br /&gt;
* 8 GP-Register&lt;br /&gt;
* Spezielle request / load Befehle um Latenzen beim externen Speicherzugriff zu vermeiden&lt;br /&gt;
* Erweiterungen für Grafik Beschleunigungen&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
Um die Softwareentwicklung (und Debuggen) zu vereinfachen, existiert einen Emulator des Systems. &lt;br /&gt;
Der Emulator deckt alle Hardwarekomponenten des Systems ab, bietet aber noch viele Möglichkeiten der Überwachung (runtime Disassembler, Register, Hardwaremonitor, …) an.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für UCORE und HCORE gibt es einen Assembler der den Maschinencode erzeugt (auch in Emulator integriert), ein Compiler existiert bis jetzt nicht.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.dropbox.com/sh/2n1o8dfium4bdgi/TK_Da_o4rx/goldmomo_endlos_daily_build Dokumentation, System Source Code (Emulator/Tools/VHDL/), Assembler Dateien für alle Demos/Spiele, … ] &lt;br /&gt;
&lt;br /&gt;
== Demos ==&lt;br /&gt;
&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Kategorie:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Benutzer:Goldmomo&amp;diff=79204</id>
		<title>Benutzer:Goldmomo</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Benutzer:Goldmomo&amp;diff=79204"/>
		<updated>2013-10-29T09:47:50Z</updated>

		<summary type="html">&lt;p&gt;Goldmomo: Die Seite wurde neu angelegt: „My Homepage: http://www.goldmomo.org  Dokumentation/Source/Tools(Emualtor, Assembler, GFXConvert,...) to use/emulate my FPGA based system:  https://www.dropbox…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;My Homepage: http://www.goldmomo.org&lt;br /&gt;
&lt;br /&gt;
Dokumentation/Source/Tools(Emualtor, Assembler, GFXConvert,...) to use/emulate my FPGA based system:&lt;br /&gt;
&lt;br /&gt;
https://www.dropbox.com/sh/2n1o8dfium4bdgi/TK_Da_o4rx/goldmomo_endlos_daily_build&lt;br /&gt;
&lt;br /&gt;
My videos from my FPGA based system:&lt;br /&gt;
&lt;br /&gt;
Sheriff 2213 (Level 1-5) http://www.youtube.com/embed/WcUinTuIObA&amp;lt;br/&amp;gt;&lt;br /&gt;
SpacePilotOfDeath FINAL http://www.youtube.com/embed/ctVRjXSUPnw&amp;lt;br/&amp;gt;&lt;br /&gt;
Tilemapper test http://www.youtube.com/embed/uKNQfi4BDl8&amp;lt;br/&amp;gt;&lt;br /&gt;
test GFX instructions http://www.youtube.com/embed/ke_z5vKetXk&amp;lt;br/&amp;gt;&lt;br /&gt;
Emulator overview http://www.youtube.com/embed/MKoS0bCZ_38&amp;lt;br/&amp;gt;&lt;br /&gt;
MOD Player final Version http://www.youtube.com/embed/W0ChHagGEAQ&amp;lt;br/&amp;gt;&lt;br /&gt;
MOD Player beta 2 Version http://www.youtube.com/embed/Yy9mM5lHSA0&amp;lt;br/&amp;gt;&lt;br /&gt;
MOD Player beta Version http://www.youtube.com/embed/O9RUoHj54Gg&amp;lt;br/&amp;gt;&lt;br /&gt;
SRAM to SDRAM software rotozoom http://www.youtube.com/embed/ZE8hn5Nqa4g&amp;lt;br/&amp;gt;&lt;br /&gt;
MOD Player alpha Version http://www.youtube.com/embed/I83u6VxUcw0&amp;lt;br/&amp;gt;&lt;br /&gt;
6 Channel Audio Test http://www.youtube.com/embed/aH5pF4WBsVU&amp;lt;br/&amp;gt;&lt;br /&gt;
Space Pilot of Death updated Version http://www.youtube.com/embed/eK75rcHrX0c&amp;lt;br/&amp;gt;&lt;br /&gt;
self written MODPlayer for Windows http://www.youtube.com/embed/Y04lMvfCgm8&amp;lt;br/&amp;gt;&lt;br /&gt;
Boot from SDCard http://www.youtube.com/embed/mlu24aY84MY&amp;lt;br/&amp;gt;&lt;br /&gt;
Playing video from SDCard (uncompressed) http://www.youtube.com/embed/uCjt68XQOQ4&amp;lt;br/&amp;gt;&lt;br /&gt;
UCore drawing some &#039;software&#039; sprites into framebuffer http://www.youtube.com/embed/_GDSuAsApBg&amp;lt;br/&amp;gt;&lt;br /&gt;
Space Pilot of Death running on goldmomo_endlos http://www.youtube.com/embed/q64eGbGddhk&amp;lt;br/&amp;gt;&lt;br /&gt;
UCore make motion blur on framebuffer (inject some &#039;fire&#039; objects) http://www.youtube.com/embed/hZ0Bh3xF3x4&amp;lt;br/&amp;gt;&lt;br /&gt;
UCore memory test http://www.youtube.com/embed/Pr89wex3YbU&amp;lt;br/&amp;gt;&lt;br /&gt;
UCore PS/2 KEyboard interface test http://www.youtube.com/embed/eNDLkwafubE&amp;lt;br/&amp;gt;&lt;br /&gt;
Emulator of goldmomo_endlos running native code http://www.youtube.com/embed/xZNF1klLHL0&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Goldmomo</name></author>
	</entry>
</feed>