Address decoding

A project log for Big Daddy 68k

Making a games console from the ground-up

SimonHSimonH 05/17/2017 at 22:090 Comments

Two posts ago our CPU was demonstrated connected to an Arduino to provided memory-mapped I/O. This MMIO space could hold code, other board-level I/O functions or perform functions on the host PC. The 'memory' area of this MMIO space was slow - each access had to be interpretted by code running on the Arduino.

In the next post the Arduino was taken away and replaced with memory that went as fast as the bus could drive it! But it had no I/O and no code to run on it.

Let's combine the two. This is pretty easy. To recap the signals required for each device. The changes we need to make are highlighted in bold.



Address decoding

So the set-up of two devices is pretty similar. We really only need to do two things - send AS to the right place and receive DTACK from the right place. This place will depend on which address is on the address bus.

In the previous post, as only A0-A18 were connected to the RAM and A19 was left free this turned our 1 MB address space into two 512 KB mirrors of the same RAM. If for instance we only triggered the RAM's chip enable with AS when A19 was low - ie the low 512 KB of the address space - the upper 512 KB could be used for something else. Or vice versa - if the AS signal triggered CE when A19=1 then the 512 KB RAM would appear in the top 512 KB of the address space and the bottom 512 KB would be undefined. There would be no data on the bus and the CPU would read junk.

The same thing applies to the Arduino. Suppose on our shift register we shift in the CPU R/W signal and eight bits of address (A0-A7), if the Arduino interrupt was triggered on every AS then the Arduino address space would mirror every 256 bytes from address zero to the top address: 1 MB. If this signal was only triggered when A19=0 then the Arduino MMIO space would only exist from address zero to the middle of the address space - 512 KB in. The top 512 KB would be undefined.

With a tiny bit of logic we can make ourselves some address decoding. Let's map the Arduino into 256 byte mirrors in the bottom 512 KB and the 512 KB SRAM into the top 512 KB.

Here's a truth table for the chip selects. Remember that AS and the two chip enables are active low.

CPU /ASCPU A19SRAM /CEArduino /interrupt

Using this solver we can make ourselves some logical equation for this.

SRAM /CE = !A19 || /AS

Arduino /int = A19 || AS

and a truth table for the /DTACK signal that goes to the CPU. Also active low.



Adding some gates

In order to implement our three equations we will need some logic gates. We could just use NAND or NOR gates but perhaps let's just use the logical operations described by the equations above: NOT, OR and AND.

For NOT I'm going to use a 74'04 - six NOT gates in one package.
For AND I'm going to use a 74'08 - four two-input AND gates
For OR I'm going to use a 74'32 - four two-input OR gates.

So far I've been using the "HC" variants of these chips. Compatible with TTL logic, can use a ~5V power supply and reasonably fast switching times. Mine are all from Texas Instruments.


Wire this up. This is the CPU, SRAM and Arduino connection (along with the Arduino's shift register).

And here's the logic to wire up too. This implements the three equations described above.


At this point you have a CPU with 512 KB of fast working memory, in addition to an Arduino which can perform any I/O that you want. It can also supply code - replacing a ROM or other file store. The address space looks like this:

At this point some may notice I have not described how to reset the do this reliably is more complex than you might imagine but that will be for another day!