Wie kann ich einen sehr einfachen asynchronen DRAM-Controller implementieren?

Ich würde gerne wissen, wie man einen asynchronen DRAM-Controller ohne Knochen baut. Ich habe einige 30-polige 1-MB-SIMM-70-ns-DRAM-Module (1Mx9 mit Parität), die ich in einem Homebrew-Retro-Computerprojekt verwenden möchte. Leider gibt es kein Datenblatt dafür, also bin ich vom Siemens HYM 91000S-70 und "Understanding DRAM Operation" von IBM ausgegangen.

Die grundlegende Schnittstelle, mit der ich enden möchte, ist

  • /CS: ein, Chip auswählen
  • R/W: ein, lesen/nicht schreiben
  • RDY: aus, HIGH, wenn Daten bereit sind
  • D: Ein/Aus, 8-Bit-Datenbus
  • A: Eingang, 20-Bit-Adressbus

Die Aktualisierung scheint ziemlich einfach zu sein, mit mehreren Möglichkeiten, es richtig zu machen. Ich sollte in der Lage sein, eine verteilte (verschachtelte) Nur-RAS-Aktualisierung (ROR) während des CPU-Takts LOW (wo in diesem bestimmten Chip kein Speicherzugriff erfolgt) unter Verwendung eines beliebigen alten Zählers für die Zeilenadressenverfolgung durchzuführen. Ich glaube, dass alle Zeilen gemäß JEDEC mindestens alle 64 ms aktualisiert werden müssen (512 pro 8 ms gemäß dem Seimens-Datenblatt, dh Standardaktualisierung von Zyklus/15,6 us), also sollte dies gut funktionieren, und wenn ich nicht weiterkomme, poste ich einfach eine andere Frage. Ich bin mehr daran interessiert, einfach und korrekt lesen und schreiben zu können und zu bestimmen, was ich in Bezug auf die Geschwindigkeit erwarten sollte.

Ich werde zuerst kurz beschreiben, wie ich denke, dass es funktioniert und welche möglichen Lösungen ich bisher gefunden habe.

Grundsätzlich teilen Sie eine 20-Bit-Adresse in zwei Hälften, wobei Sie eine Hälfte für die Spalte und die andere für die Zeile verwenden. Sie stroben die Zeilenadresse, dann die Spaltenadresse, wenn /W HIGH ist, wenn /CAS auf LOW geht, dann ist es ein Lesevorgang, andernfalls ist es ein Schreibvorgang. Wenn es sich um einen Schreibvorgang handelt, müssen sich die Daten zu diesem Zeitpunkt bereits auf dem Datenbus befinden. Wenn es sich um einen Lesevorgang handelt, sind die Daten nach einer gewissen Zeit verfügbar, oder wenn es sich um einen Schreibvorgang handelt, sind die Daten sicher geschrieben worden. Dann müssen /RAS und /CAS in der kontraintuitiv als "Vorlade"-Periode wieder HIGH gebracht werden. Damit schließt sich der Kreislauf.

Im Grunde ist es also ein Übergang durch mehrere Zustände mit ungleichmäßigen spezifischen Verzögerungen zwischen jedem Übergang. Ich habe es als "Tabelle" aufgelistet, die nach der Dauer jeder Phase der Transaktion in der Reihenfolge indiziert ist:

  1. t(ASR) = 0ns
    • /AUSSCHLAG
    • /CAS: H
    • A0-9: RA
    • /W:H
  2. t(RAH) = 10ns
    • /RAS: L
    • /CAS: H
    • A0-9: RA
    • /W:H
  3. t(ASC) = 0ns
    • /RAS: L
    • /CAS: H
    • A0-9: CA
    • /W:H
  4. t(CAH) = 15ns
    • /RAS: L
    • /CAS: L
    • A0-9: CA
    • /W:H
  5. t(CAC) - t(CAH) = ?
    • /RAS: L
    • /CAS: L
    • A0-9: X
    • /B: H (Daten verfügbar)
  6. t(RP) = 40 ns
    • /AUSSCHLAG
    • /CAS: L
    • A0-9: X
    • /W:X
  7. t(CP) = 10 ns
    • /AUSSCHLAG
    • /CAS: H
    • A0-9: X
    • /W:X

Die Zeiten, auf die ich mich beziehe, sind im folgenden Diagramm dargestellt.

Zeitdiagramm

(CA = Spaltenadresse, RA = Zeilenadresse, X = egal)

Auch wenn es nicht genau das ist, es ist so etwas und ich denke, dass die gleiche Art von Lösung funktionieren wird. Ich habe mir bisher ein paar Ideen ausgedacht, aber ich denke, nur die letzte hat Potenzial und ich suche nach besseren Ideen. Ich ignoriere hier Refreshing, Fast Page und Parity Checking/Generating.

