ram은 대부분 Byte 접근을 많이 하기 때문에 Byte align 많이 한다!
$5에 순차적으로 0x87654321을 lw, lh, lb. lhu, lbu를 진행
data_cache의 byte 기준 14번지의 값인 0x87654321에 따라 진행됨을 알 수있다.
그런데 halfword나 하위byte msb가 0이라 signed extension인지 zero extension인지 구분 불가!
그래서 이번엔 data_cache의 14번지 값을 0x8765438f로 변경
이렇게 진행하니 lb, lbu를 진행 후 $5의 값을 보니
lb : 0xffff_ff8f
lbu : 0x0000_008f
잘 설계됨을 알 수 있다.
funct3의 5가지 경우를 다 테스트했음을 알 수 있다.
opcode를보면 R, S, I type 진행했음을 알 수 있다.
funct3를보면 R-type을 제외하고 모든 가짓수 테스트했음을 알 수 있다.
module data_mem (
input logic clk,
input logic d_wr_en,
input logic [31:0] dAddr,
input logic [31:0] dWdata,
input logic [2:0] funct3, // instr_code[14:12]를 직접 받는 것이 더 명확합니다.
output logic [31:0] dRdata
);
logic [31:0] data_memory[0:15]; // 16-word memory
// 주소 변환: 바이트 주소 -> 워드 인덱스
wire [3:0] word_index = dAddr[5:2];
// 읽기 동작 (조합 논리)
assign dRdata = data_memory[word_index];
// 쓰기 동작 (순차 논리)
always_ff @(posedge clk) begin
if (d_wr_en) begin
case (funct3)
// Store Byte (sb)
3'b000: begin
// dAddr[1:0] 값에 따라 해당 바이트만 덮어쓰기
if (dAddr[1:0] == 2'b00) data_memory[word_index][7:0] <= dWdata[7:0];
if (dAddr[1:0] == 2'b01) data_memory[word_index][15:8] <= dWdata[7:0];
if (dAddr[1:0] == 2'b10) data_memory[word_index][23:16] <= dWdata[7:0];
if (dAddr[1:0] == 2'b11) data_memory[word_index][31:24] <= dWdata[7:0];
end
// Store Halfword (sh)
3'b001: begin
// dAddr[1] 값에 따라 해당 halfword만 덮어쓰기
if (dAddr[1] == 1'b0) data_memory[word_index][15:0] <= dWdata[15:0];
if (dAddr[1] == 1'b1) data_memory[word_index][31:16] <= dWdata[15:0];
end
// Store Word (sw)
3'b010: begin
data_memory[word_index] <= dWdata;
end
endcase
end
end
endmodule