FPGA-RISC-V-CPU / hardware / src / riscv_core / ctrl_logic.v
ctrl_logic.v
Raw
`include "opcode.vh"

module branch_ctrl (
    input [31:0] inst,
    input BrEq,
    input BrLt,
    output branch
);

    wire [4:0] opcode = inst[6:2];
    wire [2:0] funct3 = inst[14:12];

    assign branch = (opcode == `OPC_BRANCH_5) && (funct3[2] ? BrLt : BrEq) ^ (funct3[0]);
    
endmodule

module imm_ctrl (
    input [31:0] inst,
    output [2:0] ImmSel
);

    wire [4:0] opcode = inst[6:2];

    reg [2:0] ImmSelOut;
    always @(*) begin
        case (opcode)
            `OPC_STORE_5:  ImmSelOut = 3'b001;
            `OPC_AUIPC_5:  ImmSelOut = 3'b011;
            `OPC_LUI_5:    ImmSelOut = 3'b011;
            `OPC_JAL_5:    ImmSelOut = 3'b100;
            `OPC_BRANCH_5: ImmSelOut = 3'b010;
            default:       ImmSelOut = 3'b000;
        endcase
    end
    assign ImmSel = ImmSelOut;

endmodule

module exec_mem_ctrl (
    input [31:0] inst,
    output BrUn,
    output [2:0] ImmSel,
    output ASel,
    output BSel,
    output [3:0] ALUSel,
    output [3:0] MemRW
);

    wire [4:0] opcode = inst[6:2];
    wire [2:0] funct3 = inst[14:12];
    
    assign BrUn = funct3[1];

    reg [2:0] ImmSelOut;
    always @(*) begin
        case (opcode)
            `OPC_STORE_5:  ImmSelOut = 3'b001;
            `OPC_AUIPC_5:  ImmSelOut = 3'b011;
            `OPC_LUI_5:    ImmSelOut = 3'b011;
            `OPC_JAL_5:    ImmSelOut = 3'b100;
            `OPC_BRANCH_5: ImmSelOut = 3'b010;
            default:       ImmSelOut = 3'b000;
        endcase
    end
    assign ImmSel = ImmSelOut;

    assign ASel = (opcode == `OPC_BRANCH_5) | (opcode == `OPC_AUIPC_5) | (opcode == `OPC_JAL_5);
    assign BSel = ~(opcode == `OPC_ARI_RTYPE_5);

    reg [3:0] ALUSelOut;
    always @(*) begin
        case (opcode)
            `OPC_ARI_RTYPE_5: ALUSelOut = {inst[30], funct3};
            `OPC_ARI_ITYPE_5: begin
                case (funct3)
                    `FNC_SRL_SRA: ALUSelOut = {inst[30], funct3};
                    `FNC_SLL:     ALUSelOut = {inst[30], funct3};
                    default:      ALUSelOut = {1'd0, funct3};
                endcase
            end
            `OPC_LUI_5: ALUSelOut = 4'b1111;
            default: ALUSelOut = 4'd0;
        endcase
    end
    assign ALUSel = ALUSelOut;

    reg [3:0] MemRWOut;
    always @(*) begin
        case ({opcode, funct3})
            default:                MemRWOut = 4'b0000;
            {`OPC_STORE_5, 3'b000}: MemRWOut = 4'b0001; // SB
            {`OPC_STORE_5, 3'b001}: MemRWOut = 4'b0011; // SH
            {`OPC_STORE_5, 3'b010}: MemRWOut = 4'b1111; // SW
        endcase
    end
    assign MemRW = MemRWOut;

endmodule

module writeback_ctrl (
    input [31:0] inst,
    output [1:0] WBSel,
    output RegWEn 
);

    wire [4:0] opcode = inst[6:2];

    reg [1:0] WBSelOut;
    always @(*) begin
        case (opcode)
            `OPC_LOAD_5:      WBSelOut = 2'b00; // Mem
            `OPC_ARI_RTYPE_5: WBSelOut = 2'b01; // ALU
            `OPC_ARI_ITYPE_5: WBSelOut = 2'b01; // ALU
            `OPC_AUIPC_5:     WBSelOut = 2'b01; // ALU
            `OPC_LUI_5:       WBSelOut = 2'b01; // ALU
            `OPC_JALR_5:      WBSelOut = 2'b10; // PC + 4
            `OPC_JAL_5:       WBSelOut = 2'b10; // PC + 4
            default:          WBSelOut = 2'b00;
        endcase
    end
    assign WBSel = WBSelOut;

    reg RegWEnOut;
    always @(*) begin
        case (opcode)
            `OPC_BRANCH_5: RegWEnOut = 1'b0;
            `OPC_STORE_5:  RegWEnOut = 1'b0;
            default:       RegWEnOut = 1'b1;
        endcase
    end 
    assign RegWEn = RegWEnOut;

endmodule

module csr_ctrl (
    input [31:0] inst,
    output CSRSel,
    output CSRWEn
);

    wire [4:0] opcode = inst[6:2];
    wire [2:0] funct3 = inst[14:12];

    assign CSRSel = funct3[2];
    assign CSRWEn = (opcode == 5'b11100) && (inst[31:20] == 12'h51e);

endmodule