diff options
Diffstat (limited to 'core/rtl/exe.sv')
-rw-r--r-- | core/rtl/exe.sv | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/core/rtl/exe.sv b/core/rtl/exe.sv new file mode 100644 index 0000000..4615638 --- /dev/null +++ b/core/rtl/exe.sv @@ -0,0 +1,179 @@ +module exe ( + input logic clk, + input logic rst, + + //----------------- + // Decode Interface + //----------------- + input logic idu_exe_rs1Vld_EXE, + input logic [REG_IDX-1:0] idu_exe_rs1Idx_EXE, + + input logic idu_exe_rs2Vld_EXE, + input logic [REG_IDX-1:0] idu_exe_rs2Idx_EXE, + + input alu_op_t idu_exe_aluOp_EXE, + + //----------------- + // Memory Interface + //----------------- + output logic [WORD_WID-1:0] exe_mem_aluOpOut_EXE, + + //----------------------- + // Fetch Branch Interface + //----------------------- + output logic exe_ifu_brRes_EXE, + output logic exe_ifu_brTaken_EXE, + output logic [WORD_WID-1:0] exe_ifu_brPC_EXE, + + //-------------------- + // Writeback Interface + //-------------------- + input logic wb_exe_rdVld_WB, + input logic [ REG_IDX-1:0] wb_exe_rdIdx_WB, + input logic [WORD_WID-1:0] wb_exe_rdData_WB + +); + + // Alu + logic [WORD_WID-1:0] aluSumDiff_EXE; + logic [WORD_WID-1:0] aluSumDiffIn1_EXE; + logic [WORD_WID-1:0] aluSumDiffIn2_EXE; + + logic [WORD_WID-1:0] aluLeftShft_EXE; + logic [WORD_WID-1:0] aluRightShft_EXE; + logic [WORD_WID-1:0] aluRightShftUsign_EXE; + logic [WORD_WID-1:0] aluRightShftSext_EXE; + + logic [WORD_WID-1:0] aluCmp_EXE; + logic [WORD_WID-1:0] aluCmpSign_EXE; + logic [WORD_WID-1:0] aluCmpUsign_EXE; + logic aluCmpMsbDiff_EXE; + logic aluCmpLowUsign_EXE; + + // Branch Resolution + logic [ 5:0] brResChoice_EXE; + + //-------------------- + // Decode Output Flops + //-------------------- + assign stallVld_ID = ~exe_idu_exeRdy_EXE; + + // Flop Decode information + AFF #( .DTYPE(alu_op_t) ) AFF_EXE_aluOp ( .q(idu_exe_aluOp_EXE), .d(idu_exe_aluOp_ID), .en(stallVld_ID), .clk(clk) ); + AFF #( .WIDTH(WORD_WID) ) AFF_EXE_pc ( .q(idu_exe_pc_EXE), .d(idu_exe_pc_ID), .en(stallVld_ID), .clk(clk) ); + AFF #( .WIDTH(1) ) AFF_EXE_instrJmp ( .q(idu_exe_instrJmp_EXE), .d(idu_exe_instrJmp_ID), .en(stallVld_ID), .clk(clk) ); + AFF #( .WIDTH(1) ) AFF_EXE_brRes ( .q(idu_exe_brRes_EXE), .d(brResNxt_EXEM1), .en(stallVld_ID), .clk(clk) ); + + //-------------- + // Register File + //-------------- + // FIXME: Add support for the zero register + always_ff @(posedge clk) begin + + // RS1 Read Port with Forwarding + if (instrRs1Vld_ID) begin + idu_exe_rs1Data_EXE <= (wb_exe_rdVld_WB & (idu_exe_rs1Idx_ID == wb_exe_rdIdx_WB)) ? wb_exe_rdData_WB : regData_XXX[idu_exe_rs1Idx_ID]; + end + + // RS2 Read Port with Forwarding + if (instrRdVld_ID) begin + idu_exe_rs2Data_EXE <= (wb_exe_rdVld_WB & (idu_exe_rs1Idx_ID == wb_exe_rdIdx_WB)) ? wb_exe_rdData_WB : regData_XXX[idu_exe_rs2Idx_ID]; + end + + // RD Write Port + if (wb_exe_rdData_WB) begin + regData_XXX[wb_exe_rdIdx_WB] <= wb_exe_rdData_WB; + end + + end + + //---- + // ALU + //---- + + // Operand Selection + assign aluIn1_EXE = (aluOp_EXE.rs1Sel == PC) ? pc_EXE : // PC for AUIPC, JAL + (aluOp_EXE.rs1Sel == ZERO) ? WORD_WID'(0) : // 0 for LUI + rs1Data_EXE; // RS1 for other operations + + assign aluIn2_EXE = (aluOp_EXE.rs2Sel == RS2) ? rs2Data_EXE : // RS2 for R type operations + aluOp_EXE.immediate; // Immediate for all other operations + + // Two's complement negation of aluIn2 if func7 is set (subtract) + assign aluSumDiffIn1_EXE = aluIn1_EXE; + assign aluSumDiffIn2_EXE = ({WORD_WID{aluOp_EXE.func7}} ^ aluIn2_EXE) + aluOp_EXE.func7; + assign aluSumDiff_EXE = aluSumDiffIn1_EXE + aluSumDiffIn2_EXE; + + // Shifter, TODO: Explicit signed barrel shifter + assign aluRightShftUsign_EXE = aluIn1_EXE >> aluIn2_EXE[4:0]; + assign aluRightShftSext_EXE = ~({WORD_WID{1'b1}} >> aluIn2_EXE[4:0]); + assign aluRightShft_EXE = aluRightShftUsgn_EXE | (aluRightShftSext_EXE & {WORD_WID{aluOp_EXE.func7}}); + + FLIP #( + .WIDTH(WORD_WID) + ) EXE_aluLeftShft ( + .in (aluRightShftUsign_EXE), + .out(aluLeftShft_EXE) + ); + + // Set Less Than + assign aluCmpMsbDiff_EXE = aluIn2_EXE ^ aluIn1_EXE; + assign aluCmpLowUsign_EXE = aluIn1_EXE[WORD_WID-2:0] < aluIn2_EXE[WORD_WID-2:0]; + assign aluCmpSign_EXE = aluCmpMsbDiff_EXE ? aluIn1_EXE[WORD_WID-1] : aluCmpLowUsign_EXE; // If diff signs (MSB) and in1 negative, then in1 < 0 < in2, else compare low bits + assign aluCmpUSign_EXE = aluCmpMsbDiff_EXE ? aluIn2_EXE[WORD_WID-1] : aluCmpLowUsign_EXE; // If diff MSB and MSB in2[31] == 1, then in1 < in2, else compare low bits + + // Bitwise Operations + assign aluXor_EXE = aluIn1_EXE ^ aluIn2_EXE; + assign aluOr_EXE = aluIn1_EXE | aluIn2_EXE; + assign aluAnd_EXE = aluIn1_EXE & aluIn2_EXE; + + // ALU Operation Select + assign aluOpRes_EXE[0] = aluSumDiff_EXE; + assign aluOpRes_EXE[1] = aluLeftShft_EXE; + assign aluOpRes_EXE[2] = {(WORD_WID - 1)'(0), aluCmpSign_EXE}; + assign aluOpRes_EXE[3] = {(WORD_WID - 1)'(0), aluCmpUSign_EXE}; + assign aluOpRes_EXE[4] = aluXor_EXE; + assign aluOpRes_EXE[5] = aluRightShft_EXE; + assign aluOpRes_EXE[6] = aluOr_EXE; + assign aluOpRes_EXE[7] = aluAnd_EXE; + + EMUX #( + .WIDTH (WORD_WID), + .INPUTS(8) + ) EMUX_exe_aluOpSel ( + .in (aluOpResults_EXE), + .out(aluOpOut_EXE), + .sel(aluOp_EXE.func3) + ); + + // rd is either PC from jump instr or alu output + assign exe_mem_rdData_EXE = instrJmp_EXE ? pc_EXE : aluOpOut_EXE; + + //------------------ + // Branch Resolution + //------------------ + assign exe_ifu_brPC_EXE = aluOpOut_EXE; + assign exe_ifu_brRes_EXE = brRes_EXE; // FIXME: Only send this once after a branch is processed until stall is lifted + + assign brResChoice_EXE[0] = ~|aluXor_EXE; + assign brResChoice_EXE[1] = |aluXor_EXE; + assign brResChoice_EXE[2] = aluCmpSign_EXE; + assign brResChoice_EXE[3] = ~aluCmpSign_EXE; + assign brResChoice_EXE[4] = aluCmpUSign_EXE; + assign brResChoice_EXE[5] = ~aluCmpUSign_EXE; + + EMUX #( + .WIDTH (1), + .INPUTS(6) + ) EMUX_exe_aluOpSel ( + .in (brResChoice_EXE), + .out(exe_ifu_brTaken_EXE), + .sel(idu_exe_brOp_ID) + ); + + //--------------------- + // Pipeline passthrough + //--------------------- + + +endmodule |