-------------------------------------------------------------------------------
--   ____  ____ 
--  /   /\/   / 
-- /___/  \  /    Vendor: Xilinx 
-- \   \   \/     Version : 1.12
--  \   \         Application : Virtex-6 FPGA GTX Transceiver Wizard  
--  /   /         Filename : frame_check.vhd
-- /___/   /\      
-- \   \  /  \ 
--  \___\/\___\ 
--
--
-- Module FRAME_CHECK
-- Generated by Xilinx Virtex-6 FPGA GTX Transceiver Wizard  
-- 
-- 
-- (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved.
-- 
-- This file contains confidential and proprietary information
-- of Xilinx, Inc. and is protected under U.S. and
-- international copyright and other intellectual property
-- laws.
-- 
-- DISCLAIMER
-- This disclaimer is not a license and does not grant any
-- rights to the materials distributed herewith. Except as
-- otherwise provided in a valid license issued to you by
-- Xilinx, and to the maximum extent permitted by applicable
-- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
-- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
-- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
-- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
-- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
-- (2) Xilinx shall not be liable (whether in contract or tort,
-- including negligence, or under any other theory of
-- liability) for any loss or damage of any kind or nature
-- related to, arising under or in connection with these
-- materials, including for any direct, or any indirect,
-- special, incidental, or consequential loss or damage
-- (including loss of data, profits, goodwill, or any type of
-- loss or damage suffered as a result of any action brought
-- by a third party) even if such damage or loss was
-- reasonably foreseeable or Xilinx had been advised of the
-- possibility of the same.
-- 
-- CRITICAL APPLICATIONS
-- Xilinx products are not designed or intended to be fail-
-- safe, or for use in any application requiring fail-safe
-- performance, such as life-support or safety devices or
-- systems, Class III medical devices, nuclear facilities,
-- applications related to the deployment of airbags, or any
-- other applications that could lead to death, personal
-- injury, or severe property or environmental damage
-- (individually and collectively, "Critical
-- Applications"). Customer assumes the sole risk and
-- liability of any use of Xilinx products in Critical
-- Applications, subject only to applicable laws and
-- regulations governing limitations on product liability.
-- 
-- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
-- PART OF THIS FILE AT ALL TIMES. 


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
use std.textio.all;
use ieee.std_logic_textio.all;
use ieee.std_logic_misc.all;
library UNISIM;
use UNISIM.VCOMPONENTS.ALL;

--***********************************Entity Declaration************************

entity FRAME_CHECK is
generic
(
    RX_DATA_WIDTH            : integer := 16;
    RXCTRL_WIDTH             : integer := 2;
    USE_COMMA                : integer := 1;
    NONE_MSB_FIRST_DEC       : integer := 0;
    COMMA_DOUBLE_DEC         : integer := 0;
    CHANBOND_SEQ_LEN         : integer := 1;
    WORDS_IN_BRAM            : integer := 256;
    CONFIG_INDEPENDENT_LANES : integer := 0;
    START_OF_PACKET_CHAR     : std_logic_vector(15 downto 0) ;
    COMMA_DOUBLE_CHAR        : std_logic_vector(15 downto 0) := x"f628";
    MEM_00       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_01       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_02       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_03       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_04       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_05       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_06       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_07       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_08       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_09       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_0A       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_0B       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_0C       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_0D       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_0E       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_0F       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_10       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_11       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_12       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_13       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_14       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_15       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_16       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_17       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_18       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_19       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_1A       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_1B       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_1C       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_1D       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_1E       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_1F       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_20       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_21       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_22       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_23       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_24       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_25       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_26       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_27       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_28       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_29       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_2A       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_2B       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_2C       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_2D       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_2E       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_2F       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_30       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_31       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_32       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_33       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_34       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_35       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_36       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_37       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_38       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_39       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_3A       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_3B       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_3C       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_3D       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_3E       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_3F       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_00      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_01      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_02      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_03      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_04      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_05      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_06      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_07      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000"
);
port
(
    -- User Interface
    RX_DATA                  : in  std_logic_vector((RX_DATA_WIDTH-1) downto 0); 
    RXCTRL_IN                : in  std_logic_vector((RXCTRL_WIDTH-1) downto 0); 
  
    RX_ENMCOMMA_ALIGN        : out std_logic;
    RX_ENPCOMMA_ALIGN        : out std_logic;
    RX_ENCHAN_SYNC           : out std_logic; 
    RX_CHANBOND_SEQ          : in  std_logic; 

    -- Control Interface
    INC_IN                   : in std_logic; 
    INC_OUT                  : out std_logic; 
    PATTERN_MATCH_N          : out std_logic;
    RESET_ON_ERROR           : in std_logic; 
      
    -- Error Monitoring
    ERROR_COUNT              : out std_logic_vector(7 downto 0);
    
    -- Track Data
    TRACK_DATA               : out std_logic;
   
    -- System Interface
    USER_CLK                 : in std_logic;       
    SYSTEM_RESET             : in std_logic
  
);


end FRAME_CHECK;


architecture RTL of FRAME_CHECK is


--***********************************Parameter Declarations********************

    constant DLY : time := 1 ns;

--***************************Internal Register Declarations********************

    signal  begin_r                     :   std_logic;
    signal  data_error_detected_r       :   std_logic;
    signal  error_count_r               :   unsigned(8 downto 0);
    signal  error_detected_r            :   std_logic;
    signal  read_counter_i              :   unsigned(8 downto 0);    
    signal  rx_chanbond_seq_r           :   std_logic;
    signal  rx_chanbond_seq_r2          :   std_logic;
    signal  rx_chanbond_seq_r3          :   std_logic;
    signal  rx_data_r                   :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_r2                  :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_r3                  :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_r4                  :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_r5                  :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_r6                  :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_r7                  :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_r_track             :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rxctrl_r                    :   std_logic_vector((RXCTRL_WIDTH-1) downto 0);
    signal  rxctrl_r2                   :   std_logic_vector((RXCTRL_WIDTH-1) downto 0);
    signal  rxctrl_r3                   :   std_logic_vector((RXCTRL_WIDTH-1) downto 0);
    signal  rxctrl_or                   :   std_logic;
    signal  start_of_packet_detected_r  :   std_logic;    
    signal  track_data_r                :   std_logic;
    signal  track_data_r2               :   std_logic;
    signal  track_data_r3               :   std_logic;
    signal  track_data_r4               :   std_logic;
    signal  sel                         :   std_logic_vector(1 downto 0);
    signal  bram_data_r                 :   std_logic_vector(31 downto 0);
         
 
--*********************************Wire Declarations***************************
   
    signal  bram_data_i                 :   std_logic_vector(31 downto 0);

    signal  chanbondseq_in_data         :   std_logic;
    signal  error_detected_c            :   std_logic;
    signal  input_to_chanbond_data_i    :   std_logic;
    signal  input_to_chanbond_reg_i     :   std_logic;
    signal  next_begin_c                :   std_logic;
    signal  next_data_error_detected_c  :   std_logic;
    signal  next_track_data_c           :   std_logic;
    signal  start_of_packet_detected_c  :   std_logic;
    signal  rx_chanbond_reg             :   std_logic_vector((CHANBOND_SEQ_LEN-1) downto 0);
    signal  rx_chanbond_reg_bitwise_or_i:   std_logic;
    signal  rx_data_aligned             :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_has_start_char_c    :   std_logic;
    signal  rx_data_matches_bram_c      :   std_logic;
    signal  tied_to_ground_i            :   std_logic;
    signal  tied_to_ground_vec_i        :   std_logic_vector(31 downto 0);
    signal  tied_to_vcc_i               :   std_logic;


--*********************************Main Body of Code***************************
begin

    --_______________________  Static signal Assigments _______________________   

    tied_to_ground_i        <= '0';
    tied_to_ground_vec_i    <= (others=>'0');
    tied_to_vcc_i           <= '1';

    --______________________ Register RXDATA once to ease timing ______________   

    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            rx_data_r <= RX_DATA after DLY;
        end if;
    end process;

    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            rxctrl_r <= RXCTRL_IN after DLY;
        end if;
    end process;
    --________________________________ State machine __________________________    
    
    
    -- State registers
    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            if(RESET_ON_ERROR ='1' or SYSTEM_RESET = '1' ) then
                begin_r                <=  '1' after DLY;
                track_data_r           <=  '0' after DLY;
                data_error_detected_r  <=  '0' after DLY;
            else
                begin_r                <=  next_begin_c after DLY;
                track_data_r           <=  next_track_data_c after DLY;
                data_error_detected_r  <=  next_data_error_detected_c after DLY;
            end if;
        end if;
    end process;

    -- Next state logic
    next_begin_c               <=   (begin_r and not start_of_packet_detected_r) or data_error_detected_r ;

    next_track_data_c          <=   (begin_r and start_of_packet_detected_r) or (track_data_r and not error_detected_r);
                                      
    next_data_error_detected_c <=   (track_data_r and error_detected_r);                               
          
    start_of_packet_detected_c <=   INC_IN when (CONFIG_INDEPENDENT_LANES=0) else rx_data_has_start_char_c;

    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        start_of_packet_detected_r    <=   start_of_packet_detected_c after DLY;
    end if;    
    end process;
    
    -- Registering for timing
    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        track_data_r2    <=   track_data_r after DLY;
    end if;    
    end process;

    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        track_data_r3    <=   track_data_r2 after DLY;
    end if;    
    end process;

    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        track_data_r4    <=   track_data_r3 after DLY;
    end if;    
    end process;

    --______________________________ Capture incoming data ____________________ 



datapath_width_32_40_16_or_20: if ((RX_DATA_WIDTH=16) or (RX_DATA_WIDTH=20) or (RX_DATA_WIDTH=32) or (RX_DATA_WIDTH=40)) generate
    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            if(SYSTEM_RESET = '1') then 
                rx_data_r2      <=  (others => '0') after DLY;
                rx_data_r4      <=  (others => '0') after DLY;
                rx_data_r5      <=  (others => '0') after DLY;
                rx_data_r6      <=  (others => '0') after DLY;
                rx_data_r7      <=  (others => '0') after DLY;
                rx_data_r_track <=  (others => '0') after DLY;
            else
                rx_data_r2      <=  rx_data_r after DLY;
                rx_data_r4      <=  rx_data_r3 after DLY;
                rx_data_r5      <=  rx_data_r4 after DLY;
                rx_data_r6      <=  rx_data_r5 after DLY;
                rx_data_r7      <=  rx_data_r6 after DLY;
                rx_data_r_track <=  rx_data_r7 after DLY;
            end if;
        end if;    
    end process;

    rx_data_aligned <= rx_data_r3;

    --___________________________ Code for Channel bonding ____________________    
    -- code to prevent checking of clock correction sequences for the start of packet char
    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            rx_chanbond_seq_r    <=  RX_CHANBOND_SEQ after DLY;
            rx_chanbond_seq_r2   <=  rx_chanbond_seq_r after DLY;
            rx_chanbond_seq_r3   <=  rx_chanbond_seq_r2 after DLY;
        end if;    
    end process;

    input_to_chanbond_reg_i  <= rx_chanbond_seq_r2;
    input_to_chanbond_data_i <= tied_to_ground_i;
end generate datapath_width_32_40_16_or_20;

datapath_width_8_or_10: if ((RX_DATA_WIDTH=8) or (RX_DATA_WIDTH=10)) generate
    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            if(SYSTEM_RESET = '1') then 
                rx_data_r2      <=  (others => '0') after DLY;
                rx_data_r3      <=  (others => '0') after DLY;
                rx_data_r4      <=  (others => '0') after DLY;
                rx_data_r5      <=  (others => '0') after DLY;
                rx_data_r_track <=  (others => '0') after DLY;
            else
                rx_data_r2      <=  rx_data_r after DLY;
                rx_data_r3      <=  rx_data_r2 after DLY;
                rx_data_r4      <=  rx_data_r3 after DLY;
                rx_data_r5      <=  rx_data_r4 after DLY;
                rx_data_r_track <=  rx_data_r5 after DLY;
            end if;
        end if;    
    end process;
    
    rx_data_aligned <= RX_DATA;
    input_to_chanbond_reg_i  <= RX_CHANBOND_SEQ;
    input_to_chanbond_data_i <= RX_CHANBOND_SEQ;
end generate datapath_width_8_or_10;



   



    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            if(SYSTEM_RESET = '1') then
              rxctrl_r2      <=  (others => '0') after DLY;
              rxctrl_r3      <=  (others => '0') after DLY;
            else
              rxctrl_r2      <=  rxctrl_r after DLY;
              rxctrl_r3      <=  rxctrl_r2 after DLY;
            end if;
        end if;
    end process;

    --___________________________ Code for Channel bonding ____________________    
    -- code to prevent checking of clock correction sequences for the start of packet char
    register_chan_seq: for i in 0 to (CHANBOND_SEQ_LEN-1) generate
        case_i_equal_to_0: if (i=0) generate 
            rx_chanbond_reg_0 : FD port map (Q => rx_chanbond_reg(i),D => input_to_chanbond_reg_i,C => USER_CLK);
        end generate case_i_equal_to_0;
        case_i_greater_than_0: if (i>0) generate 
            rx_chanbond_reg_i :FD port map (Q => rx_chanbond_reg(i),D => rx_chanbond_reg(i-1),C => USER_CLK);
        end generate case_i_greater_than_0;
    end generate register_chan_seq;
    
    chanbondseq_in_data <= input_to_chanbond_data_i or rx_chanbond_reg_bitwise_or_i;

    process(rx_chanbond_reg)
    variable rx_chanbond_var : std_logic;
    variable i               : std_logic;
    begin
        rx_chanbond_var := '0';
        bit_wise_or : for  i in 0 to (CHANBOND_SEQ_LEN-1) loop
            rx_chanbond_var :=  rx_chanbond_var or rx_chanbond_reg(i);
        end loop;
        rx_chanbond_reg_bitwise_or_i <= rx_chanbond_var;
    end process;

    process(RXCTRL_IN)
    variable or_rxctrl_var : std_logic;
    variable i             : std_logic;
    begin
        or_rxctrl_var := '0';
        bit_wise_rxctrl_or : for  i in 0 to (RXCTRL_WIDTH-1) loop
            or_rxctrl_var :=  or_rxctrl_var or RXCTRL_IN(i);
        end loop;
        rxctrl_or <= or_rxctrl_var;
    end process;



    rx_data_has_start_char_c <= '1' when ((rx_data_aligned(7 downto 0) = START_OF_PACKET_CHAR(7 downto 0)) and (chanbondseq_in_data='0') and (rxctrl_or='1')) else '0';

    --_____________________________ Assign output ports _______________________    

    TRACK_DATA      <=  track_data_r;    


    -- Drive the enamcommaalign port of the mgt for alignment
    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        if(SYSTEM_RESET = '1') then 
            RX_ENMCOMMA_ALIGN   <= '0' after DLY;
        else              
            RX_ENMCOMMA_ALIGN   <= '1' after DLY;
        end if;
    end if;    
    end process;

    -- Drive the enapcommaalign port of the mgt for alignment
    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        if(SYSTEM_RESET = '1') then  
            RX_ENPCOMMA_ALIGN   <= '0' after DLY;
        else              
            RX_ENPCOMMA_ALIGN   <= '1' after DLY;
        end if;
    end if;    
    end process;

    INC_OUT         <=  start_of_packet_detected_c;   

    PATTERN_MATCH_N <=  data_error_detected_r;

    -- Drive the enchansync port of the mgt for channel bonding
    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        if(SYSTEM_RESET = '1') then 
            RX_ENCHAN_SYNC   <= '0' after DLY;
        else              
            RX_ENCHAN_SYNC   <= '1' after DLY;
        end if;
    end if;    
    end process;
    
    --___________________________ Check incoming data for errors ______________
         
    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
            bram_data_r   <= bram_data_i after DLY;
    end if;    
    end process;
    
    --An error is detected when data read for the BRAM does not match the incoming data
use_40bit : if RX_DATA_WIDTH = 40 generate
    rx_data_matches_bram_c <= '0' when (rx_data_r_track /= (tied_to_ground_vec_i(7 downto 0) & bram_data_r)) else '1';
end generate use_40bit;

not_40bit : if RX_DATA_WIDTH /= 40 generate
    rx_data_matches_bram_c <= '0' when (rx_data_r_track /= bram_data_r((RX_DATA_WIDTH-1) downto 0)) else '1';
end generate not_40bit;

    error_detected_c    <=   track_data_r4 and not rx_data_matches_bram_c;   
    
    
enable_error_check : if USE_COMMA = 1 generate
    --We register the error_detected signal for use with the error counter logic
    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        if(not(track_data_r = '1')) then 
            error_detected_r    <= '0' after DLY;
        else
            error_detected_r    <=  error_detected_c after DLY;
        end if;
    end if;    
    end process;
end generate enable_error_check;

disable_error_check : if USE_COMMA = 0 generate
    -- Since the comma detect logic has not been enabled, the error counter has been disabled since
    -- it doesnt make sense to be searching for an align character in the data. To enable the error 
    -- count again, please see the code above
    
       error_detected_r    <= '0';

end generate disable_error_check;

    
    --We count the total number of errors we detect. By keeping a count we make it less likely that we will miss
    --errors we did not directly observe. This counter must be reset when it reaches its max value
    process ( USER_CLK )
    begin
    if( USER_CLK'event and USER_CLK = '1') then
        if(SYSTEM_RESET='1') then
            error_count_r       <=  (others => '0') after DLY;
        elsif(error_detected_r = '1') then
            error_count_r       <=  error_count_r + 1 after DLY;
        end if;
    end if;
    end process;
        
            
    --Here we connect the lower 8 bits of the count (the MSbit is used only to check when the counter reaches
    --max value) to the module output
    ERROR_COUNT     <=   std_logic_vector(error_count_r(7 downto 0));

    --____________________________ Counter to read from BRAM __________________________    
four_byte : if RX_DATA_WIDTH > 20 generate
    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        if((SYSTEM_RESET='1') or (read_counter_i = (WORDS_IN_BRAM-1)))  then
            read_counter_i   <=  (others => '0') after DLY;
        elsif(((start_of_packet_detected_r and not track_data_r)='1')) then
            read_counter_i   <=  "000000001" after DLY;
        else read_counter_i  <=  read_counter_i + 1 after DLY;
        end if;
    end if;
    end process;
end generate four_byte;

one_or_two_byte : if RX_DATA_WIDTH <= 20 generate
    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        if((SYSTEM_RESET='1') or (read_counter_i = (WORDS_IN_BRAM-1))
        or ((start_of_packet_detected_r and not track_data_r)='1'))  then
            read_counter_i   <=  (others => '0') after DLY;
        else read_counter_i  <=  read_counter_i + 1 after DLY;
        end if;
    end if;
    end process;
end generate one_or_two_byte;

    --________________________________ BRAM Instantiation _____________________________    

    dual_port_block_ram_i  :  RAMB16_S36_S36 
    generic map
    (
        INIT_00          =>  MEM_00,
        INIT_01          =>  MEM_01,
        INIT_02          =>  MEM_02,
        INIT_03          =>  MEM_03,
        INIT_04          =>  MEM_04,
        INIT_05          =>  MEM_05,
        INIT_06          =>  MEM_06,
        INIT_07          =>  MEM_07,
        INIT_08          =>  MEM_08,
        INIT_09          =>  MEM_09,
        INIT_0A          =>  MEM_0A,
        INIT_0B          =>  MEM_0B,
        INIT_0C          =>  MEM_0C,
        INIT_0D          =>  MEM_0D,
        INIT_0E          =>  MEM_0E,
        INIT_0F          =>  MEM_0F,
        INIT_10          =>  MEM_10,
        INIT_11          =>  MEM_11,
        INIT_12          =>  MEM_12,
        INIT_13          =>  MEM_13,
        INIT_14          =>  MEM_14,
        INIT_15          =>  MEM_15,
        INIT_16          =>  MEM_16,
        INIT_17          =>  MEM_17,
        INIT_18          =>  MEM_18,
        INIT_19          =>  MEM_19,
        INIT_1A          =>  MEM_1A,
        INIT_1B          =>  MEM_1B,
        INIT_1C          =>  MEM_1C,
        INIT_1D          =>  MEM_1D,
        INIT_1E          =>  MEM_1E,
        INIT_1F          =>  MEM_1F,
        INIT_20          =>  MEM_20,
        INIT_21          =>  MEM_21,
        INIT_22          =>  MEM_22,
        INIT_23          =>  MEM_23,
        INIT_24          =>  MEM_24,
        INIT_25          =>  MEM_25,
        INIT_26          =>  MEM_26,
        INIT_27          =>  MEM_27,
        INIT_28          =>  MEM_28,
        INIT_29          =>  MEM_29,
        INIT_2A          =>  MEM_2A,
        INIT_2B          =>  MEM_2B,
        INIT_2C          =>  MEM_2C,
        INIT_2D          =>  MEM_2D,
        INIT_2E          =>  MEM_2E,
        INIT_2F          =>  MEM_2F,
        INIT_30          =>  MEM_30,
        INIT_31          =>  MEM_31,
        INIT_32          =>  MEM_32,
        INIT_33          =>  MEM_33,
        INIT_34          =>  MEM_34,
        INIT_35          =>  MEM_35,
        INIT_36          =>  MEM_36,
        INIT_37          =>  MEM_37,
        INIT_38          =>  MEM_38,
        INIT_39          =>  MEM_39,
        INIT_3A          =>  MEM_3A,
        INIT_3B          =>  MEM_3B,
        INIT_3C          =>  MEM_3C,
        INIT_3D          =>  MEM_3D,
        INIT_3E          =>  MEM_3E,
        INIT_3F          =>  MEM_3F,
        INITP_00         =>  MEMP_00,
        INITP_01         =>  MEMP_01,
        INITP_02         =>  MEMP_02,
        INITP_03         =>  MEMP_03,
        INITP_04         =>  MEMP_04,
        INITP_05         =>  MEMP_05,
        INITP_06         =>  MEMP_06,
        INITP_07         =>  MEMP_07

    )
    port map 
    (
        ADDRA            =>  std_logic_vector(read_counter_i),
        DIA              =>  tied_to_ground_vec_i(31 downto 0),
        DIPA             =>  tied_to_ground_vec_i(3 downto 0),
        DOA              =>  bram_data_i,
        DOPA             =>  open, 
        WEA              =>  tied_to_ground_i,
        ENA              =>  tied_to_vcc_i,
        SSRA             =>  tied_to_ground_i, 
        CLKA             =>  USER_CLK,
                  
        ADDRB            =>  tied_to_ground_vec_i(8 downto 0),
        DIB              =>  tied_to_ground_vec_i(31 downto 0),
        DIPB             =>  tied_to_ground_vec_i(3 downto 0),
        DOB              =>  open,  
        DOPB             =>  open, 
        WEB              =>  tied_to_ground_i,
        ENB              =>  tied_to_ground_i,
        SSRB             =>  tied_to_ground_i,
        CLKB             =>  tied_to_ground_i       
    );       
    
    
end RTL;           

