The 20c – Episodio 4 – ROM, Read Only Memory

Introducción 

En este episodio vamos a conocer al Chip ROM o Read Only Memory el cual tiene la funcionalidad de darnos una memoria de sólo lectura. Esta memoria nos va a servir para poder almacenar todas las instrucciones de nuestros programas.

Para usar este chip diseñamos una placa Dual que va a poder correr tanto un chip ROM como uno RAM que comparten el mismo pinout, en este episodio nos vamos a enfocar en la ROM.

Vamos a estudiar el pinout del chip, como funciona, como poder grabarlo usando un programador de EEPROM y vamos a realizar experimentos que nos dejen almacenar y ejecutar nuestro primer programa.

Como siempre vamos a explicar como crear la placa desde cero y como funciona la misma.

Descripción general de la placa ROM

Nuestra Placa RAM/ROM, cuando la configuramos en modo ROM, sirve para almacenar los programas que vamos a ejecutar en nuestra 20c. 

En nuestro caso el chip a utilizar es el AT28C256 de ATMEL. Este chip posee 32768 registros de 8 bits cada uno, por lo que podemos tener hasta 32k bytes de información en este tipo de memorias. El 256K del nombre, se refiere a los 256 Kbits individuales que posee la placa los que equivalen a 32 Kbytes (256/8=32). 

Para grabar este chip con instrucciones utilizaremos un grabador de memorias EEPROM.

Este chip viene en formato DIP (Dual Inline Pins).

Descripción del Pin Out del chip AT28C256 

Este chip presenta 28 pines con el siguiente funcionamiento:


A14 – A0: Estos pines nos permiten seleccionar qué registro de ocho bits queremos acceder dentro de nuestra memoria, al ser 15 pines podemos direccionar 2ˆ15 = 32768 registros de 8 bits. Estos pines se conectan al bus de direccionamiento o ADDRESS BUS .

I/O 0 a I/O 7: Los pines de input/ouput o I/O es donde vamos a ver el contenido de cada registro previamente seleccionado para leer la memoria, o donde vamos a enviar los datos que tenemos para escribir la memoria. Estos pines se conectan al bus de datos o DATA BUS .

VCC: En este pin es donde el chip espera una alimentación de +5Volts.

GND: Este es el pin de referencia a tierra del chip.

/WE: El pin de Write Enable al recibir una señal de low o 0 Volts permite grabar en los registros de la memoria. Como la estamos utilizando como una ROM conectamos este pin directamente a +5 Volts para que sea de sólo lectura. La barra / significa que este pin es active low con lo cual espera 0 Volts para activarse.

/OE: El pin de output enable conecta o desconecta los pines de I/O del bus de datos. Si el pin está en +5 Volts la memoria se desconecta del bus de datos poniendo sus pines de datos en un estado de alta impedancia. La barra / significa que este pin es active low con lo cual espera 0 Volts para activarse.

/CE: El pin de chip enable conecta o desconecta los pines del chip para una lectura o escritura trabajando en conjunto con /OE y /WE. Es active low con lo cual espera 0 Volts para activarse.

Mapa de Memoria

El 6502 puede direccionar hasta 65536 registros de 8 bits cada uno o 64K como nos gusta decir. Esto nos dejaría utilizar hasta 2 chips EEPROM de 32k cada uno.

Las direcciones que maneja el procesador van desde la $0000 hasta la $FFFF, siempre en hexadecimal como indicamos al anteponer el signo pesos. Si quisiéramos repartir estas direcciones entre 2 chips podríamos asignar de $0000 a $7FFF para el primero y de $8000 a $FFFF para el segundo.

Nuestro chip posee 32kb de espacio pero vamos a tener que decidir con qué direcciones de memoria vamos a querer accederlo, esto se denomina mapa de memoria.

El mapa de memoria indica para cada chip y periférico de nuestra 20c qué direcciones del ADDRESS BUS van a activarlo para acceder a sus registros, en el caso de chips con registros para configurarlos o en el caso del chips de memorias ROM y RAM para leer o modificar su contenido.

Vamos a decidir colocar nuestro chip ROM en las direcciones de la $8000 a $FFFF principalmente por que ahi vamos a tener 3 posiciones de memoria o vectores muy importantes, los dos de interrupciones NMI e INT y el de RESET que como recordamos es donde el chip 20c busca la dirección donde va a estar el primer programa a ejecutar cuando prendemos el mismo.

Este mapa de memoria es el recomendado originariamente en el manual de Hardware y el en de Programación de MOS Technologies.

El siguiente es el mapa de memoria de la 20c

En este mapa podemos ver donde tenemos el chip ROM y algunos otros chips extra que vamos a estudiar en futuros episodios.

Cómo acceder al Chip

El chip no se encuentra todo el tiempo activo ya que si no tendría siempre el DATA BUS ocupado. El CPU ordena a los chips de la computadora y le indica al chip que quiere leer sus datos a través de los pines de ChipSelect /CS y OutputEnable /OE.

