//----------------------------------------------------------------------------
// fsl_timer - module
//----------------------------------------------------------------------------
// IMPORTANT:
// DO NOT MODIFY THIS FILE EXCEPT IN THE DESIGNATED SECTIONS.
//
// SEARCH FOR --USER TO DETERMINE WHERE CHANGES ARE ALLOWED.
//
// TYPICALLY, THE ONLY ACCEPTABLE CHANGES INVOLVE ADDING NEW
// PORTS AND GENERICS THAT GET PASSED THROUGH TO THE INSTANTIATION
// OF THE USER_LOGIC ENTITY.
//----------------------------------------------------------------------------
//
// ***************************************************************************
// ** Copyright (c) 1995-2011 Xilinx, Inc.  All rights reserved.            **
// **                                                                       **
// ** Xilinx, Inc.                                                          **
// ** XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"         **
// ** AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND       **
// ** SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,        **
// ** OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,        **
// ** APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION           **
// ** THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,     **
// ** AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE      **
// ** FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY              **
// ** WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE               **
// ** IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR        **
// ** REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF       **
// ** INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS       **
// ** FOR A PARTICULAR PURPOSE.                                             **
// **                                                                       **
// ***************************************************************************
//
//----------------------------------------------------------------------------
// Filename:          fsl_timer
// Version:           1.00.a
// Description:       Example FSL core (Verilog).
// Date:              Thu Oct 17 17:31:32 2013 (by Create and Import Peripheral Wizard)
// Verilog Standard:  Verilog-2001
//----------------------------------------------------------------------------
// Naming Conventions:
//   active low signals:                    "*_n"
//   clock signals:                         "clk", "clk_div#", "clk_#x"
//   reset signals:                         "rst", "rst_n"
//   generics:                              "C_*"
//   user defined types:                    "*_TYPE"
//   state machine next state:              "*_ns"
//   state machine current state:           "*_cs"
//   combinatorial signals:                 "*_com"
//   pipelined or register delay signals:   "*_d#"
//   counter signals:                       "*cnt*"
//   clock enable signals:                  "*_ce"
//   internal version of output port:       "*_i"
//   device pins:                           "*_pin"
//   ports:                                 "- Names begin with Uppercase"
//   processes:                             "*_PROCESS"
//   component instantiations:              "<ENTITY_>I_<#|FUNC>"
//----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
//
//
// Definition of Ports
// FSL_Clk             : Synchronous clock
// FSL_Rst           : System reset, should always come from FSL bus
// FSL_S_Clk       : Slave asynchronous clock
// FSL_S_Read      : Read signal, requiring next available input to be read
// FSL_S_Data      : Input data
// FSL_S_Control   : Control Bit, indicating the input data are control word
// FSL_S_Exists    : Data Exist Bit, indicating data exist in the input FSL bus
// FSL_M_Clk       : Master asynchronous clock
// FSL_M_Write     : Write signal, enabling writing to output FSL bus
// FSL_M_Data      : Output data
// FSL_M_Control   : Control Bit, indicating the output data are contol word
// FSL_M_Full      : Full Bit, indicating output FSL bus is full
//
////////////////////////////////////////////////////////////////////////////////

//----------------------------------------
// Module Section
//----------------------------------------
module fsl_timer 
	(
		// ADD USER PORTS BELOW THIS LINE 
		// -- USER ports added here 
		// ADD USER PORTS ABOVE THIS LINE 

		// DO NOT EDIT BELOW THIS LINE ////////////////////
		// Bus protocol ports, do not add or delete. 
    FSL_Clk_0,
    FSL_Rst_0,
    FSL_S_Clk_0,
    FSL_S_Read_0,
    FSL_S_Data_0,
    FSL_S_Control_0,
    FSL_S_Exists_0,
    FSL_M_Clk_0,
    FSL_M_Write_0,
    FSL_M_Data_0,
    FSL_M_Control_0,
    FSL_M_Full_0,

    FSL_Clk_1,
    FSL_Rst_1,
    FSL_S_Clk_1,
    FSL_S_Read_1,
    FSL_S_Data_1,
    FSL_S_Control_1,
    FSL_S_Exists_1,
    FSL_M_Clk_1,
    FSL_M_Write_1,
    FSL_M_Data_1,
    FSL_M_Control_1,
    FSL_M_Full_1,

    FSL_Clk_2,
    FSL_Rst_2,
    FSL_S_Clk_2,
    FSL_S_Read_2,
    FSL_S_Data_2,
    FSL_S_Control_2,
    FSL_S_Exists_2,
    FSL_M_Clk_2,
    FSL_M_Write_2,
    FSL_M_Data_2,
    FSL_M_Control_2,
    FSL_M_Full_2,

    FSL_Clk_3,
    FSL_Rst_3,
    FSL_S_Clk_3,
    FSL_S_Read_3,
    FSL_S_Data_3,
    FSL_S_Control_3,
    FSL_S_Exists_3,
    FSL_M_Clk_3,
    FSL_M_Write_3,
    FSL_M_Data_3,
    FSL_M_Control_3,
    FSL_M_Full_3
		// DO NOT EDIT ABOVE THIS LINE ////////////////////
	);

