Einfachstmögliche E/A für Homebrew 8-Bit-CPU

Ich arbeite ohne wirklichen Grund daran, eine 8-Bit-CPU als persönliches Projekt zu entwerfen. Ich verwende hauptsächlich Chips der 74HC-Serie und konzentriere mich im Allgemeinen auf die einfache Programmierung über die Leistung.

Ich nutze verschiedene Projekte im Internet als Inspiration und habe das Gefühl, dass ich ein ziemlich gutes Verständnis dafür habe, wie die Grundlagen funktionieren, einschließlich der Alu, Register und des grundlegenden Speicherpfads.

Das einzige, wovon ich keine Ahnung habe, ist Input und Output. Ich interessiere mich nicht wirklich für etwas Superschickes wie TCP/IP oder UARTS, aber ich hätte gerne eine Tastatur und eine einfache Textausgabe auf irgendeinen Monitor. Ich habe wirklich keine Ahnung, welche Hardware ich verwenden soll oder welche Anweisungen ich machen soll, um sie zu benutzen.

Ich könnte ein paar spezialisiertere Anweisungen aus meiner ISA herausquetschen, um auf spezialisierte Hardware zuzugreifen, aber wenn ich das alles mit einer Art Speicherzuordnungsschema machen könnte, wäre das sogar noch besser. Ich plane die Verwendung eines 64K-RAM-Chips, aber vielleicht könnten bestimmte Adressen auf andere Hardware oder so umgeleitet werden.

Ich möchte eigentlich keine Interrupts implementieren, aber ich möchte auch keine Tastaturdaten verlieren. Bedeutet das, dass ich eine Art Warteschlangenpuffer-Chip für meine Tastatur benötige? Ich weiß nicht einmal, wo ich anfangen soll, nach einem Videochip zu suchen, oder wie ich damit umgehen soll.

Irgendwelche Tipps würden sehr geschätzt. Auch hier brauche ich nichts Besonderes, ein einfaches getChar und putChar würde ausreichen. Die Steuerung von Grafiken auf Pixelebene könnte cool sein, ist aber nicht unbedingt erforderlich. Ich glaube, ich muss nur in die richtige Richtung weisen.

Wie wäre es mit RS232 und einem Terminalfenster zu Ihrem PC?
Um das zu erweitern, was @kenny meiner Meinung nach vielleicht beabsichtigt hat - es wäre viel einfacher, einen UART zu verwenden, anstatt nach Tastatur und Video zu suchen. Sie benötigen ungefähr 16 Bit parallele E / A, um mit einer Tastatur umzugehen, und Video erfordert viel kniffliges Timing sowie mindestens 1 KB oder 2 KB Videopuffer, im Vergleich zu vielleicht 2 Registern, um so etwas wie a abzubilden 6851/6551 UART (wenn Sie einen finden können)

Antworten (6)

Die "einfachst mögliche E/A" hängt von Ihren E/A-Anforderungen ab. Wenn Sie die Kontrolle über das CPU-Design haben, wäre es sehr einfach, ein paar spezielle Anweisungen zu implementieren, um einige Bits paralleler E / A ein- und auszugeben.

Aber da Sie Tastatur und Video erwähnen, scheint es, dass Ihre Anforderung darin besteht, auf diese Weise mit Ihrem System interagieren zu können - und der einfachste Weg, dies zu tun , besteht darin, eine serielle Schnittstelle mit fester Baudrate zu integrieren und einen PC und ein Terminal zu verwenden Programm zur Versorgung von Tastatur und Video. Die Verwendung von 9600 bps ist für menschliche Konsolenzwecke in Ordnung, oder wenn Sie erwarten, Binärdateien zu übertragen, könnte 115200 64 KB in etwa 6 Sekunden verarbeiten.

