Sehr einfaches CPU-Design in LogiSim


8

Ich bin derzeit ein Junior in der Highschool und habe mich für Computer- / Elektrotechnik interessiert, insbesondere für das Design von Mikroprozessoren. Ich habe Code von Charles Petzold gelesen und mit dem Lesen des Mikroprozessor-Design-Wikibooks begonnen (das unvollständig zu sein scheint). Durch das Lesen von Code verstehe ich die grundlegende Logik hinter einer CPU und habe begonnen, eine in LogiSim zu erstellen. Kapitel 17 in Code beschreibt die CPU, die ich bauen möchte, aber den Schaltkreisen fehlen Schlüsselkomponenten - Taktsignale und Befehlsdecodierung. Einige der Taktsignale scheinen ziemlich offensichtlich zu sein (der PC scheint ein stetiges Taktsignal zu benötigen), andere (wie das Speichern von RAM-Werten) musste ich mir überlegen und versuchen, mich an die Arbeit zu machen.

Ich kann einen funktionierenden Akkumulator bauen (ich glaube, er kann nicht genau als ALU bezeichnet werden, weil ihm der L-Teil fehlt), der mit einem einzigen Eingang zwischen Addition und Subtraktion umschaltet, und ich verstehe, dass dies alles ist, was ich für den arithmetischen Teil benötige - Sobald ich Sprung-Opcodes zum Laufen gebracht habe, kann ich Multiplikation und Division im Code implementieren. Der Teil, mit dem ich zu kämpfen habe, ist die Befehlsdecodierung. Bei einigen Google-Suchen sehe ich, dass jeder Opcode als mehrere Mikrobefehle interpretiert werden muss, aber ich weiß nicht, wie ich das brauche, um zu funktionieren. Derzeit ist mein Befehlsdecoder nur eine kombinatorische Analyseschaltung mit einem einzigen Binärausgang für jeden Opcode - insgesamt 13.

Der Code funktioniert so, dass er einen 8-Bit-Codewert hat (ich verwende nur das Low-End-Byte) und dann zwei separate 8-Bit-Adresswerte, die ich dann als 16-Bit-Adresseingabe in den RAM kombiniere. Um die Werte zu speichern, habe ich einen separaten Zähler, der bis zu 10b zählt und dann auf 00b zurückgesetzt wird. Es ist der Takteingang für jeden Latch nacheinander (für die drei Latches gibt es a, b und c. Die zweiten Takte haben a 1, während b & c 0 sind, dann ist b 1 und 1 & c sind 0, dann c ist eins und 1 & b sind 0, dann wird es zurückgesetzt). Bei Anweisungen wie ADD 000Ah springt der PC jedoch zu 000AH ..., das in den Akkumulator eingefügt werden soll, aber tatsächlich in den Code-Latch zwischengespeichert wird und dann als nächster Opcode interpretiert wird, der das Ganze zum Laufen bringt verrückt.

Ich habe das Gefühl, dass mir einige wichtige Informationen zur Befehlsdecodierung und zur Ausführung von Taktsignalen fehlen ...

Hier sind die LogiSim .circ-Dateien: https://dl.dropboxusercontent.com/u/61676438/PetzoldMk5/8BitAdder.circ https://dl.dropboxusercontent.com/u/61676438/PetzoldMk5/8BitAdderSubtractor.c https dl.dropboxusercontent.com/u/61676438/PetzoldMk5/8BitInverter.circ https://dl.dropboxusercontent.com/u/61676438/PetzoldMk5/8BitLatch.circ https://dl.dropboxusercontent.com/u/61676438/ ID.circ https://dl.dropboxusercontent.com/u/61676438/PetzoldMk5/PetzoldMk5.circ

PetzoldMk5 ist die Haupt-CPU und basiert auf den anderen Dateien, die als Bibliotheken importiert werden sollen.

Hier ist eine Liste von Opcodes (alle binär):

