¿Cómo puedo implementar un controlador DRAM asíncrono muy simple?

Me gustaría saber cómo construir un controlador DRAM asíncrono básico. Tengo algunos módulos DRAM SIMM 70ns de 1 MB de 30 pines (1Mx9 con paridad) que me gustaría usar en un proyecto de computadora retro homebrew. Desafortunadamente, no hay una hoja de datos para ellos, así que he ido desde Siemens HYM 91000S-70 y "Comprender el funcionamiento de DRAM" de IBM.

La interfaz básica con la que me gustaría terminar es

  • /CS: en, selección de chip
  • R/W: en, leer/no escribir
  • RDY: fuera, ALTO cuando los datos están listos
  • D: entrada/salida, bus de datos de 8 bits
  • A: entrada, bus de direcciones de 20 bits

Actualizar parece bastante sencillo con varias formas de hacerlo bien. Debería poder hacer una actualización distribuida (intercalada) solo de RAS (ROR) durante el reloj de la CPU BAJO (donde no se realiza acceso a la memoria en este chip en particular) usando cualquier contador antiguo para el seguimiento de la dirección de la fila. Creo que todas las filas deben actualizarse al menos cada 64 ms según JEDEC (512 por 8 ms según la hoja de datos de Siemens, es decir, actualización estándar de ciclo/15.6us), por lo que debería funcionar bien y si me quedo atascado, solo publicaré otra pregunta. Estoy más interesado en leer y escribir de manera simple, correcta y determinar qué debo esperar en cuanto a velocidad.

Primero describiré rápidamente cómo creo que funciona y las posibles soluciones que he encontrado hasta ahora.

Básicamente, divide una dirección de 20 bits por la mitad, usando una mitad para la columna y la otra para la fila. Muestra la dirección de la fila, luego la dirección de la columna, si / W es ALTO cuando / CAS pasa a BAJO, entonces es una lectura, de lo contrario es una escritura. Si se trata de una escritura, los datos ya deben estar en el bus de datos en ese punto. Después de un período de tiempo, si se trata de una lectura, los datos están disponibles o si se trata de una escritura, es seguro que los datos se han escrito. Luego, /RAS y /CAS deben volver a ponerse ALTOS en el período de "precarga" llamado de forma contraria a la intuición. Esto completa el ciclo.

Entonces, básicamente es una transición a través de varios estados con retrasos específicos no uniformes entre cada transición. Lo he enumerado como una "tabla" indexada por la duración de cada fase de la transacción en orden:

  1. t(ASR) = 0ns
    • /SARPULLIDO
    • /DINERO
    • A0-9: AR
    • /An: Al
  2. t(RAH) = 10ns
    • /RAS:L
    • /DINERO
    • A0-9: AR
    • /An: Al
  3. t(ASC) = 0ns
    • /RAS:L
    • /DINERO
    • A0-9: CA
    • /An: Al
  4. t(CAH) = 15ns
    • /RAS:L
    • /CAS: L
    • A0-9: CA
    • /An: Al
  5. t(CAC) - t(CAH) = ?
    • /RAS:L
    • /CAS: L
    • A0-9: X
    • /W: H (datos disponibles)
  6. t(RP) = 40ns
    • /SARPULLIDO
    • /CAS: L
    • A0-9: X
    • /W: X
  7. t(PC) = 10ns
    • /SARPULLIDO
    • /DINERO
    • A0-9: X
    • /W: X

Los tiempos a los que me refiero están en el siguiente diagrama.

diagrama de tiempo

(CA = dirección de columna, RA = dirección de fila, X = no importa)

Incluso si no es exactamente eso, es algo así y creo que funcionará el mismo tipo de solución. Así que se me ocurrieron un par de ideas hasta ahora, pero creo que solo la última tiene potencial y estoy buscando mejores ideas. Estoy ignorando la actualización, la página rápida y la verificación/generación de paridad aquí.

La solución más simple es usar un contador y una ROM donde la salida del contador es la entrada de la dirección de la ROM y cada byte tiene la salida de estado adecuada para el período de tiempo al que corresponde la dirección. Esto no funcionará porque las ROM son lentas. Incluso una SRAM precargada parece ser demasiado lenta para valer la pena.

La segunda idea era usar un GAL16V8 o algo así, pero creo que no los entiendo lo suficientemente bien, los programadores son muy caros y el software de programación es de código cerrado y solo Windows, hasta donde yo sé.

Mi última idea es la única que creo que podría funcionar. La familia lógica 74ACT tiene retrasos de propagación bajos y acepta frecuencias de reloj altas. Estoy pensando que la lectura y la escritura se pueden hacer con un registro de desplazamiento CD74ACT164E y SN74ACT573N .

Básicamente, cada estado único tiene su propio pestillo programado estáticamente usando rieles de 5V y GND. Cada salida del registro de desplazamiento va al pin /OE de un pestillo. Si entiendo bien las hojas de datos, la demora entre cada estado solo podría ser 1/SCLK, pero eso es mucho mejor que una solución PROM o 74HC.