Ein handelsüblicher UART-Chip wie der 6850 oder 8250 (na ja, jedenfalls aus der Junk-Box) benötigt nur 2 bis 8 Register für eine vollständige stdin/stdout-Lösung. Dies ist ein winziger Fußabdruck im Vergleich zu dem Versuch, eine Tastatur- und Videoschnittstelle direkt zu implementieren. Sie können wahrscheinlich eine Tastaturmatrix mit nur einem einzigen 8-Bit-Ausgangsport und einem einzigen 8-Bit-Eingangsport ansteuern, aber Video benötigt 2K-Adressen, nur um den Frame-Puffer für eine Anzeige mit 80 x 25 Zeichen bereitzustellen. Wenn Sie sogenannte LSI-Lösungen wie den 8250 für Schummelei halten, würde ich entgegnen, dass der Bau eines UART aus 74xx wahrscheinlich einfacher wäre als der Bau eines Videogenerators aus derselben Technologie.

Der Nachteil des UART ist jedoch, dass Sie wahrscheinlich Eingaben verlieren, wenn Sie ihn nicht (a) häufig genug abfragen oder (b) Interrupts implementieren. Für einen einfachen Proof-of-Concept für Ihre CPU sollte nur das Polling ausreichen - es sei denn, Sie versuchen auch, die Interrupt-Fähigkeiten Ihrer CPU zu beweisen (falls/wenn sie diese hat). In diesem Fall müssen Sie mit der seriellen Eingabe Schritt halten Die Verwendung von UART-Interrupts wäre ein guter Testfall.

Ich bin nicht wirklich besorgt über Betrug auf der I/O-Seite. Ich möchte mich hauptsächlich auf das CPU-Design konzentrieren, nicht auf Input/Output. Vielleicht werde ich schummeln und ein Arduino hineinstecken und Opcodes erstellen, um jeweils ein Byte ein- und auszugeben. Irgendwie widerspricht es dem Zweck, eine CPU zu bauen, wenn ich eine überlegene für IO verwende, aber das ist auch nicht wirklich der Punkt.
@CMP - Sie meinen, verwenden Sie das Arduino, um von 8 parallelen E / A-Bits auf seriell (rs232) zur PC / Terminal-Kombination zu wechseln? Das könnte funktionieren - obwohl Sie ein paar zusätzliche Bits für den Handshake zum Arduino benötigen würden, es sei denn, Sie möchten, dass es kontinuierlich das Byte überträgt, das Sie ihm präsentieren - und das Empfangen würde definitiv Handshake-Bits erfordern. Coole Idee, da diese alten UART/Comm-Adapter-Chips schwer zu bekommen sind.
Setzen Sie so ziemlich einen Pin auf Arduino, um ihm mitzuteilen, dass er die Eingabe verarbeiten oder die Ausgabe durchlaufen soll. Wenn ich es für einen meiner Zyklen hoch setze, sollte das Arduino genug schneller sein, dass es sich um das Byte innerhalb dieses Zyklus kümmern kann.
@CMP - Sache ist, wenn das Arduino schneller genug ist als Ihre CPU und zurückkommt und diesen Pin erneut überprüft, bevor Ihre CPU ihn löschen kann, könnten Sie am Ende doppelte Zeichen senden. Aber wenn Sie das Arduino auf Low-to-High-Übergänge (oder umgekehrt Ihre Wahl) und nicht nur auf ein Niveau achten lassen, sollte das Problem behoben sein.
Guter Punkt. Glücklicherweise gibt es eine gute Debouncer-Bibliothek, die Änderungen ziemlich genau erkennen kann.

Abgesehen von standardmäßigen parallelen E/A-Ports möchten Sie auf jeden Fall auch serielle E/A wie U(S)ART. Wir brauchen es in einer Minute.

