My6502 (part thirteen) – address decoding revisited … again

I want to add more devices to my computer, memory mapped as usual (see part six). Some of those devices need more bytes than others.

Up until now I’ve been using discrete logic to select the correct device, given the status of the address lines … but as the computer gets more complicated, using simple logic gates becomes more problematic.

  • More discrete logic requires more space, more power, more board design, and more development time.
  • Each time you add another “layer” to that decoder logic (by “layer” I mean a component whose input depends on the output of another, which in turn may depend on the output of another, and so on) you increase the “propagation time” – the time between address lines changing, and the correct device being selected. Eventually this will limit the max speed the computer will function.
  • My computer design is still very-much “in progress”, so I can expect to be revisiting this a lot!

Instead, people are approaching this problem with more programmable logic: GALs, and the like. I’m not familiar with GALs (nor do I have the tools to program them) so that would be something new to learn.

But then I thought … what about an EEPROM? Treat it like a look-up table. The input into the table is the address, and the eight digital outputs could become the select lines for eight different peripherals! All you need to do is write data to the EEPROM that selects just one output pin, for each different address.

The propagation time remains constant, and anytime I want to rearrange my memory map, all I have to do is reflash my EEPROM. It felt like it could work … but had anyone else done this?

Then, at an electronics-and-beer meetup in Nottingham with likeminded geeks, I started explaining my thoughts about my address decoding problem. Before I could get to the bit where I said “has anyone here tried using an EEPROM to do it?” someone interrupted with “have you thought about using an EEPROM to do it?”.

So I had a go. And it worked, first time!

The circuit

address_decoder

The 74LS00 is used to gate write-enable and output-enable on phi, as in my previous design.

I decided to use an 8KB EEPROM (28c64) for no other reason than I had one or two knocking around which were just too small for me to use for anything else.

There are 16 address lines in my computer (because that’s the 6502 for you) giving me an address space of 64KB. The EEPROM has only 13 address lines, for its 8KB storage space.

So we wire the highest thirteen lines to the EEPROM, leaving the lowest three alone. This means that the EEPROM ignores the lowest three address lines, so one byte in the EEPROM covers eight bytes in the computer.

Effectively, this means that the best “granularity” I can manage (how small a range of bytes I can designate to a device) is eight bytes. This is a bit wasteful as some devices might only need one or two bytes … but it’s still a pretty acceptable compromise. If I ever get to the point where this isn’t enough, I could revise the decoder to use a 16KB EEPROM, which would give me a granularity of four bytes; or a 32KB EEPROM, which would give a granularity of two bytes.

The EEPROM obviously has eight outputs; therefore, I can select one of eight devices.

What if I want more? Well, the great thing is about this circuit is that I could duplicate it for an extra eight devices if/when needed. I just need to remember (when I’m creating the data to go onto the EEPROMs) that only ONE device should be selected at a time.

Creating the data

I’ve written a very quick C program that generates the lookup table to go on the EEPROM. I include it here for reference. It’s not pretty, but it’s commented and should compile on any modern OS. It works by considering each byte of the EEPROM, and scnning through a list of address ranges to decide which device should be selected by it.

Download MemMapGenerator.cpp (6KB)

It’s worth me mentioning active-low versus active-high selected devices here.

Most devices I’ve encountered seem to be active-low; that is, they consider themselves selected when their select line is pulled low. However: some devices prefer to be pulled high (for example: those Hitachi LCD screens). By dealing with that issue in data in the EEPROM (inverting bits before they get stored) means that we don’t have to add any physical NOT gates in the circuit.

The BBC Micro Memory Map

I can be pretty flexible with my memory map – it’s my computer, after all. But part of me wants to make it vaguely similar to the BBC Micro, to minimise any potential compatibility issues if (ha-ha) I ever get to the point of running BBC programs on my own computer.

