7 / 24 · Concept
Timing contracts for memory requests and responses
Distinguish synchronous reads, delayed tags, and same-address collisions.
Lessons are free to read. Enroll to save your learning progress.
A memory is more than a large register array
A memory interface needs a timing contract as well as capacity. An asynchronous read changes combinational output when its address changes. A synchronous read samples an address at an edge and changes the output afterward. These models require different schedules. Inference into a device memory resource also depends on coding style and the target tool. Here we specify sixteen eight-bit entries with a synchronous read.
Sample address and tag at edge k. The corresponding data and delayed tag appear after that edge; their first consumption opportunity is edge k+1. A one-cycle read does not mean immediate combinational response. Response valid must follow the same delay. Combining a delayed value with the current input tag breaks successive requests.
logic [7:0] mem [0:15];
logic [7:0] rd_data;
logic [3:0] rd_tag;
logic rd_valid;
always_ff @(posedge clk) begin
if (wr_en) mem[wr_addr] <= wr_data;
rd_valid <= req_valid;
if (req_valid) begin
rd_data <= mem[req_addr];
rd_tag <= req_tag;
end
if (rst) rd_valid <= 1'b0;
endFor this behavioral model, simultaneous reading and writing of one address returns the old value because nonblocking assignments read old state. Actual memory primitives have explicit collision modes and restrictions; see AMD UG901's read/write modes and verify the intended mode against the target and synthesis result. Resetting valid does not initialize the array.
| Edge | Accepted request | Effect |
|---|---|---|
| 2 | addr=3,tag=7 | Capture old mem[3]=42 |
| 3 | addr=4,tag=8 | Consume 42,7 and capture the next value |
| 4 | No request | Clear response valid |
This schedule assumes the consumer never stalls. If it stalls at edge 3, the next response can overwrite rd_data. Add response storage or limit requests using available capacity, including responses already in flight. Initialize test memory explicitly before checking values. Verify address and tag correspondence, not only response data; a correct value attached to the wrong request is still a failure.
Try it yourself
With mem[3]=42, read address 3 and write 99 to it at the same edge. What does this model put in rd_data, and what is the new memory value? What is needed for output stalls?
Read the explanation
rd_data becomes 42, while mem[3] becomes 99. Both assignments read old state. Stalls require response storage and admission control that counts in-flight responses. Verify the actual target memory's collision mode separately.