7 / 24 · 개념
메모리 요청과 응답의 시간 계약
동기 읽기, 주소·tag 지연과 같은 주소 읽기/쓰기를 구분합니다.
내용은 무료로 볼 수 있습니다. 수강 신청하면 학습 기록을 저장할 수 있어요.
메모리는 큰 레지스터 배열만이 아니다
메모리를 쓰는 데이터패스에서는 저장 용량뿐 아니라 읽기 시점을 정해야 합니다. 주소가 바뀌면 조합 출력이 바로 바뀌는 비동기 읽기 모델과, 에지에서 주소를 샘플하고 그 뒤 출력이 바뀌는 동기 읽기 모델은 제어 일정이 다릅니다. FPGA 메모리 자원으로의 추론 여부도 RTL 형태와 대상 도구에 영향을 받습니다. 여기서는 같은 클록을 쓰는 독립된 읽기 포트 1개와 쓰기 포트 1개를 갖춘 동기 읽기 모델을 사용합니다. 저장 공간은 16개 항목이며 항목당 8비트입니다.
요청 주소와 tag를 에지 k에서 샘플하면 데이터와 지연한 tag가 에지 k 뒤의 사이클에 함께 나타납니다. 소비자가 이를 수락하는 첫 기회는 에지 k+1입니다. '한 사이클 읽기'가 요청 직후 조합적으로 데이터를 내준다는 뜻은 아닙니다. req_valid가 0인 에지에서는 읽기 결과가 유효하지 않으므로 response-valid도 같은 지연 규칙을 따라야 합니다. 주소만 지연시키거나 tag만 현재 입력에서 가져오면 요청들이 연달아 들어올 때 서로 바뀝니다.
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;
end위 모델에서 같은 에지에 같은 주소를 읽고 쓰면 읽기에는 에지 전 값이 들어갑니다. nonblocking 대입들이 이전 상태를 읽기 때문입니다. 그러나 실제 메모리 primitive는 read-first, write-first, no-change 등 여러 모드와 포트 충돌 제약을 가질 수 있습니다. AMD UG901의 RAM 읽기/쓰기 모드 설명을 참고하고, 같은 주소 충돌을 금지하거나 선택한 모드를 명시한 뒤 대상 메모리와 합성 결과를 확인해야 합니다. 메모리를 전체 reset하는 루프는 원하는 블록 RAM 추론과 맞지 않을 수 있어 여기서는 valid만 reset합니다.
| 에지 | 수락한 요청 | 메모리 상태/응답 |
|---|---|---|
| 2 | addr=3,tag=7 | 이전 mem[3]=42를 rd_data에 저장 |
| 3 | addr=4,tag=8 | 이전 응답 42,7을 소비하고 다음 값 저장 |
| 4 | 요청 없음 | rd_valid=0, 저장된 data는 의미 없음 |
이 표는 출력에 정지가 없는 경우입니다. 상대가 에지 3에 ready=0이면 단순 rd_data 레지스터가 다음 응답으로 덮어쓸 수 있습니다. 따라서 응답 버퍼를 두거나, 남은 공간을 기준으로 새 요청을 제한해야 합니다. ready가 낮아진 바로 그 사이클에도 이미 메모리 내부에 들어간 요청의 응답이 올 수 있으므로 '지금 ready=0'만 보고 정지하는 것은 충분하지 않습니다.
기준 모델을 작성할 때 요청 수락 큐와 응답 큐를 구분하고, 각 응답의 값뿐 아니라 주소와 tag 대응을 확인하세요. 초기화하지 않은 메모리 값은 기대값으로 사용할 수 없습니다. 시험 전에 쓰기로 값을 채우거나 별도의 초기 이미지 계약을 정합니다. 읽기 지연과 충돌 모드를 명확히 한 작은 표가 데이터가 틀렸다는 막연한 파형 관찰보다 훨씬 유용한 디버깅 기준이 됩니다.
직접 생각해 보기
mem[3]=42에서 같은 에지에 addr=3을 읽고 mem[3]<=99를 쓰면 위 RTL의 rd_data와 이후 mem[3]은 얼마인가요? 출력 정지가 가능하다면 무엇을 추가해야 하나요?
해설 보기
rd_data=42,에지 후 mem[3]=99입니다. 두 대입 모두 이전 상태를 읽습니다. 출력 정지를 허용하려면 응답을 보관할 버퍼와 진행 중인 응답까지 포함한 요청 수락 제어가 필요합니다. 실제 메모리에서는 선택한 충돌 모드도 따로 확인합니다.