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