///////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------
// 
// © 2022 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_even.v
// Created      : November-2017
// Description  : This module implements the Checker logic for the counter 
//                pattern coming from receiver side
// Hierarchy    :
//                Top_SD
//                  -- pattern_chk_even.v             <-- This module
//
// Target device: <Family:PolarFire> <Die:MPF300TS_ES> <Pkg:FCG1152>
//-------------------------------------------------------------------

module pattern_chk_even(clk_i,
                   reset_n_i,
                   start_i,
                   clear_i,
                   rx_val_i,
                   data_in_i,
                   Rx_K_Char_i,
                   error_count_o,
                   error_o,
                   rx_val_o,
                   lock_o);

  parameter g_DATA_WID = 32;
  
  //STATE parameter declaration
  parameter[2 : 0] STATE_0 = 3'b000;
  parameter[2 : 0] STATE_1 = 3'b001;
  parameter[2 : 0] STATE_2 = 3'b010;
  parameter[2 : 0] STATE_3 = 3'b011;
  parameter[2 : 0] STATE_4 = 3'b100;
  parameter[2 : 0] STATE_5 = 3'b101;

  input clk_i;                                  // input clock
  input reset_n_i;                              // Reset for logic
  input start_i;                                // Start data processing
  input clear_i;                                // Clear all output and status
  input rx_val_i;                               // RX vaild input
  input wire[g_DATA_WID - 1 : 0] data_in_i;     // Recivered data
  input wire[3 : 0] Rx_K_Char_i;                // Recivered K characters
  output reg[g_DATA_WID - 1 : 0] error_count_o; // Error count
  output reg error_o;                           // Error status
  output reg rx_val_o;                          // RX valid status
  output reg lock_o;                            // Lock status
  
  
  reg[g_DATA_WID - 1 : 0] s_count_data;
  reg[g_DATA_WID - 1 : 0] s_data;
  reg s_count_start;
  reg[2 : 0] s_count;
  reg[g_DATA_WID - 1 : 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,negedge reset_n_i)
    begin
      if (reset_n_i == 1'b0)
        begin
          s_count <= 3'b000;
          s_count_data <= 32'h00000000;
          s_count_start <= 1'b0;
        end
      else
        begin
          case (s_count)
            STATE_0:
              begin
                if ((Rx_K_Char_i == 4'b0001) && (data_in_i == 32'h000000BC))
                  begin
                    s_count <= STATE_1;
                    s_count_start <= 1'b0;
                  end
                else
                  begin
                    s_count <= STATE_0;
                  end
              end
            STATE_1:
              begin
                if ((Rx_K_Char_i == 4'b0001) && (data_in_i == 32'h000000BC))
                  begin
                    s_count <= STATE_2;
                    s_count_start <= 1'b0;
                  end
                else
                  begin
                    s_count <= STATE_0;
                  end
              end
            STATE_2:
              begin
                if ((Rx_K_Char_i == 4'b0001) && (data_in_i == 32'h000000BC))
                  begin
                    s_count <= STATE_3;
                    s_count_start <= 1'b0;
                  end
                else
                  begin
                    s_count <= STATE_0;
                  end
              end
            STATE_3:
              begin
                if ((Rx_K_Char_i == 4'b0001) && (data_in_i == 32'h000000BC))
                  begin
                    s_count <= STATE_4;
                    s_count_start <= 1'b1;
                  end
                else
                  begin
                    s_count <= STATE_0;
                  end
              end
            STATE_4:
              begin
                if (Rx_K_Char_i == 4'b0000)
                  begin
                    s_count_data <= 32'h00000001;
                    s_count_start <= 1'b1;
                    s_count <= STATE_5;
                  end
                else
                  begin
                    s_count <= STATE_4;
                    s_count_data <= s_count_data;
                    s_count_start <= s_count_start;
                  end
              end
            STATE_5:
              begin
                if (s_count_data < 32'h80000000)
                  begin
                    s_count_data <= s_count_data + 2;
                    s_count_start <= 1'b1;
                    s_count <= STATE_5;
                  end
                else
                  begin
                    s_count_data <= 32'h00000000;
                    s_count_start <= 1'b0;
                    s_count <= STATE_0;
                  end
              end
            default:
              begin
                s_count_data <= 32'h00000000;
                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 <= 32'h00000000;
        end
      else
        begin
          s_data <= data_in_i;
        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_data))
            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
