retro-silicon

Components

memory/sdram

Byte-port controller for a 2M x 32 SDR SDRAM, such as the Tang Nano 20K's

Board verified Sim: passing (17 passed). Used by Nintendo Entertainment System, shell-sdram. Source.

BoardStateRun
Sipeed Tang Nano 20Kverified2026-10-28, at ac84cec

Verified: the latest run on that board of a system using it passed every test, and the component hasn't changed since. Stale: it has changed since that run.

README

Controller for a 2M × 32 SDR SDRAM (8 MB: 4 banks, 2048 rows, 256 columns), such as the 64 Mbit chip inside the Tang Nano 20K’s GW2AR-18. The user side is a byte port. Each access opens its row and closes it with auto-precharge, so every access takes the same number of clocks except when a refresh gets there first; that fixed bound is what lets a system fit an access into a CPU cycle.

Module sdram_ctrl.

Timing

Ports

PortDirWidthMeaning
clk, rstin1Clock; synchronous reset, which restarts the power-up sequence
reqin1Access request, held until ack
wein1The access is a write
addrin23Byte address: bank [22:21], row [20:10], column [9:2], byte lane [1:0]
wdatain8Byte to write
ackout1One-cycle pulse: the access is done
rdataout8Byte read, valid with ack
readyout1The power-up sequence is done
sd_cke, sd_cs_n, sd_ras_n, sd_cas_n, sd_we_nout1SDRAM control
sd_ba, sd_addr, sd_dqmout2, 11, 4SDRAM bank, address, byte masks
sd_dq_o, sd_dq_oe, sd_dq_iout, out, in32, 1, 32SDRAM data, split for the board’s tristate buffer

Parameters

ParameterDefaultMeaning
FREQ_MHZ27clk frequency; the chip timings are converted to clocks from it
CAS_LATENCY22 or 3
INIT_US200Power-up wait before the first command
REFRESH_NS15000One refresh this often; 4096 rows in 64 ms needs 15,625 or less

Status

Sim tests, at 27, 47 and 100 MHz, against sim/sdram_model.hpp, a model of the chip that checks every command against its timing limits (power-up sequence, tRCD, tRP, tRC, tRAS, tWR, refresh interval) and puts read data on the bus only at the cycle the CAS latency allows:

Planted bugs (capture one cycle late, no refresh, wrong byte lane, tRCD of 0, no wait after a refresh) are each caught.

Fixed: up to milestone 5 a WRITE waited only tRAS less its own tWR, so from about 40 MHz the chip’s auto-precharge could start before tRAS. At 27 MHz it was 49 ns after the ACTIVE against tRAS’s 42; at the Tang Nano 20K’s 46.4 MHz the NES’s HDMI sim caught it at 33.5 ns, and the 47 MHz tests fail without the fix.

On a Tang Nano 20K at 27 MHz, through systems/shell-sdram: 8 MB of random data written, checked by the shell’s CRC command and sampled back, with the same CRC32 as the sim (0x0e8da31c).