The Segment Address Decoder (SAD)
The 6502 CPU has no special I/O instructions or hardware support signals; unlike the Z80 CPU for example, so for the most part any expansion boards need to occupy one or more addresses within the 64K memory map. In the 6502 world, hardware is usually classed as “memory mapped”. Whilst 64K sounds like a lot, it doesn’t go very far especially when you start reserving large blocks of it for ROM and RAM.
One of the simplest add-on expansion boards that I often create is a board consisting of just eight LEDs. These LEDs are connected to the eight data bus lines via a latch, and are accessed by writing a value to a designated single address that momentarily enables the latch to store the value on the data bus thus keep that value displayed on the LEDs until the next time.
Above is the circuit diagram of my original 8 x LED board.
Writing an 8-bit value to any address within the range $F000-$F7FF will latch the data bus value into the 74LS537 and thus display the value on the LEDs. The value will remain displayed on the LEDs until a new value is written.
The NOR gate allows the value to be latched whenever the CPU performs a memory write operation to any address within the $F000-$F7FF memory range by combining the /WRDS and /$F000-$F7FF signals. This is because there is a signal from the CPU board that indicates when the CPU is accessing this memory range. (Unlike the original Acorn System 1 CPU board, my version of the CPU board brings some additional signals to the edgeway connector on unused pins, and the $F000-$F7FF signal is one of them).
Using the entire range $F000-$F7FF to control eight LEDs is however rather wasteful of the address space as this range is 2K (2048 bytes) in size.
What’s really needed is to pick one address and use just that.
The $F000-$F7FF signal is decoding the top 6 address lines (A10 to A15) so whilst it’s helping, if we wanted to to single out one address it would require decoding the additional ten address lines (A0 to A9).
As this was a quick test board to allow me to soak test the CPU board, I didn’t mind wasting such a large address range, but it’s wasteful and if you carry on like this you soon run into problems with lack of available address space for other things. Also, the CPU board only decodes a couple of these address ranges for you. But there’s another issue.
What happens if you later decide that you want to move the board to another address; $1200 for example, or you wanted several identical boards (multiple boards all need their own address). The design above isn’t flexible enough to allow this.
A better possible design would be something like this:
This improved design uses two 8-bit comparators to compare the address on the bus with that selected on the two 8 bit DIP switches. If the addresses match, the value being written is stored in the latch and displayed.
This has two benefits over the previous design in that the board uses only one memory address, and the address used can be set to any location within the 64K memory map area by the user via the DIP switches on the board.
It’s possible to accomplish this using discrete logic gates but I find that using comparators gives the most flexibility.
However, the 74LS688 comparators used for this are fairly expensive, and their pinouts make them tricky to use on two layer PCBs.
It is also limiting if you want multiple addresses for a single board. There is an alternative to the 74LS688, the 74AS885 which has a much easier to use pinout, but these chips are extremely expensive.
Often, expansion boards use a single hardcoded address range that cannot be changed. With these the board can be located anywhere within the fixed range of addresses and allows for logic to decode most of the address and just a small amount of electronics to allow the user to configure a small part of the address. For example, it could be decided that all expansion boards are located within the address space $F000-$FFFF. Some fixed logic on the board could decode the top 4-bits of the address ($Fxxx) and then customisable logic could decode the remaining 12 bits. It all depends on what the requirements are as to how much of the address decode is fixed or customisable.
The 6522 VIA chip has 16 internal registers that can be read/written by the user to control the chips internal functions and read data back from the device. These 16 registers are accessed by read/writing 16 different memory addresses. The above comparator circuit wouldn’t work as is, though it could be modified. However, maybe your device needs a larger block of memory. A VDU may need 1K or more space within the memory space to function correctly.
A common theme here is that every device that is connected to the CPU, will almost always require one or more addresses in the memory map address space, and that typically each board is responsible for it’s own decoding of the address bus to determine if it’s being accessed or not.
Wouldn’t it be nice if the address decoding could be done centrally, with one board, and then leave decoding within that memory address range subset to each device as required. This could reduce the amount of electronics required considerably. As the address decoding would be done by one board instead of each individual board, it would reduce the loading on the address bus, would help reduce complexity of the expansion boards and also help keeps costs and power demands down.
Enter the Segment Address Decoder.
The Segment Address Decoder (SAD) divides the entire memory map into three types of memory area; Blocks, Pages and Segments.
A block consists of 4K of address space, so the 64K memory space contains 16 such Blocks.
Each 4K block can then be sub divided into 16, 256 byte Pages.
Finally, each Page can be further sub divided into 16, 16 byte Segments.
There are 14 control signals; MAP0 to MAP13 that run along the backplane and are presented to every expansion socket.
When the SAD decodes an address presented by the CPU that falls within a requested memory range, it activates one of the MAP signals.
MAP signals can be triggered on detection of either a Block, Page or Segment.
The following schematic shows a section of the SAD that is responsible for Block address decoding.
The Block Page decoder, decodes the top 4 address bits of the address bus; A12 to A15 and results in one of the 16 outputs on the left of the diagram being activated. Any of these outputs can be connected to one (or more if required) of the MAP control signals.
So a device; a VDU for example, that requires a 4K block of address space could be configured to monitor the MAP0 signal.
Within the SAD, address range $5000-$5FFF could then be connected or “mapped” to the MAP0 signal. This means that whenever the CPU presents an address on the address bus within the range $5000-$5FFF, the SAD will activate the MAP0 control signal. Later if there is a requirement to reorganise the memory map for some reason, the SAD address mapping could be updated as required.
Next there is the Page decoder.
The Page decoder, decodes address lines A8 to A11, but requires an additional input from one of the Block decoded outputs.
So, if Block decode output $1000-$1FFF (4K block) is connected to the Page decoder, then the Page decoder will divide the 4K block specified into 16 sub Pages of 256 bytes each. Any of the decoded Page outputs can be connected to any of the MAP signals.
Finally we have the Segment decoder.
The Segment decoder can further subdivide a 256 byte Page , into 16, 16 byte Segments.
Imagine we have a completed system that contains the following devices:
2 x VIA boards – Each needs 16 addresses in the map (1 board used the MAP0 signal, and the other the MAP1 signal)
1 x B&W VDU board – Needs 4K in the address map (uses MAP2 signal)
1 x Colour VDU board – Needs only 4 addresses in the address map as it’s not internally memory mapped (uses the MAP3 signal)
1 x Serial Communication ports – Needs 16 addresses in the map (uses MAP4 signal)
1 x 8-bit LED displays. Needs only 1 address in the map (uses MAP5 signal)
1 x 16K RAM board. Needs 16K of address space in the map (uses MAP6 signal)
Add in a SAD board, and a CPU board, and that’s a standard 9 slot backplane fully populated.
We will use address $A000 to $DFFF for the 16K RAM board, $6000 to $6FFF for the B&W VDU, and $7000 to $7FFF for everything else.
The ONLY device configuration required, is to connect the board select signal to the appropriate MAP control signal. All the rest of the device address decoding is handled by the SAD board.
The above diagram shows the logical interconnections that would be required to give us the required memory map. In reality, the connections to the MAP6 signal would need to be made with signal diodes as you cannot connect multiple outputs from 1 of 16 decoder ICs used in the SAD together.
VIA board 1, using MAP0 is at address $7F00-$7F0F
VIA board 2, using MAP1 is at address $7F10-$7F1F
B&W VDU, using MAP2 is at address $600-$6777
Colour VDU, using MAP3 is at address $7F30-$7F3F
Serial device, using MAP4 is at address $7F40-$7F4F
LED display, using MAP5 is at address $7F50-$7F5F
16K RAM, using MAP6 is at address $A000-$DFFF
The links for the 16K RAM board are actually diode links.
Now only the least number of address lines needs to be decoded by the actual device board, and it’s a simple matter to move any device anywhere within the memory map – only the configuration of the SAD board needs to be updated.
It’s also possible for a MAP control signal to be used by multiple boards.
For example, the LED display board only needs one address, so A0 to A3 could be decoded be either a 74LS138 allowing for 8 identical boards to occupy the same MAP range so share the same MAP signal, or a larger 74LS154 could be used allowing for 16 identical boards to occupy the same MAP range.
The SAD board significantly reduces the amount of address decoding required by each device, the amount and complexity of the electronics on each device board, and makes it much simpler to move any device to any suitable location within the memory map.
There’s more. If required you can use multiple SAD boards, each decoding completely different memory ranges all without the need to redesign the existing expansion cards.