Accept one read or write request at a time through a valid/ready handshake.
For a write: drive the RAM for one cycle and be ready again.
For a read: drive the address, wait for the RAM's read latency, then present the data with a one-cycle rsp_valid.
Keep working correctly whatever the requester does to its inputs after the handshake.
The requester side uses a valid/ready handshake. The RAM side uses fixed-latency accesses.
Signal | Direction | Meaning |
|---|---|---|
| in | A request is offered. The requester holds it, with stable fields, until |
| out | High only in IDLE. A transfer happens when |
| in | Operation, address, write data. Valid only while |
| out | One-cycle pulse for each uncancelled read. No rsp_ready: consumer must capture every pulse. Writes produce no response; reset cancels outstanding requests. |
Signal | Direction | Meaning |
|---|---|---|
| out | One-cycle access strobe |
| out | Write enable (only during a write access) |
| out | Address and write data, driven from the latched request |
| in | RD_LAT registered stages: count the launch edge as stage 1. For launch at edge 1, data is available after edge RD_LAT, sampled by the consumer at RD_LAT+1. |
Property | This controller |
|---|---|
Outstanding requests | One at a time |
Ordering | Strictly in order; a read after a write to the same address sees the written data |
Write timing (accept = edge 0) | Commit and ready restored after edge 1; earliest next acceptance edge 2. Initiation interval 2. |
Read timing (accept = edge 0) | RAM launch edge 1; response available after edge RD_LAT; consumer captures at RD_LAT+1. Ready restored after that edge; earliest next acceptance RD_LAT+2. |
Read the picture left to right. Each arrow is a rising clock edge, and the box after it is the state the controller holds until the next edge.
Edge 0 accepts the read and moves to ACCESS, which drives mem_en for one cycle.
Edge 1 is the RAM launch: it counts as stage 1 of the two read stages. The controller waits in WAIT.
Edge 2 completes stage 2, so the data is available while the controller sits in RESP with rsp_valid high.
Edge 3 is where the always-accepting consumer captures it. Ready returns after that edge, so edge 4 (RD_LAT + 2) is the earliest next acceptance.
Edge (RD_LAT = 2) | Pre-edge action | Post-edge state / signals |
|---|---|---|
0 | Accept read | ACCESS; mem_en = 1 |
1 | RAM launches read | WAIT; mem_en = 0 |
2 | RAM pipeline advances | RESP; rsp_valid = 1 and data available |
3 | Always-accepting consumer captures response | IDLE; req_ready = 1 |
4 | Earliest next acceptance | ACCESS for next request |
One request at a time keeps the FSM small and the ordering correct. More throughput needs a pipelined controller with a queue for outstanding reads; see the pipelining topic.
rsp_valid after a write?Nothing: writes produce no response. A requester that must know a write has completed can treat the return of req_ready as completion, since the controller accepts a new request only once the write has gone to the RAM.