module exe ( input logic clk, input logic rst, //----------------- // Decode Interface //----------------- input logic idu_exe_instrVld_ID, // Register Access input logic idu_exe_rs1Vld_ID, input logic [REG_IDX-1:0] idu_exe_rs1Idx_ID, input logic idu_exe_rs2Vld_ID, input logic [REG_IDX-1:0] idu_exe_rs2Idx_ID, // Branch Type input logic idu_exe_instrJmp_ID, input logic idu_exe_instrBr_ID, // ALU information input alu_op_t idu_exe_aluOp_ID, // Passthrough Information input mem_op_t idu_exe_instrMemOp_ID, input mem_size_t idu_exe_instrMemSize_ID, input rd_data_sel_t idu_exe_instrRdDataSel_ID, //----------------- // Memory Interface //----------------- // ALU Result information output logic [WORD_WID-1:0] exe_mem_aluOpOut_EXE, // Stall input logic mem_exe_stallVld_EXE, // Memory Information output mem_op_t exe_mem_instrMemOp_EXE, output mem_size_t exe_mem_instrMemSize_EXE, // Passthrough information output rd_data_sel_t exe_mem_instrRdDataSel_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 ); logic instrVld_EXE; // 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; // Reg File logic [NUM_REG-1:1] [WORD_WID-1:0] regData_XXX; // Stall Signal assign stallVld_ID = exe_mem_instrVld_EXE & ~mem_exe_stallVld_EXE; //-------------------- // Decode Output Flops //-------------------- // Flop Decode information AFFR #(.WIDTH(1)) AFFR_EXE_instrVld (.q(exe_mem_instrVld_EXE), .d(idu_exe_instrVld_ID), .en(stallVld_ID), .clk(clk), rst(rst)); 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 //-------------- assign rs1WrFwd_ID = wb_exe_rdWrVld_WB & (idu_exe_rs1Idx_ID == wb_exe_rdIdx_WB); assign rs2WrFwd_ID = wb_exe_rdWrVld_WB & (idu_exe_rs2Idx_ID == wb_exe_rdIdx_WB); always_ff @(posedge clk) begin // RS1 Read Port with Forwarding if (instrRs1Vld_ID) begin if (idx_exe_rs1Idx == REG_IDX'0) // X0 Register idu_exe_rs1Data_EXE <= WORD_SIZE'0; else if (rs1WrFwd_ID) begin // Write Foward idu_exe_rs1Data_EXE <= wb_exe_rdData_WB; else // Normal Read idu_exe_rs1Data_EXE <= regData_XXX[idu_exe_rs1Idx_ID]; end // RS2 Read Port with Forwarding if (instrRs2Vld_ID) begin if (idx_exe_rs2Idx == REG_IDX'0) // X0 Register idu_exe_rs2Data_EXE <= WORD_WID'0; else if (rs2WrFwd_ID) begin // Write Foward idu_exe_rs2Data_EXE <= wb_exe_rdData_WB; else // Normal Read idu_exe_rs2Data_EXE <= regData_XXX[idu_exe_rs1Idx_ID]; end // RD Write Port if (wb_exe_rdWrVld_WB & (~|wb_exe_rdIdx_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 with sign bit 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; assign exe_ifu_brTaken_EXE = (brTaken_EXE & idu_exe_instrBr_ID) | idu_exe_instrJmp_ID; 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(brTaken_EXE), .sel(idu_exe_brOp_ID) ); //--------------------- // Pipeline passthrough //--------------------- // Memory AFF #(.DTYPE(mem_op_t)) AFF_EXE_instRdDataSel ( .q(exe_mem_instrMemOp_EXE), .d(idu_exe_instrMemOp_ID), .en(stallVld_ID), .clk(clk) ); AFF #(.DTYPE(mem_op_size_t)) AFF_EXE_instMemSize ( .q(exe_mem_instrMemSize_EXE), .d(idu_exe_instrMemSize_ID), .en(stallVld_ID), .clk(clk) ); // Write Back AFF #(.DTYPE(rd_data_sel_t)) AFF_EXE_instRdDataSel ( .q(exe_mem_instrRdDataSel_EXE), .d(idu_exe_instrRdDataSel_ID), .en(stallVld_ID), .clk(clk) ); endmodule