Making our girl Turing-complete.
It suddenly occured to me that Veronica is missing something rather important which is needed to be called a “computer”. RAM! With all the chaos of developing EEPROM programmers and VGA boards and such, I completely neglected to add any RAM to the main system. Time to remedy that!
Luckily, the RAM board is about as simple as things get. All that’s needed is RAM chips and address-decode logic. Here’s the schematic (and Eagle file):
Once again, I’m using 32k DIP SRAMs here, when using a single larger one would be much easier. Why? I dunno- I just think they’re neat.
The RAM board is simply listening for all lower memory addresses, and patching into the bus when it hears them. This is dictated by the system memory map, which for Veronica currently looks like this:
- $0000..$00ff: 6502 zero-page
- $0100..$01ff: 6502 stack
- $0200..$dfff: Program memory
- $e000..$effe: Reserved
- $efff: VGA command buffer & status register
- $f000..$ffff: System ROM
One thing to note- the 6502 has a two-phase clock, with a low part and a high part. The low part is used for internal housekeeping, and RAM access is performed on the high part. The critical bit is that you must protect your RAM during the low part of the clock phase. There is no guarantee that the CPU won’t put stuff out on the bus during this time, and it may cause random memory to be overwritten. In my case, I include the phase 2 clock signal in my address decode, so that RAM cannot be activated when the clock is low.
As you might expect by now, I started by prototyping this circuit on a breadboard to make sure it worked. As usual, it’s connected using the big header on the end of my backplane that allows things to be patched into Veronica’s system bus.
Sadly, all was not well. I was having difficulty reading and writing memory locations in the new RAM. After some basic debugging, the problem became clear. The address decode logic on my ROM board was actually wrong! I didn’t catch it until now because nothing else had ever tried to use lower memory addresses. Some quick hacking on the ROM board straightened that out. Luckily, all the gates needed to make the corrections were already available in the chips on the board. I was able to fix it with some judicious trace-cutting and jumper-adding.
So, with the prototype now working on the breadboard, it was etchin’ time. I opted to try using a two-layer board this time. This was a good test-case, because it’s such a simple board. Here’s the two-layer Eagle layout I ended up with:
I documented my experience with etching a two-layer board over here. The short version is that it went well! The final result, all installed in our girl, looks something like this:
So, to make sure the final product is really worked as expected, I wanted to write a full RAM checking routine. That’s quite a bit more 6502 code than I’ve needed until now, so I put together a cross-development system so I can write this code conveniently on my laptop. Here’s what I ended up with:
That code is for the CA65 6502 cross-assembler. I can’t say enough good things about the whole CC65 package. If you’re doing anything 6502, give this a look. The macro assembler is just peachy and does everything you could possibly need. For more information on how I’m using CA65 to develop Veronica’s ROM code, look here.
So, does it work? Let’s find out. Veronica’s ROM will now run a full RAM check on startup. It writes a known bit pattern from a register into every memory location, clears the register, then reads the memory back in. If it gets the same bit pattern back, all is assumed to be well. It counts the bytes as it goes along, so if something goes wrong, we know where. It also lets the user know how much RAM is actually available for program use. To display this onscreen, I’m using the 6502’s nifty BCD mode, which makes displaying numbers as ASCII text really easy. I apologize for the quality of these videos. I’m trying to find a reasonably-priced way to record Veronica’s video output directly, but I haven’t found one yet. You’ll have to bear with my “point-camera-at-screen” method in the meantime. Set the quality setting in the YouTube player to 720P for best results.
Here’s a test of the address decoding. I’ve changed the ram test code to continue one address past the limit of RAM. If the decode is working, then the last address will not activate the RAM board, thus nothing will be read or written successfully. The write will do nothing, and the read will get garbage from whatever noise was on the bus. That means the ram test will fail on the very last address.
Huzzah! Veronica has RAM. Good times were had by all.