diff --git a/rv32.sv b/rv32.sv index 663fe91..db79ab7 100644 --- a/rv32.sv +++ b/rv32.sv @@ -1,4 +1,5 @@ `include "rv32_decode.sv" +`include "rv32_execute.sv" `include "rv32_fetch.sv" module rv32 ( @@ -12,6 +13,7 @@ module rv32 ( .instr_out(fetch_instr) ); + /* fetch -> decode data */ logic [31:0] fetch_pc; logic [31:0] fetch_instr; @@ -20,6 +22,52 @@ module rv32 ( /* data in */ .pc_in(fetch_pc), - .instr_in(fetch_instr) + .instr_in(fetch_instr), + + /* control out */ + .alu_op_out(decode_alu_op), + .alu_sub_sra_out(decode_alu_sub_sra), + .alu_src1_out(decode_alu_src1), + .alu_src2_out(decode_alu_src2), + + /* data out */ + .pc_out(decode_pc), + .rs1_value_out(decode_rs1_value), + .rs2_value_out(decode_rs2_value), + .imm_out(decode_imm) ); + + /* decode -> execute control */ + logic [3:0] decode_alu_op; + logic decode_alu_sub_sra; + logic decode_alu_src1; + logic decode_alu_src2; + + /* decode -> execute data */ + logic [31:0] decode_pc; + logic [31:0] decode_rs1_value; + logic [31:0] decode_rs2_value; + logic [31:0] decode_imm; + + rv32_execute execute ( + .clk(clk), + + /* control in */ + .alu_op_in(decode_alu_op), + .alu_sub_sra_in(decode_alu_sub_sra), + .alu_src1_in(decode_alu_src1), + .alu_src2_in(decode_alu_src2), + + /* data in */ + .pc_in(decode_pc), + .rs1_value_in(decode_rs1_value), + .rs2_value_in(decode_rs2_value), + .imm_in(decode_imm), + + /* data out */ + .result_out(execute_result) + ); + + /* execute -> mem data */ + logic [31:0] execute_result; endmodule diff --git a/rv32_alu.sv b/rv32_alu.sv new file mode 100644 index 0000000..fc7a99a --- /dev/null +++ b/rv32_alu.sv @@ -0,0 +1,67 @@ +localparam RV32_ALU_OP_ADD_SUB = 4'b0000; +localparam RV32_ALU_OP_XOR = 4'b0001; +localparam RV32_ALU_OP_OR = 4'b0010; +localparam RV32_ALU_OP_AND = 4'b0011; +localparam RV32_ALU_OP_SLL = 4'b0100; +localparam RV32_ALU_OP_SRL_SRA = 4'b0101; +localparam RV32_ALU_OP_SLT = 4'b0110; +localparam RV32_ALU_OP_SLTU = 4'b0111; +localparam RV32_ALU_OP_SRC2 = 4'b1000; + +localparam RV32_ALU_SRC1_REG = 1'b0; +localparam RV32_ALU_SRC1_PC = 1'b1; + +localparam RV32_ALU_SRC2_REG = 1'b0; +localparam RV32_ALU_SRC2_IMM = 1'b1; + +module rv32_alu ( + input clk, + + /* control in */ + input [3:0] op_in, + input sub_sra_in, + input src1_in, + input src2_in, + + /* data in */ + input [31:0] pc_in, + input [31:0] rs1_value_in, + input [31:0] rs2_value_in, + input [31:0] imm_in, + + /* data out */ + output [31:0] result_out +); + logic [31:0] src1 = src1_in ? rs1_value_in : pc_in; + logic [31:0] src2 = src2_in ? rs2_value_in : imm_in; + + logic src1_sign = src1[31]; + logic src2_sign = src2[31]; + + logic shamt = src2[4:0]; + + logic [32:0] add_sub = sub_sra_in ? src1 - src2 : src1 + src2; + logic [31:0] srl_sra = $signed({sub_sra_in ? src1_sign : 1'b0, src1}) >>> shamt; + + logic carry = add_sub[32]; + logic sign = add_sub[31]; + logic ovf = (!src1_sign && src2_sign && sign) || (src1_sign && !src2_sign && !sign); + + logic lt = sign != ovf; + logic ltu = carry; + + always @(posedge clk) begin + case (op_in) + RV32_ALU_OP_ADD_SUB: result_out <= add_sub[31:0]; + RV32_ALU_OP_XOR: result_out <= src1 ^ src2; + RV32_ALU_OP_OR: result_out <= src1 | src2; + RV32_ALU_OP_AND: result_out <= src1 & src2; + RV32_ALU_OP_SLL: result_out <= src1 << shamt; + RV32_ALU_OP_SRL_SRA: result_out <= srl_sra; + RV32_ALU_OP_SLT: result_out <= {31'b0, lt}; + RV32_ALU_OP_SLTU: result_out <= {31'b0, ltu}; + RV32_ALU_OP_SRC2: result_out <= src2; + default: result_out <= 32'bx; + endcase + end +endmodule diff --git a/rv32_decode.sv b/rv32_decode.sv index 02391a9..bf64c9e 100644 --- a/rv32_decode.sv +++ b/rv32_decode.sv @@ -10,6 +10,10 @@ module rv32_decode ( /* control out */ output valid, + output [3:0] alu_op_out, + output alu_sub_sra_out, + output alu_src1_out, + output alu_src2_out, /* data out */ output [31:0] pc_out, @@ -36,8 +40,12 @@ module rv32_decode ( rv32_regs regs ( .clk(clk), + + /* control in */ .rs1_in(rs1), .rs2_in(rs2), + + /* data out */ .rs1_value_out(rs1_value_out), .rs2_value_out(rs2_value_out) ); @@ -46,6 +54,10 @@ module rv32_decode ( pc_out <= pc_in; valid <= 0; + alu_op_out <= 4'bx; + alu_sub_sra_out <= 1'bx; + alu_src1_out <= 1'bx; + alu_src2_out <= 1'bx; imm_out <= 32'bx; casez ({opcode, funct3, funct7}) diff --git a/rv32_execute.sv b/rv32_execute.sv new file mode 100644 index 0000000..0d471e4 --- /dev/null +++ b/rv32_execute.sv @@ -0,0 +1,39 @@ +`include "rv32_alu.sv" + +module rv32_execute ( + input clk, + + /* control in */ + input [3:0] alu_op_in, + input alu_sub_sra_in, + input alu_src1_in, + input alu_src2_in, + + /* data in */ + input [31:0] pc_in, + input [31:0] rs1_value_in, + input [31:0] rs2_value_in, + input [31:0] imm_in, + + /* data out */ + output [31:0] result_out +); + rv32_alu alu ( + .clk(clk), + + /* control in */ + .op_in(alu_op_in), + .sub_sra_in(alu_sub_sra_in), + .src1_in(alu_src1_in), + .src2_in(alu_src2_in), + + /* data in */ + .pc_in(pc_in), + .rs1_value_in(rs1_value_in), + .rs2_value_in(rs2_value_in), + .imm_in(imm_in), + + /* data out */ + .result_out(result_out) + ); +endmodule