Die einfachste Lösung besteht darin, einfach einen Zähler und ein ROM zu verwenden, wobei der Zählerausgang der ROM-Adresseneingang ist und jedes Byte den entsprechenden Zustandsausgang für die Zeitdauer hat, der die Adresse entspricht. Dies wird nicht funktionieren, da ROMs langsam sind. Selbst ein vorinstallierter SRAM scheint viel zu langsam zu sein, um sich zu lohnen.

Die zweite Idee war, einen GAL16V8 oder so etwas zu verwenden, aber ich glaube, ich verstehe sie nicht gut genug, Programmierer sind sehr teuer und die Programmiersoftware ist, soweit ich weiß, nur Closed Source und Windows.

Meine letzte Idee ist die einzige, von der ich denke, dass sie tatsächlich funktionieren könnte. Die 74ACT-Logikfamilie hat geringe Ausbreitungsverzögerungen und akzeptiert hohe Taktfrequenzen. Ich denke, das Lesen und Schreiben könnte mit einem CD74ACT164E -Schieberegister und SN74ACT573N erfolgen .

Grundsätzlich erhält jeder eindeutige Zustand seinen eigenen Latch, der unter Verwendung von 5-V- und GND-Schienen statisch programmiert wird. Jeder Ausgang des Schieberegisters geht an den /OE-Pin eines Latches. Wenn ich die Datenblätter richtig verstehe, könnte die Verzögerung zwischen den einzelnen Zuständen nur 1/SCLK betragen, aber das ist viel besser als eine PROM- oder 74HC-Lösung.

Wird der letzte Ansatz also wahrscheinlich funktionieren? Gibt es eine schnellere, kleinere oder allgemein bessere Möglichkeit, dies zu tun? Ich glaube, ich habe gesehen, dass der IBM PC/XT 7400-Chips für etwas verwendet, das mit DRAM zu tun hat, aber ich habe nur Top-Board-Fotos gesehen, daher bin ich mir nicht sicher, wie das funktioniert hat.

ps Ich möchte, dass dies in DIP machbar ist und nicht mit einem FPGA oder modernen uC "schummelt".

pps Vielleicht ist es eine bessere Idee, die Gate-Verzögerung direkt mit dem gleichen Latch-Ansatz zu verwenden. Mir ist klar, dass sowohl Schieberegister- als auch direkte Gate- / Ausbreitungsverzögerungsmethoden mit der Temperatur variieren, aber ich akzeptiere dies.

Für alle, die dies in Zukunft finden, deckt diese Diskussion zwischen Bil Herd und André Fachat mehrere der in diesem Thread erwähnten Designs ab und diskutiert andere Probleme, einschließlich DRAM-Tests.

Welche CPU wird Ihr Retro-Computer verwenden?
6502, Speicher wird natürlich eingebucht.
Ist es möglich, das Fahrrad nicht für Sie zu erfinden, gibt es bereits verfügbare Designs mit DRAMs? Ich bin mit dieser Maschinenfamilie nicht vertraut, aber C64 muss gut passen. Es verwendet jedoch ursprünglich den 6567 "VIC" -Chip zur Steuerung des RAM. Aber noch einmal, ich bin mir sicher, dass es seitdem Projekte gab, die mit dem zu tun hatten, was Sie tun wollten.
Ein leicht verzerrter Vorschlag: Der Z80 hatte genug eingebauten DRAM-Controller, um die Refresh-Logik zu handhaben. (Sie brauchten jedoch noch Adressmultiplexer)
Dies wäre für uns schwierig/unmöglich, da DRAM-Controller in die heutigen CPUs und MPUs eingebaut sind. Sie sind sehr komplex und es ist absurd, sie manuell zu erstellen. Grundsätzlich ist ein DRAM-Controller für DRAM-Aktualisierungsvorgänge zuständig und gewährt der CPU oder GPU für einige Millisekunden Zugriff, wenn Abschnitte des DRAM nicht aktualisiert werden. Die typische Aktualisierungsrate beträgt 16 ms für alle Zellen. Um die Dinge effizienter zu machen, verschiebt ein DMA-Controller Daten in Bursts nach Seitengröße(n).
@Brian Ja, das habe ich gesehen. Ich überlege, aber es ist auf der "verzerrten" Seite.
@ Sparky256 Wie ich für Chips aus dieser Zeit sagte, sind es 64 ms und ich denke, die anderen Timings sind ähnlich wie bei den Siemens-Chips. Ja, mir ist bewusst, dass neuere IMCs und RAM-Module mehr Funktionen haben und schneller sind, aber danach habe ich nicht gefragt. Es gibt viele Schaltungen zur Durchführung von 30-Pin- und 72-Pin-SIMM-Aktualisierungen, die ziemlich portabel sind, aber ich konnte sie nicht finden. Was Sie beschreiben, ist genau das, was ich mit "verschachtelter" Aktualisierung gemeint habe. Ich denke, DMA und FPM haben sogar in den 8088-Tagen begonnen, aber wie gesagt, ich brauche nichts davon. Ich suche nach Barebones-Designs.
@Anonymous: Ich habe bei der Suche noch nicht allzu viel gefunden, aber ich werde mir weitere Commadore-Maschinen ansehen, um zu sehen, ob welche mehr DRAM haben. Ich denke, der Apple II hatte ein vereinfachtes Schema, bei dem nur Zeilenadressierung durchgeführt wurde. Die Verwendung dieses Schemas sollte bis zu 512.000 funktionieren, also bin ich mir nicht sicher, ob irgendjemand zu diesem Zeitpunkt etwas anderes getan hätte.
@BrianDrummond Bitte empfehlen Sie nicht, auf die dunkle Seite zu gehen. Daraus kann nichts Gutes entstehen.
@BrianDrummond: Der Z80 enthält KEINEN DRAM-Controller. Das einzige Merkmal, das es zur Unterstützung des DRAM-Betriebs haben muss, ist die Tatsache, dass es unmittelbar nach dem Abrufen des ersten Bytes eines Befehls den Inhalt eines 8-Bit-Zählers für zwei Taktzyklen auf den Adressbus legt, während es ein Signal namens RFSH aktiviert . Das ist es. Sie benötigen noch eine externe Logik, um das Timing für RAS, CAS, WE, OE und ein Multiplexer-Steuersignal zu generieren. Eine Möglichkeit, dies zu erreichen, finden Sie in der Ferguson Big Board-Dokumentation .

