Add 512K of external SRAM to Arduino Mega. Part 1 - Theory

Arduino Arduino Mega

Often when prototyping with an Arduino you run into the memory limitations inherent in a microcontroller programming environment. The Arduino Mega series goes a long way to solving the program size issues, offering as it does 128Kb and 256Kb formats. But what about the SRAM? Even the mega only comes with a very small 8Kb allocation.

Thankfully the mega series comes with the ability to add additional SRAM that your programs can seamlessly access as if it were internal to the microcontroller itself. This article will explain the hardware side of the memory expansion project. The next in the series will present the software tweaks that you can use to exploit your new-found freedom to code.

Add 512K of external SRAM to Arduino Mega

XMEM

The ATmega1280 datasheet contains all the documentation that an engineer needs to expand the memory. It’s in chapter 9: ‘external memory interface’.

Block diagram of the xmem interface.
Block diagram of the xmem interface. The block in the center is a high-speed 8-bit latch.

The above diagram is lifted from the datasheet and shows how the microcontroller interfaces with an external memory. The most interesting part about the above diagram is the block in the center which represents a high-speed 8-bit latch.

Multiplexing and the latch

The Arduino Mega can address 64K of external memory with 8-bit data transfers. Ordinarily this would require a lot of pins: 16 for the address lines, 8 for the data lines plus another 2 at least for the control lines.

To cut down on this requirement the ATmega multiplexes the lower 8 address lines with the 8 data lines, saving on 8 pins. It does this by using an 8-bit latch that you supply, and it works because the memory transactions look like this:

The memory transaction timing
The memory transaction timing

The time period indicated in red shows the gap in between the address lines being valid (valid data on A0..A15) and the data transfer starting (valid data on D0..D7). The logic in the ATmega starts a memory transaction by asserting a valid address on A0..A15. The multiplexed lines A0..A7 pass straight through the latch which is set to transparent mode. Then the latch is placed into hold mode where it ignores its inputs and continues to assert the last data it saw on its outputs. The ATmega then sets valid data on the multiplexed lines and bingo, we have successfully set up all the lines for the memory transaction and saved 8 pins in the process.

When choosing a latch we must ensure that it is fast enough to cope with the 16Mhz core clock of the Arduino. 74HC series latches are too slow. The datasheet recommends that we use the 74AHC series.

Addressing more than 64K

If you’ve got this far you’re probably wondering how I’m going to squeeze 512Kb into a 64Kb address space. The answer is to split the 512Kb into 8 banks of 64Kb and control which bank is visible at any one time by using 3 Arduino GPIO pins.

512Kb requires 19 bits of address space mapped to address lines A0..A18. I will connect A0..15 through the xmem interface and control the high bits A16..A18 using Arduino digital pins

Расделение 512 КБайт SRAM на 8 банков памяти по 64 КБайт
Memory banks and the SRAM

A further limitation of the ATmega memory map is that the lower 8Kb of SRAM will always be occupied by the internal memory on the MCU. That means that we will be addressing external memory only in the range 0×2200 to 0xFFFF. This represents a total loss of 69632 bytes from the theoretical total of 524288 held by the SRAM. The datasheet does explain a method of making this ‘lost’ 8Kb addressable but it’s a bit of a hack and not really worth it IMHO.

Part 2 - Schematic and PCB

andybrown.me.uk