Eingabe
Für die Eingabe würde ich eine Schnittstelle für eine gewöhnliche PC-Tastatur (die sogenannte PS/2) bauen. Dies verwendet ein synchrones serielles Protokoll ; Dafür brauchst du die serielle Schnittstelle. Das bedeutet SIPO (Serial In/Parallel Out) und PISO (Parallel In/Serial Out). Ein synchrones Protokoll wie das der PS/2-Tastatur hat den Vorteil, dass es auch ein Taktsignal gibt, was die Konvertierung einfacher macht als beispielsweise ein UART. (Sie werden bald auch einen UART wollen)

Display
Der größte Teil des TRS-80 -Heimcomputers war, abgesehen von der CPU (Z80) und dem Speicher, mit TTL-ICs ausgestattet, einschließlich des 16-Zeilen-x-64-Zeichen -Videos , sodass Ihnen die Schaltpläne beim Einstieg helfen können.
Aber das ist vielleicht schon ein großer Schritt, und ich würde mit etwas Einfacherem beginnen, damit Sie sich auf die CPU konzentrieren können, die höchstwahrscheinlich etwas Debugging benötigen wird, bevor sie richtig funktioniert. Und es wäre schön, dafür so etwas wie ein Display zu haben. (Sie möchten die CPU und die Videologik nicht gleichzeitig debuggen. Machen Sie einen Schritt nach dem anderen.)
Ich würde vorschlagen, ein gewöhnliches 4x20- Zeichen-LCD zu verwenden (größer ist auch in Ordnung). Dies ist einfach zu bedienen und kann bereits viele (Debug-)Informationen anzeigen.
Eine andere Möglichkeit besteht darin, dass Sie eine UART-Schnittstelle erstellen . Es ist bei den meisten Mikrocontrollern Standard und Sie werden es früher oder später sowieso brauchen. Mit dem UART können Sie eine Verbindung zu einem PC herstellen, und mit einem einfachen Protokoll können Sie die Anzeige des PCs verwenden, um eine virtuelle Anzeige Ihres eigenen Computers in einem Fenster anzuzeigen.

Interrupts
Mike kommentiert, dass Interrupts nicht so schwer zu implementieren sind, aber ich denke, es ist eine gute Idee, sie für den Moment wegzulassen. Sie fügen ein gewisses Maß an Komplexität und ein Risiko der Instabilität hinzu (mehr auf Software- als auf Hardwareebene); Sicherheitskritische Mikroprozessoren haben normalerweise keine Interrupts. Ich erinnere mich an die alte Viper, die in Kampfflugzeugen eingesetzt wurde.
Um sicherzustellen, dass eingehende Daten nicht verloren gehen, müssen Sie sie puffern. Die übliche Lösung ist ein FIFO . Dies ist ein Baustein aus der 74HC-Serie, also können Sie diesen einfach verwenden oder Ihren eigenen rollen. (Ich weiß nicht, was Ihre Make-or-Buy-Kriterien sind.)


Weitere Lektüre
TRS-80 Technisches Handbuch

Gedanken: - Ursprüngliches Z8-Video. - DMA

I/O-Mapping

"Einige Speicherzuordnungsschemata" ist so ziemlich die Definition von speicherabgebildeter E/A.

Probieren Sie den Commodore 64-Trick aus: Peripheriegeräte teilen sich den Speicherplatz mit dem RAM, und jede Adresse, die nicht von einem Peripheriegerät belegt wird, geht in den RAM.

Oder der Intel-x86-Trick: I/O bekommt einen eigenen, vom RAM getrennten Adressraum. Dies erschwert die Verwendung von Zeigern mit Peripheriegeräten erheblich.

Peripheriegeräte haben im Allgemeinen gerade genug Adresspins, um ihre Register zu adressieren, einen Chip-Select-Pin (CS), der anzeigt, wann er ausgewählt ist, und entweder einen Read/Write-Pin oder ein Paar von Read-Enable- und Write-Enable-Pins.

Bildspeicher, Framebuffer

