risc-processor-211 / CPEN Lab 7 / fsm_controller.v
fsm_controller.v
Raw
/* CPEN 211 Lab 7: Simple RISC Machine */
/* Prayetnaa Kansakar & Danial Jaber */
/* fsm_controller.v */

//state encoding definitions
`define SW 5
//`define Wait     5'b00000
`define Decode   5'b00001
`define GetA     5'b00010
`define GetB     5'b00011
`define ALU      5'b00100
`define WriteReg 5'b00101
`define WriteImm 5'b00110
`define MovRegA  5'b00111
`define MovRegB  5'b01000
`define MovRegC  5'b01001

`define RST      5'b01010
`define IF1      5'b01011
`define IF2      5'b01100
`define UpdatePC 5'b01101
`define Halt     5'b01110
`define AALU     5'b01111
`define Ld_Addr  5'b10000
`define Start_LDR 5'b10001
`define Start_STR 5'b10010
`define Mid_STR	 5'b10011
`define LDR	 5'b10100
`define STR	 5'b10101

`define MNONE 2'b00
`define MREAD 2'b01
`define MWRITE 2'b10

module fsm_controller(clk, reset, opcode, op, write,
    loada, loadb, loadc, loads, asel, bsel, vsel, nsel,
    reset_pc, load_pc, mem_cmd, addr_sel, load_ir, load_addr);
 
    //i/o signals
    input clk, reset;
    input [2:0] opcode;
    input [1:0] op;
    output write, loada, loadb, loadc, loads, asel, bsel, reset_pc, load_pc, addr_sel, load_ir, load_addr; 
    output [1:0] mem_cmd;
    output [3:0] vsel;
    output [2:0] nsel;

    wire [`SW-1:0] present_state, state_next_reset, state_next;
    reg [25:0] next;

    //clk controlled state DFF
    vDFFc #(`SW) STATE(.clk(clk), .in(state_next_reset), .out(present_state));
    //reset mux
    assign state_next_reset = reset ? `RST : state_next;

//combinational logic for FSM control
always @(*) begin

    casex({present_state, opcode, op})
   
    // begining states of FSM controller
    {`RST, 3'bxxx, 2'bxx} : next <= {`IF1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b1, 1'b1, `MNONE, 1'b0, 1'b0, 1'b0};
    {`IF1, 3'bxxx, 2'bxx} : next <= {`IF2, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MREAD, 1'b1, 1'b0, 1'b0};
    {`IF2, 3'bxxx, 2'bxx} : next <= {`UpdatePC, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MREAD, 1'b1, 1'b1, 1'b0};
    {`UpdatePC, 3'bxxx, 2'bxx} : next <= {`Decode, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b1, `MNONE, 1'b0, 1'b0, 1'b0};

    //decodes the type instruction using OPCODE (and OP for MOV)
    {`Decode, 3'b101, 2'bxx} : next <= {`GetA, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //ALU
    {`Decode, 3'b110, 2'b10} : next <= {`WriteImm, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //MOV
    {`Decode, 3'b110, 2'b00} : next <= {`MovRegA, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //MOV
    {`Decode, 3'b011, 2'bxx} : next <= {`GetA, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //LDR Memory
    {`Decode, 3'b100, 2'bxx} : next <= {`GetA, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //STR Memory
    {`Decode, 3'b111, 2'bxx} : next <= {`Halt, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //HALT Special

    {`GetA, 3'b011, 2'bxx} : next <= {`AALU, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b100, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //LDR: Get Rn
    {`GetA, 3'b100, 2'bxx} : next <= {`AALU, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b100, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //STR: Get Rn
    {`GetA, 3'b101, 2'bxx} : next <= {`GetB, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b100, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //ALU: Get Rn

    {`GetB, 3'bxxx, 2'b00} : next <= {`ALU, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b001, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //ADD: Get Rm
    {`GetB, 3'bxxx, 2'b10} : next <= {`ALU, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b001, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //AND: Get Rm
    {`GetB, 3'bxxx, 2'b11} : next <= {`ALU, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b001, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //MVN: Get Rm

    {`ALU, 3'bxxx, 2'bxx} : next <= {`WriteReg, 1'b0, 1'b0, 1'b0, 1'b1, 1'b1, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b1}; //ALU operation, lab 6
    {`WriteReg, 3'bxxx, 2'bxx} : next <= {`IF1, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0001, 3'b010, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //place into Rd w/ datapath_out

    //new type of ALU operation sequence in lab 7, which uses sximm5 to shift Rn
    {`AALU, 3'bxxx, 2'bxx} : next <= {`Ld_Addr, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1, 4'b0000, 3'b000, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //bsel = 1, loadc = 1

    //after finishing ALU operations, load_addr = 1 to enable data address register, addr_sel = 0
    {`Ld_Addr, 3'b011, 2'bxx} : next <= {`Start_LDR, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b1};
    {`Ld_Addr, 3'b100, 2'bxx} : next <= {`Start_STR, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b1};

    //the start of LDR Memory instruction branch
    {`Start_LDR, 3'bxxx, 2'bxx} : next <= {`LDR, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MREAD, 1'b0, 1'b0, 1'b0}; //change m_cmd to MREAD
    //info on read_data, due to previous step
    //vsel = mdata, to write into Rd
    {`LDR, 3'bxxx, 2'bxx} : next <= {`IF1, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0010, 3'b010, 1'b0, 1'b0, `MREAD, 1'b0, 1'b0, 1'b0}; 

    //the start of STR Memory instruction branch
    {`Start_STR, 3'bxxx, 2'bxx} : next <= {`Mid_STR, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b010, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; // loadb = 1 to 
    {`Mid_STR, 3'bxxx, 2'bxx} : next <= {`STR, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b1, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; // asel = 1, loadc = 1
    {`STR, 3'bxxx, 2'bxx} : next <= {`IF1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MWRITE, 1'b0, 1'b0, 1'b0}; //m_cmd to MWRITE  

    //MOV immediate instuction
    {`WriteImm, 3'bxxx, 2'bxx} : next <= {`IF1, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0100, 3'b100, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //place into Rn

    //MOV register instruction
    {`MovRegA, 3'bxxx, 2'bxx} : next <= {`MovRegB, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b001, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //Loadb into Rm
    {`MovRegB, 3'bxxx, 2'bxx} : next <= {`MovRegC, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b1, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //put asel to one, loadc = 1
    {`MovRegC, 3'bxxx, 2'bxx} : next <= {`IF1, 1'b1, 1'b0, 1'b0, 1'b1, 1'b1, 1'b0, 1'b0, 4'b0001, 3'b010, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //place Load B into Rd

    //HALT Special instruction
    {`Halt, 3'bxxx, 2'bxx} : next <= {`Halt, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 4'b0000, 3'b000, 1'b0, 1'b0, `MNONE, 1'b0, 1'b0, 1'b0}; //self loop to Halt, so that user must reset
     
    default : next <= {26{1'bx}};
    endcase
end
assign {state_next, write, loada, loadb, loadc, loads, asel, bsel, vsel, nsel, reset_pc, load_pc, mem_cmd, addr_sel, load_ir, load_addr} = next;
endmodule 

//D flip flop without load enable
module vDFFc(clk, in, out);
    parameter n = 1;
    input clk;
    input [n-1:0] in;
    output reg [n-1:0] out;

    always @(posedge clk)
        out = in;
endmodule