A Library that allows the Arduino UNO to read/write data to older DIP DRAM chips
Before explaining how the functions in the library work it is necessary to briefly describe the layout of the DRAM chip.
The chip in question is the Hitachi HM50256-15 which has:
- 9 Address pins
- 1 Data Out pin
- 1 Data In pin
- 1 Row Address Strobe (RAS) pin
- 1 Column Address Strobe (CAS) pin
- 1 Vcc (+5V) pin
- 1 Vss (GND) pin
More information about the chip can be found here: Hitachi HM50256-15 Datasheet
Most DRAM chips follow a standard sequence of signals for reading, writing, and refreshing, as well as other specialized read/write operations like Read-Modify-Write, Extended Data Out (EDO), etc.
DRAMutils only provides the simple read, write, and refresh functions. Their operation in conjunction with the chip will be described below.
The timing diagrams used to explain each function as well as further information on the previously mentioned Read-Modify-Write and EDO modes can be found here: Understanding DRAM operation
Prior to being able to perform any operation on the DRAM chip, it must first be wired correctly to the Arduino. The setup should be as follows:
- Digital pins 2 - 7 should be wired to A0 - A5 of the DRAM address bus
- Analog pins A0 - A2 should be wired to A6 - A8 of the DRAM address bus
- Digital pin 13 should be wired to the RAS pin
- Digital pin 12 should be wired to the CAS pin
- Digital pin 11 should be wired to the WE pin
Once everything is properly connected, the Arduino pins must be setup internally.
DRAMutils provides a DRAM_setup
function that, when called in the setup()
function of the Arduino sketch will setup all the pins for proper operation
like so:
void setup()
{
DRAM_setup();
//insert remaining code here
}
The timing diagram below shows how a write operation is performed
The steps that allow a write operation to occur are as follows:
RAS
andCAS
must be set HIGH first.WE
can be LOW or HIGH when starting but for simplicity is set LOW in the beginning and must be set LOW later (if it is HIGH) to signal a write operation- A row address is applied to the address bus
RAS
must go from HIGH to LOW- A column address is applied to the address bus
- The desired data to be written is sent on the Data In pin
CAS
must go from HIGH to LOWRAS
andCAS
are set to their original HIGH states and the operation is complete
The DRAM_write
function included in the DRAMutils library allows you to
write a bit to the DRAM chip given a memory address and the desired bit to
be written, expressed as a boolean.
DRAMutils defines a variable type known as mem_addr
which is a struct
holding a row and column address as type uint16_t
. The address that you
would like to write to can be expressed as such:
void loop()
{
mem_addr address = {.row = 0x076, .col = 0x1AA};
}
Thus, an example of a full write operation can be seen below:
void setup()
{
DRAM_setup(); //sets up Arduino pins
}
void loop()
{
mem_addr write_addres = {.row = 0x076, .col = 0x1AA}; // Declare DRAM address
bool Data = 0; //Data to be written
DRAM_write(write_addres, Data); //Data written to specified address
}
The timing diagram below shows how a read operation is performed
The steps that allow a read operation occurs as follows:
RAS
andCAS
must be set HIGH in the beginning.WE
can be either LOW or HIGH but for the sake of convenience is set HIGH in the very beginning to denote a Read operation is being performed.- A row address is applied to the address bus
RAS
goes from HIGH to LOW- A column address is applied to the address bus
CAS
goes from HIGH to LOW- Data is outputted via the Data Out pin
RAS
andCAS
are set back to their original states, which is HIGH
The DRAM_read
function included in the DRAMUtils library reads data from the
DRAM chip given an address declared in the mem_addr type as displayed
in the Write Operation description and returns the data read as a boolean.
An example of a full read operation can be seen below:
void setup()
{
DRAM_setup(); //Setup Arduino pins for read operation
}
void loop()
{
mem_addr mem_address = {.row = 0x076, .col = 0x1AA}; // Memory address declared
bool write_data = 0; // Data to be written
bool data_read; // Place to store data created
DRAM_write(mem_address, write_data); //Write data to address
data = DRAM_read(read_address); //Read data written to address
}
It should be noted that you should only read a memory address that has already
been written to. So in the example above there would be an accompanying
DRAM_write
call before DRAM_read
The timing diagram below shows how a standard Row refresh is performed
The steps that allow a Refresh operation are as follows:
- The row address of the data to be refreshed is put out on pins
RAS
must be set from HIGH to LOWRAS
must be set from LOW back to HIGH
The DRAM_refresh
function included in the DRAMutils library performs such
an operation and can be invoked between DRAM_write
and DRAM_read
operations
should certain data require storage for more than ~6-7 seconds ( in the case
of the DRAM chip this library was designed for )
An example of its usage can be seen below:
void setup()
{
DRAM_setup(); //Setup pins for DRAM operations
}
void loop()
{
mem_addr memory_address = {.row = 0x077, .col = 0x011}; //Declare memory address
bool data_write = 0; //Data to be written
bool data_read; //Storage for data read
DRAM_write(memory_address, data_write); //Write data to address
delay(6000); //Delay read operation for 7 seconds
refresh(memory_address); //Refresh data at memory address
delay(6000); //Delay read for another 7 seconds
data_read = DRAM_read(memory_address); //Store data read in variable
}
The timing diagram below shows how a Read-Modify-Write operation is performed.
Read-Modify-Write is a special operation in DRAM that allows a given memory location to first be read, then written to without incurring the time penalty of having to reapply any of the addresses or perform one single read, then one single write operation afterwards which can be time consuming.
WARNING: The Read-Modify-Write cycle for the HM50256-15 chip seems to be slightly different from the one displayed in the IBM "Understanding DRAM" PDF mentioned earlier in How it Works. The functions provided in this library were mostly based off the IBM PDF to ensure compatibility with other DRAM chips but this cycle seems specific to the HM50256-15 chip.
Thus, the explanation below for how it works is specific to the HM50256-15 chip. Please refer to the IBM PDF for a possibly more universal display of how the operation works.
The steps for a Read-Modify-Write operation are as follows:
RAS
andCAS
must be HIGH in the beginning.WE
can be LOW or HIGH but for the sake of convenience is set HIGH in the beginning.- The row address is applied to the address bus
RAS
is set LOW- The column address is applied to the address bus
CAS
is set LOW- Data to be written is applied to the Data In pin
WE
is set LOWWE
is set HIGH- Data to be read is set on the Data Out pin
RAS
is set back HIGHCAS
is set back HIGH
The timing makes it seem as if it is reading the data you just wrote but in reality it is reading the data that was already there prior.
The DRAMutils DRAM_rmw
function allows you to perform a Read-Modify-Write
operation right after any read, write, or refresh operation. An example
of its usage can be seen below:
void setup()
{
DRAM_setup(); //Setup pins for interface with DRAM
}
void loop()
{
mem_addr memory_address = {.row = 0x1AA, .col = 0x1AA}; //Set memory address
bool write_data = 0; //Data to be written
bool data_read; //Storage for data read
DRAM_write(memory_address, 0); //Write a 0 to memory address indicated
data_read = DRAM_rmw(memory_address, 1); //Read data at memory and write data
}
- Download the library: https://github.com/johnzl-777/DRAMutils/archive/master.zip
- (In the Arduino IDE) Sketch > Include Library > Add .ZIP Library > select the downloaded file > Open
As mentioned before, there are some functions that haven't been implemented in the library but I would like to implement soon. The Serial DRAM R/W program in the examples folder already hints at one of them but here's a list of some of the things I'm considering:
-
Software
Implement Read-Modify-Write functionRead-Modify-Write successfully added- Implement Page Mode Read and Write functions
- Test CAS before RAS refresh and Hidden Refresh Cycle
- Implement a "master" read/write function (can read and write any kind of data)
-
Hardware
- Provide the option to use a 7400-based shift register to reduce pin count