Aquí es donde entra en juego el mapa de memoria, vamos a activar los pines de /CS y /OE cuando en el ADDRESS BUS se escriba una dirección de las que definimos como parte del chip ROM. Este chip por definición va a ser de sólo lectura.

Lectura

Para realizar una lectura deberemos primero poner en el bus de direccionamiento el address de la memoria que queremos acceder y acto seguido poner los pines:

/WE en +5 Volts (High)

/OE en 0 Volts (Low)

/CE en 0 Volts (Low)

En el bus de Datos tendremos la información asociada a la dirección que pusimos en el address bus. El /WE o el /CE deberá ser un pulso, cuando indicamos que una señal debe ser un pulso se debe a que el chip reacciona, no al valor específico en volts, sino al cambio de voltaje, en el caso de /CE de +5Volts a 0V también llamado Falling Edge.

Escritura

Para realizar una escritura deberemos primero poner en el bus de ADDRESS BUS la dirección de la memoria que queremos escribir, luego en el bus de datos o DATA BUS la información a grabar y acto seguido poner los pines:

/WE en 0 Volts (Low)

/OE en +5 Volts (High)

/CE en 0 Volts (Low)

Recordemos que al tratarse de una ROM no vamos a realizar escrituras a la misma, esto lo vamos a lograr conectando el chip /OE de output enable siempre a +0v o Ground.

Cómo seleccionamos la memoria desde el procesador

Nuestro chip está en las direcciones desde $8000 a $FFFF. Vamos a ver como se ven estas direcciones en binario para observar si podemos sacar algún patrón útil.

Espacio de DireccionamientoHexaBinario
Superior$80001000 0000 0000 0000
Superior$80011000 0000 0000 0001
Superior………………………………………
Superior$FFFE1111 1111 1111 1110
Superior$FFFF1111 1111 1111 1111

Podemos observar que el primer bit en Binario es uno. Para direccionar todos los registros de la eeprom necesitamos 15 pines del A0 al A14 con lo que nos sobra el pin A15. 

Para poner en modo de lectura solamente al chip podríamos entonces conectar en forma permanente los pines:

/WE en +5 Volts (High)

/OE en 0 Volts (Low)

También podemos conectar el pin /WE al pin de R/W del procesador 6502 ya que el mismo emitirá un pulso de +5V al realizar una lectura, pero por si se equivoca y envia una escritura no queremos que esto afecte a nuestra memoria así que no lo hacemos.

El pin A15 queda con un valor de 1 o +5 Volts (High) no podríamos conectarlo directamente al pin de /CE ya que no se activaría por ser Active Low el pin. Lo que deberíamos hacer es invertir el valor de 1 a 0 y propongo hacerlo con una compuerta NAND.

Una compuerta NAND tiene la siguiente tabla de verdad que es la opuesta a una compuerta AND.

Input AInput BResultado
LOWLOWHIGH
LOWHIGHHIGH
HIGHLOWHIGH
HIGHHIGHLOW

Con lo que si conectamos en la misma compuerta NAND como input A la salida en +5 Volts (HIGH) del pin A15 y como input B también la salida en +5 Volts (HIGH) del pin A15 el resultado será un 0 Volts (LOW) que permitirá activar el pin /CE de chip enable.


Para esto podemos utilizar un clásico chip como ser el 74HC00 que posee cuatro compuertas NAND de dos inputs cada una.


Veremos cómo realizar la conexión a nuestra placa en la sección Guía de Conexión.

Programando en Assembler

Para poder programar nuestro chip 6502 con facilidad vamos a utilizar un programa Assembler llamado VASM. Este ensamblador nos va a permitir compilar a binario nuestro programa. El link para descargarlo se encuentra en las referencias.

Programa

Empecemos con un programa assembler sencillo que emula nuestros experimentos anteriores con resistencias para codificar la instrucción de no operación NOP cuyo opcode es 0xEA.

Vamos a explicar línea por línea que hace nuestro programa:

Líneas 1 y 2 comentarios

Línea 3 .org 8000 

Indica que queremos comenzar nuestro programa a partir de la dirección $8000 justo donde comienza nuestra ROM. Esto va a hacer que el compilador cuando traduzca nuestro programa a los OPCODEs de cada operación los situe a partir de la dirección $8000.

Línea 4 vacia

Línea 5 RESET 

Esto se denomina un LABEL nos sirve para poder indicar una parte del código donde vamos a querer llegar sin tener que saber exactamente que dirección hexadecimal posee en la memoria, el ensamblador se va a encargar de poner la dirección Correcta durante el ensamblaje (el ensamblador que ensamble un buen ensamblaje, buen ensamblador será).

