RAM & Transfer Register
To fetch addresses coming from the Program Counter(PC), the SAP-1 uses a Memory Address Register(MAR) to first store the addresses before accessing them in RAM. My build has no need for a MAR, as it has a dedicated memory/system bus. With a system bus, the PC and all other memory-related modules interface with the RAM and each other directly.
The transfer register, which I call the BR (Bridge), is a 16-bit register that moves data between the 8-bit data bus and the 16-bit system/memory bus in two cycles. The CPU canât directly read from the data bus into the 16-bit special registers, except for the Segmented Display (SD) register. In my programs, I use little endian to load values into the BR, which is really just an arbitrary preference over big endian. Endianness refers to the order in which bytes are arranged. In little endian, the least significant byte is stored first, while in big endian, the most significant byte comes first. This choice doesnât change the computerâs performance; itâs just a different way of organizing data.
Implementations
Transfer Register
Control lines involved(5):
- |â ~BRE Bridge Enable: Enables the address bus to the transfer registerâs input.
- |â BRlW Bridge Lower Write: Writes data from the data bus to the lower byte of the transfer register.
- |â BRhW Bridge Higher/Upper Write: Writes the content on the data bus to the upper byte of the transfer register.
- |â ~BRhE Bridge Higher/Upper Enable: Enables the upper byte of the transfer register to the data bus.
- |â ~BRlE Bridge Lower Enable: Enables the lower byte of the transfer register to the data bus.
The transfer register consists of a 16-bit register made with two 8-bit 74HCT574. The 574âs layout turned out be extremely convenient for this module as the large amount of jumper wires are evenly spread on both sides of the breadboard. Like every module interacting with the address bus; it has two pairs of transceivers; One(The left pair) to load BR from the address bus in one cycle with ~BRE, and the other to either write to or read from the data bus in two cycles using BRlW, BRhW ~BRhE, and ~BRlE.
RAM
Control lines involved(3):
- |â ~SPE Stack access control line: Enables stack memory when LOW, and ROM when HIGH.
- |â ~ME Enables memory output to the data bus.
- |â ~MW Memory write
My RAM chip is a UM61512A 64K X 8 BIT HIGH SPEED CMOS SRAM, which is perfect for my use case, as it is cheap(About $15 for a set of 10 on Ebay), and very compact! The lower 48K of the memory is used for program memory, and the remaining/top 16K of memory is for either stack memory or a boot loader ROM.
The OS EEPROM (X28C256) is a 32K x 8-bit. However, dedicating 48K of the addressable memory space for RAM means that I can only access half(16K) of the ROM at a time. To work around this, I use a manual switch on the ROMâs most significant address bit. This essentially lets me switch between two 16KB ROMS.
Just like the SAP-1, my build can be set to either Programming or Run mode. When in programming mode, some DIP switches are used to manually point to memory addresses and enter data into RAM. An SPDT switch is used to switch between the two modes, and a push button is used to trigger the RAMâs write pin.
Below is a high level diagram to better illustrate the memory logic.
As mentioned before; I allocate the lower 48K Bytes of the RAM, spanning address 0X0000
to 0XBFFF
, to address memory; and the remaining 16K Bytes, from 0XC000
to 0XFFF
, to either the boot loader or stack memory.
In binary:
0X0000 0000000000000000 }
| } RAM
⌠} memory
0XBFFF 1011111111111111 }
0XC000 1100000000000000 }
^^ | } ROM & Stack
⌠} memory
0XFFF 1111111111111111 }
Note that the ROM/stack address space begins when the 15th and 16th bits of the memory address are HIGH. This means that the boot loader ROM is accessed only when both A14 and A15 are HIGH, and the Stack Pointer Enable ~SPE is inactive(HIGH). This is simply implemented by the three-input NAND at the center of the diagram.
The RAM chip, conveniently has two input enables; one is active-low and the other is active-high. The output of the three input NAND gate is connected to the ROMâs active-low chip enable, and the RAMâs active-high chip enable, meaning that the the ROM chip would always be completely inactive unless the boot loader memory space is addressed.
The UM61512A RAM has all-in-one I/O data pins, which means that, using the appropriate control pins, it can either, be written to, or output data using the same pins.
In Run Mode (PGM node is HIGH)
The RAM is controlled by the control logic, the I/O pins get routed to the data bus, and the address pins to the system bus:
Node D is HIGH, and C alternates between HIGH and LOW inversely to CLK, while B matches CLK. The RAMâs Write Enable (~WE) node is HIGH by default, and goes LOW(At the rising edge of the clock), only when the Memory Write (~MW) control signal is active. And since both PGM and D are **HIGH, the data and address input transceivers for the DIP switches are locked (On high impedance mode).
- When the Memory Enable(Enables memory content to data bus)(~ME) control line is active and ~MW is inactive, node H goes HIGH, G goes **LOW, and the RAMâs data I/O transceiver directs data flow from the RAMâs I/O pins to the data bus.
- Inversely, when ~MW is active and ~ME is inactive, node H goes HIGH and the RAMâs data I/Oâs transceiver directs data flow from the data bus to the RAMâs I/O pins.
- When neither ~MW or ~ME is active, node H goes LOW, the RAMâs data I/Oâs transceiver switches to high impedance mode, and the RAM chip gets disabled through ~CE1 as G and ~MW are HIGH.
~ME and ~MW being active at the same time is a forbidden state as you canât read from and write to RAM at the same time(At least not in my build).
Note: ~WE has priority over ~OE, provided the chip is enabled.
In Programming Mode (PGM node is LOW)
The RAMâs I/O pins get routed/connected to the data DIP switches, and the address pins to the address DIP switches:
PGM being LOW, the address input transceiver connects the memory address DIP switchâs value to the RAMâs address input. The NAND gate on the far right of the diagram controlling the I/O transceiver outputs LOW, thus keeping the RAM from interacting with the data bus.
~MW and CLK now have no control on the state of ~WE as node A and C are always HIGH. Each time the programming push button is pressed, D goes LOW, simultaneously activating ~WE and routing the value on the data DIP switch to the RAMâs data input pins.
ICs
- UM61512AK (Datacheet)
- 1x 74HCT32 OR Gate (Jameco, Datacheet)
- 1x 8-bit DIP switch (Jameco).
- 2x 74HCT245, Octal Bus Transceivers With 3-State Outputs, (Digikey, Datasheet).
- 74HCT00 Quadruple 2-Input Positive-Nand Gates (Digikey, Datasheet)
- 74HCT08 QUAD 2-INPUT POSITIVE AND GATE (Jameco, Datasheet)
«««««««««« Previous Post: RAM & ROM Primer
        Next Post: EPROM Programmer  »»»»»»»»»»
Updated: