S SmartDocs
系列: RISC V Hardware verilog 106 行 · 更新於 2026-07-04

control.v

RISC_V_Hardware/verilog/rtl/control.v

// ============================================================
// control.v -- main decoder + ALU control for RV32I
// Outputs are the classic single-cycle control signals.
// ============================================================
`timescale 1ns/1ps

module control (
    input  wire [6:0] opcode,
    input  wire [2:0] funct3,
    input  wire       funct7b5,   // instr[30]
    output reg        reg_write,  // write rd
    output reg        alu_src,    // 1: ALU B = imm, 0: ALU B = rs2
    output reg  [1:0] wb_sel,     // 00: ALU, 01: mem, 10: PC+4, 11: imm(LUI)
    output reg        mem_read,
    output reg        mem_write,
    output reg        branch,     // conditional branch
    output reg        jump,       // JAL
    output reg        jalr,       // JALR
    output reg        alu_a_pc,   // 1: ALU A = PC (AUIPC)
    output reg  [3:0] alu_op
);
    localparam OP_R    = 7'b0110011;
    localparam OP_IMM  = 7'b0010011;
    localparam OP_LOAD = 7'b0000011;
    localparam OP_STORE= 7'b0100011;
    localparam OP_BR   = 7'b1100011;
    localparam OP_LUI  = 7'b0110111;
    localparam OP_AUIPC= 7'b0010111;
    localparam OP_JAL  = 7'b1101111;
    localparam OP_JALR = 7'b1100111;

    localparam ALU_ADD  = 4'b0000, ALU_SUB  = 4'b0001,
               ALU_SLL  = 4'b0010, ALU_SLT  = 4'b0011,
               ALU_SLTU = 4'b0100, ALU_XOR  = 4'b0101,
               ALU_SRL  = 4'b0110, ALU_SRA  = 4'b0111,
               ALU_OR   = 4'b1000, ALU_AND  = 4'b1001;

    // ALU operation for OP/OP-IMM instructions
    reg [3:0] arith_op;
    always @(*) begin
        case (funct3)
            3'b000: arith_op = (funct7b5 && opcode == OP_R) ? ALU_SUB : ALU_ADD;
            3'b001: arith_op = ALU_SLL;
            3'b010: arith_op = ALU_SLT;
            3'b011: arith_op = ALU_SLTU;
            3'b100: arith_op = ALU_XOR;
            3'b101: arith_op = funct7b5 ? ALU_SRA : ALU_SRL;
            3'b110: arith_op = ALU_OR;
            default: arith_op = ALU_AND;
        endcase
    end

    always @(*) begin
        // defaults
        reg_write = 1'b0;  alu_src  = 1'b0;  wb_sel   = 2'b00;
        mem_read  = 1'b0;  mem_write = 1'b0;
        branch    = 1'b0;  jump     = 1'b0;  jalr     = 1'b0;
        alu_a_pc  = 1'b0;  alu_op   = ALU_ADD;
        case (opcode)
            OP_R: begin
                reg_write = 1'b1;
                alu_op    = arith_op;
            end
            OP_IMM: begin
                reg_write = 1'b1;
                alu_src   = 1'b1;
                alu_op    = arith_op;
            end
            OP_LOAD: begin
                reg_write = 1'b1;
                alu_src   = 1'b1;
                mem_read  = 1'b1;
                wb_sel    = 2'b01;
            end
            OP_STORE: begin
                alu_src   = 1'b1;
                mem_write = 1'b1;
            end
            OP_BR: begin
                branch    = 1'b1;
                alu_op    = ALU_SUB;   // comparison result computed separately
            end
            OP_LUI: begin
                reg_write = 1'b1;
                wb_sel    = 2'b11;     // rd = imm
            end
            OP_AUIPC: begin
                reg_write = 1'b1;
                alu_src   = 1'b1;
                alu_a_pc  = 1'b1;      // rd = PC + imm
            end
            OP_JAL: begin
                reg_write = 1'b1;
                jump      = 1'b1;
                wb_sel    = 2'b10;     // rd = PC + 4
            end
            OP_JALR: begin
                reg_write = 1'b1;
                jalr      = 1'b1;
                alu_src   = 1'b1;
                wb_sel    = 2'b10;     // rd = PC + 4
            end
            default: ;                 // ecall/ebreak/fence: NOP here
        endcase
    end
endmodule

相關文章