Este importante esta LABEL en particular ya que el 6502 automáticamente busca en la dirección $FFFC y $FFFD la dirección donde está la primera instrucción a ejecutar y nosotros le vamos a pedir que sea la dirección donde esta el LABEL RESET.

Línea 6 comentario

Línea 7 a 16 NOP

Comienzan nuestras instrucciones con la instrucción NOP de no operación, el 6502 lo va a leer y va a pasar dos ciclos de reloj sin hacer nada. En nuestro programa compilado va a poner 10 bytes EA consecutivos.

Línea 17 vacia

Línea 18 comentario

Línea 19 .org FFFA

Aquí le decimos al compilador que a partir de esta dirección ponga las instrucciones siguientes

Línea 20 RESET

Entonces como dato la dirección del label RESET, como escribe LowByte, HighByte por se rel procesador 6502 Little Endian va a ir en la dirección $FFFA $00 y en la $FFFB $80. Esta dirección carga el vector de interrupciones NMI.

Línea 21 .org FFFC

Aquí le decimos al compilador que a partir de esta dirección ponga las instrucciones siguientes

Línea 22 RESET

Entonces como dato la dirección del label RESET, como escribe LowByte, HighByte por se rel procesador 6502 Little Endian va a ir en la dirección $FFFC $00 y en la $FFFD $80. Esta dirección carga el vector de interrupciones de la operación RESET, luego de un reset del procesador va a cargar como primera instrucción la que aquí se encuentre.

Línea 23 comentario

Línea 24 .org FFFE

Aquí le decimos al compilador que a partir de esta dirección ponga las instrucciones siguientes

Línea 25 RESET

Entonces como dato la dirección del label RESET, como escribe LowByte, HighByte por se rel procesador 6502 Little Endian va a ir en la dirección $FFFE $00 y en la $FFFF $80. Esta dirección carga el vector de interrupciones IRQ.

Compilando

Ahora que ya tenemos nuestro código fuente, vamos a compilar nuestro código assembler  a código de máquina usando vasm.


Aquí le doy varias opciones al compilador, vamos a verlas

Vasm6502_oldstyle, esta opción le dice al ensamblador que utilice el módulo de sintaxis Oldstyle, esto va a definir distintas particularidades de como escribir los LABELs y otros detalles

-Fbin, vamos a señalar como módulo de Output el simply binary output module, este módulo va a escribir la salida de todas instrucciones que tenemos en nuestro código fuente como un archivo binario. Los espacios vacíos entre secciones .org que no llenamos con instrucciones van a tener el byte $00

-dotdir, que acepte en nuestro código direcciones especiales al ensamblador como ser por ejemplo .org

ep4_firstprogram.asm, el nombre de nuestro archivo con el código fuente

-o, a continuación indicaremos el archivo donde poner el código binario ya ensamblado

ep4_firstprogram.bin, el nombre de nuestro programa ensamblado en binario

Análisis del código máquina

Ahora utilizando el programa hexdump examinemos nuestro código máquina y tratemos de interpretar donde están las instrucciones anteriores.

A las direcciones que vemos sumemosle $8000 por como muestra el archivo hexdump, con lo que donde dice 00000000 miremos 000008000. ¿Por qué es así? Por que la ROM sólo tiene 32kb y nosotros lo ponemos en el mapa de memoria de nuestro 6502 a partir de la dirección $8000, pero no existe esta dirección dentro de la ROM ya que 32kb van desde $0000 a $7FFF. Hexdump solo muestra la realidad del interior del archivo sin saber donde vamos a mapear nosotros.

Línea 00000000 aquí vemos 10 veces el byte EA que corresponde al código de operación de NOP

Línea 00000010 todos ceros, recuerden como -Fbin rellenaba los espacios que no definimos

Línea 00007ff0 aqui finalmente vemos los últimos 6 bytes como 00 80 00 80 00 80 que corresponde a las direcciones LOW y HIGH para el LABEL de reset que está definido en la dirección $8000 para los 3 vectores de 6502 NMI, RESET e IRQ.

Ahora que tenemos nuestro código máquina vamos a grabarlo en el chip de EEPROM 

Cómo grabar el Chip con un grabador de EEPROM

Para escribir las instrucciones de nuestro chip vamos a usar un grabador externo que nos va a permitir completar cada casillero de memoria con las instrucciones que queramos

Ya que tenemos nuestro primer programa como un archivo binario de 32768 bytes, solo nos resta grabar el mismo en una EEPROM y esto se realiza con un grabador de eeproms. En este ejemplo vamos a usar un TL866 II Plus o el T48.

Este programador de eeprom es muy sencillo de utilizar a través del programa minipro, al mismo se le indica qué tipo de chip eeprom vamos a grabar y que archivo queremos grabar. 

Antes de comenzar a grabar conectamos el grabador a nuestra computadora, e insertamos el chip eeprom en el zócalo zif 

Vamos a utilizar el programa minipro para poder hacer la escritura del chip, donde conseguir el mismo está incluido en las referencias de este mismo episodio.