Der einfachste Weg, ein Videosignal zu erzeugen, besteht darin, eine Schaltung herzustellen, die aufeinanderfolgende Adressen aus dem RAM liest und sie in ein Videosignal umwandelt. Wie Sie das Signal erzeugen, hängt davon ab, welches Signal Sie erzeugen möchten (NTSC, CGA, VGA, LVDS usw.). Lassen Sie den Framebuffer RAM in der anderen Hälfte des Zyklus lesen (der Commodore 64 tat dies). Wenn Ihr Speicherbus Wartezustände handhabt, könnten Sie alternativ dem Framebuffer Prioritätszugriff auf RAM geben.

Der Vorteil dieses Framebuffers ist, dass er einfach zu implementieren und zu schreiben ist. Der Nachteil ist, dass es viel RAM benötigt und die Textgenerierung auf die CPU schiebt (aber Sie können damit auch Schriftarten mit variabler Breite und Höhe erstellen).

Das Traurige ist, dass Sie hier ziemlich auf sich allein gestellt sind; Der Markt für diese Art von Low-Level-Videochips ist heutzutage so gut wie nicht existent. Denken Sie jedoch daran, dass der Apple II seine Videoerzeugung in diskreten Komponenten ohne einen dedizierten Chip durchgeführt hat, also können Sie das auch. ^_-

Unterbricht

Interrupts sollten nicht so schwer zu implementieren sein: Wenn eine Interrupt-Leitung angesteuert wird und Interrupts global aktiviert sind und dieser bestimmte Interrupt nicht deaktiviert ist, dann schieben Sie den PC auf den Stapel (genau wie bei einem Unterprogrammaufruf) und schließlich entweder Laden Sie einen neuen PC-Wert von einer Adresse in Abhängigkeit von der Interrupt-Nummer (die Vektortabellenmethode) oder setzen Sie den PC einfach auf einen festen Wert in Abhängigkeit von der Interrupt-Nummer und erwarten Sie ein GOTO an dieser Adresse, um den Prozessor dorthin zu bringen, wo er hin muss ( die Sprungtabellenmethode).

Tastaturschnittstelle

Stevenvh hat seine Antwort gepostet, als ich mit meiner ungefähr zur Hälfte fertig war, also schließe ich mich der Empfehlung an, die PS/2-Schnittstelle zu verwenden. Eine interessante Sache ist, dass die PS/2-Schnittstelle Hot-Swap gemacht werden kann und automatisch erkennen kann, ob eine Tastatur oder Maus angeschlossen ist. Diese Funktionen haben es nie auf Motherboards geschafft, weil niemand die zusätzlichen $$$ bezahlen oder umschreiben wollte ihre Treiber, um es zu unterstützen, aber ich habe es in einem FPGA gemacht, also können Sie es auch.

Der Trick besteht jedoch darin, dass die PS/2-Schnittstelle bidirektional ist, sodass Sie wahrscheinlich ein Interrupt-basiertes serielles Port-Design verwenden möchten, um sich damit zu verbinden. Sie könnten Chips namens FIFOs verwenden (Cypress stellt viele davon her), um die Latenzanforderungen zu lockern. Sie benötigen einen für jede Richtung.

Ich denke, Sie werden feststellen, dass der C64-Videogenerator die CPU ausgesetzt und DMA verwendet hat, um 40 Bytes in jeder 8. Scanzeile während des aktiven Rasters einzusaugen ) schalten Sie das Videoraster aus oder warten Sie und führen Sie dies während des vertikalen Rücklaufs durch. Aber Ihr Punkt zum verschachtelten Video- / CPU-Zugriff ist dennoch machbar.
Papa, das stimmt. Ich muss an etwas anderes gedacht haben, vielleicht an den TRS-80-Farbcomputer (MC6809-CPU und MC6847-Videochip mit einem anderen Chip zur Verwaltung von DRAM, dessen Nummer mir nicht bekannt ist).
Ja, dieses System hat Video auf diese Weise verschachtelt, indem es den "Synchronous Address Multiplexer" AKA "SAM" -Chip, das Motorola 6883, verwendet hat. (Mann, ich wünschte, ich könnte diese Synapsen für etwas anderes wiederverwenden)
Das ist es! Danke! Und viel Glück mit den Neuronen; Ich erinnere mich noch SYS 64738(startet einen C64 neu), was für mich völlig nutzlos ist. Und die funky C64-Speicherkarte mit ihrem sich selbst modifizierenden Codezeilen-Editor.

