//----------------------------------------------------------------------------
// user_mutex - 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:          user_mutex
// Version:           1.00.a
// Description:       Example FSL core (Verilog).
// Date:              Thu Jul 11 11:23:19 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 user_mutex 
  (
    // ADD USER PORTS BELOW THIS LINE 
    Debug1,
    Debug2,
    Debug3,
    Debug4,
    Debug_mutex_0,
    Debug_mutex_1,
    Debug_mutex_2,
    Debug_mutex_3,
    Debug_actual_mutex_we,
    Debug_we0,
    Debug_we1,
    Debug_we2,
    Debug_we3,

    debug_FSL_Clk_0,
    debug_FSL_S_Clk_0,
    debug_FSL_S_Read_0,
    debug_FSL_S_Data_0,
    debug_FSL_S_Control_0,
    debug_FSL_S_Exists_0,
    debug_FSL_M_Clk_0,
    debug_FSL_M_Write_0,
    debug_FSL_M_Data_0,
    debug_FSL_M_Control_0,
    debug_FSL_M_Full_0,

    debug_FSL_Clk_1,
    debug_FSL_S_Clk_1,
    debug_FSL_S_Read_1,
    debug_FSL_S_Data_1,
    debug_FSL_S_Control_1,
    debug_FSL_S_Exists_1,
    debug_FSL_M_Clk_1,
    debug_FSL_M_Write_1,
    debug_FSL_M_Data_1,
    debug_FSL_M_Control_1,
    debug_FSL_M_Full_1,
    // -- 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 
output [0:2] Debug1;
output [0:2] Debug2;
output [0:2] Debug3;
output [0:2] Debug4;
output [0:31] Debug_mutex_0;
output [0:31] Debug_mutex_1;
output [0:31] Debug_mutex_2;
output [0:31] Debug_mutex_3;
output Debug_actual_mutex_we;
output Debug_we0;
output Debug_we1;
output Debug_we2;
output Debug_we3;

output debug_FSL_Clk_0;
output debug_FSL_S_Clk_0;
output debug_FSL_S_Read_0;
output [0:31] debug_FSL_S_Data_0;
output debug_FSL_S_Control_0;
output debug_FSL_S_Exists_0;
output debug_FSL_M_Clk_0;
output debug_FSL_M_Write_0;
output [0:31] debug_FSL_M_Data_0;
output debug_FSL_M_Control_0;
output debug_FSL_M_Full_0;

output debug_FSL_Clk_1;
output debug_FSL_S_Clk_1;
output debug_FSL_S_Read_1;
output [0:31] debug_FSL_S_Data_1;
output debug_FSL_S_Control_1;
output debug_FSL_S_Exists_1;
output debug_FSL_M_Clk_1;
output debug_FSL_M_Write_1;
output [0:31] debug_FSL_M_Data_1;
output debug_FSL_M_Control_1;
output debug_FSL_M_Full_1;
// -- 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;

// ADD USER PARAMETERS BELOW THIS LINE 


// ADD USER PARAMETERS ABOVE THIS LINE


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

   // 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 lock_phase = 3'b110;
   localparam unlock_phase = 3'b001;
   localparam Write_Outputs  = 3'b101;

  //signal declaration

  reg [0:2] state [0:3];//one state per fsl port

  reg lock_unlock [0:3];//lock or unlock
  reg [0:5] mutex_num [0:3];//mutex instance number
  reg [0:31] pattern [0:3];//store the lock pattern of incoming locking attempt

  // 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];


  wire actual_mutex_we;
  wire [0:5] actual_mutex_num;
  wire [0:7] actual_write_pattern;

  wire mutex_we [0:3];
  wire [0:7] write_pattern [0:3];

  //circuit instantiation
  arbiter u2(.clk(FSL_Clk_0), .rst(FSL_Rst_0), .we_0(mutex_we[0]), .we_1(mutex_we[1]),
             .we_2(mutex_we[2]), .we_3(mutex_we[3]), .mutex_num_0(mutex_num[0]),
             .mutex_num_1(mutex_num[1]), .mutex_num_2(mutex_num[2]), .mutex_num_3(mutex_num[3]),
             .pattern_0(write_pattern[0]), .pattern_1(write_pattern[1]), .pattern_2(write_pattern[2]),
             .pattern_3(write_pattern[3]), .do_0(FSL_M_Data_0), .do_1(FSL_M_Data_1), .do_2(FSL_M_Data_2),
             .do_3(FSL_M_Data_3));
  


  /*debug signals below*/
  assign Debug1 = state[0];
  assign Debug2 = state[1];
  assign Debug3 = state[2];
  assign Debug4 = state[3];
  assign Debug_mutex_0 = actual_mutex_num;
  assign Debug_mutex_1 = actual_write_pattern;
  assign Debug_actual_mutex_we = actual_mutex_we;
  assign Debug_we0 = mutex_we[0];
  assign Debug_we1 = mutex_we[1];
  assign Debug_we2 = mutex_we[2];
  assign Debug_we3 = mutex_we[3];
  //assign Debug_mutex_2 = mutex[2];
  //assign Debug_mutex_3 = mutex[3];

  assign debug_FSL_Clk_0       = FSL_Clk_0;
  assign debug_FSL_S_Clk_0     = FSL_S_Clk_0;
  assign debug_FSL_S_Read_0    = FSL_S_Read_0;
  assign debug_FSL_S_Data_0    = FSL_S_Data_0;
  assign debug_FSL_S_Control_0 = FSL_S_Control_0;
  assign debug_FSL_S_Exists_0  = FSL_S_Exists_0;
  assign debug_FSL_M_Clk_0     = FSL_M_Clk_0;
  assign debug_FSL_M_Write_0   = FSL_M_Write_0;
  assign debug_FSL_M_Data_0    = FSL_M_Data_0;
  assign debug_FSL_M_Control_0 = FSL_M_Control_0;
  assign debug_FSL_M_Full_0    = FSL_M_Full_0;

  assign debug_FSL_Clk_1       = FSL_Clk_1;
  assign debug_FSL_S_Clk_1     = FSL_S_Clk_1;
  assign debug_FSL_S_Read_1    = FSL_S_Read_1;
  assign debug_FSL_S_Data_1    = FSL_S_Data_1;
  assign debug_FSL_S_Control_1 = FSL_S_Control_1;
  assign debug_FSL_S_Exists_1  = FSL_S_Exists_1;
  assign debug_FSL_M_Clk_1     = FSL_M_Clk_1;
  assign debug_FSL_M_Write_1   = FSL_M_Write_1;
  assign debug_FSL_M_Data_1    = FSL_M_Data_1;
  assign debug_FSL_M_Control_1 = FSL_M_Control_1;
  assign debug_FSL_M_Full_1    = FSL_M_Full_1;

  /*debug signals above*/

  assign FSL_S_Read_0  = ((state[0] == Read_Inputs) || (state[0] == lock_phase) || (state[0] == unlock_phase))   ? 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) || (state[1] == lock_phase) || (state[1] == unlock_phase))   ? 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) || (state[2] == lock_phase) || (state[2] == unlock_phase))   ? 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) || (state[3] == lock_phase) || (state[3] == unlock_phase))   ? FSL_S_Exists_3 : 0;
  assign FSL_M_Write_3 = (state[3] == Write_Outputs) ? ~FSL_M_Full_3  : 0;


  assign mutex_we[0] = ((state[0] == lock_phase) && (FSL_S_Exists_0 == 1))? (FSL_M_Data_0[31] == 0) :
                       ((state[0] == unlock_phase) && (FSL_S_Exists_0 == 1))? (FSL_M_Data_0[24:31] == FSL_S_Data_0[24:31]) : 0;

  assign write_pattern[0] = (state[0] == lock_phase)? FSL_S_Data_0[24:31] : 0;

  assign mutex_we[1] = ((state[1] == lock_phase) && (FSL_S_Exists_1 == 1))? (FSL_M_Data_1[31] == 0) :
                       ((state[1] == unlock_phase) && (FSL_S_Exists_1 == 1))? (FSL_M_Data_1[24:31] == FSL_S_Data_1[24:31]) : 0;

  assign write_pattern[1] = (state[1] == lock_phase)? FSL_S_Data_1[24:31] : 0;

  assign mutex_we[2] = ((state[2] == lock_phase) && (FSL_S_Exists_2 == 1))? (FSL_M_Data_2[31] == 0) :
                       ((state[2] == unlock_phase) && (FSL_S_Exists_2 == 1))? (FSL_M_Data_2[24:31] == FSL_S_Data_2[24:31]) : 0;

  assign write_pattern[2] = (state[2] == lock_phase)? FSL_S_Data_2[24:31] : 0;

  assign mutex_we[3] = ((state[3] == lock_phase) && (FSL_S_Exists_3 == 1))? (FSL_M_Data_3[31] == 0) :
                       ((state[3] == unlock_phase) && (FSL_S_Exists_3 == 1))? (FSL_M_Data_3[24:31] == FSL_S_Data_3[24:31]) : 0;

  assign write_pattern[3] = (state[3] == lock_phase)? FSL_S_Data_3[24:31] : 0;



   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]   <= NUMBER_OF_INPUT_WORDS - 1;
           nr_of_writes[0]  <= NUMBER_OF_OUTPUT_WORDS - 1;
           lock_unlock[0]   <= 0;
           mutex_num[0]     <= 0;
           pattern[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;
                lock_unlock[0] <= 0;
                mutex_num[0]   <= 0;
                pattern[0]     <= 0;
              end

          Read_Inputs: 
            if (FSL_S_Exists_0 == 1) 
              begin
                if(nr_of_reads[0] == 1)
                  // FSL_S_Data is mutex_num
                  begin
                    nr_of_reads[0] <= nr_of_reads[0] - 1;
                    mutex_num[0]   <= FSL_S_Data_0[26:31];
                    if(lock_unlock[0] == 0)
                      state[0]  <= lock_phase;
                    else
                      state[0]  <= unlock_phase;
                  end
                else if(nr_of_reads[0] == 2)
                  // FSL_S_Data is lock_unlock
                  begin
                    nr_of_reads[0] <= nr_of_reads[0] - 1;
                    lock_unlock[0] <= FSL_S_Data_0[31];
                  end
              end
          lock_phase:
            if (FSL_S_Exists_0 == 1) begin
              state[0] <= Write_Outputs;
            end
          unlock_phase:
            if (FSL_S_Exists_0 == 1)
              state[0] <= Write_Outputs;
          Write_Outputs: 
              state[0] <= Idle;
        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]   <= NUMBER_OF_INPUT_WORDS - 1;
             nr_of_writes[1]  <= NUMBER_OF_OUTPUT_WORDS - 1;
             lock_unlock[1]   <= 0;
             mutex_num[1]     <= 0;
             pattern[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;
                  lock_unlock[1] <= 0;
                  mutex_num[1]   <= 0;
                  pattern[1]     <= 0;
                end

            Read_Inputs: 
              if (FSL_S_Exists_1 == 1) 
                begin
                  if(nr_of_reads[1] == 1)
                    // FSL_S_Data is mutex_num
                    begin
                      nr_of_reads[1] <= nr_of_reads[1] - 1;
                      mutex_num[1]   <= FSL_S_Data_1[26:31];
                      if(lock_unlock[1] == 0)
                        state[1]  <= lock_phase;
                      else
                        state[1]  <= unlock_phase;
                    end
                  else if(nr_of_reads[1] == 2)
                    // FSL_S_Data is lock_unlock
                    begin
                      nr_of_reads[1] <= nr_of_reads[1] - 1;
                      lock_unlock[1] <= FSL_S_Data_1[31];
                    end
                end
            lock_phase:
              if (FSL_S_Exists_1 == 1) begin
                state[1] <= Write_Outputs;
              end
            unlock_phase:
              if (FSL_S_Exists_1 == 1)
                state[1] <= Write_Outputs;
            Write_Outputs: 
                state[1] <= Idle;
          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]   <= NUMBER_OF_INPUT_WORDS - 1;
           nr_of_writes[2]  <= NUMBER_OF_OUTPUT_WORDS - 1;
           lock_unlock[2]   <= 0;
           mutex_num[2]     <= 0;
           pattern[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;
                lock_unlock[2] <= 0;
                mutex_num[2]   <= 0;
                pattern[2]     <= 0;
              end

          Read_Inputs: 
            if (FSL_S_Exists_2 == 1)
              begin
                if(nr_of_reads[2] == 1)
                  // FSL_S_Data is mutex_num
                  begin
                    nr_of_reads[2] <= nr_of_reads[2] - 1;
                    mutex_num[2]   <= FSL_S_Data_2[26:31];
                    if(lock_unlock[2] == 0)
                      state[2]  <= lock_phase;
                    else
                      state[2]  <= unlock_phase;
                  end
                else if(nr_of_reads[2] == 2)
                  // FSL_S_Data is lock_unlock
                  begin
                    nr_of_reads[2] <= nr_of_reads[2] - 1;
                    lock_unlock[2] <= FSL_S_Data_2[31];
                  end
              end
          lock_phase:
            if (FSL_S_Exists_2 == 1) begin
              state[2] <= Write_Outputs;
            end
          unlock_phase:
            if (FSL_S_Exists_2 == 1)
              state[2] <= Write_Outputs;
          Write_Outputs: 
              state[2] <= Idle;
        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]   <= NUMBER_OF_INPUT_WORDS - 1;
           nr_of_writes[3]  <= NUMBER_OF_OUTPUT_WORDS - 1;
           lock_unlock[3]   <= 0;
           mutex_num[3]     <= 0;
           pattern[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;
                lock_unlock[3] <= 0;
                mutex_num[3]   <= 0;
                pattern[3]     <= 0;
              end

          Read_Inputs: 
            if (FSL_S_Exists_3 == 1) 
              begin
                if(nr_of_reads[3] == 1)
                  // FSL_S_Data is mutex_num
                  begin
                    nr_of_reads[3] <= nr_of_reads[3] - 1;
                    mutex_num[3]   <= FSL_S_Data_3[26:31];
                    if(lock_unlock[3] == 0)
                      state[3]  <= lock_phase;
                    else
                      state[3]  <= unlock_phase;
                  end
                else if(nr_of_reads[3] == 2)
                  // FSL_S_Data is lock_unlock
                  begin
                    nr_of_reads[3] <= nr_of_reads[3] - 1;
                    lock_unlock[3] <= FSL_S_Data_3[31];
                  end
              end
          lock_phase:
            if (FSL_S_Exists_3 == 1) begin
              state[3] <= Write_Outputs;
            end
          unlock_phase:
            if (FSL_S_Exists_3 == 1)
              state[3] <= Write_Outputs;
          Write_Outputs: 
              state[3] <= Idle;
        endcase
   end


endmodule




module arbiter
(
  clk,
  rst,
  we_0,
  we_1,
  we_2,
  we_3,
  mutex_num_0,
  mutex_num_1,
  mutex_num_2,
  mutex_num_3,
  pattern_0,
  pattern_1,
  pattern_2,
  pattern_3,
  do_0,
  do_1,
  do_2,
  do_3
);


  input clk,rst,we_0,we_1,we_2,we_3;
  input [0:5] mutex_num_0,mutex_num_1,mutex_num_2,mutex_num_3;
  input [0:7] pattern_0,pattern_1,pattern_2,pattern_3;
  output [0:31] do_0,do_1,do_2,do_3;


  reg [0:1] token [0:3];//for arbitration
  reg [0:31] array [0:63];
  wire we_arr [0:3];
  wire [0:5] mutex_num_arr [0:3];
  wire [0:7] pattern_OUT_arr [0:3];
  assign we_arr[0] = we_0;
  assign we_arr[1] = we_1;
  assign we_arr[2] = we_2;
  assign we_arr[3] = we_3;
  assign mutex_num_arr[0] = mutex_num_0;
  assign mutex_num_arr[1] = mutex_num_1;
  assign mutex_num_arr[2] = mutex_num_2;
  assign mutex_num_arr[3] = mutex_num_3;
  assign pattern_OUT_arr[0] = pattern_0;
  assign pattern_OUT_arr[1] = pattern_1;
  assign pattern_OUT_arr[2] = pattern_2;
  assign pattern_OUT_arr[3] = pattern_3;

  assign do_0 = array[mutex_num_0];
  assign do_1 = array[mutex_num_1];
  assign do_2 = array[mutex_num_2];
  assign do_3 = array[mutex_num_3];



  always @ (posedge clk) begin
    if(rst) begin
      token[0] <= 0;
      token[1] <= 1;
      token[2] <= 2;
      token[3] <= 3;
    end
    if(we_arr[token[0]]) begin
      array[mutex_num_arr[token[0]]] <= {24'b0,pattern_OUT_arr[token[0]]};
      token[0] <= token[1];
      token[1] <= token[2];
      token[2] <= token[3];
      token[3] <= token[0];
    end
    else if(we_arr[token[1]]) begin
      array[mutex_num_arr[token[1]]] <= {24'b0,pattern_OUT_arr[token[1]]};
      token[0] <= token[0];
      token[1] <= token[2];
      token[2] <= token[3];
      token[3] <= token[1];
    end
    else if(we_arr[token[2]]) begin
      array[mutex_num_arr[token[2]]] <= {24'b0,pattern_OUT_arr[token[2]]};
      token[0] <= token[0];
      token[1] <= token[1];
      token[2] <= token[3];
      token[3] <= token[2];
    end
    else if(we_arr[token[3]]) begin
      array[mutex_num_arr[token[3]]] <= {24'b0,pattern_OUT_arr[token[3]]};
      token[0] <= token[0];
      token[1] <= token[1];
      token[2] <= token[2];
      token[3] <= token[3];
    end
  end

endmodule