Antworten (3)

Vollständige Schaltpläne für den IBM PC/XT finden Sie im technischen Referenzhandbuch für den IBM Personal Computer XT (Anhang D), das Sie möglicherweise online finden können.

Das Problem hierbei ist, dass Sie bei einer gegebenen Strobe-Leitung, die beim Lesen oder Schreiben des Speichers aktiviert wird, RAS, CAS und eine Steuerleitung (nennen Sie sie MUX) für den Adressmultiplexer erzeugen möchten. Der Einfachheit halber nehme ich unrealistisch an, dass Strobe, RAS und CAS alle aktiv hoch sind.

Wenn ich mir den PC/XT-Schaltplan und die Schaltpläne einiger anderer Computer aus dieser Zeit anschaue, sehe ich drei grundlegende Strategien, die ungefähr die folgenden sind:

  • Verwenden Sie den Blitz für RAS. Verwenden Sie eine Verzögerungsleitung (ein Teil, dessen Ausgang eine zeitverzögerte Version seines Eingangs ist) auf RAS, um MUX zu erzeugen, und verwenden Sie eine andere Verzögerungsleitung, um eine noch spätere Version von RAS zu erzeugen, die für CAS verwendet wird. Diese Strategie wird vom PC/XT und dem TRS-80 Model II verwendet.

    Ein Beispiel für ein (modernes) Verzögerungsleitungsteil ist das Maxim DS1100.

  • Verwenden Sie das Strobe für RAS und verzögern Sie es für MUX und CAS, aber tun Sie dies mit einem Hochgeschwindigkeits-Schieberegister anstelle einer Verzögerungsleitung. Diese Strategie wird vom TRS-80 Model I und dem Apple II verwendet.

  • Verwenden Sie benutzerdefinierte ICs. Das ist die Strategie des Commodore 64.

Anscheinend hatte ich erst gestern eine XT TR ohne Anhang D gefunden. Ich habe es jetzt, das ist großartig. Ich wusste nicht, dass es diese Verzögerungsleitungs-ICs gibt, und habe mich gefragt, wie sie mit der Temperatur umgehen. Vielen Dank für die Erwähnung des modernen Beispiels. +1 auch für mehrere Lösungen.

Ihre Frage ist so kompliziert, dass ich nicht einmal sicher bin, was Ihr eigentliches Problem ist, aber ich werde es versuchen!

Das "sauberste" 6502-basierte DRAM-Design, das ich finden konnte, stammt vom Commodore PET 2001-N . Es hat einen 6502, der mit 1 MHz läuft, aber die DRAM-Logik wird mit 16 MHz getaktet, was wahrscheinlich alle Timings erzeugt.

