diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-03-17 02:39:24 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-03-17 02:39:24 +0800 |
| commit | cd638dacbe7d0f890206209317cc119246cf700b (patch) | |
| tree | 8e16bd601d0ae163b795cb58a4b1c1b7b063c268 /rv64cpu/rtl | |
| parent | bb51da5bb8b5c8621661695bdf3c7bca42f2f49d (diff) | |
| download | rcc-project-cd638dacbe7d0f890206209317cc119246cf700b.tar.gz rcc-project-cd638dacbe7d0f890206209317cc119246cf700b.tar.xz | |
Execute Stage unit and tests
Diffstat (limited to 'rv64cpu/rtl')
| -rw-r--r-- | rv64cpu/rtl/core/ex_stage.sv | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/rv64cpu/rtl/core/ex_stage.sv b/rv64cpu/rtl/core/ex_stage.sv new file mode 100644 index 0000000..0991b50 --- /dev/null +++ b/rv64cpu/rtl/core/ex_stage.sv @@ -0,0 +1,114 @@ +// Richard CPU +// Copyright (C) 2026 Richard Qin + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +// File path: rtl/core/ex_stage.sv +// Description: Execute Stage +// Performs ALU operations, branch/jump calculations, and generates memory addresses. + +module ex_stage + import rv64_pkg::*; +( + // Input from ID/EX level pipeline register + input logic [XLEN-1:0] ex_pc, + input logic [XLEN-1:0] ex_rs1_rdata, + input logic [XLEN-1:0] ex_rs2_rdata, + input logic [XLEN-1:0] ex_imm, + + // Execution Control Signals + input alu_op_t ex_alu_op, + input logic ex_alu_src1_sel, // 0: rs1_rdata, 1: PC + input logic ex_alu_src2_sel, // 0: rs2_rdata, 1: imm + input logic ex_is_branch, + input branch_op_t ex_branch_op, + input logic ex_is_jump, + input logic ex_is_word_op, + + // Output to EX/MEM pipeline register & hazard unit + output logic [XLEN-1:0] ex_alu_result, + output logic ex_branch_taken, + output logic [XLEN-1:0] ex_branch_target +); + + logic [XLEN-1:0] alumux_a; + logic [XLEN-1:0] alumux_b; + logic [XLEN-1:0] alu_operand_a; + logic [XLEN-1:0] alu_operand_b; + logic [XLEN-1:0] alu_raw_result; + logic bu_branch_taken; + + // ------------- + // ALU Input Multiplexers (MUX) + assign alumux_a = (ex_alu_src1_sel == 1'b1) ? ex_pc : ex_rs1_rdata; + assign alumux_b = (ex_alu_src2_sel == 1'b1) ? ex_imm : ex_rs2_rdata; + + // ------------- + // RV64 Word Operation (32-bit) Pre-conditioning + // RV64 requires word operations (ADDW/SLLW/SRLW/SRAW) to operate on the + // lower 32 bits and sign-extend the result. + always_comb begin + if (ex_is_word_op) begin + // Shift operations require specific 32-bit extension forms + if (ex_alu_op == ALU_SRA) + alu_operand_a = { {32{alumux_a[31]}}, alumux_a[31:0] }; // Sign extend for arithmetic shift + else if (ex_alu_op == ALU_SRL) + alu_operand_a = { 32'b0, alumux_a[31:0] }; // Zero extend for logical shift + else + alu_operand_a = alumux_a; // ADDW/SUBW/SLLW don't care about upper bits + + // RV32 shift amount is strictly 5 bits (0-31), ignoring bit 5 which might be set in 64-bit registers + if (ex_alu_op == ALU_SLL || ex_alu_op == ALU_SRL || ex_alu_op == ALU_SRA) + alu_operand_b = { 59'b0, alumux_b[4:0] }; + else + alu_operand_b = alumux_b; + end else begin + // 64-bit operations pass through unchanged + alu_operand_a = alumux_a; + alu_operand_b = alumux_b; + end + end + + // -------------- + // Instantiate the core computing engine ALU + alu alu_inst ( + .alu_op (ex_alu_op), + .operand_a (alu_operand_a), + .operand_b (alu_operand_b), + .alu_result (alu_raw_result) + ); + + // ------------- + // Branch Unit + branch_unit bu_inst ( + .is_branch (ex_is_branch), + .branch_op (ex_branch_op), + .operand_a (ex_rs1_rdata), + .operand_b (ex_rs2_rdata), + .branch_taken (bu_branch_taken) + ); + + // ------------- + // 32-bit instruction result truncation and sign extension + assign ex_alu_result = ex_is_word_op ? + { {32{alu_raw_result[31]}}, alu_raw_result[31:0] } : + alu_raw_result; + + // ------------- + // Branch Target Calculation + assign ex_branch_target = alu_raw_result & ~64'b1; + + assign ex_branch_taken = ex_is_jump | (ex_is_branch & bu_branch_taken); + +endmodule |