Para grabar un archivo binario con el nombre por ejemplo ep4_firstprogram.bin ejecutaremos el siguiente comando.

$ minipro -p AT28C256 -w ep4_firstprogram.bin

La opción -p es para especificar el modelo de la memoria que vamos a grabar en este caso una AT28C256 de ATMEL.

La opción -w para especificar que queremos hacer una escritura y a continuación el nombre del archivo a grabar.

Y con esto tenemos nuestro primer programa grabado en ROM, en los experimentos vamos a ver que ejecuta nuestra computadora con este primer programa

Circuito de la Placa ROM de la 20c

El siguiente gráfico muestra el circuito que explica el funcionamiento de la Placa ROM de la 20c.

El circuito posee los siguientes elementos:

SOCKET RAMROM

El cual está representado físicamente como un socket DIP-28 de 28 pines, a cada uno de estos pines se le conectó un Netlist representando cada una de las funciones de estos pines por ejemplo el netlist A0 representa el pin A0 que estará conectado a todos los elementos que tenga que estar conectados con la línea o trace del address 0. 

Tiene conectado los netlists de A0 a A14, D0 a D7 y todos los netlist de /RW (señal de Write Enable), OE y CS. Para darle energía esta conectado a los planos de +5b y GROUND.

HEADER ADDRESS

Este es un header hembra de 16 pines el cuál se usa para conectar el address bus, el mismo tiene conectados 16 netlist (o conexiones entre varios pines que tienen la misma información). Estos netlist corresponden a los pines A0 hasta A15. 

Tenemos dos de estos conectores para poder tener la información en la parte superior e inferior de la placa y realizar interconexiones con otras placas.

HEADER DATA

Este es un header hembra de 8 pines el cuál se usa para conectar el data bus, el mismo tiene conectados 8 netlist (o conexiones entre varios pines que tienen la misma información). Estos netlist corresponden a los pines D0 hasta D7.

Tenemos dos de estos conectores para poder tener la información en la parte superior e inferior de la placa y realizar interconexiones con otras placas.

HEADER EXPANSION

Este es un header hembra de 16 pines el cuál se usa para conectar el expansion bus, el mismo tiene conectados 16 netlist (o conexiones entre varios pines que tienen la misma información). Estos netlist corresponden a algunos netlist conectados directamente a pines de RAMROM como ser:

RW, OE, CS

o señales genéricas que pueden transmitir información a otras placas como ser:

RST, CLOCK, RW, E5 hasta E15

Tenemos dos de estos conectores para poder tener la información en la parte superior e inferior de la placa y realizar interconexiones con otras placas.

HEADER POWER y GROUND

Este header posee dos pines y están conectados a las capas de 5V y de GROUND respectivamente. Tenemos cuatro de estos conectores, uno en cada esquina de la placa.

CAPACITOR

Tenemos un capacitor de 0.1 microFaradios para que cuando el CPU arranca pueda disponer del pico extra de energía que necesita.

AGUJEROS para TORNILLOS

Para poder fijar nuestra placa a distintos lugares la misma cuenta con 6 agujeros para tornillos de 3mm o M3.

SWITCH RAMROM SW1

Este switch no posee ninguna característica eléctrica y no está conectado a ning;un circuito, como nuestra placa puede funcionar tanto como ROM como RAM vamos a correr el switch y dejarlo en la posición en que vamos a usar la placa.

NETLIST

Los componentes están conectados entre sí a través de un objeto llamado netlist el cual nos permite tener diagramas más limpios.

Este funciona de forma tal que todo lo que tenga el mismo nombre pertenece al mismo netlist y deberá estar conectado junto cuando hagamos el PCB (con traces). 

En nuestro ejemplo todas las conexiones A0 estarán conectadas por traces en el PCB

PCB de la Placa ROM de la 20c

El siguiente PCB explica cómo se ubican los elementos y traces para conectar nuestro circuito. El PCB que diseñamos está hecho con 4 capas de cobre.

TOP

En la capa llamada TOP que es la que podríamos ver como arriba y de frente en nuestra PCB vamos a tener algunas las conexiones de nuestros netlist a través de traces, los cuáles son finas líneas de cobre que conectan los mismos como si fueran cables y los todos los componentes ya sea sockets, capacitores y headers.

LAYER 5V

En la capa +5v conectaremos las conexiones de power. Al usar estas conexiones en una capa separada nos ahorramos muchos centímetros de traces que deberían conectarse a pines con los voltajes de 5V podemos conectar directamente el pin de cada componente a esta capa a través de un agujero llamado VIA.


LAYER GROUND

En la capa GROUND conectamos las conexiones de ground o masa. Al de tener una capa entera para GROUND es poder aislar el ruido eléctrico de las conexiones entre componentes.

BOTTOM

