diff options
author | Joshua Yun <joshua@joshuayun.com> | 2025-05-17 11:04:47 -0500 |
---|---|---|
committer | Joshua Yun <joshua@joshuayun.com> | 2025-05-17 11:04:47 -0500 |
commit | e580017e209a0888c3f5a2063d265de50c66c56b (patch) | |
tree | 28ba8b4784fa33d539571e26f00b0017ca5ab173 | |
parent | 86021b3616c24efe38d8869b45d201bf24fe9a07 (diff) | |
download | riscv-processor-e580017e209a0888c3f5a2063d265de50c66c56b.tar.gz |
initial commit
-rw-r--r-- | core/pkg/riscv_types.sv | 57 | ||||
-rw-r--r-- | core/rtl/decode.sv | 135 | ||||
-rw-r--r-- | core/rtl/exe.sv | 179 | ||||
-rw-r--r-- | core/rtl/fetch.sv | 22 | ||||
-rw-r--r-- | core/rtl/idu.sv | 160 | ||||
-rw-r--r-- | core/rtl/ifu.sv | 30 | ||||
-rw-r--r-- | core/tb/core_tb.sv | 2 | ||||
-rw-r--r-- | primitives/rtl/DMUX.sv | 0 | ||||
-rw-r--r-- | primitives/rtl/FLIP.sv | 16 |
9 files changed, 426 insertions, 175 deletions
diff --git a/core/pkg/riscv_types.sv b/core/pkg/riscv_types.sv index 48ca87b..59c1f74 100644 --- a/core/pkg/riscv_types.sv +++ b/core/pkg/riscv_types.sv @@ -1,14 +1,21 @@ package riscv_types; + WORD_WIDTH = 32; + NUM_REG = 32; + REG_IDX = $clog2(NUM_REG); + + //----------------- + // Decode Types + //----------------- typedef enum logic [6:0] { - INSTR_TYPE_LUI = 7'b0110111, // U load upper immediate - INSTR_TYPE_AUIPC = 7'b0010111, // U add upper immediate PC - INSTR_TYPE_JAL = 7'b1101111, // J jump and link - INSTR_TYPE_JALR = 7'b1100111, // I jump and link register - INSTR_TYPE_BR = 7'b1100011, // B branch - INSTR_TYPE_LD = 7'b0000011, // I load - INSTR_TYPE_ST = 7'b0100011, // S store - INSTR_TYPE_IMM = 7'b0010011, // I arith ops with register/immediate operands - INSTR_TYPE_REG = 7'b0110011, // R arith ops with register operands + INSTR_TYPE_LUI = 7'b0110111, // U load upper immediate + INSTR_TYPE_AUIPC = 7'b0010111, // U add upper immediate PC + INSTR_TYPE_JAL = 7'b1101111, // J jump and link + INSTR_TYPE_JALR = 7'b1100111, // I jump and link register + INSTR_TYPE_BR = 7'b1100011, // B branch + INSTR_TYPE_LD = 7'b0000011, // I load + INSTR_TYPE_ST = 7'b0100011, // S store + INSTR_TYPE_IMM = 7'b0010011, // I arith ops with register/immediate operands + INSTR_TYPE_REG = 7'b0110011, // R arith ops with register operands INSTR_TYPE_CSR = 7'b1110011 // I control and status register } opcode_t; @@ -18,21 +25,37 @@ package riscv_types; MEM_OP_NONE } mem_op_t; - typedef enum logic [1:0] { - REG_IMM_OFFSET, - PC_IMM_OFFSET, - OFFSET_NONE - } brjmp_op_t; + typedef enum logic [2:0] { + BEQ = 0, + BNE = 1, + BLT = 2, + BGE = 3, + BLTU = 4, + BGEU = 5 + } br_op_t; + + //------------ + // ALU Control + //------------ typedef enum logic [1:0] { RS1, PC, - OP_NONE - } aluSelOp1_t; + ZERO + } alu_sel_op_1_t; typedef enum logic { RS2, IMM - } aluSelOp2_t; + } alu_sel_op_2_t; + + typedef struct packed { + logic func7; + logic [2:0] func3; + logic [WORD_WIDTH-1:0] immediate; + + alu_sel_op_1_t rs1Sel; + alu_sel_op_2_t rs2Sel; + } alu_op_t; endpackage diff --git a/core/rtl/decode.sv b/core/rtl/decode.sv deleted file mode 100644 index 8642013..0000000 --- a/core/rtl/decode.sv +++ /dev/null @@ -1,135 +0,0 @@ -module decode -import riscv_types::*; -#( - ) - ( - input logic clk, - input logic rst_l, - - // I-MEM Interface - input logic [31:0] imem_id_instr_ID, - - // Fetch Interface - input logic [31:0] imem_id_pc_ID - - // Dispatch Interface - ); - -// OpCode -opcode_t instrOpCode_ID; - -// Instruction Type -logic instrTypeR_ID; -logic instrTypeI_ID; -logic instrTypeS_ID; -logic instrTypeB_ID; -logic instrTypeU_ID; -logic instrTypeJ_ID; - - // Immediate -logic [31:0] instrImm_ID; -logic instrImmSign_ID; - -// Register Indices -logic [4:0] instrRs1Idx_ID; -logic instrRs1Vld_ID; -logic [4:0] instrRs2Idx_ID; -logic instrRs2Vld_ID; -logic [4:0] instrRdIdx_ID; -logic instrRdVld_ID; - -// Funct3 and Funct7 -logic [2:0] instrFunct3_ID; -logic instrFunct7_ID; - -// Control Bits - -// Memory Op -mem_op_t instrMemOp_ID; - -// Branch OP -brjmp_op_t instrBrJmpOp_ID; - -// ALU Operand Selection -aluSelOp1_t instrAluOp1_ID; -aluSelOp2_t instrAluOp2_ID; - -// DEBUG: Display decode instr -always_ff @(clk) begin : f_print_decode - $display("OpCode: %s", instrOpCode_ID.name()); - $display("Immediate: %0d", instrImm_ID); - $display("Memory: %s", instrMemOp_ID.name()); - $display("Branch: %s", instrBrJmpOp_ID.name()); - $display("ALU Sel 1: %s", instrAluOp1_ID.name()); - $display("ALU Sel 2: %s", instrAluOp2_ID.name()); - $display("Funct3: %0x", instrFunct3_ID); - $display("Funct7: %0x", instrFunct7_ID); -end - -// Instruction Type Decode -// FIXME: Add support for FENCE + ECALL + EBREAK + CSRs -assign instrTypeI_ID = (instrOpCode_ID == INSTR_TYPE_IMM) - | (instrOpCode_ID == INSTR_TYPE_JALR) - | (instrOpCode_ID == INSTR_TYPE_LD); -assign instrTypeU_ID = (instrOpCode_ID == INSTR_TYPE_LUI) - | (instrOpCode_ID == INSTR_TYPE_AUIPC); -assign instrTypeR_ID = (instrOpCode_ID == INSTR_TYPE_REG); -assign instrTypeS_ID = (instrOpCode_ID == INSTR_TYPE_ST); -assign instrTypeB_ID = (instrOpCode_ID == INSTR_TYPE_BR); -assign instrTypeJ_ID = (instrOpCode_ID == INSTR_TYPE_JAL); - -// Register Index Decode -assign instrRs1Idx_ID = imem_id_instr_ID[19:15]; -assign instrRs1Vld_ID = instrTypeR_ID | instrTypeI_ID | instrTypeS_ID | instrTypeB_ID; - -assign instrRs2Idx_ID = imem_id_instr_ID[24:20]; -assign instrRs2Vld_ID = instrTypeR_ID | instrTypeS_ID | instrTypeB_ID; - -assign instrRdIdx_ID = imem_id_instr_ID[11:7]; -assign instrRdVld_ID = instrTypeR_ID | instrTypeI_ID | instrTypeU_ID | instrTypeJ_ID; - -// Func Bit decode -assign instrFunct7_ID = imem_id_instr_ID[30]; -assign instrFunct3_ID = imem_id_instr_ID[14:12]; - -// Instruction Type (OpCode) Decode -assign instrImmSign_ID = imem_id_instr_ID[31]; -assign instrOpCode_ID = opcode_t'(imem_id_instr_ID[6:0]); - -// Immediate Decode -assign instrImm_ID[0] = instrTypeJ_ID ? imem_id_instr_ID[25] : // Bit 25 for I-Type - instrTypeS_ID ? imem_id_instr_ID[7] : // Bit 7 for S-Type - '0; // All other instructions set to 0 - -assign instrImm_ID[4:1] = instrTypeI_ID ? imem_id_instr_ID[24:21] : // I-Type bits - (instrTypeS_ID | instrTypeB_ID) ? imem_id_instr_ID[11:8] : // S-Type + B-Type bits - '0; // All other instructions set to 0 - -assign instrImm_ID[10:5] = instrTypeU_ID ? '0 : imem_id_instr_ID[30:25]; // Only J type is an immediate instruction that doesn't have it in 30:25 - - -assign instrImm_ID[11] = (instrTypeI_ID | instrTypeS_ID) ? imem_id_instr_ID[31] : - (instrTypeB_ID) ? imem_id_instr_ID[7] : - (instrTypeJ_ID) ? imem_id_instr_ID[20] : - '0; - -assign instrImm_ID[19:12] = (instrTypeU_ID | instrTypeJ_ID) ? imem_id_instr_ID[19:12] : { 8{instrImmSign_ID}}; // Only J and U types use 19:12 as not sign bit -assign instrImm_ID[31:20] = (instrTypeU_ID) ? imem_id_instr_ID[31:20] : {12{instrImmSign_ID}}; // Only U type use 31:20 as not sign bit - -// Control Bits -assign instrMemOp_ID = (instrOpCode_ID == INSTR_TYPE_ST) ? MEM_OP_STORE : - (instrOpCode_ID == INSTR_TYPE_LD) ? MEM_OP_LOAD : - MEM_OP_NONE; - -assign instrBrJmpOp_ID = (instrOpCode_ID == INSTR_TYPE_JALR) ? REG_IMM_OFFSET : - (instrOpCode_ID == INSTR_TYPE_BR | instrOpCode_ID == INSTR_TYPE_JAL) ? PC_IMM_OFFSET : - OFFSET_NONE; - -assign instrAluOp1_ID = (instrOpCode_ID == INSTR_TYPE_AUIPC) | (instrOpCode_ID == INSTR_TYPE_JAL) ? PC : // Loading PC for AUIPC, PC Offset for JAL - (instrOpCode_ID == INSTR_TYPE_LUI) ? OP_NONE : // Only loading immediate for LUI - RS1; // All else use RS1 value - -assign instrAluOp2_ID = (instrOpCode_ID == INSTR_TYPE_REG) ? RS2 : IMM; // Only R2R needs non-immediate op in ALU - - -endmodule 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 diff --git a/core/rtl/fetch.sv b/core/rtl/fetch.sv deleted file mode 100644 index d2b5ed0..0000000 --- a/core/rtl/fetch.sv +++ /dev/null @@ -1,22 +0,0 @@ -module fetch -import riscv_types::*; -( - input logic clk, - input logic rst_l, - - // IMEM interface - output logic [31:0] if_imem_addr_IF -); - -logic [31:0] pc_IF; -logic [31:0] pcNxt_IF; - -assign if_imem_addr_IF = pc_IF; // Always fetch PC from IMEM, addresses are always 32 bit aligned - // TODO: Find out if 32 is the best fetching width vs 16 - -// Program Counter (PC) -assign pcNxt_IF = pc_IF + 32'd4; - -AFFR #(.WIDTH(32)) ff_IF_pc ( .clk(clk), .rst_l(rst_l), .en(1'b1), .q(pc_IF), .d(pcNxt_IF) ); - -endmodule diff --git a/core/rtl/idu.sv b/core/rtl/idu.sv new file mode 100644 index 0000000..0bfd073 --- /dev/null +++ b/core/rtl/idu.sv @@ -0,0 +1,160 @@ +module idu +import riscv_types::*; +#( + ) + ( + input logic clk, + input logic rst_l, + + // I-MEM Interface + input logic [INSTR_SIZE-1:0] imem_id_instr_ID, + + // Fetch Interface + input logic [PC_SIZE-1:0] imem_id_pc_ID, + + //------------------ + // Execute Interface + //------------------ + input logic exe_idu_exeRdy_EXE, + + // Alu information + output alu_op_t idu_exe_aluOp_ID, + + // Register Idx + output logic idu_exe_rs1Vld_EXE, + output logic [REG_IDX-1:0] idu_exe_rs1Idx_EXE, + + output logic idu_exe_rs2Vld_EXE, + output logic [REG_IDX-1:0] idu_exe_rs2Idx_EXE + ); + +// OpCode +opcode_t instrOpCode_ID; + +// Instruction Type +logic instrTypeR_ID; +logic instrTypeI_ID; +logic instrTypeS_ID; +logic instrTypeB_ID; +logic instrTypeU_ID; +logic instrTypeJ_ID; + + // Immediate +logic [WORD_WID-1:0] instrImm_ID; +logic instrImmSign_ID; + +// Register Indices +logic [REG_IDX-1:0] instrRs1Idx_ID; +logic instrRs1Vld_ID; +logic [REG_IDX-1:0] instrRs2Idx_ID; +logic instrRs2Vld_ID; +logic [REG_IDX-1:0] instrRdIdx_ID; +logic instrRdVld_ID; + +// Funct3 and Funct7 +logic [2:0] instrFunct3_ID; +logic instrFunct7_ID; + +// Control Bits + +// Memory Op +mem_op_t instrMemOp_ID; + +// Branch OP +brjmp_op_t instrBrJmpOp_ID; + +// ALU Operand Selection +aluSelOp1_t instrAluIn1_ID; +aluSelOp2_t instrAluIn2_ID; + +// Reg File +logic [NUM_REG-1:0] [WORD_WID-1:0] regData_XXX; + +//------------------------ +// Instruction Type Decode +//------------------------ + +// FIXME: Add support for FENCE + ECALL + EBREAK + CSRs +assign instrTypeI_ID = (instrOpCode_ID == INSTR_TYPE_IMM) + | (instrOpCode_ID == INSTR_TYPE_JALR) + | (instrOpCode_ID == INSTR_TYPE_LD); +assign instrTypeU_ID = (instrOpCode_ID == INSTR_TYPE_LUI) + | (instrOpCode_ID == INSTR_TYPE_AUIPC); +assign instrTypeR_ID = (instrOpCode_ID == INSTR_TYPE_REG); +assign instrTypeS_ID = (instrOpCode_ID == INSTR_TYPE_ST); +assign instrTypeB_ID = (instrOpCode_ID == INSTR_TYPE_BR); +assign instrTypeJ_ID = (instrOpCode_ID == INSTR_TYPE_JAL); + +// Register Index Decode +assign instrRs1Idx_ID = imem_id_instr_ID[19:15]; +assign instrRs1Vld_ID = instrTypeR_ID | instrTypeI_ID | instrTypeS_ID | instrTypeB_ID; + +assign instrRs2Idx_ID = imem_id_instr_ID[24:20]; +assign instrRs2Vld_ID = instrTypeR_ID | instrTypeS_ID | instrTypeB_ID; + +assign instrRdIdx_ID = imem_id_instr_ID[11:7]; +assign instrRdVld_ID = instrTypeR_ID | instrTypeI_ID | instrTypeU_ID | instrTypeJ_ID; + +// Func Bit decode +assign instrFunct7_ID = imem_id_instr_ID[30]; +assign instrFunct3_ID = imem_id_instr_ID[14:12]; + +// Instruction Type (OpCode) Decode +assign instrImmSign_ID = imem_id_instr_ID[31]; +assign instrOpCode_ID = opcode_t'(imem_id_instr_ID[6:0]); + +//---------------- +// ALU Information +//---------------- + +// Immediate Decode +assign idu_exe_aluOp_ID.imm[0] = instrTypeJ_ID ? imem_id_instr_ID[25] : // Bit 25 for I-Type + instrTypeS_ID ? imem_id_instr_ID[7] : // Bit 7 for S-Type + 1'b0; // All other instructions set to 0 + +assign idu_exe_aluOp_ID.imm[4:1] = ({3{instrTypeI_ID | instrTypeJ_ID}} & imem_id_instr_ID[24:21]) // I-Type + J-Type bits + | ({3{instrTypeS_ID | instrTypeB_ID}} & imem_id_instr_ID[11:8]); // S-Type + B-Type bits + +assign idu_exe_aluOp_ID.imm[10:5] = {6{~instrTypeU_ID}} & imem_id_instr_ID[30:25]; // U type is the only instr that doesn't have 10:5 + + +assign idu_exe_aluOp_ID.imm[11] = ((instrTypeI_ID | instrTypeS_ID) & imem_id_instr_ID[31]) // I-Type + S-Type bit + | ( instrTypeB_ID & imem_id_instr_ID[7]) // B-Type bit + | ( instrTypeJ_ID & imem_id_instr_ID[20]); // J-Type bit + +assign idu_exe_aluOp_ID.imm[19:12] = (instrTypeU_ID | instrTypeJ_ID) ? imem_id_instr_ID[19:12] : { 8{instrImmSign_ID}}; // Only J and U types use 19:12 as not sign bit +assign idu_exe_aluOp_ID.imm[31:20] = (instrTypeU_ID) ? imem_id_instr_ID[31:20] : {12{instrImmSign_ID}}; // Only U type use 31:20 as not sign bit + +assign idu_exe_aluOp_ID.rs1Sel = (instrOpCode_ID == INSTR_TYPE_AUIPC) | (instrOpCode_ID == INSTR_TYPE_JAL) ? PC : // Loading PC for AUIPC, PC Offset for JAL + (instrOpCode_ID == INSTR_TYPE_LUI) ? ZERO : // Only loading immediate for LUI + RS1; // All else use RS1 value + +assign idu_exe_aluOp_ID.rs2Sel = (instrOpCode_ID == INSTR_TYPE_REG) ? RS2 : IMM; // Only R Type needs non-immediate op in ALU + +assign idu_exe_aluOp_ID.func3 = imem_id_instr_ID[14:12]; +assign idu_exe_aluOp_ID.func7 = imem_id_instr_ID[30]; + +//--------------- +// Branch Control +//--------------- +assign idu_exe_instrJmp_ID = (instrOpCode_ID == INSTR_TYPE_JALR) | (instrOpCode_ID == INSTR_TYPE_JAL); +assign idu_exe_brAluOp_ID = (idu_exe_aluOp_ID.func3 == 3'b0) ? BR_ALU_XOR : BR_ALU_CMP; // Only equality needs XOR all other OPs use compare +assign idu_exe_brCmpSign_ID = (idu_exe_aluOp_ID.func3[2:1] == 2'b11); // Unsigned comparisons have func3 top two bits set +assign idu_exe_brCmpGreater_ID = (idu_exe_aluOp_ID.func3[2:1] == 2'b11); // Unsigned comparisons have func3 top two bits set + +//--------------- +// Memory Control +//--------------- +assign instrMemOp_ID = (instrOpCode_ID == INSTR_TYPE_ST) ? MEM_OP_STORE : + (instrOpCode_ID == INSTR_TYPE_LD) ? MEM_OP_LOAD : + MEM_OP_NONE; + +//------------------ +// Writeback Control +//------------------ + + +assign instrAluOp_ID = ; + + +endmodule diff --git a/core/rtl/ifu.sv b/core/rtl/ifu.sv new file mode 100644 index 0000000..0eb3b1d --- /dev/null +++ b/core/rtl/ifu.sv @@ -0,0 +1,30 @@ +module ifu + import riscv_types::*; +( + input logic clk, + input logic rst_l, + + // IMEM interface + output logic [31:0] if_imem_addr_IF +); + + logic [31:0] pc_IF; + logic [31:0] pcNxt_IF; + + assign if_imem_addr_IF = pc_IF; // Always fetch PC from IMEM, addresses are always 32 bit aligned + // TODO: Find out if 32 is the best fetching width vs 16 + + // Program Counter (PC) + assign pcNxt_IF = pc_IF + 32'd4; + + AFFR #( + .WIDTH(32) + ) ff_IF_pc ( + .q(pc_IF), + .d(pcNxt_IF), + .en(1'b1), + .clk(clk), + .rst_l(rst_l) + ); + +endmodule diff --git a/core/tb/core_tb.sv b/core/tb/core_tb.sv index 3252a13..5824ed8 100644 --- a/core/tb/core_tb.sv +++ b/core/tb/core_tb.sv @@ -22,7 +22,7 @@ initial begin $dumpfile("dump.fst"); $dumpvars; - // Reset Set up + // Reset Set up rst_l = 1'b0; repeat (5) @(posedge clk); rst_l = 1'b1; diff --git a/primitives/rtl/DMUX.sv b/primitives/rtl/DMUX.sv new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/primitives/rtl/DMUX.sv diff --git a/primitives/rtl/FLIP.sv b/primitives/rtl/FLIP.sv new file mode 100644 index 0000000..baf3c2b --- /dev/null +++ b/primitives/rtl/FLIP.sv @@ -0,0 +1,16 @@ +module FLIP +#( + parameter WIDTH = 1 +) +( + input [WIDTH-1:0] in, + output [WIDTH-1:0] out +); + +genvar flip_idx; + +for (flip_idx = 0, flip_idx < WIDTH; flip_idx++) begin + assign out[flip_idx] = in[WIDTH-flip_idx-1]; +end + +endmodule |