// ADD USER PORTS BELOW THIS LINE 
// -- USER ports added here 
// ADD USER PORTS ABOVE THIS LINE 
input                                     FSL_Clk_0;
input                                     FSL_Rst_0;
input                                     FSL_Clk_1;
input                                     FSL_Rst_1;
input                                     FSL_Clk_2;
input                                     FSL_Rst_2;
input                                     FSL_Clk_3;
input                                     FSL_Rst_3;

input                                     FSL_S_Clk_0;
output                                    FSL_S_Read_0;
input      [0 : 31]                       FSL_S_Data_0;
input                                     FSL_S_Control_0;
input                                     FSL_S_Exists_0;
input                                     FSL_M_Clk_0;
output                                    FSL_M_Write_0;
output     [0 : 31]                       FSL_M_Data_0;
output                                    FSL_M_Control_0;
input                                     FSL_M_Full_0;

input                                     FSL_S_Clk_1;
output                                    FSL_S_Read_1;
input      [0 : 31]                       FSL_S_Data_1;
input                                     FSL_S_Control_1;
input                                     FSL_S_Exists_1;
input                                     FSL_M_Clk_1;
output                                    FSL_M_Write_1;
output     [0 : 31]                       FSL_M_Data_1;
output                                    FSL_M_Control_1;
input                                     FSL_M_Full_1;

input                                     FSL_S_Clk_2;
output                                    FSL_S_Read_2;
input      [0 : 31]                       FSL_S_Data_2;
input                                     FSL_S_Control_2;
input                                     FSL_S_Exists_2;
input                                     FSL_M_Clk_2;
output                                    FSL_M_Write_2;
output     [0 : 31]                       FSL_M_Data_2;
output                                    FSL_M_Control_2;
input                                     FSL_M_Full_2;

