-------------------------------------------------------------------------------
--$Date: 2007/08/01 23:10:49 $
--$RCSfile: frame_check_vhd.ejava,v $
--$Revision: 1.1.2.1 $
-------------------------------------------------------------------------------
--   ____  ____ 
--  /   /\/   / 
-- /___/  \  /    Vendor: Xilinx 
-- \   \   \/     Version : 1.7
--  \   \         Application : GTP Wizard 
--  /   /         Filename : frame_check.vhd
-- /___/   /\     Timestamp : 
-- \   \  /  \ 
--  \___\/\___\ 
--
--
-- Module FRAME_CHECK
-- Generated by Xilinx GTP Wizard

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library UNISIM;
use UNISIM.VCOMPONENTS.ALL;

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

entity FRAME_CHECK is
generic
(
    RX_DATA_WIDTH            : integer := 16;
    USE_COMMA                : integer := 1;
    WORDS_IN_BRAM            : integer := 256;
    CONFIG_INDEPENDENT_LANES : integer := 0;
    START_OF_PACKET_CHAR     : std_logic_vector := x"55fb";
    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); 
    RX_ENMCOMMA_ALIGN        : out std_logic;
    RX_ENPCOMMA_ALIGN        : out std_logic;
    RX_ENCHAN_SYNC           : out 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);

    -- 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_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  start_of_packet_detected_r  :   std_logic;    
    signal  track_data_r                :   std_logic;
    
 
--*********************************Wire Declarations***************************
   
    signal  bram_data_r                 :   std_logic_vector(31 downto 0);
    signal  error_detected_c            :   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_data_has_start_char_c    :   std_logic;
    signal  rx_data_matches_bram_c      :   std_logic;
    signal  start_of_packet_char_c      :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    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';

    --______________________ Assign the start of packet character _____________   

    start_of_packet_char_c  <= START_OF_PACKET_CHAR;

    --________________________________ 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);                               
        
    rx_data_has_start_char_c   <=   '1' when (RX_DATA = start_of_packet_char_c) else '0';

    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;
    
    --______________________________ Capture incoming data ____________________    

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

    --_____________________________ Assign output ports _______________________    

    INC_OUT         <=  start_of_packet_detected_c;   

    PATTERN_MATCH_N <=  data_error_detected_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; --'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; --'1' after DLY;
        end if;
    end if;    
    end process;

    -- 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 ______________
         
    
    --An error is detected when data read for the BRAM does not match the incoming data
    rx_data_matches_bram_c <= '0' when (rx_data_r2 /= bram_data_r((RX_DATA_WIDTH-1) downto 0)) else '1';

    error_detected_c    <=   track_data_r 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 __________________________    

    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        if((RESET_ON_ERROR='1') or (SYSTEM_RESET='1') or 
        (read_counter_i = (WORDS_IN_BRAM-1)) or (start_of_packet_detected_c='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;

    --________________________________ 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_r,
        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;           