Por último tenemos la capa de BOTTOM donde se sueldan nuestros componentes y tenemos conexiones adicionales.


Modelado 3D

Cuando terminamos de realizar nuestra Placa debemos proceder al modelado 3D de la misma para observar cómo queda y si nos gusta el lugar donde pusimos cada componente

.

Generación de archivos fuent

Para poder mandar a fabricar nuestro PCB deberemos contar con al menos 3 archivos:

  1. Archivo .gerber donde le indicamos al fabricante como armar nuestra placa
  2. Archivo BOM o Bill of materials donde se encuentran todos los componentes que forman nuestra placa con el código de producto del fabricante.
  3. Archivo Pick and Place donde le indicamos al fabricante cómo ubicar los componentes en nuestra placa PCB.

lista de archivos

Estos archivos los van a encontrar previamente generados en el github de Osolabs. También incluimos archivos para poder editar el circuito con el software EasyEDA, Kickcad o Altium Designer.

Con estos tres archivos vamos a poder fabricar nuestra placa

Gerber_v03_RAM_ROM_4Plane_2026-05-26.zip Este archivo contiene todos los planos para poder generar nuestra placa PCB.

BOM_v03_RAM_ROM_4Plane_v03_RAM_ROM_4Plane_2026-05-26.xlsx Contiene todos los componentes de nuestra placa y el código del fabricante que identifica a ese componente.

PickAndPlace_v03_RAM_ROM_4Plane_2026-05-26.xlsx

Indica en qué parte del PCB va cada componente y en qué capa debe ubicarse.

Los siguientes archivos se proveen para poder editar el circuito 

3DModel_ramrom_front.png

Es una imágen con la parte de atrás de nuestra placa modelada en 3D

3DModel_ramrom_back.png

Es una imágen con la parte de adelante de nuestra placa modelada en 3D

Altium_Circuit_1_v03_RAM_ROM_4Plane.schdoc

Contiene el diseño del circuito editable con el programa Altium Designer.

Altium_PCB_v03_RAM_ROM_4Plane.pcbdoc

Contiene el diseño del PCB editable con el programa Altium Designer.

PCB_v03_RAM_ROM_4Plane_2026-05-26.pdf

Es un PDF con un dibujo de cada capa del PCB

ProDoc_v03_RAM_ROM_4Plane_2026-05-26.epro

Archivo para EasyEDAPro con el circuito y el PCB el cual puede editarse.

SCH_v03_RAM_ROM_4Plane_2026-05-26.pdf

Es un PDF con los circuitos lógicos de la placa

Preparación de las Placa ROM

Al recibir nuestra placa de la fábrica y antes de comenzar a utilizar la misma y al momento que la sacamos de la caja, hay algunas tareas que deberemos hacer para poder hacer uso al máximo de la misma:

  1. Remover los bordes de manipulación de la placa
  1. Limpiar placa con alcohol isopropílico
  1. OPCIONAL – Poner un zócalo ZIF de 28 pines en el socket de la placa
  1. Poner el chip AT28C256 en el socket
  1. Ajustar a mano las patas del chip para que calcen el socket
  2. Alinear pin 1 con el pin 1 en el socket
  3. Primero insertar un lado del chip, poniendo el mismo en diagonal y luego el otro lado
  4. Verificar que ninguna patita quedó doblada
  5. Hacer presión y ver que todas están bien ajustadas en el socket
  1. Poner Tornillos de soporte de la placa para que esté levantada por encima de la superficie o instalarla, en nuestro caso usamos la base impresa en 3D de la 20c que vamos a aprender a crearla e imprimirla en un próximo Episodio
  1. Configurar switch SW1 en modo ROM para acordarnos que función cumple la placa.

Guía de Conexión de la placa ROM de la 20c

Vamos a explicar como conectar los distintos componentes de la placa para dejar esta lista para funcionar en una maqueta. Tené esta sección como referencia para cuando ensambles toda la 20c.

La memoría ROM queremos activarla para que funcione en las direcciones $8000 a $FFFF. Para esto vamos a necesitar tener el pin  A15 en uno como ya hemos visto.

A15A14A13A12address
ROM1XXX8000-FFFF

La memoria ROM tiene dos pines para activarse /OE y / CS ambos tienen que estar en cero para que la misma esté activada.

/OE memoria ROM

El Pin /OE vamos a conectarlo directamente a la señal de GROUND para que esté siempre activo .

R/W memoria ROM

El Pin R/W vamos a conectarlo directamente a +5v para que la memoria sea de sólo lectura siempre .

/CS memoria ROM

El pin de chip select vamos a seleccionarlo con el pin A15. Al pin A15 vamos a combinarlo consigo mismo en una compuerta NAND de forma tal que cuando valga un 1 lógico o +5v la  compuerta NAND dará un 0 lógico o +0v. Como ya estudiamos por el comportamiento de la compuerta NAND

