aboutsummaryrefslogtreecommitdiff
path: root/core/rtl
diff options
context:
space:
mode:
Diffstat (limited to 'core/rtl')
-rw-r--r--core/rtl/decode.sv135
1 files changed, 118 insertions, 17 deletions
diff --git a/core/rtl/decode.sv b/core/rtl/decode.sv
index e337e11..8642013 100644
--- a/core/rtl/decode.sv
+++ b/core/rtl/decode.sv
@@ -7,28 +7,129 @@ import riscv_types::*;
input logic rst_l,
// I-MEM Interface
- input logic [31:0] imem_id_instr_ID
+ 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;
-assign instrOpCode_ID = opcode_t'(imem_id_instr_ID[6:0]);
+// 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
-always_ff @(posedge clk) begin
- $display("Instruction: %x", imem_id_instr_ID);
- case (instrOpCode_ID)
- INSTR_TYPE_LUI: begin $display("Instr type: LUI"); end
- INSTR_TYPE_AUIPC: begin $display("Instr type: AUIPC"); end
- INSTR_TYPE_JAL: begin $display("Instr type: JAL"); end
- INSTR_TYPE_JALR: begin $display("Instr type: JALR"); end
- INSTR_TYPE_BR: begin $display("Instr type: BR"); end
- INSTR_TYPE_LD: begin $display("Instr type: LD"); end
- INSTR_TYPE_ST: begin $display("Instr type: ST"); end
- INSTR_TYPE_IMM: begin $display("Instr type: IMM"); end
- INSTR_TYPE_REG: begin $display("Instr type: REG"); end
- INSTR_TYPE_CSR: begin $display("Instr type: CSR"); end
- default: begin $display("Instr type: Unknown"); end
- endcase
+// 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