How to Implement Finite State Machine Control Module for ALU and Register File

Viewed 36

I am trying to implement a control block module with a Register File module and an ALU. It is a two process finite state machine, although tips for one or three process are also welcome. The finite state machine has five states, the control flow is as such.

enter image description here

The full code is as such

module controller (
    // Port Declaration
    input wire clk,
    input wire reset,

    // Register File
    output reg  [4:0]  rf_raddr_a,     // read register address of port A
    input  wire [15:0] rf_rdata_a,     // read register data of port A
    output reg  [4:0]  rf_raddr_b,     // read register address of port B
    input  wire [15:0] rf_rdata_b,     // read register data of port B
    output reg  [4:0]  rf_waddr,       // register address of write operation
    output reg  [15:0] rf_wdata,       // data of write operation
    output reg  rf_wen,                // enable signal of write

    // ALU          
    output reg [15:0]      alu_a,      // A
    output reg [15:0]      alu_b,      // B
    output reg [3:0]       alu_op,     // operand
    input  wire [15:0]      alu_y,      // Y = A operand B

    // Control
    input  wire             step,       // push_btn
    input  wire [31:0]      dip_sw,   // 32 bit instruction (R type and I type) 
    output reg [15:0]       leds        // 16 leds
);
    // Internal Wire Declaration
    logic [31:0] instruction_registers; 
    logic is_r_type_register;
    logic is_i_type_register;
    logic is_poke;
    logic is_peek;
    logic [15:0] imm;
    logic [4:0] rd, rs1, rs2;
    logic [3:0] opcode;

    always_comb begin
        is_r_type_register = (instruction_registers[2:0] == 3'b001);
        is_i_type_register = (instruction_registers[2:0] == 3'b010);
        is_peek = (is_i_type_register && (instruction_registers[6:3] == 4'b0010));
        is_poke = (is_i_type_register && (instruction_registers[6:3] == 4'b0001));

        imm     = instruction_registers[31:16];
        rd      = instruction_registers[11:7];
        rs1     = instruction_registers[19:15];
        rs2     = instruction_registers[24:20];
        opcode  = instruction_registers[6:3];
    end

    // enum of logic type
    typedef enum logic [3:0] {
        STATE_INIT,
        STATE_DECODE,
        STATE_CALC,
        STATE_READ_REG,
        STATE_WRITE_REG
    } state_t;

    state_t state;
    state_t next_state;
    

    // two process state machine
    always_ff @(posedge clk) begin
        if (reset) begin
            state <= STATE_INIT;
        end else begin
            state <= next_state;    
        end 
    end 

    always @* begin
        case(state)
            STATE_INIT: begin
                rf_wen = 1'b0;
                if (step) begin
                    instruction_registers = dip_sw;
                    next_state = STATE_DECODE;
                end 
            end 
            STATE_DECODE: begin  
                if (is_r_type_register) begin
                    rf_raddr_a = rs1;
                    rf_raddr_b = rs2;
                    next_state = STATE_CALC;
                end else if (is_peek) begin
                    rf_raddr_a = rd;
                    next_state = STATE_READ_REG;
                end else if (is_poke) begin
                    rf_waddr = rd;
                    next_state = STATE_WRITE_REG;
                end else begin
                    next_state = STATE_INIT;
                end 

            end 

            STATE_CALC: begin
                alu_a = rf_rdata_a;
                alu_b = rf_rdata_b;
                alu_op = opcode;
                next_state = STATE_WRITE_REG;
            end

            STATE_WRITE_REG: begin
                rf_wen = 1'h1;                      // enable write
                rf_waddr = rd;                      // set w address
                if (is_r_type_register) begin       
                    rf_wdata = alu_y;
                end else begin                      // poke
                    rf_wdata = imm;
                end 
                next_state = STATE_INIT;
            end 

            STATE_READ_REG: begin
                leds = rf_rdata_a;
                next_state = STATE_INIT;
            end 

            default: begin
                next_state = STATE_INIT;
            end 
        endcase
    end 
endmodule

To summarize the code, in the INIT stage, once we press "step", we take our 'dip_sw' input, which represents a 32 bit coding (that represents a RISCV instruction) to the 'instruction_registers', then go onto the 'DECODE' stage and so on.

The final block module design should be enter image description here

However, looking at the synthesized schematics on Vivado, I get

enter image description here

The ports are correct, why would there be more output/input "wires" then there are ones that I defined in the module? Can anyone point me in the right direction

0 Answers
Related