So let’s talk about how the Beeb has its devices mapped.

  • &0000 – &7FFF – RAM
  • &8000 – &BFFF – Sideways ROM
  • &C000 – &FFFF – Operating System ROM, apart from:
  • &FC00 – &FCFF – FRED
  • &FD00 – &FDFF – JIM
  • &FE00 – &FEFF – SHEILA

On a Beeb, there’s a 16K ROM for the OS, and another 16K ROM that’s the currently selected “Sideways ROM” (for example: the BASIC interpreter). On my DIY6502, I’m using a single 32K EEPROM doing the job of both 16K ROMs. I intend to implement the OS in the second-half, keeping the first half for a language.

FRED, JIM and SHEILA are areas of memory which do NOT select the OS ROM, and instead select peripherals. In the BBC Micro, FRED and JIM are designated for accessing external expansion devices, and SHEILA is used for the BBC Micro’s internal peripherals.

The DIY6502 Memory Map

It’s not essential for me to adopt the beeb system … but there’s no harm in it either. So to begin with, I’m going to map devices 1 to 7 to the second-half of SHEILA, giving them sixteen bytes each:

  • &FE80 – &FE8F – Device 1
  • &FE90 – &FE9F – Device 2
  • &FEA0 – &FEAF – Device 3
  • &FEB0 – &FEBF – Device 4
  • &FEC0 – &FECF – Device 5
  • &FED0 – &FEDF – Device 6
  • &FEE0 – &FEEF – Device 7

I’m not going to implement a 1-MHz bus interface soon, but there’s no harm in considering it in the future. I certainly have some Beeb expansion boards that would be interesting to try. Therefore, I’ll keep the FRED and JIM address ranges reserved for now.

The great thing is about doing this with an EEPROM is that I can shuffle this around later if/when I need to; and thanks to every assembler’s ability to use constants, it’s not an onerous task to modify code when the address mapping changes:

SERIAL_BASE = &FEA0
VIA_BASE = &FEB0
...etc ...

The PCB

You know the drill, right? Yep: OSHpark, again!

address_decoder

The last six pins of the 40-way backplane connector are now the select lines for the first six devices (from 0 to 5). Device 6 and Device 7 are exposed with a pin-header, so that when I need to use them, I can use a short Dupont wire to join them.

So there we have it – a simple but flexible of building a memory map!

[To the My6502 Project Page]


3 thoughts on “My6502 (part thirteen) – address decoding revisited … again

  1. I know there can be a propagation issue when implementing layers of discrete logic using TTL devices, but I though most EEPROMs had quite slow access times. You’ve obviously got this working so it isn’t an issue, but how fast can you get the 6502 running using this technique do you think?

    Or can it be that, say, for a 64k x 8 bit EEPROM that it would stay enabled 100% of the time. I appreciate this is the extreme version of utilising this method but it’s an interesting thought experiment.

    I guess, in theory, for a 32k RAM/32k ROM 6502 homebrew (with interspersed I/O for peripherals) that you’d utilise A15 as the RAM or ROM selector and then A14-A0 for the lookup and this would give “1-byte granularity”?

    Dave

  2. Yeah, the EEPROM as selector logic was quite an elegant solution, and is great for experimentation … but I also wonder about the speed. I’ve managed to run my computer at 4MHz, but it refused to go any faster. My plan (if I ever had the time) would be to work out the max speed of each card in turn – create a test rig, send access pulses to it, time how long before there was a response. I’m pretty sure that the selection logic would end-up being the slowest part. Or maybe I should build a more minimal computer, so I only need a few simple 74-series chips to do selection, and then see how fast I can push it.

    I think using the EEPROM as selection logic might also have been driven by laziness … I haven’t learned how to program GALs yet, which is how everyone else seems to do it. Or maybe when I’m more confident that I’ve got my memory map “nailed down”, I could implement it in 74-series logic instead.

  3. And yes, in theory, you could go down to 1-byte granularity … but it’s a trade-off, and it’s normally considered acceptable to compromise with 4, 8 or 16 byte granularity. It’s not normally worth the saving, for the more complex board.