Add LB, LBU, LH, LHU, SB and SH instructions

This commit is contained in:
Graham Edgecombe 2017-12-03 16:15:43 +00:00
parent e2a533babb
commit 871e1f4a32
5 changed files with 125 additions and 3 deletions

12
rv32.sv
View file

@ -53,6 +53,8 @@ module rv32 (
.alu_src2_out(decode_alu_src2),
.mem_read_en_out(decode_mem_read_en),
.mem_write_en_out(decode_mem_write_en),
.mem_width_out(decode_mem_width),
.mem_zero_extend_out(decode_mem_zero_extend),
.branch_op_out(decode_branch_op),
.branch_pc_src_out(decode_branch_pc_src),
.rd_out(decode_rd),
@ -72,6 +74,8 @@ module rv32 (
logic decode_alu_src2;
logic decode_mem_read_en;
logic decode_mem_write_en;
logic [1:0] decode_mem_width;
logic decode_mem_zero_extend;
logic [1:0] decode_branch_op;
logic decode_branch_pc_src;
logic [4:0] decode_rd;
@ -93,6 +97,8 @@ module rv32 (
.alu_src2_in(decode_alu_src2),
.mem_read_en_in(decode_mem_read_en),
.mem_write_en_in(decode_mem_write_en),
.mem_width_in(decode_mem_width),
.mem_zero_extend_in(decode_mem_zero_extend),
.branch_op_in(decode_branch_op),
.branch_pc_src_in(decode_branch_pc_src),
.rd_in(decode_rd),
@ -107,6 +113,8 @@ module rv32 (
/* control out */
.mem_read_en_out(execute_mem_read_en),
.mem_write_en_out(execute_mem_write_en),
.mem_width_out(execute_mem_width),
.mem_zero_extend_out(execute_mem_zero_extend),
.branch_op_out(execute_branch_op),
.rd_out(execute_rd),
.rd_writeback_out(execute_rd_writeback),
@ -120,6 +128,8 @@ module rv32 (
/* execute -> mem control */
logic execute_mem_read_en;
logic execute_mem_write_en;
logic [1:0] execute_mem_width;
logic execute_mem_zero_extend;
logic [1:0] execute_branch_op;
logic [4:0] execute_rd;
logic execute_rd_writeback;
@ -135,6 +145,8 @@ module rv32 (
/* control in */
.read_en_in(execute_mem_read_en),
.write_en_in(execute_mem_write_en),
.width_in(execute_mem_width),
.zero_extend_in(execute_mem_zero_extend),
.branch_op_in(execute_branch_op),
.rd_in(execute_rd),
.rd_writeback_in(execute_rd_writeback),

View file

@ -3,6 +3,7 @@
`include "rv32_alu_ops.sv"
`include "rv32_branch_ops.sv"
`include "rv32_mem_ops.sv"
`include "rv32_opcodes.sv"
`include "rv32_regs.sv"
@ -26,6 +27,8 @@ module rv32_decode (
output alu_src2_out,
output mem_read_en_out,
output mem_write_en_out,
output [1:0] mem_width_out,
output mem_zero_extend_out,
output [1:0] branch_op_out,
output branch_pc_src_out,
output [4:0] rd_out,
@ -83,6 +86,8 @@ module rv32_decode (
rd_writeback_out <= 0;
mem_read_en_out <= 0;
mem_write_en_out <= 0;
mem_width_out <= 2'bx;
mem_zero_extend_out <= 1'bx;
branch_op_out <= RV32_BRANCH_OP_NEVER;
branch_pc_src_out <= 1'bx;
imm_out <= 32'bx;
@ -200,6 +205,8 @@ module rv32_decode (
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_BYTE;
mem_zero_extend_out <= 0;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
@ -211,6 +218,8 @@ module rv32_decode (
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_HALF;
mem_zero_extend_out <= 0;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
@ -222,6 +231,7 @@ module rv32_decode (
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_WORD;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
@ -233,6 +243,8 @@ module rv32_decode (
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_BYTE;
mem_zero_extend_out <= 1;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
@ -244,6 +256,8 @@ module rv32_decode (
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_HALF;
mem_zero_extend_out <= 1;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
@ -255,6 +269,7 @@ module rv32_decode (
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
mem_write_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_BYTE;
imm_out <= imm_s;
end
{RV32_OPCODE_STORE, RV32_FUNCT3_STORE_SH, RV32_FUNCT7_ANY}: begin
@ -265,6 +280,7 @@ module rv32_decode (
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
mem_write_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_HALF;
imm_out <= imm_s;
end
{RV32_OPCODE_STORE, RV32_FUNCT3_STORE_SW, RV32_FUNCT7_ANY}: begin
@ -275,6 +291,7 @@ module rv32_decode (
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
mem_write_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_WORD;
imm_out <= imm_s;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_ADD_SUB, RV32_FUNCT7_ANY}: begin

View file

@ -14,6 +14,8 @@ module rv32_execute (
input alu_src2_in,
input mem_read_en_in,
input mem_write_en_in,
input [1:0] mem_width_in,
input mem_zero_extend_in,
input [1:0] branch_op_in,
input branch_pc_src_in,
input [4:0] rd_in,
@ -28,6 +30,8 @@ module rv32_execute (
/* control out */
output mem_read_en_out,
output mem_write_en_out,
output [1:0] mem_width_out,
output mem_zero_extend_out,
output [1:0] branch_op_out,
output [4:0] rd_out,
output rd_writeback_out,
@ -74,6 +78,8 @@ module rv32_execute (
always_ff @(posedge clk) begin
mem_read_en_out <= mem_read_en_in;
mem_write_en_out <= mem_write_en_in;
mem_width_out <= mem_width_in;
mem_zero_extend_out <= mem_zero_extend_in;
branch_op_out <= branch_op_in;
rd_out <= rd_in;
rd_writeback_out <= rd_writeback_in;

View file

@ -2,6 +2,7 @@
`define RV32_MEM
`include "rv32_branch.sv"
`include "rv32_mem_ops.sv"
module rv32_mem (
input clk,
@ -9,6 +10,8 @@ module rv32_mem (
/* 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,
@ -45,12 +48,67 @@ module rv32_mem (
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)
data_mem[result_in[31:2]] <= rs2_value_in;
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
@ -59,7 +117,28 @@ module rv32_mem (
rd_writeback_out <= rd_writeback_in;
result_out <= result_in;
read_value_out <= read_value;
case (width_in)
RV32_MEM_WIDTH_WORD: begin
read_value_out <= read_value;
end
RV32_MEM_WIDTH_HALF: begin
case (result_in[0])
1'b0: read_value_out <= {{16{zero_extend_in ? 1'b0 : read_value[31]}}, read_value[31:16]};
1'b1: read_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: read_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[31]}}, read_value[31:24]};
2'b01: read_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[23]}}, read_value[23:16]};
2'b10: read_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[15]}}, read_value[15:8]};
2'b11: read_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[7]}}, read_value[7:0]};
endcase
end
default: begin
read_value_out <= 32'bx;
end
endcase
end
endmodule

8
rv32_mem_ops.sv Normal file
View file

@ -0,0 +1,8 @@
`ifndef RV32_MEM_OPS
`define RV32_MEM_OPS
localparam RV32_MEM_WIDTH_WORD = 2'b00;
localparam RV32_MEM_WIDTH_HALF = 2'b01;
localparam RV32_MEM_WIDTH_BYTE = 2'b10;
`endif