Monday, January 17, 2022

Figuring out how Amiga 500 RAM expansion projects work

 (Wow, what a shift in topics here..)

Yeah I picked up an Amiga 500. Specifically, a rev6 amiga 500. It has 4 extra spots on the mainboard for another 512k of chip ram that isn't populated.

Crap I'm going to have to explain chip RAM.

Ok, so the Amiga is a pretty nifty architecture, especially if you realise it was designed in the early 80s. I won't go into it all because that's not the point of the article and that's covered on the internet.

What I will go into is what I've figured out with the RAM expansions.

So - the RAM types. This is the bits I knew back as a teenager.

The Amiga has three kinds of RAM:

  • Fast RAM is RAM that the CPU can see, but the custom chipsets can't address. It's not slowed down by any contention with the chipset access to its RAM.
  • Chip RAM is RAM that the CPU and the custom chipsets can see. This RAM sits /behind/ the custom chipsets; access to it from the CPU is lower priority than from said chipsets.
  • Slow RAM is RAM that also sits behind the custom chipsets, but for reasons internal to said chipsets they can't actively use. If the custom chipsets are using chip RAM for functions then the CPU will also be blocked.

The reason for chip/slow RAM on the early Amigas only makes sense if you peer into Agnus, the DMA and RAM arbiter chipset. It has a variety of features, but it's basically a big RAM arbiter and DMA engine. The earliest version in the Amiga 1000 supported DMAing to/from 512KB of RAM. However, it supports controlling 1MB of RAM. The next major version update (which I have) supports DMA from and to 1MB of RAM.

Now, because of this early limitation, the Amiga designers put the first 512k that Agnus can control early in the memory map (at $000000), and moved that second 512k of RAM much later in the memory map (address $C00000). That way a future chip that supported more DMA accessible RAM would just extend the chip RAM memory map in a contiguous fashion.

However, this meant a bunch of software was written that assumes the first 512k is at $000000 and the second 512K is at $C00000. Not a lot, but some.

My goal is to have 1MB of chip RAM and at least 512k of slow RAM. That should give the maximum compatibility with all of the Amiga 500 software in the past and set things up pretty well for the future.

Now, this is something people have already done. PeteAU on the Amiga Forums kickstarted a bunch of designs which were debugged and improved upon by forum members. Let's talk about how it works.

First up, Agnus decodes a bunch of address lines to know what the CPU is requesting. However, it only treats things as a memory access if Gary, another custom chip, decoded the address bus and said "yup, this is a RAM access." Gary asserts /RAMEN to Agnus to let Agnus know it's a RAM access and Agnus takes care of doing the memory transfer.

JP2 on the Amiga 500 rev6 board chooses whether Agnus sees the CPU A19 line as A19 or A23. If it's A23, the default, then the second half of Agnus' address bus as viewed by the CPU is at the slow RAM address of $C00000. But if JP2 is cut and the other link is joined, it becomes A19 and both 512KB RAM blocks show up as contiguous RAM at $000000, as chip RAM.

Agnus decodes its A19 line to select which of two 512KB RAM blocks to enable. It does this using the /RAS0 and /RAS1 lines. /RAS0 enables the onboard 512KB RAM. /RAS1 enables the unpopulated 512KB RAM chips on the mainboard. Also, BOTH /RAS0 and /RAS1 appear at the trapdoor RAM expansion underneath the Amiga 500, and the Amiga 501 512KB RAM expansion uses /RAS1 by default.

So, you can easily choose between 1MB of chip RAM and a 512KB chip/512KB slow by changing JP2. That's easy.

JP7 controls whether Gary sees the /EXRAM line from the trapdoor expansion. Gary uses this to control which address ranges are treated as RAM and sent as an enable line to Agnus via /RAMEN.

JP3 controls which 512KB bank is /RAS0 or /RAS1. It lets you swap them, so the trapdoor RAM and onboard RAM sees /RAS0 as /RAS1 and vice versa. You normally shouldn't have to fiddle with this.