Ich habe die Details nicht analysiert, aber die Hauptaktion scheint mit einem 74191 4-Bit-Zähler zu geschehen, der mit einem 74164 Schieberegister verbunden ist. Dies gibt 8 separate Leitungen aus, die in einen 74157 MUX gehen, der von der R/W-Leitung gesteuert wird. Der Ausgang des MUX geht in ein 7474-Flip-Flop und eine diskrete Logik, um die endgültigen RAS/CAS-Signale zu erzeugen. Hier ist ein Auszug, der auf die entsprechende Seite im Referenzschema verweist.

PET 2001-N Referenzseite 6

Das Auffrischen wird mit einem separaten Zähler gehandhabt, und jede Adressleitung ist mit einem Multiplexer verbunden, der entweder die "echte" Adresse oder die Auffrischadresse auswählt.

Teile dieser Logik scheinen auch Timings für das Videosubsystem zu generieren. Ich bin sicher, dass es für Ihre speziellen Bedürfnisse vereinfacht werden kann, aber ich denke, dass etwas Ähnliches nützlich sein kann: Ein Hochfrequenzzähler, Schieberegister und Multiplexer.

Daran dachte ich, aber ich war dumm genug, mehrere Latches anstelle von ein oder zwei MUX zu erstellen. Der 16-MHz-Takt wirft mich jedoch ab, weil a) er viel höher ist als der CPU-Takt, den ich gerade seltsam fand, aber sinnvoll ist, und b) die Phasen ein Minimum von ~ 62 ns plus Ausbreitungsverzögerungen betragen können, was ich für langsam hielt, aber jetzt ich Sehen Sie, das ist in der gleichen Reihenfolge wie der IBM PC/XT.
Der Apple II ist sehr ähnlich und verwendet den 14,318-MHz-Videotakt zum Timing und zur gemeinsamen Nutzung des Speichers zwischen CPU und Video in abwechselnden Halbzyklen ohne Konflikte. Es ist nicht einmal ein separater Aktualisierungszähler erforderlich, da die Videoaktualisierungsaktivität auch dazu dient, den Speicher auf dem neuesten Stand zu halten.

ps Ich möchte, dass dies in DIP machbar ist und nicht mit einem FPGA oder modernen uC "schummelt".

Obwohl ich den Geist Ihres Projekts und Ihren Wunsch, nicht ausgefallene Teile zu verwenden, vollkommen verstehe, würde ich an Ihrer Stelle definitiv den FPGA-Weg gehen .

Mehrere Gründe:

  1. Es ist eine perfekte Gelegenheit zum Lernen. Das Entwerfen eines DRAM-Controllers ist kein "Hallo-Welt"-Projekt, und danach können Sie zuversichtlich sagen, dass Sie FPGA "können".
  2. Aus diesem Speicher könnte man jedes Quäntchen Leistung herauskitzeln, besonders wenn es sich um einen älteren DRAM-Chip handelt. Sie hätten nicht nur Ihren selbstgebauten 6502-basierten PC, es ist möglich, dass Sie den schnellsten 6502-basierten PC haben;
  3. Es kann viel einfacher sein, Probleme zu debuggen oder Statistiken über die von Ihrer CPU ausgegebenen Speicheroperationen zu erstellen. Sie können Logikanalysatoren auf parallelen Bussen verwenden, aber es macht nie Spaß (ein Freund von mir macht etwas in dieser Richtung - er möchte eine zyklusgenaue Simulation von 8088 schreiben und muss aus diesem Grund diese Statistiken über Speicherzugriffe und Timing sammeln Muster. Er verwendet den Original-Chipsatz (8288, 8280, 8237) und einen Logikanalysator mit vielen Kanälen, aber aus seiner Erfahrung kann ich Ihnen sagen, dass es eine Verzögerung ist).
Ich bin mir nicht sicher, wie dies eine Antwort anstelle eines Kommentars ist. 1) Er sagt nicht, dass er FPGAs lernen will. 2) DRAMs aus den 80ern sind schon langsam genug für diskrete Logik. 3) Das Debuggen kann schwierig sein. Warum nicht alles im FPGA oder sogar nur in Software implementieren? Warum überhaupt den RAM verwenden ... :)
@pipes: Ja, genau. Ich möchte im Moment keine Zeit damit verbringen, FPGAs zu lernen. Mit einem zweiten analogen Projekt ohne Bezug habe ich schon genug zu tun. FPGAs und PLDs im Allgemeinen haben das Gefühl, dass sie an dieser Stelle nur im Weg sind, obwohl ich eines Tages lernen werde, wie man sie benutzt.
@pipe: Das Neuverdrahten von Platinen ist oft schwierig, zeitaufwändig und frustrierend, besonders wenn man nicht besonders geschickt darin ist. Die Verwendung einiger ziemlich einfacher PLDs (z. B. 22V10) für einige Teile des Designs wird es einfacher machen, Dinge zu optimieren.