//-------------------------------------------------------------------
//                                                                 
//-------------------------------------------------------------------------
//© 2024 Microchip Technology Inc. and its subsidiaries
//All rights reserved.
//ANY USE OR REDISTRIBUTION IN PART OR IN WHOLE MUST BE HANDLED IN
//ACCORDANCE WITH THE MICROCHIP LICENSE AGREEMENT AND MUST BE APPROVED
//IN ADVANCE IN WRITING.
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------
// Title        : bit_slip_chk.v
// Created      : November-2017
// Description  : This module implements the Checker logic for the 
// 		  counter pattern coming from receiver side
// Revision     : NA
// Hierarchy    :
//                bit_slip_PMA_top

//                  -- bit_slip_chk.v             <-- This module
//
// Target device: <Family:PolarFire> <Die:MPF300TS_ES> <Pkg:FCG1152>
//-------------------------------------------------------------------

module bit_slip_chk(
               clk_i          ,
	       reset_n_i   , 	
               start_i        ,
               clear_i        ,
               rx_val_i       ,
               data_in_i      ,
	       valid_signal, 	
               error_count_o  ,
               error_o        ,
               rx_val_o       ,
               lock_o
               );

//***************************************************************************
//****************** Signal Declaration     *********************************
//***************************************************************************
parameter  g_DATA_WID = 40;

//----------STATE parameter declaration---------
parameter [2:0] STATE_0 = 3'b000;
parameter [2:0] STATE_1 = 3'b001;
parameter [2:0] STATE_2 = 3'b010;
//----------------------------------------------

input clk_i; //input clock
input reset_n_i; //Reset signal for logic
input start_i; //start signal from UART interface to start pattern check
input clear_i; //clear signal from UART itnerface to clear error flags
input rx_val_i; //RX VALID signal from XCVR
input valid_signal; //denotes symbol alignment
input wire [g_DATA_WID-1:0]data_in_i; //XCVR RX data
output reg [31:0]error_count_o; //error counter output to UART
output reg error_o; //error flag output to UART
output reg rx_val_o; //RX_VALID output to UART
output reg lock_o; //data lock status to UART

reg [g_DATA_WID-1:0]s_count_data;
reg [g_DATA_WID-1:0]s_data;
reg [g_DATA_WID-1:0]s_data2;
reg s_count_start;
reg [2:0]s_count;


reg [31:0]s_error_count;
reg s_error;
reg s_lock;
reg s_rx_val;

reg clear_d1, clear_d2;

always@(posedge clk_i,negedge reset_n_i)
 begin
    if (reset_n_i == 1'b0)
    begin
        clear_d1 <= 1'b0;
        clear_d2 <= 1'b0;
    end
    else
    begin
        clear_d1 <= clear_i;
        clear_d2 <= clear_d1;
    end
end

//**************************************************************************
//********************* Count Checker Logic    *****************************
//**************************************************************************
 always@(posedge clk_i or negedge reset_n_i)
 begin
    if (reset_n_i == 1'b0)
    begin
        s_count <= 3'b000;
        s_count_data <= 40'h0000000000;
        s_count_start <= 1'b0;
    end
    else
    begin
       case (s_count)
            STATE_0:
              begin
              if(valid_signal == 1'b1) 
              s_count <=STATE_1;
              else
              s_count <= STATE_0;
              end
            STATE_1:
              begin 
              if(data_in_i == 40'h00000000bc)//check for K28.5 character
              
              begin
              
              s_count_start <= 1'b0;
              s_count <=STATE_1;
              end
              else if(s_data == 40'h0000000000)  
              begin             
             
              s_count_start <= 1'b0;
              s_count <=STATE_2;
              end         
              end
            
             STATE_2:
              begin 
              if(s_count_data < 40'h8000000000)
                begin   
                s_count_data <= s_count_data +1;//increment internal counter
                s_count_start <= 1'b1;
                s_count <=STATE_2;     
                end
              else
                begin
                s_count_data <= 40'h0000000000;
                s_count_start <= 1'b0;
                s_count <=STATE_0;
                end
              end       
              
            default:
              begin
              s_count_data <= 40'h0000000000;
              s_count_start <= 1'b0;
              s_count <=STATE_0;
              end
          endcase   
    end
end

//******************************************************************************
//***************** Registering Data input *************************************
//******************************************************************************
 always@(posedge clk_i,negedge reset_n_i)
 begin
    if (reset_n_i == 1'b0)
    begin
        s_data <= 40'h0000000000;
        s_data2 <= 40'h0000000000;
    end
    else
    begin
        s_data <= data_in_i;
        s_data2 <= s_data;
    end
end
//*****************************************************************************
//**************** Error and Lock Checking ************************************
//*****************************************************************************
 always@(posedge clk_i,negedge reset_n_i)
 begin
    if (reset_n_i == 1'b0)
    begin
        s_lock <= 1'b0;
        s_rx_val <= 1'b0;
        s_error_count <= 32'h00000000;
        s_error <= 1'b1;
    end
    else
    begin
        s_rx_val <= rx_val_i;
        if((s_count_start==1'b1) && (s_count_data == s_data2))//Compare received data with internal counter
        begin
        s_lock <= 1'b1;
        s_error_count <= 32'h00000000;
        s_error <= 1'b0;
        end
        else
        begin
        if(clear_d2==1'b1)begin
        s_error_count <= 32'h00000000;
        s_lock <= 1'b1;
        s_error <= 1'b0;
        end
        else
        begin
        s_error_count <= s_error_count +1;
        s_lock <= 1'b0;
        s_error <= 1'b1;
        end
        end
    end
  end  
  
//****************************************************************************
//*************** Registering UART Output*************************************
//****************************************************************************

always@(posedge clk_i,negedge reset_n_i)
 begin
    if (reset_n_i == 1'b0)
    begin
    rx_val_o <= 1'b0;
    lock_o <= 1'b0;
    error_count_o <= 32'h00000000;
    error_o <= 1'b0;
    end
    else if(start_i == 1'b1)
    begin
    rx_val_o <= s_rx_val;
    lock_o <= s_lock;
    error_count_o <= s_error_count;
    error_o <= s_error;
    end
end
   

endmodule