Wenn Sie eine relativ schnelle CPU haben, ist die Schaltung am einfachsten, wenn Sie die CPU einen erheblichen Teil der Arbeit erledigen lassen, die sie erzeugt. Nehmen wir als einfachsten Fall an, dass Ihr Ziel ein 40-Spalten-Video ist, Ihr Prozessor eine Million 16-Bit-Anweisungen pro Sekunde aus dem RAM ausführt und Timings verwendet, die von einem 8-MHz-Takt abgeleitet sind, und es Ihnen nichts ausmacht, währenddessen nichts anderes tun zu können Video generieren. In diesem Fall könnten Sie ein E/A-Bit als Master-Videoaktivierung und drei weitere als Unterzeilenauswahl verwenden und dann die Dinge so anordnen, dass immer dann, wenn eine Anweisung von einer Adresse abgerufen wird, an der Bit 6 hoch ist, die die unteren 8 Bits des abgerufenen Befehls werden zusammen mit den drei Bits der Unterzeilenauswahl in einen 2Kx8-ROM eingespeist; Die Ausgabe davon speist einen 74HC165, um Pixel auszutakten. Um Videos anzuzeigen, arrangieren, Gruppen von 40 Befehlen abzurufen, wobei das LSB jedes Befehls ein Byte von Anzeigedaten ist. Ein solcher Ansatz würde die CPU völlig belasten, aber extrem wenig Hardware erfordern.

Ein etwas schönerer Ansatz wäre, ein paar Zähler hinzuzufügen, die entweder einmal pro Zeile oder Frame einen Interrupt auslösen. Die CPU wäre während des sichtbaren Teils des Frames nicht in der Lage, irgendetwas zu tun, müsste aber nicht jedes Mal die Synchronisierung verlieren, wenn sie sich entscheidet, etwas anderes als das Zeigen von Video zu tun.

Übrigens kann es einfacher sein, LCD als Video zu verwenden. Ein LCD mit integriertem Controller ist wahrscheinlich am praktischsten, aber selbst ein LCD mit nur Treibern ist möglicherweise etwas einfacher als Video, da die Timings etwas nachsichtiger sind.

Ich werde dies eher zu einer Antwort als zu einem Kommentar machen, da sich das Material besser darstellt.

Brain Fade - ich meinte Sinclair ZX80! :-(. Video in Hardware mit Z80-CPU-DMA, denke ich

Sinclair ZX80 Schaltplan hier

Bauen Sie hier Ihren eigenen ZX80

Kommentierter Schaltplan mit Funktionsblöcken

Mehr ZX80 {gut}


Electronics Australia beschrieb den Computer DREAM 6800 in xxx. Dies hatte eine speicherabgebildete reine Hardware-Videoanzeige mit sehr niedriger Auflösung. Kein Zeichengenerator - Grafiken nur mit Text, der in Software erzeugt wird.

Hier: sagt

Der DREAM 6800 Video Computer: Das Projekt wurde in den Ausgaben des Magazins Electronics Australia vom Mai, Juni und Juli 1979 veröffentlicht. EA führte eine Reihe von darauf basierenden Projekten durch, darunter „DREAM 6800-Bandsystem im Mai 1981, DREAM 6800 RTTY-Display, Januar 1981 und 4K-RAM-Erweiterung im Dezember 1980

Beginnen Sie mit einem einfachen uart/seriellen Port. Keine Notwendigkeit für Funktionen, 8 Bits, keine Parität, 1 Stoppbit ist alles, was Sie brauchen.