///******************************************************************************
//
//    File Name    : receive_control

//    Description  : This module implements the control fsm to control the receive buffer and the PRBS checker error counter 
//                   clearing signal. This module looks for a rising or falling edge transition on the RX_VALIN_IN signal to start or 
//                   stop the receive buffer module. It also restarts the receive buffer lock process if the error counter reaches 63.


// Targeted device : Family           Die          Package
//                   IGLOO2           M2S010T      484 FBGA
// Author          : Solutions Team
//                             --RK
//
// COPYRIGHT 2013 BY MICROSEMI
// THE INFORMATION CONTAINED IN THIS DOCUMENT IS SUBJECT TO LICENSING RESTRICTIONS 
// FROM ACTEL CORP.  IF YOU ARE NOT IN POSSESSION OF WRITTEN AUTHORIZATION FROM 
// ACTEL FOR USE OF THIS FILE, THEN THE FILE SHOULD BE IMMEDIATELY DESTROYED AND 
// NO BACK-UP OF THE FILE SHOULD BE MADE. 
// 

//******************************************************************************/


//******************************************************************************
//**************************** Module Declaration ******************************
//******************************************************************************
`timescale 1ns / 1ps
module receive_control (RX_CLKIN_i, RX_RESETN_i, RX_VALIN_i, ERR_CNTR_255_i, CLEARIN_i, LOCK_GENIN_i,  START_LOCK_o, CLEAR_ERRCNTR_o) /* synthesis syn_hier=1*/;
  input RX_CLKIN_i;
  input RX_RESETN_i;
  input RX_VALIN_i;
  input ERR_CNTR_255_i;
  input CLEARIN_i;
  input LOCK_GENIN_i;

  output START_LOCK_o;
  output CLEAR_ERRCNTR_o;

  reg RX_VALIN_reg /* synthesis syn_preserve=1*/; 
  reg RX_VALIN_reg_d /* synthesis syn_preserve=1*/;
  reg start_lock_reg /* synthesis syn_preserve=1*/;
  reg clear_errcnt_reg /* synthesis syn_preserve=1*/;

  parameter [1:0] RC_INIT = 2'b00, START_LOCK_SET = 2'b01, START_LOCK_UNSET = 2'b10; 
  reg [1:0] RC_FSM_state;
  
//******************************************************************************
//**************************** RX_VALID edge detection**************************
//******************************************************************************

  always @(posedge RX_CLKIN_i or negedge RX_RESETN_i)
    begin
      if (!RX_RESETN_i)
        begin
	  RX_VALIN_reg <= 1'b0;
	end
      else
        begin
	  RX_VALIN_reg <= RX_VALIN_i;
	end
    end
    
    always @(posedge RX_CLKIN_i or negedge RX_RESETN_i)
     begin
      if (!RX_RESETN_i)
        begin
	  RX_VALIN_reg_d <= 1'b0;
	end
      else
        begin
	  RX_VALIN_reg_d <= RX_VALIN_reg;
	end
    end

    assign RX_VALIN_posedge = RX_VALIN_reg & ~RX_VALIN_reg_d;
    assign RX_VALIN_negedge = ~RX_VALIN_reg & RX_VALIN_reg_d;

//******************************************************************************
//**************************** RX Control FSM***********************************
//******************************************************************************
    always @(posedge RX_CLKIN_i or negedge RX_RESETN_i)
     begin
      if (!RX_RESETN_i)
        begin
	  RC_FSM_state <= RC_INIT;
	  start_lock_reg <= 1'b0;
	end
      else
        begin
	  case (RC_FSM_state)
	    RC_INIT          : begin
	                       if ((RX_VALIN_posedge == 1'b1) || (ERR_CNTR_255_i == 1'b1))
			        begin
				  RC_FSM_state <= START_LOCK_SET;
				end
			       else
			        begin
				  RC_FSM_state <= RC_INIT;
				end
	                       end
	    START_LOCK_SET   : begin
	                         start_lock_reg <= 1'b1;
				 if (LOCK_GENIN_i || RX_VALIN_negedge)
				  begin
				   RC_FSM_state <= START_LOCK_UNSET;
				  end
				 else
				  begin
				   RC_FSM_state <= START_LOCK_SET;
				  end
	                       end

	   START_LOCK_UNSET  : begin
	                        start_lock_reg <= 1'b0;
				RC_FSM_state <= RC_INIT;
	                       end
	  default            : begin
	                        RC_FSM_state <= RC_INIT;
	                       end
          endcase
	end
     end
 

//******************************************************************************
//**************************** Error counter clear control generation***********
//******************************************************************************   
     always @(posedge RX_CLKIN_i or negedge RX_RESETN_i)
     begin
      if (!RX_RESETN_i)
        begin
	  clear_errcnt_reg <= 1'b0;
	end
        else if  (CLEARIN_i)
        begin
	  clear_errcnt_reg <= 1'b1;
	end
      else
        begin
	  clear_errcnt_reg <= 1'b0;
	end
     end

     assign CLEAR_ERRCNTR_o = clear_errcnt_reg;
     assign START_LOCK_o = start_lock_reg;

endmodule