Finally, Agnus is responsible for managing the DRAM chips. This requires:

  • Managing the multiplexed column/row address bus setup that DRAM chips use, so it has to latch rows and then columns for reading
  • Asserting the right /RAS and /CAS lines to the right chips (important for normal AND RAM expansion hacks!)
  • Handling DRAM refresh.

Ok, so now that this is done, let's talk about PeteAU's RAM expansion and how they managed to get 1MB of chip RAM and lots of slow RAM.

There are two halves - the expansion RAM board and the "Gary adapter". The easiest to talk about is the expansion RAM board, so that goes first.

The RAM expansion boards still take /RAS0 and /RAS1, and provide jumpers to which ends up at which RAM. Ok, so how does it actually enable different RAM banks?

The two wires that go to the RAM expansion boards are either A19/A20 or some decoded magic that I'll describe later. These feed into a 74LS139 which is a dual 2-to-4 demux. Each demux is responsible - this is important - for demuxing the /CAS lines. So yes, even if all the expansion RAM is using /RAS1, the /CAS lines get enabled only for the RAM that matters. It's important to understand this particular bit of magic. Agnus only has two /CAS lines - one for the lower 8 bits and one for the upper 8 bits of the 16 bit data bus. So all of the RAM gets /CAS enabled, no matter which 512KB bank it is - then the relevant bank to read gets /RAS. Now with PeteAU's design the /CAS lines for the relevant expansion bank gets enabled.

Ok, this is where it gets hairy. So, what about if you have 1MB of chip RAM on board, like I do? PeteAU's Gary board apparently takes care of that too.

One final comment before I move onto the Gary adapter board. Why not go and fiddle with /RAS to enable the right banks? Well, it has to do with DRAM refresh. Agnus also takes care of the refresh cycles which involves asserting only /RAS and enabling each row in the DRAM. If we go and gate which /RAS goes to which chip bank then a bunch of RAM won't get refreshed. You'd then have to add extra logic to see if it's a refresh cycle and manually refresh! Or, you can leave /RAS0 and /RAS1 alone, so DRAM refresh is still OK, and enable RAM using /CAS.

Right! Now onto the Gary board, where the magic happens.

A few things have to happen here for all of this magic to be, well, magic.

  • If you want to support 1MB chip RAM as well as 512K of slow RAM, you need to be able to decode both the chip RAM and slow RAM regions and enable those to Agnus via its A19 line. This is the jumper wire to JP2 on the A500 Rev6 PCB.
  • If you want to support more than 512K of slow RAM, you need to decode both A19 and A20 and fake the /REGEN and /RAMEN signals towards Agnus. (/REGEN is "chipset register space is being accessed.) That way Agnus still thinks a RAM cycle is being initiated, even if it can't "see" the larger RAM address space.
  • Then you need A19/A20 - or a modified version - to the trapdoor RAM expansion. This is the extra 2 bits, or 4 banks of 512KB, to decode all that extra RAM.
  • If Agnus is asserting /BLIT - which says it's doing a DMA cycle, then we need to ensure it's going to U1 on the RAM expansion, or the second 512KB chip RAM bank.

Now, this last point is important for me and other 1MB Amiga chip RAM amiga 500s. How can this RAM expansion even work if there is 1MB of chip RAM on-board? The on-board RAM has all of the /CAS lines from Agnus wired up, without going through the mux.

I think the answer is "not without modifying the board." /RAS0 will continue to enable the first 512K bank. The other 512KB bank and the slow RAM expansion will run off of /RAS1. What I'm likely going to have to do is:

  • Build a 74LS139 adapter board myself for the mainboard;
    • Run the /CAS lines from the expansion connector to it;
    • Run the Gary expansion adapter A19/A20 lines to it;
  • Lift the /CAS lines from the other 512KB RAM I installed, and route it to the 74LS139, like what PeteAU's RAM expansion board does;
  • Modify my A501 (that should be here soon!) to use the /CAS lines I feed it from the 74LS139 board, rather than the expansion connector /CAS lines;
  • Hope it all works!

I'll try to remember to report back with some photos!