In the last article, I mentioned the fact that there are no special IO instructions that handle peripherals. This choice on the part of the microprocessor designers is understandable: Why spend time=money on IO instructions when the MC6809/HD6309 has a rich set of memory addressing modes?
This decision does, however, reduce the maximum available program memory from a full 64K to something less. How much less depends on the complexity of the address decoding scheme: full or partial decoding.
In a fully decoded address decoder, all address lines (A0..A15) are used by the decoder so it can uniquely assign addresses to a peripheral or memory chip. Most small designs choose to simplify the address decoder by using only a few address lines, say A13..A15. This means that addresses are partitioned in blocks, in this case blocks of 16K.
Using this scheme, each block of address space can be assigned to a single chip, such as a RAM, ROM or peripheral. This coarse division is not a problem for memory; we want to have large blocks of ROM and RAM. For peripherals, however, the story is different. For example, it is wasteful to assign a 16K block just to address a UART.
Luckily, we can subdivide one block by adding a second address decoder.When the first address decoder detects the address falls within this block, it activates the second address decoder. This decoder uses the lesser significant address lines to select smaller blocks, or even individual addresses if desired. In this way, we can make more efficient use of the address space, while keeping the address decoder logic simple.
Address space of the HD6309 computer
We know from the HD6309 datasheet that the interrupt vector table, including the reset vector, resides at the very top of memory. If we have a block of RAM there, we’ll have a problem with booting the system because the RAM will contain gibberish at startup: a ROM is needed there to supply a reset vector. However, the ROM will also contain the various other interrupt vectors. The HD6309, unlike more modern processors, does not provide a way to relocate the interrupt vector table, making them fixed — quite inflexible! We’ll have to revisit that issue another time.
Apart from the top most address positions containing the reset and other vectors, we’re free to divide the address space the way we see fit. So, I’ve come up with a few features I’d like to have:
- A banked RAM system, to allow more than 64K to be used.
- A 4K ROM at the top of memory to supply the vector table and a few support routines.
- A fixed/unmapped portion of RAM to allow for an operating system to save its stack and other context data.
- Use a Microchip/Atmel ATF16V8B GAL as the first address decoder to reduce the IC count.
- Use a second address decoder to subdivide I/O addressing space.
Given these features I arrived at the following memory map:
The 32K paged RAM block can be swapped out for any one of multiple 32K RAM blocks in a large, i.e. >64K, RAM. This will be done by a special peripheral, consisting of an N-bit register. The register will provide the top N bits to the RAM chip. When the CPU accesses the fixed RAM portion, the top N bits to the RAM will be set to zero.
With the proposed layout, we’ll have a total of 56K simultaneously addressable RAM!
That’s all for this time! Next up: schematics!