Esa salida de la compuerta NAND vamos a conectarla a través del EXPANSION BUS con el pin /CS

Vamos a utilizar al el chip 74HC00, usando los pines 2A, 2B y la salida 2Y utilizando un breadboard

  1. Conectar el chip 74hc00 a un breadboard montando el lado izquierdo del chip en la parte por arriba de la canaleta del breadboard y la parte derecha en la parte inferior a la canaleta del mismo. Esto hará que respetemos la orientación del esquema que incluimos con el PIN 1 abajo a la izquierda.
  1. Conectar el pin de VCC al carril de +5v o rojo del breadboard
  1. Conectar el pin de GND o ground +0v al carril azul del breadboard.
  1. Conectar las canaletas superiores e inferiores del breadboard de +5v y 0v o ground entre sí
  1. Para poder hacer el efecto en la compuerta NAND conectaremos el pin A15 del bus de direccionamiento al pin 2B del 74HC00 y desde el mismo breadboard conectaremos el pin 2B al 2A.
  1. Conectamos la Salida 2Y al pin /CS del bus de expansión
  1. Finalmente para que el chip 74HC00 funcione no podemos dejar ninguno de sus inputs flotantes por lo que los conectamos todos a +5v. Estos son los pines 1A, 1B, 2A, 2B, 4A, 4B.

Conexión del resto de la placas

Para poder realizar nuestro experimentos tenemos que configurar el CLOCK y la CPU 6502 de la 20c asi cómo darle power en +5v.

  1. Conectamos un módulo de power a nuestro breadboard seleccionado el carril en +5v, tener en cuenta de poner el pin del módulo que dice + en el carril rojo de +5v.
  1. Conectamos el carril rojo del breadboard al pin de +5v de la placa de RAM/ROM.
  1. Colocamos al costado de la placa de RAM/ROM la placa de CLOCK y conectamos los pines de power +5v y GROUND entre las dos placas
  1. Conectamos la salida del reloj paso a paso de la placa de CLOCK al pin CLOCK de la placa de RAM/ROM pero en el pin header inferior, el que está más cerca del breadboard
  1. Colocamos la placa de CPU encima de placa de RAM/ROM y conectamos todos los headers de ADDRESS BUS y de DATA BUS. También vamos a conectar entre sí el pin de CLOCK y los pines de +5v y GROUND
  1. Instalamos la placas de DUINO PROTOCOL ANALYZER junto a su Arduino Mega en el header superior de la placa de CPU 6502
  1. Por último observamos que así nos queden todas las conexiones

Experimento 1 – Grabando solo NOPs

Vamos a reproducir el experimento que usábamos grabando la instrucción de no operación NOP, cuyo opcode es 0xEA como vinimos haciendo hasta acá y estudiaremos cómo se comporta la 20c usando la placa de DUINO PROTOCOL ANALYZER.

Vamos a usar el programa que creamos en la sección sobre código máquina. Este programa usa principalmente la instrucción NOP:

Para el detalle línea por línea de lo que hace el programa ir a la sección Programando en Assembler


Vamos a compilarlo con vasm.

Y ahora colocamos la eeprom en el programador


Corremos el comando minipro y lo grabamos


Y ahora vamos a estudiar la salida del procesador usando el DUINO PROTOCOL ANALYZER, utilizando el script 001_Arduino_DUINO_PA que ya vimos en el Episodio 3 sobre el DUINO PA y analizaremos el output de nuestro experimento.

Reset seguido de lectura de instrucciones NOP

  1. Conectamos el pin CLK del header CLOCK_555_OUT
  1. Seleccionemos el switch para el reloj paso a paso. 
  1. Presionemos el botón de reset de nuestro CPU y dejemoslo presionado.
  1. Presionar 3 veces el botón de STEP BUTTON de nuestra placa de CLOCK
  1. Soltar el botón de RESET de nuestro CPU
  1. Continuemos presionando el botón de STEP BUTTON de nuestra placa de CLOCK y veremos que cada vez que lo hacemos avanza un ciclo en  nuestro CPU, algunas instrucciones ocupan un ciclo de reloj y otras más
  1. Observamos en detalle los datos que nos da nuestro DUINO PROTOCOL ANALYZER a través del Arduino Mega.

El procesador va a encender y buscar en las posiciones $FFFC y $FFFD la dirección de la primera instrucción a ejecutar ordenados como Low Byte y High Byte. 

$FFFC contiene $00 = %0000 0000 

$FFFD contiene $80 = %1000 0000

En la misma va a encontrar los bytes $00 y $80 al utilizar la notación little endian la dirección que va a cargar el cpu 6502 en su registro de program counter va a ser $8000

Si lo ordenamos por los pines del address bus veríamos:

El Pin A A15 es un 1 que a través de la compuerta NAND se transforma en 0 equivalente a 0 Volts o Low, y como está conectado al  pin /CE nuestra EEPROM se activará.

