Dynamic Bus Sizing
I finally figured out what was going wrong with my RAM. The 68030 has a pretty unique system bus that can interface with 8-, 16-, and 32-bit wide peripherals, regardless of alignment and actual transaction size (with some exceptions). This is incredibly useful because a single instruction, MOVE.L for instance, can be used without having to know exactly how the hardware is built. The MOVE.L instruction can move 32 bits to an 8-bit peripheral one byte at a time, with the CPU automatically dividing up the transaction into bytes.
On my 68000 build, I had to use a bit of a hack with a register to use an 8-bit ROM with the CPU's 16-bit bus. For the 68030, I can just tell the CPU that it is accessing an 8-bit device, and it will go ahead and fetch that second byte.
What does this have to do with my RAM problem?
I'm using four 8-bit wide SRAM chips so that I can use the full 32-bit 68030 data bus. For any read operation, the CPU will ingest the full 32 bits and ignore what it doesn't need.
The problem comes when writing to that 32-bit memory bus. When the CPU starts a write operation, it doesn't know what size the peripheral is, and doesn't know what data may already be stored in that location (if it's even a memory device at all). So when, for instance, the CPU needs to write a 16-bit word, it will duplicate that word on both the high and low words of the 32-bit bus. It's up to the peripheral to decode the two least significant address bits and the two bit size parameter to determine which bytes the CPU actually intends to be written.
I did not implement the size decoding. Every time the CPU wrote to RAM, I was latching the entire 32-bit data bus, regardless of the transaction size.
I had been writing ever more sophisticated exception handler routines to try to get some understanding of what was happening when a program crashed. Ultimately, it was a bug in one of these routines that finally led to the answer.
Instead of printing out the system stack, a bug ended up printing out the entire contents of memory.
This gave me something I could compare against. The BASIC interpreter I'm trying to run sets up a jump table during its initialization routine. Each jump instruction in the table is three words — a one word JMP opcode ($4EF9), and a longword destination address.
Compared with the simulator output and a listing of what the table should look like, it quickly became obvious what was happening. When the code tried to write the one word opcode $4EF9, RAM was latching the two word $4EF94EF9 — mangling whatever was already in RAM at the second location.
So now I know what is going wrong, and thanks to a schematic in the 68030 manual I know how to fix it. I need to implement the size/address decoding for write operations to RAM.
There's just one problem. As it stands currently, the CPLD I'm using for glue logic only has one I/O pin free. I need to expand the one !RAM-CE signal into four, and add SIZ0, SIZ1, and A0 inputs.
I'm going to have to sacrifice something I've already wired in. Most of the logic I have in place is essential and cannot be removed. It's looking like interrupt support for the UART will have to go.















