// ********************************************************************************************* // Project Version : v1.0 // Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog // ----- // Copyright (c) : 2025 Fraunhofer IIS, Department IDS // Created : 12.Jun.2025 by Lund University [commit 5b1e415] // Last Modified : 23.Oct.2025 by Hussein Elzomor [commit 2f8f03d] // ----- // HISTORY : Date By Comments // ----------- --------- ------------------------------------------------- // 15.Oct.2025 H.Elzomor Moved PC and ALU logic to their respective files // 15.Oct.2025 H.Elzomor Absorbed the branching logic into the decoder logic // ********************************************************************************************* module decoder ( // PC input logic[31:0] CurrentPC, output logic[31:0] JumpOrBranchPC, output logic JumpOrBranch, // Memory output logic[31:0] DAddr, output logic[31:0] WData, input logic[31:0] RData, input logic[31:0] Instruction, output logic WrMem, output logic[1:0] DWidth, // Register File output logic[4:0] Rs1, output logic[4:0] Rs2, output logic[4:0] Rd, input logic[31:0] RRs1, input logic[31:0] RRs2, output logic[31:0] WRd, output logic WrReg, // Protection output logic Illegal ); // Local Parameters // OpCode: set a local parameter for each operation localparam logic[6:0] opLd = 7'b0000011; localparam logic[6:0] opAluImm = 7'b0010011; localparam logic[6:0] opUpPC = 7'b0010111; localparam logic[6:0] opSt = 7'b0100011; localparam logic[6:0] opAlu = 7'b0110011; localparam logic[6:0] opUpImm = 7'b0110111; localparam logic[6:0] opBranch = 7'b1100011; localparam logic[6:0] opJALR = 7'b1100111; localparam logic[6:0] opJAL = 7'b1101111; // Func7: set a local parameter for each function 7 localparam logic[6:0] f7neg = 7'b0100000; // Func3: set a local parameter for each function 3 // Load/Store localparam logic[2:0] f3byte = 3'b000; localparam logic[2:0] f3half = 3'b001; localparam logic[2:0] f3word = 3'b010; localparam logic[2:0] f3byteU = 3'b100; localparam logic[2:0] f3halfU = 3'b101; // ALU localparam logic[2:0] f3add = 3'b000; localparam logic[2:0] f3sl = 3'b001; localparam logic[2:0] f3slt = 3'b010; localparam logic[2:0] f3sltU = 3'b011; localparam logic[2:0] f3xor = 3'b100; localparam logic[2:0] f3sr = 3'b101; localparam logic[2:0] f3or = 3'b110; localparam logic[2:0] f3and = 3'b111; // Branch localparam logic[2:0] f3beq = 3'b000; localparam logic[2:0] f3bne = 3'b001; localparam logic[2:0] f3blt = 3'b100; localparam logic[2:0] f3bge = 3'b101; localparam logic[2:0] f3bltU = 3'b110; localparam logic[2:0] f3bgeU = 3'b111; // Local Signals // Instruction breakdown (excluding I/O) logic[6:0] theOp; logic[2:0] theFunct3; logic[6:0] theFunct7; logic[31:0] i_imm; logic[31:0] s_imm; logic[31:0] b_imm; logic[31:0] u_imm; logic[31:0] j_imm; // ALU logic[2:0] aluOp; logic aluNegAr; logic aluBypass; logic[31:0] op1; logic[31:0] op2; logic[31:0] result; logic eqFlag; // Instruction breakdown: assign values // OpCode and functions 3/7 assign theOp = Instruction[6:0]; assign theFunct3 = Instruction[14:12]; assign theFunct7 = Instruction[31:25]; // Registers assign Rs1 = Instruction[19:15]; assign Rs2 = Instruction[24:20]; assign Rd = Instruction[11:7]; // Immediates always_comb begin : Immediate_Generator i_imm = {{21{Instruction[31]}}, Instruction[30:20]}; s_imm = {{21{Instruction[31]}}, Instruction[30:25], Instruction[11:7]}; b_imm = {{20{Instruction[31]}}, Instruction[7], Instruction[30:25], Instruction[11:8], 1'b0}; u_imm = {Instruction[31:12], 12'b0}; j_imm = {{12{Instruction[31]}}, Instruction[19:12], Instruction[20], Instruction[30:21], 1'b0}; end // Decoder Logic always_comb begin : Main_Decoder // Factored port/signal values JumpOrBranch = '0; JumpOrBranchPC = '0; DAddr = '0; WData = RRs2; WrMem = '0; DWidth = f3word[1:0]; WrReg = '1; Illegal = '0; aluOp = theFunct3; aluNegAr = '0; aluBypass = '0; op1 = RRs1; op2 = RRs2; // OpCode Cases case(theOp) opLd: begin DAddr = RRs1 + i_imm; DWidth = theFunct3[1:0]; aluBypass = '1; op1 = RData; case(theFunct3) f3byte: op1[31:8] = {24{RData[7]}}; f3byteU: op1[31:8] = {24{1'b0}}; f3half: op1[31:16] = {16{RData[15]}}; f3halfU: op1[31:16] = {16{1'b0}}; f3word: ; default: begin Illegal = '1; WrReg = '0; JumpOrBranch = '1; JumpOrBranchPC = CurrentPC; end endcase end opAluImm: begin op2 = i_imm; aluOp = theFunct3; aluNegAr = (theFunct7 == f7neg) & (theFunct3 == f3sr); end opUpPC: begin op1 = u_imm; op2 = CurrentPC; aluOp = f3add; end opSt: begin WrReg = '0; WrMem = '1; DAddr = RRs1 + s_imm; DWidth = theFunct3[1:0]; end opAlu: begin aluOp = theFunct3; aluNegAr = (theFunct7 == f7neg) & ((theFunct3 == f3add) | (theFunct3 == f3sr)); end opUpImm: begin op1 = u_imm; aluBypass = '1; end opBranch: begin WrReg = '0; JumpOrBranchPC = CurrentPC + b_imm; aluOp = f3slt; case(theFunct3) f3beq : begin JumpOrBranch = ( eqFlag)? '1 : '0; end f3bne : begin JumpOrBranch = (~eqFlag)? '1 : '0; end f3blt : begin JumpOrBranch = ( result[0])? '1 : '0; end f3bge : begin JumpOrBranch = (~result[0])? '1 : '0; end f3bltU: begin aluOp = f3sltU; JumpOrBranch = ( result[0])? '1 : '0; end f3bgeU: begin aluOp = f3sltU; JumpOrBranch = (~result[0])? '1 : '0; end default: begin Illegal = '1; JumpOrBranch = '1; JumpOrBranchPC = CurrentPC; end endcase end opJALR: begin JumpOrBranch = '1; JumpOrBranchPC = (RRs1 + i_imm) & 32'hFFFFFFFE; op1 = CurrentPC; op2 = 4; aluOp = f3add; end opJAL: begin JumpOrBranch = '1; JumpOrBranchPC = CurrentPC + j_imm; op1 = CurrentPC; op2 = 4; aluOp = f3add; end default: begin Illegal = '1; WrReg = '0; JumpOrBranch = '1; JumpOrBranchPC = CurrentPC; end endcase end // ALU module instantiation alu theALU ( .aluOp(aluOp), .aluNegAr(aluNegAr), .aluBypass(aluBypass), .op1(op1), .op2(op2), .result(result), .eqFlag(eqFlag) ); assign WRd = result; endmodule