module idu import riscv_types::*; #( ) ( input logic clk, input logic rst_l, // I-MEM Interface input logic imem_idu_vld_ID, input logic [INSTR_SIZE-1:0] imem_idu_data_ID, //---------------- // Fetch Interface //---------------- input logic [PC_SIZE-1:0] ifu_idu_pc_ID, input logic ifu_idu_instrVld_ID //------------------ // Execute Interface //------------------ output logic idu_exe_instrVld_EXE, // 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, // Branch Type output logic idu_exe_instrJmp_ID, output logic idu_exe_instrBr_ID, // Alu information output alu_op_t idu_exe_aluOp_ID, // Passthrough information output mem_op_t idu_exe_instrMemOp_ID, output mem_size_t idu_exe_instrMemSize_ID, output rd_data_sel_t idu_exe_instrRdDataSel_ID ); // OpCode opcode_t instrOpCode_ID; // Instruction Op logic instrAuipc_ID; logic instrJal_ID; logic instrJal_ID; logic instrLui_ID; logic instrReg_ID; logic instrImm_ID; logic instrLd_ID; logic instrSt_ID; logic instrBr_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; // Branch OP brjmp_op_t instrBrJmpOp_ID; // ALU Operand Selection aluSelOp1_t instrAluIn1_ID; aluSelOp2_t instrAluIn2_ID; //------------------- // Instruction Decode //------------------- assign instr_ID = imem_idu_data_ID; // Instruction Type (OpCode) Decode assign instrOpCode_ID = opcode_t'(instr_ID[6:0]); assign instrAuipc_ID = (instrOpCode_ID == INSTR_TYPE_AUIPC); assign instrJal_ID = (instrOpCode_ID == INSTR_TYPE_JAL); assign instrJal_ID = (instrOpCode_ID == INSTR_TYPE_JALR); assign instrLui_ID = (instrOpCode_ID == INSTR_TYPE_LUI); assign instrReg_ID = (instrOpCode_ID == INSTR_TYPE_REG); assign instrImm_ID = (instrOpCode_ID == INSTR_TYPE_IMM); assign instrLd_ID = (instrOpCode_ID == INSTR_TYPE_LD); assign instrSt_ID = (instrOpCode_ID == INSTR_TYPE_ST); assign instrBr_ID = (instrOpCode_ID == INSTR_TYPE_BR); // FIXME: Add support for FENCE + ECALL + EBREAK + CSRs assign instrTypeI_ID = instrImm_ID | instrJal_IDR | instrLd_ID; assign instrTypeU_ID = instrLui_ID | instrLui_PC; assign instrTypeR_ID = instrReg_ID; assign instrTypeS_ID = instrSt_ID; assign instrTypeB_ID = instrBr_ID; assign instrTypeJ_ID = instrJal_ID; // Register Index Decode assign instrRs1Idx_ID = instr_ID[19:15]; assign instrRs1Vld_ID = instrTypeR_ID | instrTypeI_ID | instrTypeS_ID | instrTypeB_ID; assign instrRs2Idx_ID = instr_ID[24:20]; assign instrRs2Vld_ID = instrTypeR_ID | instrTypeS_ID | instrTypeB_ID; assign instrRdIdx_ID = instr_ID[11:7]; assign instrRdVld_ID = instrTypeR_ID | instrTypeI_ID | instrTypeU_ID | instrTypeJ_ID; // Func Bit decode assign instrFunct7_ID = instr_ID[30]; assign instrFunct3_ID = instr_ID[14:12]; //---------------- // ALU Information //---------------- // Immediate Decode assign instrImmSign_ID = instr_ID[31]; assign idu_exe_aluOp_ID.imm[0] = instrTypeI_ID ? instr_ID[20] : // Bit 20 for I-Type instrTypeS_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}} & instr_ID[24:21]) // I-Type + J-Type bits | ({3{instrTypeS_ID | instrTypeB_ID}} & instr_ID[11:8]); // S-Type + B-Type bits assign idu_exe_aluOp_ID.imm[10:5] = {6{~instrTypeU_ID}} & instr_ID[30:25]; // U type doesn't use 10:5 assign idu_exe_aluOp_ID.imm[11] = ((instrTypeI_ID | instrTypeS_ID) & instr_ID[31]) // I-Type + S-Type bit | ( instrTypeB_ID & instr_ID[7]) // B-Type bit | ( instrTypeJ_ID & instr_ID[20]); // J-Type bit assign idu_exe_aluOp_ID.imm[19:12] = (instrTypeU_ID | instrTypeJ_ID) ? instr_ID[19:12] : // J and U types use 19:12 {8{instrImmSign_ID}}; // Else use SEXT Bit assign idu_exe_aluOp_ID.imm[31:20] = (instrTypeU_ID) ? instr_ID[31:20] : // U type uses 31:20 {12{instrImmSign_ID}}; // Else use SEXT bit // ALU Operand Selection // FIXME: Make Non Priority Mux assign idu_exe_aluOp_ID.rs1Sel = (instrAuipc) | (instrJal) ? PC : // Loading PC for AUIPC, PC Offset for JAL (instrLui) ? ZERO : // Only loading immediate for LUI RS1; // All else use RS1 value assign idu_exe_aluOp_ID.rs2Sel = (instrReg) ? RS2 : // RS2 Used in R2R Instr IMM; // Immediate used for all other instructions // Alu Control Signals assign idu_exe_aluOp_ID.func3 = instr_ID[14:12]; assign idu_exe_aluOp_ID.func7 = instr_ID[30]; // Supply PC for Jmp and AUIPC assign idu_exe_pc_ID = ifu_idu_pc_ID; //--------------- // Branch Control //--------------- assign idu_exe_instrJmp_ID = instrJal_ID | instrJalr_ID; assign idu_exe_instrBr_ID = instrBr_ID; //--------------- // Memory Control //--------------- assign idu_exe_instrMemOp_ID = (instrSt_ID) ? MEM_OP_STORE : (instrID_ID) ? MEM_OP_LOAD : MEM_OP_NONE; //------------------ // Writeback Control //------------------ assign idu_exe_instrRdDataSel_ID = (instrJal_ID | instrJalr_ID) ? PC : // Jump loads PC into RD (instrLd_ID | instrSt_ID) ? MEM : // Mem loads memory into RD ALU // All Other OPs load AlU result endmodule