232 lines
7.2 KiB
Systemverilog
232 lines
7.2 KiB
Systemverilog
// *********************************************************************************************
|
|
// 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
|