Load                 0001
Add                  0010
Add w/ Carry         0011
Sub                  0100
Sub w/ Borrow        0101
Jump                 0110
Jump w/ Carry        0111
Jump W/ 0            1000
Jump w/o C           1001
Jump W/o 0           1010
Store                1011
Halt                 1100
Reset                1101

1
Sind Sie bereit, Ihre vorhandene Logisim CPU .circ-Datei freizugeben? Und um das Leben etwas komplizierter zu gestalten, sollten Sie die Logisim-Hilfe unter der Überschrift "Value Propagation" sorgfältig lesen und verstehen. Wenn nicht, schon. (Sie können haben, angesichts all der Arbeit, die Sie bereits beworben haben. Sehr froh zu hören, dass Sie dies übernehmen!)
Jonk

@ Jonk danke für die schönen Worte. Bearbeiten des Beitrags mit den zugehörigen .circ-Dateien.
Will Hodges

Sind das also insgesamt 6 Dateien? (Ich nehme an, dies ist für LogiSim 2.7.1, 2011?)
Jonk

@ Jonk ja, es ist, auf beide Fragen
Will Hodges

Wie gehst du mit Subtraktion um? Verwenden Sie das / Q von einem Eingangs-Latch zu einem der A / B-Eingänge Ihrer ALU und ändern Sie den Carry-In? Oder eine andere Methode?
Jonk

Antworten:


3

Ich hasse es, eine "nur Link" -ähnliche Antwort zu posten, aber ich denke, Sie sollten auf Warren Toomeys Arbeit mit CPUs in Logisim aufmerksam gemacht werden, da es wahrscheinlich genau das ist, wonach Sie suchen.

Er hat ein paar Tutorials, die hier zu einer einigermaßen einfachen CPU aufbauen ...

http://minnie.tuhs.org/CompArch/Tutes/

Und wenn das Ihr Boot nicht schwimmt, hat er hier eine ausgefeiltere CPU ...

http://minnie.tuhs.org/Programs/UcodeCPU/

... All dies ist gut erklärt und hat Downloads in .circ-Dateien.


Eine weitere großartige und wohl funktionalere DIY-CPU / Computer ist Magic-1 unter http://www.homebrewcpu.com/ . Obwohl es nicht in Logisim gemacht wird, ist es ziemlich gut dokumentiert, einschließlich Bilder, Schaltplan, Beschreibung. Es ist auch mehr als nur eine CPU in einem Simulator. Es verfügt über einen ANSI C-Compiler, ein Betriebssystem und einige Software. Es hat auch den entscheidenden Vorteil, dass es tatsächlich in Hardware eingebaut wurde. Tatsächlich ist es derzeit in Betrieb und bedient Webseiten!


Schließlich sind die Elemente von Computersystemen und die zugehörige Website nand2tetris.org die empfohlene Informationsquelle Nr. 1 für den Aufbau Ihres eigenen Computers von Grund auf, wenn ich ihn mir anschaue. Viele (alle?) Inhalte sind meiner Meinung nach kostenlos. YouTube würde zustimmen; Viele Leute haben Projekte aus dieser einen Quelle gemacht.


1
Das Youtbue-Video von Ben Eater zum Bau eines 8-Bit-Brotbrettcomputers ist ebenfalls sehr hilfreich!
Francis Cugler

1

Ich denke, Sie vermissen einen wichtigen Aspekt der Funktionsweise von ALUs. Normalerweise ist jedes Bit des Akkumulators über einen Demultiplexer mit jedem der verschiedenen Funktionsblöcke verbunden. Mit einem Befehlsbyte wird die Funktion ausgewählt und jedes Bit des Akkumulators mit dem richtigen Eingang des Funktionsblocks verbunden. Die Größe des Demultiplexers bestimmt, wie viele Funktionen die ALU ausführen kann. In meinem sehr groben Beispiel unten könnte eine ALU mit einem 4-Bit-Eingang mit dem Demultiplexer auf 16 verschiedene Funktionen verweisen:

Anschließen des Akkus an verschiedene Funktionsblöcke innerhalb einer ALU

Beachten Sie, dass in den meisten CPUs dieses Design in einem Durcheinander von Gattern optimiert ist, um die Transistoranzahl zu reduzieren.

