`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: nope
// Engineer: Jose
// 
// Create Date: 02/20/2026 09:21:52 AM
// Design Name: Control Unit
// Module Name: control
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Manages the logic in the ID stage
// 
// Dependencies: 
// 
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module control(
    input [6:0] opcode,
    input [2:0] aux,
    input [6:0] func,
    output reg we_reg,
    output reg we_mem,
    output reg mem_to_reg,
    output reg alu_src,
    output reg [3:0] alu_op,
    output reg branch,
    output reg jump
);

// formatos de instrucciones
localparam ALU_R     = 7'b0110011;
localparam ALU_I     = 7'b0010011;
localparam OP_LOAD   = 7'b0000011;
localparam OP_STORE  = 7'b0100011;
localparam OP_BRANCH = 7'b1100011;
localparam OP_JAL    = 7'b1101111;
localparam OP_JALR   = 7'b1100111;

always @(*) begin 
    we_reg = 0;
    we_mem = 0;
    mem_to_reg = 0;
    alu_src = 0;
    alu_op = 4'b0000;
    branch = 0;
    jump = 0; 
    
    case(opcode) 
        ALU_R: begin 
            we_reg = 1;
            alu_src = 0;
            case({func,aux}) 
                10'b0000000000: alu_op = 4'b0000; // ADD
                10'b0100000000: alu_op = 4'b0001; // SUB
                10'b0000000111: alu_op = 4'b0010; // AND
                10'b0000000110: alu_op = 4'b0011; // OR
                10'b0000000100: alu_op = 4'b0100; // XOR
                10'b0000000001: alu_op = 4'b0101; // SLL
                10'b0000000101: alu_op = 4'b0110; // SRL
                10'b0100000101: alu_op = 4'b0111; // SRA
                10'b0000000010: alu_op = 4'b1000; // SLT
                10'b0000000011: alu_op = 4'b1001; // SLTU
            endcase
        end
        
        ALU_I: begin 
            we_reg = 1;
            alu_src = 1;
            case(aux) 
                3'b000: alu_op = 4'b0000; // ADDI
                3'b111: alu_op = 4'b0010; // ANDI
                3'b110: alu_op = 4'b0011; // ORI
                3'b100: alu_op = 4'b0100; // XORI
                3'b001: alu_op = 4'b0101; // SLLI
                3'b101: alu_op = (func==7'b0000000)?4'b0110:4'b1001; // SRLI/SRAI
                3'b010: alu_op = 4'b1000; // SLTI
                3'b011: alu_op = 4'b1001; // SLTIU
            endcase
        end
        
        OP_LOAD: begin
            we_reg = 1;
            mem_to_reg = 1;
            alu_src = 1; 
        end

        OP_STORE: begin
            we_mem = 1;
            alu_src = 1; 
        end

        OP_BRANCH: begin
            branch = 1;
            alu_op = 4'b0001;
        end

        OP_JAL: begin
            we_reg = 1; // para guardar la dirección de retorno
            jump = 1;
        end

        OP_JALR: begin
            we_reg = 1;
            alu_src = 1;
            jump = 1;
        end
        
        default: begin end
    endcase
end

endmodule