input                                     FSL_S_Clk_3;
output                                    FSL_S_Read_3;
input      [0 : 31]                       FSL_S_Data_3;
input                                     FSL_S_Control_3;
input                                     FSL_S_Exists_3;
input                                     FSL_M_Clk_3;
output                                    FSL_M_Write_3;
output     [0 : 31]                       FSL_M_Data_3;
output                                    FSL_M_Control_3;
input                                     FSL_M_Full_3;



   // Total number of input data.
   localparam NUMBER_OF_INPUT_WORDS  = 1;

   // Total number of output data
   localparam NUMBER_OF_OUTPUT_WORDS = 1;

   // Define the states of state machine
   localparam Idle  = 3'b100;
   localparam Read_Inputs = 3'b010;
   localparam Write_Outputs  = 3'b001;

   reg [0:2] state [0:3];

   // Accumulator to hold sum of inputs read at any point in time
   reg [0:31] timer;
   reg [0:6] counter;

   // Counters to store the number inputs read & outputs written
   reg [0:NUMBER_OF_INPUT_WORDS - 1] nr_of_reads [0:3];
   reg [0:NUMBER_OF_OUTPUT_WORDS - 1] nr_of_writes [0:3];

   assign FSL_S_Read_0  = (state[0] == Read_Inputs)   ? FSL_S_Exists_0 : 0;
   assign FSL_M_Write_0 = (state[0] == Write_Outputs) ? ~FSL_M_Full_0  : 0;
   assign FSL_S_Read_1  = (state[1] == Read_Inputs)   ? FSL_S_Exists_1 : 0;
   assign FSL_M_Write_1 = (state[1] == Write_Outputs) ? ~FSL_M_Full_1  : 0;
   assign FSL_S_Read_2  = (state[2] == Read_Inputs)   ? FSL_S_Exists_2 : 0;
   assign FSL_M_Write_2 = (state[2] == Write_Outputs) ? ~FSL_M_Full_2  : 0;
   assign FSL_S_Read_3  = (state[3] == Read_Inputs)   ? FSL_S_Exists_3 : 0;
   assign FSL_M_Write_3 = (state[3] == Write_Outputs) ? ~FSL_M_Full_3  : 0;

   assign FSL_M_Data_0 = timer;
   assign FSL_M_Data_1 = timer;
   assign FSL_M_Data_2 = timer;
   assign FSL_M_Data_3 = timer;


  always @(posedge FSL_Clk_0)
  begin
    if(FSL_Rst_0) begin
      timer <= 0;
      counter <= 0;
    end
    else if(counter == 83) begin
      counter <= 0;
      timer <= timer + 1;
    end
    else
      counter <= counter + 1;
  end


   always @(posedge FSL_Clk_0) 
   begin  // process The_SW_accelerator
      if (FSL_Rst_0)               // Synchronous reset (active high)
        begin
           // CAUTION: make sure your reset polarity is consistent with the
           // system reset polarity
           state[0]        <= Idle;
           nr_of_reads[0]  <= 0;
           nr_of_writes[0] <= 0;
        end
      else
        case (state[0])
          Idle: 
            if (FSL_S_Exists_0 == 1)
            begin
              state[0]       <= Read_Inputs;
              nr_of_reads[0] <= NUMBER_OF_INPUT_WORDS - 1;
            end

          Read_Inputs: 
            if (FSL_S_Exists_0 == 1) 
            begin
              // Coprocessor function (Adding) happens here
              if (nr_of_reads[0] == 0)
                begin
                  state[0]        <= Write_Outputs;
                  nr_of_writes[0] <= NUMBER_OF_OUTPUT_WORDS - 1;
                end
              else
                nr_of_reads[0] <= nr_of_reads[0] - 1;
            end

          Write_Outputs: 
            if (nr_of_writes[0] == 0) 
              state[0] <= Idle;
            else
              if (FSL_M_Full_0 == 0)  nr_of_writes[0] <= nr_of_writes[0] - 1;
        endcase
   end

   always @(posedge FSL_Clk_1) 
   begin  // process The_SW_accelerator
      if (FSL_Rst_1)               // Synchronous reset (active high)
        begin
           // CAUTION: make sure your reset polarity is consistent with the
           // system reset polarity
           state[1]        <= Idle;
           nr_of_reads[1]  <= 0;
           nr_of_writes[1] <= 0;
        end
      else
        case (state[1])
          Idle: 
            if (FSL_S_Exists_1 == 1)
            begin
              state[1]       <= Read_Inputs;
              nr_of_reads[1] <= NUMBER_OF_INPUT_WORDS - 1;
            end

          Read_Inputs: 
            if (FSL_S_Exists_1 == 1) 
            begin
              // Coprocessor function (Adding) happens here
              if (nr_of_reads[1] == 0)
                begin
                  state[1]        <= Write_Outputs;
                  nr_of_writes[1] <= NUMBER_OF_OUTPUT_WORDS - 1;
                end
              else
                nr_of_reads[1] <= nr_of_reads[1] - 1;
            end

          Write_Outputs: 
            if (nr_of_writes[1] == 0) 
              state[1] <= Idle;
            else
              if (FSL_M_Full_1 == 0)  nr_of_writes[1] <= nr_of_writes[1] - 1;
        endcase
   end

   always @(posedge FSL_Clk_2) 
   begin  // process The_SW_accelerator
      if (FSL_Rst_2)               // Synchronous reset (active high)
        begin
           // CAUTION: make sure your reset polarity is consistent with the
           // system reset polarity
           state[2]        <= Idle;
           nr_of_reads[2]  <= 0;
           nr_of_writes[2] <= 0;
        end
      else
        case (state[2])
          Idle: 
            if (FSL_S_Exists_2 == 1)
            begin
              state[2]       <= Read_Inputs;
              nr_of_reads[2] <= NUMBER_OF_INPUT_WORDS - 1;
            end

          Read_Inputs: 
            if (FSL_S_Exists_2 == 1) 
            begin
              // Coprocessor function (Adding) happens here
              if (nr_of_reads[2] == 0)
                begin
                  state[2]        <= Write_Outputs;
                  nr_of_writes[2] <= NUMBER_OF_OUTPUT_WORDS - 1;
                end
              else
                nr_of_reads[2] <= nr_of_reads[2] - 1;
            end

          Write_Outputs: 
            if (nr_of_writes[2] == 0) 
              state[2] <= Idle;
            else
              if (FSL_M_Full_2 == 0)  nr_of_writes[2] <= nr_of_writes[2] - 1;
        endcase
   end

   always @(posedge FSL_Clk_3) 
   begin  // process The_SW_accelerator
      if (FSL_Rst_3)               // Synchronous reset (active high)
        begin
           // CAUTION: make sure your reset polarity is consistent with the
           // system reset polarity
           state[3]        <= Idle;
           nr_of_reads[3]  <= 0;
           nr_of_writes[3] <= 0;
        end
      else
        case (state[3])
          Idle: 
            if (FSL_S_Exists_3 == 1)
            begin
              state[3]       <= Read_Inputs;
              nr_of_reads[3] <= NUMBER_OF_INPUT_WORDS - 1;
            end

          Read_Inputs: 
            if (FSL_S_Exists_3 == 1) 
            begin
              // Coprocessor function (Adding) happens here
              if (nr_of_reads[3] == 0)
                begin
                  state[3]        <= Write_Outputs;
                  nr_of_writes[3] <= NUMBER_OF_OUTPUT_WORDS - 1;
                end
              else
                nr_of_reads[3] <= nr_of_reads[3] - 1;
            end

          Write_Outputs: 
            if (nr_of_writes[3] == 0) 
              state[3] <= Idle;
            else
              if (FSL_M_Full_3 == 0)  nr_of_writes[3] <= nr_of_writes[3] - 1;
        endcase
   end

endmodule