Durch ein größeres Befehlsregister können mehr Funktionen verwendet werden, dies würde jedoch auch mehr Taktzyklen erfordern, um den Befehl zu laden.

Ich empfehle dringend, das folgende Buch zu lesen, wenn Sie mehr über digitales Design erfahren möchten: Grundlagen des Logikdesigns 7. Ausgabe.


Diese Antwort verwechselt Anweisungen mit ALU-Operationen. Insbesondere würde dieser Demultiplexer nur verwendet, um auszuwählen, welche arithmetische Operation für einen arithmetischen Befehl ausgewählt werden soll. Sie würden den Demultiplexer beispielsweise mit 3 Bits aus einem 8-Bit-Befehl versorgen, um die arithmetische Operation auszuwählen. Sie benötigen einen völlig separaten Mechanismus, um Anweisungen im Allgemeinen zu dekodieren und zu sequenzieren. Abgesehen davon verwenden die meisten CPUs, die ich mir angesehen habe, keinen solchen Demultiplexer in der ALU, sondern ein optimiertes Durcheinander von Gates, um die richtige Operation auszuführen.
Ken Shirriff

1
@ KenShirriff Ich habe einige Änderungen zur Klarheit vorgenommen. Nehmen Sie einige Änderungen vor, wie Sie es für richtig halten.
Takide

1

Es scheint, als wären Sie auf dem richtigen Weg.

Wenn Sie Ihre Mikroanweisungen planen, müssen Sie das "Verkehrs" -Muster für Ihre Datenbewegung durch Ihre verschiedenen Blöcke in Ihrem eigenen Kopf klar definieren. Das Ausführen eines ADD erfordert mehrere Schritte. Wenn Sie Halteregister für Ihre beiden ALU-Operanden haben, müssen diese aus dem RAM oder einem Register oder Bus geladen werden. Wenn Sie einen gemeinsam genutzten internen Bus haben, müssen Sie möglicherweise jeweils einen Operanden laden. Wenn Sie wissen, welche Bytes (Adresse, sofortiges Literal, RAM-Daten, Zeiger) wohin verschoben werden müssen, planen Sie die Reihenfolge der Bewegung der Bytes durch die Busse in und aus den verschiedenen Registern. Möglicherweise stecken Sie fest und müssen ein internes Halteregister hinzufügen, da ein Zwischenwert bis zum nächsten Mikrobefehlsschritt beibehalten werden muss.

Ich denke, das, was Sie vermuten, fehlt, ist die Komplexität, die erforderlich ist, damit die Logik den Befehl oder Opcode in mehrere Zustände innerhalb Ihrer CPU übersetzt. Es kann komplex sein, aber es ist möglich, eine etwas einfache Zustandsmaschine zu erstellen und diese dann mit grundlegenden Logikkonzepten zu erweitern.

Angenommen, Sie erstellen die Mikrobefehlsschritte für eine MOVE-Operation. Dies könnte lose durch 3 Schritte beschrieben werden: 1) Aktivieren des Inhalts des Quellregisters auf dem internen Bus, 2) Stroben des Schreibtakts des Zielregisters, 3) Deaktivieren des Inhalts des Quellregisters vom internen Bus. Die Schritte 1) bis 3) beschreiben das Timing für eine Registerausgangsfreigabe (OE) und eine Registerschreibfreigabe (WE), die selektiv auf jedes Quellregister und jedes Zielregister verteilt werden können, das mit Demultiplexern an den gemeinsam genutzten internen Bus angeschlossen ist.

Wenn Sie nicht viel Übung beim Erstellen von Finite-State-Maschinen haben, kann es hilfreich sein, die verschiedenen Ansätze zu betrachten, um einen weiteren Baustein für die Erzeugung der Steuersignale von Ihrem Mikrosequenzer zu erhalten.

Dabei bleiben. Die Menge an Wissen, die Sie erwerben, wird phänomenal sein. Und hoffentlich haben Sie viel Spaß.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.