HDLbits
Start Practicing

RTL Design Patterns/Memories

External SRAM Controller

hard
memorysramcontrollertri-statefsm

Why an external SRAM needs a controller at all

An on-chip block RAM is just a synthesized memory with clean synchronous ports. An external SRAM chip on a board is a different animal: it has its own access-time specification (it needs a certain number of nanoseconds after the address and control lines settle before its output data is valid), a single bidirectional data bus shared between reads and writes (so something has to make sure only one side drives it at a time), and separate active-low control pins (CE#, OE#, WE#) that must be sequenced correctly. A controller FSM’s job is to translate a simple internal request/response interface into that external timing and bus-direction discipline.

Interface

Signal Direction Description
clk/rst input Clock and synchronous, active-high reset.
req_valid input Request a new access.
req_we input 1 = write, 0 = read.
req_addr input Address for this access.
req_wdata input Data to write (write accesses only).
req_ready output High when the controller is idle and can accept a new request.
req_rdata output Captured read data (read accesses only), valid the cycle req_rvalid pulses.
req_rvalid output Pulses for one cycle when req_rdata is valid.
sram_addr output Address driven to the external SRAM.
sram_data inout Bidirectional data bus to/from the external SRAM.
sram_ce_n output Active-low chip-enable.
sram_oe_n output Active-low output-enable (asserted for reads).
sram_we_n output Active-low write-enable (asserted for writes).

Access sequencing

State ce_n oe_n (read) we_n (write) Bus driven? Purpose
S_IDLE 1 1 1 no Idle; accepts a new request.
S_ACCESS0 0 0 or 1 1 or 0 write only Wait state 1 — memory access time.
S_ACCESS1 0 0 or 1 1 or 0 write only Wait state 2 — memory access time.
S_CAPTURE 0→1 0→1 0→1 write only, then released Sample read data / finish write; return to idle.

Correctness constraints

  • Bus direction discipline: the controller must drive sram_data only during a write (and release it to high-Z otherwise), so the external device (or, in the testbench, the behavioral SRAM model) is free to drive the bus during a read without contention. Driving the bus during a read is a bus-contention bug.
  • The controller must insert enough wait states (S_ACCESS0, S_ACCESS1) between asserting the address/control lines and sampling read data for the external memory’s access time to be respected — sampling sram_data too early (in the same cycle control lines are first asserted) risks capturing stale or undefined data.
  • req_ready must deassert for the entire duration of an in-flight access and only reassert once the controller returns to S_IDLE.
  • req_rvalid must pulse for exactly one cycle, only for read accesses, and only once the captured data is stable.
  • Write data (wdata_latched) must remain stable on sram_data for the entire write-access window, not just the first cycle.