2017-12-02 10:22:48 +00:00
|
|
|
`ifndef RV32_MEM
|
|
|
|
|
`define RV32_MEM
|
|
|
|
|
|
2017-12-02 15:23:12 +00:00
|
|
|
`include "rv32_branch.sv"
|
2017-12-05 19:54:01 +00:00
|
|
|
|
2017-12-09 10:44:39 +00:00
|
|
|
`define RV32_MEM_WIDTH_WORD 2'b00
|
|
|
|
|
`define RV32_MEM_WIDTH_HALF 2'b01
|
|
|
|
|
`define RV32_MEM_WIDTH_BYTE 2'b10
|
2017-12-02 15:23:12 +00:00
|
|
|
|
2017-12-02 10:22:48 +00:00
|
|
|
module rv32_mem (
|
|
|
|
|
input clk,
|
2017-12-04 21:45:28 +00:00
|
|
|
|
|
|
|
|
/* control in (from hazard) */
|
|
|
|
|
input stall_in,
|
|
|
|
|
input flush_in,
|
2017-12-02 10:22:48 +00:00
|
|
|
|
|
|
|
|
/* control in */
|
2017-12-30 13:48:14 +00:00
|
|
|
input branch_predicted_taken_in,
|
2017-12-29 15:29:15 +00:00
|
|
|
input valid_in,
|
2017-12-30 14:12:23 +00:00
|
|
|
input alu_non_zero_in,
|
2017-12-06 14:51:55 +00:00
|
|
|
input read_in,
|
|
|
|
|
input write_in,
|
2017-12-03 16:15:43 +00:00
|
|
|
input [1:0] width_in,
|
|
|
|
|
input zero_extend_in,
|
2017-12-02 15:23:12 +00:00
|
|
|
input [1:0] branch_op_in,
|
2017-12-02 11:26:12 +00:00
|
|
|
input [4:0] rd_in,
|
2017-12-06 14:53:42 +00:00
|
|
|
input rd_write_in,
|
2017-12-02 10:22:48 +00:00
|
|
|
|
|
|
|
|
/* data in */
|
|
|
|
|
input [31:0] result_in,
|
|
|
|
|
input [31:0] rs2_value_in,
|
2017-12-02 15:23:12 +00:00
|
|
|
input [31:0] branch_pc_in,
|
2017-12-02 10:22:48 +00:00
|
|
|
|
2017-12-17 19:57:00 +00:00
|
|
|
/* data in (from data memory bus) */
|
|
|
|
|
input [31:0] data_read_value_in,
|
2017-12-05 22:00:47 +00:00
|
|
|
|
2017-12-02 11:26:12 +00:00
|
|
|
/* control out */
|
2017-12-29 15:29:15 +00:00
|
|
|
output logic valid_out,
|
2017-12-30 13:48:14 +00:00
|
|
|
output logic branch_mispredicted_out,
|
2017-12-09 21:03:45 +00:00
|
|
|
output logic [4:0] rd_out,
|
|
|
|
|
output logic rd_write_out,
|
2017-12-02 11:26:12 +00:00
|
|
|
|
2017-12-17 19:57:00 +00:00
|
|
|
/* control out (to data memory bus) */
|
|
|
|
|
output logic data_read_out,
|
2017-12-17 20:47:17 +00:00
|
|
|
output logic data_write_out,
|
2017-12-17 19:57:00 +00:00
|
|
|
output logic [3:0] data_write_mask_out,
|
2017-12-05 22:00:47 +00:00
|
|
|
|
2017-12-02 10:22:48 +00:00
|
|
|
/* data out */
|
2017-12-09 21:03:45 +00:00
|
|
|
output logic [31:0] rd_value_out,
|
|
|
|
|
output logic [31:0] branch_pc_out,
|
2017-12-02 10:22:48 +00:00
|
|
|
|
2017-12-17 19:57:00 +00:00
|
|
|
/* data out (to data memory bus) */
|
|
|
|
|
output logic [31:0] data_address_out,
|
|
|
|
|
output logic [31:0] data_write_value_out
|
2017-12-05 22:00:47 +00:00
|
|
|
);
|
2017-12-29 15:29:15 +00:00
|
|
|
/* branch unit */
|
2017-12-12 21:05:02 +00:00
|
|
|
rv32_branch_unit branch_unit (
|
2017-12-02 15:23:12 +00:00
|
|
|
/* control in */
|
2017-12-30 13:48:14 +00:00
|
|
|
.predicted_taken_in(branch_predicted_taken_in),
|
2017-12-30 14:12:23 +00:00
|
|
|
.alu_non_zero_in(alu_non_zero_in),
|
2017-12-02 15:23:12 +00:00
|
|
|
.op_in(branch_op_in),
|
|
|
|
|
|
|
|
|
|
/* control out */
|
2017-12-30 13:48:14 +00:00
|
|
|
.mispredicted_out(branch_mispredicted_out)
|
2017-12-02 15:23:12 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
assign branch_pc_out = branch_pc_in;
|
|
|
|
|
|
2017-12-30 11:02:18 +00:00
|
|
|
/* memory access unit */
|
2017-12-29 15:29:15 +00:00
|
|
|
logic [31:0] mem_read_value;
|
|
|
|
|
|
2017-12-17 19:57:00 +00:00
|
|
|
assign data_read_out = read_in;
|
2017-12-17 20:47:17 +00:00
|
|
|
assign data_write_out = write_in;
|
2017-12-17 19:57:00 +00:00
|
|
|
assign data_address_out = result_in;
|
2017-12-03 18:49:00 +00:00
|
|
|
|
|
|
|
|
always_comb begin
|
2017-12-29 15:29:15 +00:00
|
|
|
/* write port */
|
2017-12-06 14:51:55 +00:00
|
|
|
if (write_in) begin
|
2017-12-05 22:00:47 +00:00
|
|
|
case (width_in)
|
2017-12-09 10:44:39 +00:00
|
|
|
`RV32_MEM_WIDTH_WORD: begin
|
2017-12-17 19:57:00 +00:00
|
|
|
data_write_value_out = rs2_value_in;
|
|
|
|
|
data_write_mask_out = 4'b1111;
|
2017-12-05 22:00:47 +00:00
|
|
|
end
|
2017-12-09 10:44:39 +00:00
|
|
|
`RV32_MEM_WIDTH_HALF: begin
|
2017-12-05 22:00:47 +00:00
|
|
|
case (result_in[0])
|
|
|
|
|
2'b0: begin
|
2017-12-17 19:57:00 +00:00
|
|
|
data_write_value_out = {16'bx, rs2_value_in[15:0]};
|
|
|
|
|
data_write_mask_out = 4'b0011;
|
2017-12-05 22:00:47 +00:00
|
|
|
end
|
2017-12-26 13:38:07 +00:00
|
|
|
2'b1: begin
|
|
|
|
|
data_write_value_out = {rs2_value_in[15:0], 16'bx};
|
|
|
|
|
data_write_mask_out = 4'b1100;
|
|
|
|
|
end
|
2017-12-05 22:00:47 +00:00
|
|
|
endcase
|
|
|
|
|
end
|
2017-12-09 10:44:39 +00:00
|
|
|
`RV32_MEM_WIDTH_BYTE: begin
|
2017-12-05 22:00:47 +00:00
|
|
|
case (result_in[1:0])
|
|
|
|
|
2'b00: begin
|
2017-12-26 13:38:07 +00:00
|
|
|
data_write_value_out = {24'bx, rs2_value_in[7:0]};
|
|
|
|
|
data_write_mask_out = 4'b0001;
|
2017-12-05 22:00:47 +00:00
|
|
|
end
|
|
|
|
|
2'b01: begin
|
2017-12-17 19:57:00 +00:00
|
|
|
data_write_value_out = {16'bx, rs2_value_in[7:0], 8'bx};
|
|
|
|
|
data_write_mask_out = 4'b0010;
|
2017-12-05 22:00:47 +00:00
|
|
|
end
|
2017-12-26 13:38:07 +00:00
|
|
|
2'b10: begin
|
|
|
|
|
data_write_value_out = {8'bx, rs2_value_in[7:0], 16'bx};
|
|
|
|
|
data_write_mask_out = 4'b0100;
|
|
|
|
|
end
|
2017-12-05 22:00:47 +00:00
|
|
|
2'b11: begin
|
2017-12-26 13:38:07 +00:00
|
|
|
data_write_value_out = {rs2_value_in[7:0], 24'bx};
|
|
|
|
|
data_write_mask_out = 4'b1000;
|
2017-12-05 22:00:47 +00:00
|
|
|
end
|
|
|
|
|
endcase
|
|
|
|
|
end
|
|
|
|
|
default: begin
|
2017-12-17 19:57:00 +00:00
|
|
|
data_write_value_out = 32'bx;
|
|
|
|
|
data_write_mask_out = 4'bx;
|
2017-12-05 22:00:47 +00:00
|
|
|
end
|
|
|
|
|
endcase
|
|
|
|
|
end else begin
|
2017-12-17 19:57:00 +00:00
|
|
|
data_write_value_out = 32'bx;
|
|
|
|
|
data_write_mask_out = 4'b0;
|
2017-12-03 18:49:00 +00:00
|
|
|
end
|
2017-12-29 15:29:15 +00:00
|
|
|
|
|
|
|
|
/* read port */
|
|
|
|
|
if (read_in) begin
|
|
|
|
|
case (width_in)
|
|
|
|
|
`RV32_MEM_WIDTH_WORD: begin
|
|
|
|
|
mem_read_value = data_read_value_in;
|
|
|
|
|
end
|
|
|
|
|
`RV32_MEM_WIDTH_HALF: begin
|
|
|
|
|
case (result_in[0])
|
|
|
|
|
1'b0: mem_read_value = {{16{zero_extend_in ? 1'b0 : data_read_value_in[15]}}, data_read_value_in[15:0]};
|
|
|
|
|
1'b1: mem_read_value = {{16{zero_extend_in ? 1'b0 : data_read_value_in[31]}}, data_read_value_in[31:16]};
|
|
|
|
|
endcase
|
|
|
|
|
end
|
|
|
|
|
`RV32_MEM_WIDTH_BYTE: begin
|
|
|
|
|
case (result_in[1:0])
|
|
|
|
|
2'b00: mem_read_value = {{24{zero_extend_in ? 1'b0 : data_read_value_in[7]}}, data_read_value_in[7:0]};
|
|
|
|
|
2'b01: mem_read_value = {{24{zero_extend_in ? 1'b0 : data_read_value_in[15]}}, data_read_value_in[15:8]};
|
|
|
|
|
2'b10: mem_read_value = {{24{zero_extend_in ? 1'b0 : data_read_value_in[23]}}, data_read_value_in[23:16]};
|
|
|
|
|
2'b11: mem_read_value = {{24{zero_extend_in ? 1'b0 : data_read_value_in[31]}}, data_read_value_in[31:24]};
|
|
|
|
|
endcase
|
|
|
|
|
end
|
|
|
|
|
default: begin
|
|
|
|
|
mem_read_value = 32'bx;
|
|
|
|
|
end
|
|
|
|
|
endcase
|
|
|
|
|
end else begin
|
|
|
|
|
mem_read_value = 32'bx;
|
|
|
|
|
end
|
2017-12-03 14:27:16 +00:00
|
|
|
end
|
|
|
|
|
|
2017-12-02 18:29:51 +00:00
|
|
|
always_ff @(posedge clk) begin
|
2017-12-04 21:45:28 +00:00
|
|
|
if (!stall_in) begin
|
2017-12-29 15:29:15 +00:00
|
|
|
valid_out <= valid_in;
|
2017-12-03 20:56:47 +00:00
|
|
|
rd_out <= rd_in;
|
2017-12-06 14:53:42 +00:00
|
|
|
rd_write_out <= rd_write_in;
|
2017-12-03 20:56:47 +00:00
|
|
|
|
2017-12-30 11:34:14 +00:00
|
|
|
if (read_in)
|
2017-12-29 15:29:15 +00:00
|
|
|
rd_value_out <= mem_read_value;
|
|
|
|
|
else
|
2017-12-03 20:56:47 +00:00
|
|
|
rd_value_out <= result_in;
|
|
|
|
|
|
2017-12-29 15:29:15 +00:00
|
|
|
if (flush_in) begin
|
|
|
|
|
valid_out <= 0;
|
2017-12-06 14:53:42 +00:00
|
|
|
rd_write_out <= 0;
|
2017-12-29 15:29:15 +00:00
|
|
|
end
|
2017-12-03 17:49:20 +00:00
|
|
|
end
|
2017-12-02 10:22:48 +00:00
|
|
|
end
|
|
|
|
|
endmodule
|
|
|
|
|
|
|
|
|
|
`endif
|