//  0    1    1    2    2    3    3    4    4    5    5    6    6    7    7    8    8    9
//  5    0    5    0    5    0    5    0    5    0    5    0    5    0    5    0    5    0
//----------------------------------------------------------------------------------------
//
// The MIT License (MIT)
// Copyright (c) 2016 Enrique Sedano (enrique@esedano.es)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this 
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, 
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be included in all copies
// or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//----------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------
//
// This module is a member of
//         ____            __     
//  _   __/ __ \__  ______/ /_  __
// | | / / /_/ / / / / __  / / / /
// | |/ / _, _/ /_/ / /_/ / /_/ / 
// |___/_/ |_|\__,_/\__,_/\__, /  
//                       /____/   v 0.0 - Development
//
// Module: ctrl_top.v
// Version: 1.0
// Description:
//   Control unit. Implements the state machine that controls vRudy.
//----------------------------------------------------------------------------------------

module ctrl_top (
  //------------------------------
  // Top level control signals
  //------------------------------
  input  wire       clk,
  input  wire       rst_n,
  //------------------------------
  // Control inputs
  //------------------------------
  input  wire [1:0] ir,
  input  wire       cond,
  //------------------------------
  // Control outputs
  //------------------------------
  output reg        ld_ra,
  output reg        ld_ir,
  output reg        ld_pc,
  output reg        ld_rat,
  output reg        ld_rz,
  output reg        ld_rn,
  output reg        pc_at,
  output reg  [1:0] crf,
  output reg        erd,
  output reg        rw,
  output reg        operate
);
  
  localparam S_FETCH  = 3'b000;
  localparam S_DECO   = 3'b001;
  localparam S_LOAD   = 3'b010;
  localparam S_STORE  = 3'b011;
  localparam S_ARIT   = 3'b100;
  localparam S_BRANCH = 3'b101;

  // State of the control unit
  reg [2:0] state;
  reg [2:0] n_state;
  
  //----------------------------------------
  // State update
  //----------------------------------------
  always @(posedge clk, negedge rst_n)
  begin
    if (rst_n == 1'b0)
      state <= S_FETCH;
    else
      state <= n_state;
  end
  
  //----------------------------------------
  // Next state and output signals selection
  //----------------------------------------
  always @(*)
  begin
    //------------------------------
    // Default assignments
    //------------------------------
    n_state = state;
    ld_ra   = 1'b0;
    ld_ir   = 1'b0;
    ld_pc   = 1'b0;
    ld_rat  = 1'b0;
    ld_rz   = 1'b0;
    ld_rn   = 1'b0;
    pc_at   = 1'b0;
    crf     = 2'b00;
    erd     = 1'b0;
    rw      = 1'b0;
    operate = 1'b0;
    
    //------------------------------
    // Values selection
    //------------------------------
    case (state)
      S_FETCH:
      begin
        n_state = S_DECO;
        ld_ir   = 1'b1;
        ld_pc   = 1'b1;
      end

      S_DECO:
      begin
        case (ir)
          2'b00:
            n_state = S_LOAD;
          2'b01:
            n_state = S_STORE;
          2'b10:
            if (cond == 1'b0)
              n_state = S_FETCH;
            else
              n_state = S_BRANCH;
          2'b11:
            n_state = S_ARIT;
        endcase
        ld_ra   = 1'b1;
        ld_rat  = 1'b1;
        crf     = 1'b1;
      end

      S_LOAD:
      begin
        n_state = S_FETCH;
        ld_rz   = 1'b1;
        ld_rn   = 1'b1;
        pc_at   = 1'b1;
        erd     = 1'b1;
      end

      S_STORE:
      begin
        n_state = S_FETCH;
        pc_at   = 1'b1;
        rw      = 1'b1;
      end

      S_ARIT:
      begin
        n_state = S_DECO;
        ld_ir   = 1'b1;
        ld_pc   = 1'b1;
        ld_rz   = 1'b1;
        ld_rn   = 1'b1;
        crf     = 2'b10;
        erd     = 1'b1;
        operate = 1'b1;
      end

      S_BRANCH:
      begin
        n_state = S_DECO;
        ld_ir   = 1'b1;
        ld_pc   = 1'b1;
        pc_at   = 1'b1;
      end
    endcase
  end
  
endmodule
  
//----------------------------------------------------------------------------------------
// Trivia: The different versions of the code (except for v 0.0 - Development) will be
//     named after notable venues in the Bay Area thrash metal scene. Wikipedia only lists
//     seven of those, but I don't really expect to have many more versions than that.
//----------------------------------------------------------------------------------------
//  0    1    1    2    2    3    3    4    4    5    5    6    6    7    7    8    8    9
//  5    0    5    0    5    0    5    0    5    0    5    0    5    0    5    0    5    0
