I'd like to know how to build a bare bones asynchronous DRAM controller. I have some 30-pin 1MB SIMM 70ns DRAM (1Mx9 with parity) modules that I'd like to use in a homebrew retro computer project. Unfortunately there's no datasheet for them so I've been going from the Siemens HYM 91000S-70 and "Understanding DRAM Operation" by IBM.
The basic interface that I'd like to end up with is
- /CS: in, chip select
- R/W: in, read/not write
- RDY: out, HIGH when data is ready
- D: in/out, 8-bit data bus
- A: in, 20-bit address bus
Refresh seems pretty straight-forward with several ways to get it right. I should be able to do distributed (interleaved) RAS-only refreshing (ROR) during CPU clock LOW (where no memory access is done in this particular chip) using any old counter for the row address tracking. I believe all rows need to be refreshed at least every 64ms according to JEDEC (512 per 8ms according to the Seimens datasheetm i.e. standard refresh of cycle/15.6us), so this should work fine and if I get stuck, I'll just post another question. I'm more interested in getting read and write simple, correct and determining what I should expect as far as speed.
I'll first quickly describe how I think it works and the potential solutions I've come up with so far.
Basically, you split a 20-bit address in half, using one half for the column and the other for the row. You strobe the row address, then the column address, if /W is HIGH when /CAS goes LOW then it's a read, otherwise it's a write. If it's a write, the data needs to already be on the data bus by that point. After a period of time, if it's a read then the data is available or if it's a write, the data is sure to have been written. Then /RAS and /CAS need to be brought HIGH again in the counter-intuitively named "precharge" period. This completes the cycle.
So, basically it's a transition through several states with non-uniform specific delays between each transition. I've listed it out as a "table" indexed by the duration of each phase of the transaction in order:
- t(ASR) = 0ns
- /RAS: H
- /CAS: H
- A0-9: RA
- /W: H
- t(RAH) = 10ns
- /RAS: L
- /CAS: H
- A0-9: RA
- /W: H
- t(ASC) = 0ns
- /RAS: L
- /CAS: H
- A0-9: CA
- /W: H
- t(CAH) = 15ns
- /RAS: L
- /CAS: L
- A0-9: CA
- /W: H
- t(CAC) - t(CAH) = ?
- /RAS: L
- /CAS: L
- A0-9: X
- /W: H (data available)
- t(RP) = 40ns
- /RAS: H
- /CAS: L
- A0-9: X
- /W: X
- t(CP) = 10ns
- /RAS: H
- /CAS: H
- A0-9: X
- /W: X
The times I'm referring to are in the following diagram.
(CA = column address, RA = row address, X = don't care)
Even if it's not exactly that, it's something like that and I think the same kind of solution will work. So I've come up with a couple of ideas so far but I think only the last has potential and I'm looking for better ideas. I'm ignoring refreshing, Fast Page and Parity Checking/Generating here.
The simplest solution is just to use a counter and a ROM where the counter output is the ROM address input and each byte has the appropriate state output for the time period that the address corresponds to. This won't work because ROMs are slow. Even a pre-loaded SRAM seems like it would be far too slow to be worth it.
The second idea was to use a GAL16V8 or something but I don't think I understand them well enough, programmers are very expensive and the programming software is closed source & Windows-only as far as I know.
My last idea is the only one I think might actually work. The 74ACT logic family has low propagation delays and accepts high clock frequencies. I'm thinking read and write could be done with some CD74ACT164E shift register and SN74ACT573N.
Basically, each unique state gets its own latch statically programmed using 5V and GND rails. Each shift register output goes to one latch's /OE pin. If I understand the data sheets right, the delay between each state could only be 1/SCLK but that's much better than a PROM or 74HC solution.
So, is the last approach likely to work? Is there a faster, smaller or generally better way to do this? I think I saw that the IBM PC/XT used 7400 chips for something related to DRAM but I only saw top-board photos, so I'm not sure how that worked.
p.s. I'd like this to be doable in DIP and not "cheat" using an FPGA or modern uC.
p.p.s Maybe using gate delay directly with the same latch approach is a better idea. I realize both shift register and direct gate/propagation delay methods will vary with temperature but I accept this.
For anyone that finds this in the future, this discussion between Bil Herd and André Fachat covers several of the designs mentioned in this thread and discusses other problems including DRAM testing.