Con esto cargará el  Program Counter con la primera posición de nuestro programa ficticio que será $8000 y buscará el código de la próxima instrucción a ejecutar que será EA ya que es lo único que tenemos en el bus de datos. 

La próxima instrucción leída del data bus es la instrucción EA la cual significa la no operación NOP, sabemos que es un código de operación porque el flag S de SYNC está activado en nuestro bus de EXPANSION BUS significando un ciclo de OP-FETCH. 

Esta ejecución durará dos ciclos de reloj y luego el program counter avanzará a 8001 y volverá a leer el bus de datos en búsqueda de la próxima instrucción que seguirá siendo EA y así continuará.

El ciclo de ejecución de la primera instrucción es la siguiente:

  1. 8000 lee del databus el opcode hay +5V en el pin de SYNC lo interpreta como una instrucción Incrementa el program counter.
  2. Ejecuta la instrucción EA o sea NOP de no operación (ciclo 1 de 2)  y pone 8001 en el address bus
  3. Termina de ejecutar la instrucción NOP (ciclo 2 de 2) y trae la próxima instrucción de la dirección 8001 que sigue en el address bus. Incrementa el program counter.

Experimento 2 – Ejecutando un Loop 

En este experimento estudiaremos un simple loop y estudiaremos cómo se comporta la 20c usando la placa de DUINO PROTOCOL ANALYZER.

En este nuevo experimento vamos a usar principalmente dos instrucciones:

Creemos un segundo programa entonces donde vamos a ejecutar la instrucción de carga al acumulador LDA cargando el número 42 en hexadecimal $42. Vamos a usar la instrucción jump JMP para volver a ejecutar la instrucción de carga LDA en un bucle infinito y observar qué sucede.

Veamos línea a línea que hace nuestro programa.

Líneas 1 y 2 comentarios

Línea 3 .org 8000 

Indica que queremos comenzar nuestro programa a partir de la dirección $8000 justo donde comienza nuestra ROM. Esto va a hacer que el compilador cuando traduzca nuestro programa a los OPCODEs de cada operación los situe a partir de la dirección $8000.

Línea 4 vacia

Línea 5 RESET 

Esto se denomina un LABEL nos sirve para poder indicar una parte del código donde vamos a querer llegar sin tener que saber exactamente que dirección hexadecimal posee en la memoria, el ensamblador se va a encargar de poner la dirección Correcta durante el ensamblaje (el ensamblador que ensamble un buen ensamblaje, buen ensamblador será).

Es importante esta LABEL en particular ya que el 6502 automáticamente busca en la dirección $FFFC y $FFFD la dirección donde está la primera instrucción a ejecutar y nosotros le vamos a pedir que sea la dirección donde esta el LABEL RESET.

Línea 6 comentario

Línea 7  LDA #$42

Comienzan nuestras instrucciones con la instrucción LDA #$42 esta instrucción carga en el acumulador el valor 42 en hexadecimal, es un instrucción de modo inmediato ya que estamos cargando un número literal no una posición de memoria y su OPCODE es A9. 

Línea 8 JMP RESET

Aquí ejecutamos la instrucción JMP o Jump al label RESET, esto hara que nuestro program counter tome el valor del label RESET en este caso $8000 y volvamos a correr la instrucción LDA #$42 en un bucle infinito. El OPCODE de la instrucción JMP es $4C. 

Línea 9 vacia

Línea 10 comentario

Línea 11 .org FFFA

Aquí le decimos al compilador que a partir de esta dirección ponga las instrucciones siguientes

Línea 12 RESET

Entonces como dato la dirección del label RESET, como escribe LowByte, HighByte por se rel procesador 6502 Little Endian va a ir en la dirección $FFFA $00 y en la $FFFB $80. Esta dirección carga el vector de interrupciones NMI.

Línea 13 .org FFFC

Aquí le decimos al compilador que a partir de esta dirección ponga las instrucciones siguientes

Línea 14 RESET

Entonces como dato la dirección del label RESET, como escribe LowByte, HighByte por se rel procesador 6502 Little Endian va a ir en la dirección $FFFC $00 y en la $FFFD $80. Esta dirección carga el vector de interrupciones de la operación RESET, luego de un reset del procesador va a cargar como primera instrucción la que aquí se encuentre.

Línea 15 comentario

Línea 16 .org FFFE

Aquí le decimos al compilador que a partir de esta dirección ponga las instrucciones siguientes

Línea 17 RESET

Entonces como dato la dirección del label RESET, como escribe LowByte, HighByte por se rel procesador 6502 Little Endian va a ir en la dirección $FFFE $00 y en la $FFFF $80. Esta dirección carga el vector de interrupciones IRQ.

Vamos a compilarlo con vasm.

Y ahora colocamos la eeprom en el programador

Corremos el comando minipro y lo grabamos

