icicle/rv32_mem.sv

154 lines
4.7 KiB
Systemverilog

`ifndef RV32_MEM
`define RV32_MEM
`include "rv32_branch.sv"
`include "rv32_mem_ops.sv"
module rv32_mem (
input clk,
/* control in (from hazard) */
input stall_in,
input flush_in,
/* control in */
input read_en_in,
input write_en_in,
input [1:0] width_in,
input zero_extend_in,
input [1:0] branch_op_in,
input [4:0] rd_in,
input rd_writeback_in,
/* data in */
input [31:0] result_in,
input [31:0] rs2_value_in,
input [31:0] branch_pc_in,
/* control out */
output branch_taken_out,
output [4:0] rd_out,
output rd_writeback_out,
/* data out */
output [31:0] rd_value_out,
output [31:0] branch_pc_out
);
logic [31:0] data_mem [255:0];
rv32_branch branch (
/* control in */
.op_in(branch_op_in),
/* data in */
.result_in(result_in),
/* control out */
.taken_out(branch_taken_out)
);
assign branch_pc_out = branch_pc_in;
logic [31:0] read_value;
logic [31:0] write_value;
logic [3:0] write_mask;
always_comb begin
case (width_in)
RV32_MEM_WIDTH_WORD: begin
write_value = rs2_value_in;
write_mask = 4'b1111;
end
RV32_MEM_WIDTH_HALF: begin
case (result_in[0])
2'b0: begin
write_value = {rs2_value_in[15:0], 16'bx};
write_mask = 4'b1100;
end
2'b1: begin
write_value = {16'bx, rs2_value_in[15:0]};
write_mask = 4'b0011;
end
endcase
end
RV32_MEM_WIDTH_BYTE: begin
case (result_in[1:0])
2'b00: begin
write_value = {rs2_value_in[7:0], 24'bx};
write_mask = 4'b1000;
end
2'b01: begin
write_value = {8'bx, rs2_value_in[7:0], 16'bx};
write_mask = 4'b0100;
end
2'b10: begin
write_value = {16'bx, rs2_value_in[7:0], 8'bx};
write_mask = 4'b0010;
end
2'b11: begin
write_value = {24'bx, rs2_value_in[7:0]};
write_mask = 4'b0001;
end
endcase
end
default: begin
write_value = 32'bx;
write_mask = 4'bx;
end
endcase
end
always_ff @(negedge clk) begin
read_value <= data_mem[result_in[31:2]];
if (write_en_in) begin
if (write_mask[3])
data_mem[result_in[31:2]][31:24] <= write_value[31:24];
if (write_mask[2])
data_mem[result_in[31:2]][23:16] <= write_value[23:16];
if (write_mask[1])
data_mem[result_in[31:2]][15:8] <= write_value[15:8];
if (write_mask[0])
data_mem[result_in[31:2]][7:0] <= write_value[7:0];
end
end
always_ff @(posedge clk) begin
if (!stall_in) begin
rd_out <= rd_in;
rd_writeback_out <= rd_writeback_in;
if (read_en_in) begin
case (width_in)
RV32_MEM_WIDTH_WORD: begin
rd_value_out <= read_value;
end
RV32_MEM_WIDTH_HALF: begin
case (result_in[0])
1'b0: rd_value_out <= {{16{zero_extend_in ? 1'b0 : read_value[31]}}, read_value[31:16]};
1'b1: rd_value_out <= {{16{zero_extend_in ? 1'b0 : read_value[15]}}, read_value[15:0]};
endcase
end
RV32_MEM_WIDTH_BYTE: begin
case (result_in[1:0])
2'b00: rd_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[31]}}, read_value[31:24]};
2'b01: rd_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[23]}}, read_value[23:16]};
2'b10: rd_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[15]}}, read_value[15:8]};
2'b11: rd_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[7]}}, read_value[7:0]};
endcase
end
default: begin
rd_value_out <= 32'bx;
end
endcase
end else begin
rd_value_out <= result_in;
end
if (flush_in)
rd_writeback_out <= 0;
end
end
endmodule
`endif