//-------------------------------------------------------------------
//                                                                 
//-------------------------------------------------------------------------
//© 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        : pattern_chk.v
// Created      : June-2017
// Description  : This module implements checker logic for the incoming stream from transceiver
// Revision     : NA
// Hierarchy    :
//                PF_XCVR_64b66b
//                  
//                  -- pattern_chk.v              <-- This module
//
// Target device: <Family:PolarFire> <Die:MPF300TS_ES> <Pkg:FCG1152>
//-------------------------------------------------------------------

`timescale 1ns/1ps

module pattern_chk    (
	data_in,        // input data pattern
	data_valid,     // input data pattern
    rx_val,         // Receiver valid status
    hdr, lane_status_lock, // 64b66b related status signals
    start,
    hdr_valid, // hdr valid
	clr_err_counter, 
    error_cnt,      //error counter
 	clk,            // clock input
 	nreset,         // reset input
 	error_out,       // 0= pass, 1= fail
    rx_val_o,		// Output to UART interface
    lock_o,			// Output to UART interface
    error_count_o,	// Output to UART interface
    error_o			// Output to UART interface
	)/* synthesis syn_preserve=1 */;

 //------------Input Ports-------------- 
 input [63:0] data_in;
 input data_valid;
 input rx_val;    
 input start;
 
 input lane_status_lock;
 input [3:0] hdr;
 input hdr_valid;

 input clr_err_counter; 
 input clk, nreset;
 //----------Output Ports--------------
 output reg error_out;
 output reg [31:0]error_cnt;
 output reg rx_val_o;
 output reg lock_o;
 output reg [31:0] error_count_o;
 output reg error_o;   
 //------------Internal Variables--------
 reg [63:0] data_expected;

 reg [31:0] cnt32;

 reg [63:0] data_in_d1 , data_in_d2;
 reg [3:0] hdr_d1;
 reg lane_status_lock_d1, lane_status_lock_d2;
 
 wire start_data; // start generating and checking the data patten
 reg rx_val_t;   
 reg chk_lock;
 reg clear_d1;
 reg clear_d2;
 reg start_d1;
 reg start_d2;
    

//******************************************************************************
//-------------Code Starts Here-------
//******************************************************************************

always @(posedge clk or negedge nreset)
begin
    if (!nreset)
    begin
        clear_d1 <= 1'b0;
         clear_d2 <= 1'b0;
        start_d1 <= 1'b0;
         start_d2 <= 1'b0;
    end
    else
    begin
        clear_d1 <= clr_err_counter;
        clear_d2 <= clear_d1;
        start_d1 <= start;
        start_d2 <= start_d1;
    end
end
        

//******************************* Registering inputs Crossing ****************
always @(posedge clk or negedge nreset)
begin
	if (!nreset)
	begin
		data_in_d1 <= 64'h00;
		hdr_d1  <= 4'b0;
		lane_status_lock_d1 <= 1'b0;
		data_in_d2 <= 64'h00;
		lane_status_lock_d2 <= 1'b0;
	end
	else
	begin
        if ( data_valid == 1'b1)
            begin
            data_in_d1 <= data_in ;
            data_in_d2 <= data_in_d1 ;
            end

        if ( hdr_valid == 1'b1)
            begin
            hdr_d1  <= hdr;
            
            end

		
        lane_status_lock_d1 <= lane_status_lock;
		
        lane_status_lock_d2 <= lane_status_lock_d1;
	end

end

assign start_data = ((hdr_d1[3:0] == 4'b0001) && (lane_status_lock_d2 == 1'b1)) ? 1'b1 : 1'b0;
/**************************************************************************/
/**************************************************************************/
//count32 generator

   always @(posedge clk or negedge nreset)
     if (!nreset)
        begin
            cnt32 <= 32'h00000000;
        end
     else       
        begin
            if  ((start_data == 1'b1) && (data_valid == 1'b1)) 
                begin
                cnt32 <= cnt32 + 1'b1;
                end
        end

/*************************************************************************/
//Checking the data received with the expected data

   always @(posedge clk or negedge nreset)
    begin
     if (!nreset)
        begin
            data_expected  <= 64'h0000000000000000;
        end
     else
        begin
            if ((start_data == 1'b1) && (data_valid == 1'b1))
                begin
                    data_expected  <= {cnt32,cnt32};
                end
        end
    end

always @(posedge clk or negedge nreset)
begin
	if (!nreset)
	begin
		error_out  <= 1'b0;
        chk_lock   <= 1'b0;
        rx_val_t   <= 1'b0;
        error_cnt  <= 32'h00000000;
	end
    else
    begin
        rx_val_t   <= rx_val;
        if ((start_data == 1'b1) && (data_in_d2 == data_expected))
        begin
        error_out  <= 1'b0;
        chk_lock   <= 1'b1;
        error_cnt  <= 32'h00000000;
        end
        else 
        begin
        if (clear_d2 == 1'b1) 
        begin
        error_cnt <= 32'h00000000;
        error_out <= 1'b0;
        chk_lock  <= 1'b1;
        end
        else
        begin
        error_out <= 1'b1;
        error_cnt <= error_cnt + 'd1;
        chk_lock  <= 1'b0;
        end
        end
    end
end

/**********************************************************************/
//*********************************************************************
//********************* Registering UART Output************************
//*********************************************************************

always@(posedge clk,negedge nreset)
 begin
    if (nreset == 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_d2 == 1'b1)
    begin
    rx_val_o <= rx_val_t;
    lock_o <= chk_lock;
    error_count_o <= error_cnt;
    error_o <= error_out;
    end
end

endmodule 