Entonces, ¿es probable que funcione el último enfoque? ¿Hay una manera más rápida, más pequeña o generalmente mejor de hacer esto? Creo que vi que IBM PC/XT usaba 7400 chips para algo relacionado con DRAM, pero solo vi fotos de la placa superior, así que no estoy seguro de cómo funcionó.

ps Me gustaría que esto sea factible en DIP y no "hacer trampa" usando un FPGA o un uC moderno.

pps Tal vez usar el retraso de la puerta directamente con el mismo enfoque de bloqueo es una mejor idea. Me doy cuenta de que tanto el registro de desplazamiento como los métodos de demora de propagación/puerta directa variarán con la temperatura, pero lo acepto.

Para cualquiera que encuentre esto en el futuro, esta discusión entre Bil Herd y André Fachat cubre varios de los diseños mencionados en este hilo y analiza otros problemas, incluida la prueba de DRAM.

¿Qué CPU va a usar tu computadora retro?
6502, la memoria se almacenará obviamente.
¿Es posible que no te invente la bicicleta, ya hay diseños disponibles usando DRAMs? No estoy familiarizado con esta familia de máquinas, pero C64 debe ser una buena combinación. Sin embargo, originalmente usa el chip 6567 "VIC" para controlar la RAM. Pero de nuevo, estoy seguro que desde entonces hubo proyectos relacionados con lo que quieres hacer.
Una sugerencia ligeramente distorsionada: el Z80 tenía suficiente controlador DRAM incorporado para manejar la lógica de actualización. (Sin embargo, aún necesitaba un multiplexor de direcciones)
Esto sería difícil/imposible para nosotros, ya que los controladores dram están integrados en las CPU y MPU actuales. Son muy complejos y construir uno manualmente es absurdo. Básicamente, un controlador de dram está a cargo de las operaciones de actualización de dram y otorga acceso a la CPU o GPU durante unos pocos ms cuando las secciones de dram no se actualizan. La frecuencia de actualización típica es de 16 mS para todas las celdas. Para hacer las cosas más eficientes, un controlador DMA mueve los datos en ráfagas, por tamaño de página.
@Brian Sí, vi eso. Estoy considerando pero está en el lado "deformado".
@Sparky256 Como dije para los chips de esta era, son 64 ms y creo que los otros tiempos son similares a los chips de Siemens. Sí, soy consciente de que los módulos IMC y RAM más nuevos tienen más funciones y son más rápidos, pero eso no es lo que pregunté. Hay muchos circuitos sobre cómo hacer una actualización SIMMM de 30 pines y 72 pines que son bastante portátiles, pero no pude encontrarlos. Lo que describe es precisamente lo que quise decir con refrescante "intercalado". Creo que DMA y FPM incluso comenzaron en los 8088 días, pero como dije, no necesito nada de eso. Estoy buscando diseños barebones.
@Anónimo: aún no he encontrado mucho en la búsqueda, pero miraré más máquinas Commadore para ver si alguna tiene más DRAM. Creo que Apple II tenía un esquema simplificado en el que solo direccionaba las filas. El uso de ese esquema debería funcionar hasta quizás 512k, por lo que no estoy seguro de que alguien hubiera hecho algo más en ese momento.
@BrianDrummond Por favor, no recomiendo ir al lado oscuro. Nada bueno puede salir de eso.
@BrianDrummond: El Z80 NO incluye un controlador DRAM. La única característica que tiene para admitir la operación de DRAM es el hecho de que, inmediatamente después de obtener el primer byte de una instrucción, coloca el contenido de un contador de 8 bits en el bus de direcciones durante dos ciclos de reloj mientras afirma una señal llamada RFSH. . Eso es. Todavía necesita una lógica externa para generar la sincronización para RAS, CAS, WE, OE y una señal de control de multiplexor. Consulte la documentación de Ferguson Big Board para conocer una forma de lograr esto.

Respuestas (3)

Hay esquemas completos para IBM PC/XT en el manual de referencia técnica de IBM Personal Computer XT (Apéndice D), que puede encontrar en línea.

El problema aquí es que, dada una línea estroboscópica que se activa con una lectura o escritura de memoria, desea generar RAS, CAS y una línea de control (llámela MUX) para el multiplexor de direcciones. Para simplificar, asumiré de manera poco realista que la luz estroboscópica, RAS y CAS están todos activos en alto.

Mirando el esquema de PC/XT y los esquemas de otras computadoras de esta época, veo tres estrategias básicas, que son más o menos las siguientes:

  • Use la luz estroboscópica para RAS. Use una línea de retardo (una parte cuya salida es una versión con retardo de tiempo de su entrada) en RAS para generar MUX, y use otra línea de retardo para generar una versión aún posterior de RAS, que se usa para CAS. Esta estrategia es utilizada por el PC/XT y el TRS-80 Model II.

    Un ejemplo (moderno) de línea de retardo es el Maxim DS1100.

  • Use la luz estroboscópica para RAS y retrase para MUX y CAS, pero hágalo usando un registro de desplazamiento de alta velocidad en lugar de una línea de retardo. Esta estrategia es utilizada por el TRS-80 Model I y el Apple II.

  • Utilice circuitos integrados personalizados. Esta es la estrategia del Commodore 64.