Y ahora vamos a estudiar la salida del procesador usando el DUINO PROTOCOL ANALYZER, utilizando el script 001_Arduino_DUINO_PA que ya vimos en el Episodio 3 sobre el DUINO PA y analizaremos el output de nuestro experimento.

Reset seguido de lectura de instrucciones NOP

  1. Conectamos el pin CLK del header CLOCK_555_OUT
  1. Seleccionemos el switch para el reloj paso a paso. 
  1. Presionemos el botón de reset de nuestro CPU y dejemoslo presionado.
  1. Presionar 3 veces el botón de STEP BUTTON de nuestra placa de CLOCK
  1. Soltar el botón de RESET de nuestro CPU
  1. Continuemos presionando el botón de STEP BUTTON de nuestra placa de CLOCK y veremos que cada vez que lo hacemos avanza un ciclo en  nuestro CPU, algunas instrucciones ocupan un ciclo de reloj y otras más
  1. Observamos en detalle los datos que nos da nuestro DUINO PROTOCOL ANALYZER a través del Arduino Mega.

En las primeras tres líneas podemos leer la palabra RESET eso significa que tenemos el botón de reset presionado.

Luego contamos 7 ciclos de reloj que es lo que dura un reset y vemos que en los próximos dos ciclos buscamos el vector de reset en las direcciones FFFC y FFFD.

El procesador va a encender y buscar en las posiciones $FFFC y $FFFD la dirección de la primera instrucción a ejecutar ordenados como Low Byte y High Byte. 

La primera instrucción estará en $8000

En $8000 cargará el opcode A9 de la instrucción LDA de un valor al acumulador

En $8001 tendrá el valor a cargar en el acumulador en este caso $42

En $8002 vamos a tener el valor $4C que es la indicación de hacer una instrucción JMP

En $8003 vamos a tener el valor $00 que es el Low byte de la dirección donde tiene que saltar el JMP

En $8004 vamos a tener el valor $80 que es el High byte de la dirección donde tiene que saltar el JMP con estos dos valores el JMP ya tiene a donde saltar la dirección $8000 y eso es lo que carga en el Program Counter y vuelve a empezar el Loop.

Conclusiones

La Placa RAM_ROM nos permite incluir un chip ROM en nuestro sistema, esto nos da la gran ventaja de poder tener programas en assembler grabados para que nuestra 20c ejecute diferentes tareas. Repasamos cómo funciona el chip ROM, como crear nuestra placa y como hacer un par de experimentos para aprender su funcionamiento.

La placa RAM ROM en funcionamiento

Para ver visualmente cómo conectar la placa RAM_ROM  de la 20c les dejo como siempre un video en detalle de la serie. En este vamos a ver cómo se conectan los pines, y nuestro experimento en forma visual indicando. 

Referencias

A continuación les dejo algunos links donde profundizar el tema:

Arduino IDE

EasyEDA Pro – V2.2.39 

ATMEL AT28C256 datasheet 

74HC00 Datasheet (PDF) – NXP Semiconductors

TL866II USER GUIDE 

David Griffith / minipro · GitLab 

W65C02S 8–bit Microprocessor 

6502 Instruction Set 

vasm portable and retargetable assembler 

WEBSITE

Aquí está el sitio de OsoLabs con todos los videos y artículos.

OsoLabs.tech 

VIDEOS

Aquí el video correspondiente a este capítulo y la lista de todos los videos de esta serie.

https://www.osolabs.tech/the20c

ARTICULOS

Aquí podrán encontrar todos los artículos sobre La 20c:

https://blog.espaciotec.com.ar

https://www.osolabs.tech/the20c

CÓDIGO y DISEÑO DE PLACAS PCB

Todos los ejemplos de código de este artículo los pueden encontrar en:

https://github.com/osolabstech/The20c

OTROS RECURSOS

Como la serie donde vemos todos los juguetes y periféricos de la Commodore que siempre quisimos tener, Los chiches de la Commodore tanto en video como en artículos

https://www.osolabs.tech/los-chiches-de-la-commodore

Los Chiches De La Commodore 

C64 a Fondo – Indice

Y la serie donde comparamos en 6502 contra el 6510 utilizando breadboards.

https://www.osolabs.tech/6502vs6510

6502 vs 6510 estudio detallado y comparación – YouTube 

Y como siempre la serie de Ben Eater del 6502 que es excelente:

Build a 6502 computer | Ben Eater 

Autor: OsoLabs

Empecé con la Commodore de chico, sigo con la Commodore de grande. Programo para 6502, Arduino, Raspberry y algunos algoritmos de Bioinfomática, algo en C++, algo en Python, algo en Assembler. Fanático de la electrónica home brew desde breadboard a diseñar PCBs propios. Armé la 20c y OsoLabs https://www.osolabs.tech Mi GitHub para quien quiera sumarse a los proyectos y chusmear código: https://github.com/carlinhocr/ Desde Argentina al Mundo

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *