In my earlier post on address decoding logic, I mapped out a fairly simple way of dividing up the 64k address space for my 6502-based retro computer. But maybe it was too simple.
There is one slight complication – easily fixed, but which will require the introduction of another chip. And the reason for this is something lacking in memory.
I plan to use a fairly popular memory chip, the Atmel AS7C256B 32k SRAM. It’s typical of most RAM chips of its kind. I’ve already dropped its schematic on to the design I’m working on in KiCad. I haven’t finished hooking everything up yet (as you can tell from the little green arrows) but this image already tells us something.
How about the lack of a clock input? The chip does its stuff when the /CE (chip enable), /OE (output enable) and /WE (write enable) lines are set in the appropriate states. But unlike many of the other major chips you’ll find in the computer’s design, it doesn’t wait for the starting gun signal of the clock transitioning high.
This can lead to problems. The 6502 CPU might still be in the process of sorting out the address lines at the moment those other lines are set. This could lead to data being written to the wrong address. (Reading is less critical because that’s more under the control of the CPU.) Basically, the rule is that you should never perform a RAM operation when the 6502’s clock is low – only when it goes high.
In my original design, based on the Apatco kit I’m building, you simply connect A15 on the 6502 to the /CE of the memory chip. A15 is low whenever the address is set to a value of $7FFF or less, which equates to the 32k address space I’ve assigned to RAM. As the /CE is active low, this would seem to be a very simple solution.
In fact, this is how it’s done in the Apatco kit. And the reason for that is probably that it’s running at a modest 1MHz clock speed. That’s also the speed I plan to use for the Zolatron 64 so I’d probably get away with it. But on the basis that it’s never too early to start doing the right thing, let’s go for something a bit more reliable.
Break out the NAND
The solution is to use the most versatile of all logic gates – NAND. This is the inverted version of the AND gate. In the latter, the output is true (ie, 1) if, and only if, both of of the inputs are true. So the truth table looks like this:
The NAND gate inverts this so that the output is 1 unless both inputs are 1.
So how do we use this? Something like this:
In this case, A15 is connected to both inputs of NAND gate 1. This is a common method of using the NAND as a simple inverter – if a 1 goes in then a 0 comes out, and vice versa. PHI2 is the 6502’s phase 2 clock – the main clock the processor uses for timing. And the /CS pin on the RAM chip is active low.
So let’s walk through what happens.
If A15 is high (a logic 1) because we don’t want to talk to RAM then the output of NAND 1 will be low. That means input B to NAND 2 will be low. In this case we don’t care about the state of input A (from the clock) because the truth table tells us that whenever either of the inputs to a NAND is 0, the output will be 1. So the /CS pin on the RAM will be set high making the RAM inactive. Job done.
Now let’s say A15 is low (0) because we want to read from or write to RAM. The inputs to NAND 1 will both be 0 so the output will be 1. We’re half-way on our journey to talking to RAM.
But what about the clock? If it’s in a low state then input A is 0 and, again, that means – regardless of what’s happening on input B – we know that the NAND output must be 1 (high) making the RAM inactive. But as soon as the clock goes high (and assuming A15 hasn’t changed its mind), both of the inputs to NAND 2 will now be 1. That means the output is 0 (low), activating the RAM.
NAND gates come in the convenient form of the 74HC00 chip, which has four of them.
(A quick aside: In the post on address decoding, I talked about using the 74LS138 chip, which provides a simple way of decoding. I still plan to use this for decoding other parts of the memory map, but I’ll be using the higher speed 74HC138 or even 74HCT138 versions. The ‘LS’ family is probably fine for a 1MHz machine but is considered a bit long in the tooth and power hungry these days.)
What could we do with the two spare NAND gates in that 74HC00 chip? Well, what about using one of them for ROM?
I’ve pretty much decided that I’m going to assign a 16k ROM space at the top of the memory map. And the ROM is likely to be on the same board as the 6502 and the RAM.
The ROM space starts at address $C000 which gets selected when address pins A14 and A15 are both high. So we could do something like this:
If A15 is low because we’re accessing RAM, then input A of NAND 3 will be low and therefore the NAND’s output is high, deactivating the ROM. Similarly, if A14 is low because we’re using an address below $C000, then a similar thing happens. The output of NAND 3 will be low only when both inputs are high – ie, when address lines A14 and A15 are both high, which means we’re talking to ROM addresses.
We could also use the fourth NAND gate for help with decoding other parts of the memory map – there’s another 8k space I have earmarked for … well, something … and a bunch of 1k spaces designated for VIAs, an ACIA etc. But those devices are likely to be on other boards so the decoding is best done locally there. Whether I end up using NAND to do this or the 74HC138 I’ll decide another time.