Aparentemente, solo ayer encontré un XT TR sin el Apéndice D. Yo lo tengo ahora, esto es genial. No sabía que existían estos circuitos integrados de línea de retardo y me preguntaba cómo se ocupaban de la temperatura. Gracias por mencionar el ejemplo moderno. +1 para múltiples soluciones también.

Su pregunta es lo suficientemente complicada como para que ni siquiera esté seguro de cuál es su problema real, ¡pero lo intentaré!

El diseño de DRAM basado en 6502 "más limpio" que pude encontrar es del Commodore PET 2001-N . Tiene un 6502 funcionando a 1 MHz, pero la lógica DRAM tiene una frecuencia de 16 MHz, lo que probablemente generará todos los tiempos.

No he analizado los detalles, pero la acción principal parece ocurrir con un contador de 4 bits 74191 conectado a un registro de desplazamiento 74164. Esto genera 8 líneas separadas que van a un 74157 MUX que está controlado por la línea R/W. La salida del MUX va a un flip-flop 7474 y alguna lógica discreta para generar las señales RAS/CAS finales. Aquí hay un extracto que enlaza con la página correspondiente en el esquema de referencia.

PET 2001-N referencia página 6

La actualización se maneja con un contador separado y cada línea de dirección está conectada a un multiplexor que selecciona la dirección "real" o la dirección de actualización.

Partes de esta lógica también parecen generar tiempos para el subsistema de video. Estoy seguro de que se puede simplificar para sus necesidades particulares, pero creo que algo similar puede ser útil: un contador de alta frecuencia, un registro de desplazamiento y multiplexores.

Esto es en lo que estaba pensando, pero fui lo suficientemente tonto como para pensar en varios pestillos en lugar de uno o dos MUX. Sin embargo, el reloj de 16 MHz me desconcierta porque a) es mucho más alto que el reloj de la CPU, lo que me pareció extraño pero tiene sentido yb) Las fases pueden tener un mínimo de ~ 62 ns más retrasos de propagación que pensé que eran lentos pero ahora vea que está en el mismo orden que el IBM PC/XT.
El Apple II es muy similar, utiliza el reloj de video de 14,318 MHz para cronometrar y compartir la memoria entre la CPU y el video en semiciclos alternos sin contención. Ni siquiera necesita un contador de actualización separado, porque la actividad de actualización de video también sirve para mantener la memoria actualizada.

ps Me gustaría que esto sea factible en DIP y no "hacer trampa" usando un FPGA o un uC moderno.

Si bien entiendo completamente el espíritu de su proyecto y su deseo de usar piezas que no sean de lujo, definitivamente seguiría el camino de la FPGA si fuera usted .

Muchas rasones:

  1. Es una perfecta oportunidad de aprendizaje. Diseñar un controlador DRAM no es un proyecto de "hola mundo" y después de eso puede decir con confianza que "puede hacer" FPGA;
  2. Podría exprimir cada bit de rendimiento de esta memoria, especialmente si se trata de un chip DRAM más antiguo. No solo tendría su PC casera basada en 6502, es posible que tenga la PC basada en 6502 más rápida ;
  3. Puede ser mucho más fácil depurar problemas o hacer estadísticas de las operaciones de memoria que emitió su CPU. Puede usar analizadores lógicos en buses paralelos, pero nunca es divertido (un amigo mío hace algo en este sentido: quiere escribir una simulación de ciclo exacto de 8088 y por esa razón necesita recopilar esas estadísticas sobre accesos a memoria y tiempo patrones Él usa el conjunto de chips original (8288, 8280, 8237) y usa un analizador lógico con muchos canales, pero por su experiencia puedo decirte que es un lastre).
No estoy seguro de cómo esto es una respuesta en lugar de un comentario. 1) No dice que quiere aprender FPGA. 2) Las DRAM de los años 80 ya son lo suficientemente lentas para la lógica discreta. 3) La depuración puede ser difícil. ¿Por qué no implementar todo en el FPGA, o incluso solo en el software? ¿Por qué incluso usar la RAM en absoluto ... :)
@pipes: Sí, exactamente. No quiero perder tiempo aprendiendo FPGA en este momento. Ya tengo suficiente en mi plato con un segundo proyecto analógico no relacionado. En general, los FPGA y los PLD parecen estorbar en este punto, aunque algún día aprenderé a usarlos.
@pipe: volver a cablear las placas a menudo es difícil, lleva mucho tiempo y es frustrante, especialmente si uno no es particularmente hábil en eso. El uso de algunos PLD bastante simples (por ejemplo, 22V10) para algunas partes del diseño hará que sea más fácil modificar las cosas.