aboutsummaryrefslogtreecommitdiff
path: root/core/rtl/exe.sv
diff options
context:
space:
mode:
authorJoshua Yun <joshua@joshuayun.com>2025-05-17 11:04:47 -0500
committerJoshua Yun <joshua@joshuayun.com>2025-05-17 11:04:47 -0500
commite580017e209a0888c3f5a2063d265de50c66c56b (patch)
tree28ba8b4784fa33d539571e26f00b0017ca5ab173 /core/rtl/exe.sv
parent86021b3616c24efe38d8869b45d201bf24fe9a07 (diff)
downloadriscv-processor-e580017e209a0888c3f5a2063d265de50c66c56b.tar.gz
initial commit
Diffstat (limited to 'core/rtl/exe.sv')
-rw-r--r--core/rtl/exe.sv179
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