library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

	 entity ent_parser_krabicka is
        generic
        (
            pociatok_adresovania                            : integer := 1000000
        );

        port
        (
            --riadenie hodinami
            parser_CLK                              : in    std_logic;
            --asynchronny reset
            parser_RESET                            : in    std_logic;

            --vstupny FrameLink
            parser_INPUT_SOF_N                      : in    std_logic;
            parser_INPUT_SOP_N                      : in    std_logic;
            parser_INPUT_EOP_N                      : in    std_logic;
            parser_INPUT_EOF_N                      : in    std_logic;
            parser_INPUT_SRC_RDY_N                  : in    std_logic;
            parser_INPUT_DST_RDY_N                  : out   std_logic;
            parser_INPUT_DATA                       : in    std_logic_vector ( 63 downto 0 );
            parser_INPUT_DREM                       : in    std_logic_vector (  2 downto 0 );
            --vystupny FrameLink
            parser_OUTPUT_SOF_N                     : out   std_logic;
            parser_OUTPUT_SOP_N                     : out   std_logic;
            parser_OUTPUT_EOP_N                     : out   std_logic;
            parser_OUTPUT_EOF_N                     : out   std_logic;
            parser_OUTPUT_SRC_RDY_N                 : out   std_logic;
            parser_OUTPUT_DST_RDY_N                 : in    std_logic;
            parser_OUTPUT_DATA                      : out   std_logic_vector ( 63 downto 0 );
            parser_OUTPUT_DREM                      : out   std_logic_vector (  2 downto 0 );
            --zbernica MI32 vchadzajuca do krabicky
            parser_MI32_DWR                        : in    std_logic_vector(31 downto 0);
            parser_MI32_ADDR                       : in    std_logic_vector(31 downto 0);
            parser_MI32_RD                         : in    std_logic;
            parser_MI32_WR                         : in    std_logic;
            parser_MI32_BE                         : in    std_logic_vector(3 downto 0);
            parser_MI32_DRD                        : out   std_logic_vector(31 downto 0);
            parser_MI32_ARDY                       : out   std_logic;
            parser_MI32_DRDY                       : out   std_logic

        );
    end entity ent_parser_krabicka;


     architecture krabicka_pokus_3 of ent_parser_krabicka is
--            type typ_STAV_NAPLNANIE_BUFFERU is (stav_CAKA_RAMEC, stav_ZAHLAVIE,
--                                                stav_OSMA_1, stav_OSMA_2, stav_OSMA_3, stav_OSMA_4, stav_OSMA_5, stav_OSMA_6,
--                                                stav_ZVYSNE_DATA, stav_ZAPATIE);
--            signal fsm_AKTUALNY_STAV, fsm_NASLEDUJUCI_STAV : typ_STAV_NAPLNANIE_BUFFERU;


				signal CLK							  :  std_logic;
				signal RESET						  :  std_logic;
            -- vstupny FrameLink
            signal INPUT_SOF_N              :  std_logic;
            signal INPUT_SOP_N              :  std_logic;
            signal INPUT_EOP_N              :  std_logic;
            signal INPUT_EOF_N              :  std_logic;
            signal INPUT_SRC_RDY_N          :  std_logic;
            signal INPUT_DST_RDY_N          :  std_logic;
            signal INPUT_DATA               :  std_logic_vector ( 63 downto 0 );
            signal INPUT_DREM               :  std_logic_vector (  2 downto 0 );
            -- vystupny FrameLink
            signal OUTPUT_SOF_N             :  std_logic;
            signal OUTPUT_SOP_N             :  std_logic;
            signal OUTPUT_EOP_N             :  std_logic;
            signal OUTPUT_EOF_N             :  std_logic;
            signal OUTPUT_SRC_RDY_N         :  std_logic;
            signal OUTPUT_DST_RDY_N         :  std_logic;
            signal OUTPUT_DATA              :  std_logic_vector ( 63 downto 0 );
            signal OUTPUT_DREM              :  std_logic_vector (  2 downto 0 );

            --registre na ukladanie dat
            signal reg_MAC_DST_01           : std_logic_vector(31 downto 0);
            signal reg_MAC_DST_02           : std_logic_vector(31 downto 0);
            signal reg_MAC_SRC_01           : std_logic_vector(31 downto 0);
            signal reg_MAC_SRC_02           : std_logic_vector(31 downto 0);
            signal reg_ETHERTYPE            : std_logic_vector(31 downto 0);
            signal reg_IPV4_SRC             : std_logic_vector(31 downto 0);
            signal reg_IPV4_DST             : std_logic_vector(31 downto 0);
            signal reg_PROTOCOL             : std_logic_vector(31 downto 0);
            signal reg_PORT_SRC             : std_logic_vector(31 downto 0);
            signal reg_PORT_DST             : std_logic_vector(31 downto 0);
            --vyber registra
            signal cs_reg_MAC_DST_01  : std_logic;
            signal cs_reg_MAC_DST_02  : std_logic;
            signal cs_reg_MAC_SRC_01  : std_logic;
            signal cs_reg_MAC_SRC_02  : std_logic;
            signal cs_reg_ETHERTYPE   : std_logic;
            signal cs_reg_IPV4_SRC    : std_logic;
            signal cs_reg_IPV4_DST    : std_logic;
            signal cs_reg_PROTOCOL    : std_logic;
            signal cs_reg_PORT_SRC    : std_logic;
            signal cs_reg_PORT_DST    : std_logic;
            --povolenie zapisu
            signal we_reg_MAC_DST_01  : std_logic;
            signal we_reg_MAC_DST_02  : std_logic;
            signal we_reg_MAC_SRC_01  : std_logic;
            signal we_reg_MAC_SRC_02  : std_logic;
            signal we_reg_ETHERTYPE   : std_logic;
            signal we_reg_IPV4_SRC    : std_logic;
            signal we_reg_IPV4_DST    : std_logic;
            signal we_reg_PROTOCOL    : std_logic;
            signal we_reg_PORT_SRC    : std_logic;
            signal we_reg_PORT_DST    : std_logic;

            --zbernica
            signal intra_MI32_DWR               :   std_logic_vector(31 downto 0);
            signal intra_MI32_ADDR              :   std_logic_vector(31 downto 0);
            signal intra_MI32_RD                :   std_logic;
            signal intra_MI32_WR                :   std_logic;
            signal intra_MI32_BE                :   std_logic_vector(3 downto 0);
            signal intra_MI32_DRD               :   std_logic_vector(31 downto 0);
            signal intra_MI32_ARDY              :   std_logic;
            signal intra_MI32_DRDY              :   std_logic;

            signal reg_mi32_exp_addr_9          :   std_logic;
            signal reg_mi32_exp_addr_12         :   std_logic;
                -- predchystane pre fazu cislo 4
				--signaly na naplnanie registrov automatom
--				signal zapis_OSMA_1		: std_logic;
--				signal zapis_OSMA_2		: std_logic;
--				signal zapis_OSMA_3		: std_logic;
--				signal zapis_OSMA_4		: std_logic;
--				signal zapis_OSMA_5		: std_logic;
--				signal zapis_OSMA_6		: std_logic;


               -- -------------------------------------------------------------------------
   --                         Example instance signals
   -- -------------------------------------------------------------------------
   signal bram_do          : std_logic_vector(31 downto 0);
	signal reg_do				: std_logic_vector(31 downto 0);


--------------------------------------------------------------------


        begin

			   CLK <= parser_CLK;
				RESET <= parser_RESET;
            -- budeme pouzivat lokalne signaly bez predpony "parser_"
            -- vstupne porty => lokalne signaly
                   INPUT_SOF_N     <=  parser_INPUT_SOF_N;
                   INPUT_SOP_N     <=  parser_INPUT_SOP_N;
                   INPUT_EOP_N     <=  parser_INPUT_EOP_N;
                   INPUT_EOF_N     <=  parser_INPUT_EOF_N;
                   INPUT_SRC_RDY_N <=  parser_INPUT_SRC_RDY_N;
            parser_INPUT_DST_RDY_N <=         INPUT_DST_RDY_N;
                   INPUT_DATA      <=  parser_INPUT_DATA;
                   INPUT_DREM      <=  parser_INPUT_DREM;
            -- lokalne signaly => vystupne porty
            parser_OUTPUT_SOF_N     <=         OUTPUT_SOF_N;
            parser_OUTPUT_SOP_N     <=         OUTPUT_SOP_N;
            parser_OUTPUT_EOP_N     <=         OUTPUT_EOP_N;
            parser_OUTPUT_EOF_N     <=         OUTPUT_EOF_N;
            parser_OUTPUT_SRC_RDY_N <=         OUTPUT_SRC_RDY_N;
                   OUTPUT_DST_RDY_N <=  parser_OUTPUT_DST_RDY_N;
            parser_OUTPUT_DATA      <=         OUTPUT_DATA;
            parser_OUTPUT_DREM      <=         OUTPUT_DREM;


            process(CLK, RESET)
                begin
                if (CLK'event AND CLK = '1') then
                    if( RESET = '1')
                    then
                        fsm_AKTUALNY_STAV <= stav_CAKA_RAMEC;
                    else
                        fsm_AKTUALNY_STAV <= fsm_NASLEDUJUCI_STAV;
                    end if;
                end if;
            end process;


            process(fsm_AKTUALNY_STAV, INPUT_SOF_N, INPUT_EOF_N,
            INPUT_SOP_N, INPUT_EOP_N, INPUT_SRC_RDY_N,
            INPUT_DST_RDY_N)
                begin
                    fsm_NASLEDUJUCI_STAV <= fsm_AKTUALNY_STAV;
                    zapis_OSMA_1 <= '0';
                    zapis_OSMA_2 <= '0';
                    zapis_OSMA_3 <= '0';
                    zapis_OSMA_4 <= '0';
                    zapis_OSMA_5 <= '0';
                    zapis_OSMA_6 <= '0';
                    if( INPUT_SRC_RDY_N = '0' AND INPUT_DST_RDY_N = '0')
                    then
                        case fsm_AKTUALNY_STAV is
                            when stav_CAKA_RAMEC =>
                                if( INPUT_SOF_N     = '0' )
                                then
                                    fsm_NASLEDUJUCI_STAV <= stav_ZAHLAVIE;
                                end if;
                            when stav_ZAHLAVIE =>
                                if( INPUT_EOP_N     = '0' )
                                then
                                    fsm_NASLEDUJUCI_STAV <= stav_OSMA_1;
                                end if;
                            when stav_OSMA_1 =>
                                    fsm_NASLEDUJUCI_STAV <= stav_OSMA_2;
                                    zapis_OSMA_1 <= '1';
                            when stav_OSMA_2 =>
                                    fsm_NASLEDUJUCI_STAV <= stav_OSMA_3;
                                    zapis_OSMA_2 <= '1';
                            when stav_OSMA_3 =>
                                    fsm_NASLEDUJUCI_STAV <= stav_OSMA_4;
                                    zapis_OSMA_3 <= '1';
                            when stav_OSMA_4 =>
                                    fsm_NASLEDUJUCI_STAV <= stav_OSMA_5;
                                    zapis_OSMA_4 <= '1';
                            when stav_OSMA_5 =>
                                    fsm_NASLEDUJUCI_STAV <= stav_OSMA_6;
                                    zapis_OSMA_5 <= '1';
                            when stav_OSMA_6 =>
                                    fsm_NASLEDUJUCI_STAV <= stav_ZVYSNE_DATA;
                                    zapis_OSMA_6 <= '1';
                            when stav_ZVYSNE_DATA =>
                                if( INPUT_EOP_N = '0' AND
                                    INPUT_EOF_N = '0' )             --skoncil FrameLink ramec
                                then
                                    fsm_NASLEDUJUCI_STAV <= stav_CAKA_RAMEC;
                                elsif( INPUT_EOP_N = '0' )          --skoncila iba cast DATA v FL ramci
                                then
                                    fsm_NASLEDUJUCI_STAV <= stav_ZAPATIE;
                                else                                --prebieha cast DATA
												--zvysne data prebiehaju, my nic s nimi nerobime
                                end if;
                            when stav_ZAPATIE =>
                                if( INPUT_EOP_N = '0' AND
                                    INPUT_EOF_N = '0' )             --skoncil FrameLink ramec
                                then
                                    fsm_NASLEDUJUCI_STAV <= stav_CAKA_RAMEC;
                                end if;
                        end case;
                    end if;
            end process;

-- -- predpriprava na fazu 4
-- --   vycitanie dat na zaklade aktualneho oktetu bajtov
--
----  -------------------------------------------------------
----  vycitanie z 1 oktetu
----  -------------------------------------------------------
--            process( CLK, RESET )
--                begin
--                    if( CLK'event AND CLK = '1' )
--                    then
--                        if( RESET = '1' )
--                        then
--                            vynuluj;
--                        elsif( zapis_OSMA_1 = '1' )
--                        then
--                            niekam <= INPUT_DATA( DOWNTO );
--                        end if ;
--                    end if;
--            end process;
--
----  -------------------------------------------------------
----  vycitanie z 2 oktetu
----  -------------------------------------------------------
--            process( CLK, RESET )
--                begin
--                    if( CLK'event AND CLK = '1' )
--                    then
--                        if( RESET = '1' )
--                        then
--                            vynuluj;
--                        elsif( zapis_OSMA_2 = '1' )
--                        then
--                            niekam <= INPUT_DATA( DOWNTO );
--                        end if ;
--                    end if;
--            end process;
--
----  -------------------------------------------------------
----  vycitanie z 3 oktetu
----  -------------------------------------------------------
--            process( CLK, RESET )
--                begin
--                    if( CLK'event AND CLK = '1' )
--                    then
--                        if( RESET = '1' )
--                        then
--                            vynuluj;
--                        elsif( zapis_OSMA_3 = '1' )
--                        then
--                            niekam <= INPUT_DATA( DOWNTO );
--                        end if ;
--                    end if;
--            end process;
--
----  -------------------------------------------------------
----  vycitanie z 4 oktetu
----  -------------------------------------------------------
--            process( CLK, RESET )
--                begin
--                    if( CLK'event AND CLK = '1' )
--                    then
--                        if( RESET = '1' )
--                        then
--                            vynuluj;
--                        elsif( zapis_OSMA_4 = '1' )
--                        then
--                            niekam <= INPUT_DATA( DOWNTO );
--                        end if ;
--                    end if;
--            end process;
--
----  -------------------------------------------------------
----  vycitanie z 5 oktetu
----  -------------------------------------------------------
--            process( CLK, RESET )
--                begin
--                    if( CLK'event AND CLK = '1' )
--                    then
--                        if( RESET = '1' )
--                        then
--                            vynuluj;
--                        elsif( zapis_OSMA_5 = '1' )
--                        then
--                            niekam <= INPUT_DATA( DOWNTO );
--                        end if ;
--                    end if;
--            end process;
--
----  -------------------------------------------------------
----  vycitanie z 6 oktetu
----  -------------------------------------------------------
--            process( CLK, RESET )
--                begin
--                    if( CLK'event AND CLK = '1' )
--                    then
--                        if( RESET = '1' )
--                        then
--                            vynuluj;
--                        elsif( zapis_OSMA_6 = '1' )
--                        then
--                            PRIPRAVENE <= '1';
--                        end if ;
--                    end if;
--            end process;



    --  -------------------------------------------------------
    -- pokusy s pripojovanim a adresovanim registrov
    --  -------------------------------------------------------
     intra_MI32_DWR     <= parser_MI32_DWR;
     intra_MI32_ADDR    <= parser_MI32_ADDR;
     intra_MI32_RD      <= parser_MI32_RD;
     intra_MI32_WR      <= parser_MI32_WR;
     intra_MI32_BE      <= parser_MI32_BE;
    parser_MI32_DRD     <=  intra_MI32_DRD;
    parser_MI32_ARDY    <=  intra_MI32_ARDY;
    parser_MI32_DRDY    <=  intra_MI32_DRDY;


   -- Create one cycle reading latency
   process(CLK)
   begin
      if (CLK'event and CLK = '1') then
         if (RESET = '1') then
            intra_MI32_DRDY <= '0';
         else
            intra_MI32_DRDY <= intra_MI32_RD;
            reg_mi32_exp_addr_9 <= intra_MI32_ADDR(11);
        reg_mi32_exp_addr_12 <= intra_MI32_ADDR(12);
         end if;
      end if;
   end process;

            intra_MI32_ARDY <= intra_MI32_RD OR intra_MI32_WR;


            -- Address decoder selects which register to write into
            process( intra_MI32_ADDR )
                begin
                    cs_reg_MAC_DST_01 <= '0';
                    cs_reg_MAC_DST_02 <= '0';
                    cs_reg_MAC_SRC_01 <= '0';
                    cs_reg_MAC_SRC_02 <= '0';
                    cs_reg_ETHERTYPE  <= '0';
                    cs_reg_IPV4_SRC   <= '0';
                    cs_reg_IPV4_DST   <= '0';
                    cs_reg_PROTOCOL   <= '0';
                    cs_reg_PORT_SRC   <= '0';
                    cs_reg_PORT_DST   <= '0';
                if( intra_MI32_ADDR(12) = '1' )
                then
                    case intra_MI32_ADDR(5 downto 2) is
                        when  "0000" => cs_reg_MAC_DST_01 <= '1';
                        when  "0001" => cs_reg_MAC_DST_02 <= '1';
                        when  "0010" => cs_reg_MAC_SRC_01 <= '1';
                        when  "0011" => cs_reg_MAC_SRC_02 <= '1';
                        when  "0100" => cs_reg_ETHERTYPE  <= '1';
                        when  "0101" => cs_reg_IPV4_SRC   <= '1';
                        when  "0110" => cs_reg_IPV4_DST   <= '1';
                        when  "0111" => cs_reg_PROTOCOL   <= '1';
                        when  "1000" => cs_reg_PORT_SRC   <= '1';
                        when  "1001" => cs_reg_PORT_DST   <= '1';
                        when  others =>
                    end case;
                end if;
            end process;

            -- Control write enable to registers
            we_reg_MAC_DST_01   <= cs_reg_MAC_DST_01 AND intra_MI32_WR;
            we_reg_MAC_DST_02   <= cs_reg_MAC_DST_02 AND intra_MI32_WR;
            we_reg_MAC_SRC_01   <= cs_reg_MAC_SRC_01 AND intra_MI32_WR;
            we_reg_MAC_SRC_02   <= cs_reg_MAC_SRC_02 AND intra_MI32_WR;
            we_reg_ETHERTYPE    <= cs_reg_ETHERTYPE  AND intra_MI32_WR;
            we_reg_IPV4_SRC     <= cs_reg_IPV4_SRC   AND intra_MI32_WR;
            we_reg_IPV4_DST     <= cs_reg_IPV4_DST   AND intra_MI32_WR;
            we_reg_PROTOCOL     <= cs_reg_PROTOCOL   AND intra_MI32_WR;
            we_reg_PORT_SRC     <= cs_reg_PORT_SRC   AND intra_MI32_WR;
            we_reg_PORT_DST     <= cs_reg_PORT_DST   AND intra_MI32_WR;

            -- Select which register to read
            process(CLK)
                begin
                    if (CLK'event and CLK = '1') then
                        reg_do <= X"DEADD00D";
                        if (intra_MI32_ADDR(12) = '0')
                        then
                            case intra_MI32_ADDR(4 downto 2) is
                                when others => reg_do <= X"DEADD11D";
                            end case;
                        else
                            case intra_MI32_ADDR(5 downto 2)            -- 81000 a vyssie v nasobkoch 4
                                when "0000" => reg_do <= reg_MAC_DST_01;
                                when "0001" => reg_do <= reg_MAC_DST_02;
                                when "0010" => reg_do <= reg_MAC_SRC_01;
                                when "0011" => reg_do <= reg_MAC_SRC_02;
                                when "0100" => reg_do <= reg_ETHERTYPE;
                                when "0101" => reg_do <= reg_IPV4_SRC;
                                when "0110" => reg_do <= reg_IPV4_DST;
                                when "0111" => reg_do <= reg_PROTOCOL;
                                when "1000" => reg_do <= reg_PORT_SRC;
                                when "1001" => reg_do <= reg_PORT_DST;
                                when others => reg_do <= X"DEADDEAD";
                            end case;
                        end if;
                    end if;
            end process;

            bram_do <= X"DEADBEEF";

            -- Selects whether to read from registers or BlockRAM
            process( bram_do, reg_mi32_exp_addr_9, reg_do )
                begin
                    intra_MI32_DRD <= bram_do;
                    if (reg_mi32_exp_addr_9 = '0') AND (reg_mi32_exp_addr_12 = '0')
                    then
                        intra_MI32_DRD <= bram_do;
                    else
                        intra_MI32_DRD <= reg_do;
                    end if;
            end process;


-- riadeny z viacej zdrojov
            process(CLK)
                begin
                    if (CLK'event and CLK = '1')
                    then
                        if (RESET = '1') then
                            reg_MAC_DST_01  <= (others => '0');
                            reg_MAC_DST_02  <= (others => '0');
                            reg_MAC_SRC_01  <= (others => '0');
                            reg_MAC_SRC_02  <= (others => '0');
                            reg_ETHERTYPE   <= (others => '0');
                            reg_IPV4_SRC    <= (others => '0');
                            reg_IPV4_DST    <= (others => '0');
                            reg_PROTOCOL    <= (others => '0');
                            reg_PORT_SRC    <= (others => '0');
                            reg_PORT_DST    <= (others => '0');
                        else
                            if( we_reg_MAC_DST_01 = '1')
                            then
                                reg_MAC_DST_01 <= intra_MI32_DWR;
                            end if;
                            if( we_reg_MAC_DST_02 = '1')
                            then
                                reg_MAC_DST_02 <= intra_MI32_DWR;
                            end if;
                            if( we_reg_MAC_SRC_01 = '1')
                            then
                                reg_MAC_SRC_01 <= intra_MI32_DWR;
                            end if;
                            if( we_reg_MAC_SRC_02 = '1')
                            then
                                reg_MAC_SRC_02 <= intra_MI32_DWR;
                            end if;
                            if( we_reg_ETHERTYPE  = '1')
                            then
                                reg_ETHERTYPE  <= intra_MI32_DWR;
                            end if;
                            if( we_reg_IPV4_SRC   = '1')
                            then
                                reg_IPV4_SRC   <= intra_MI32_DWR;
                            end if;
                            if( we_reg_IPV4_DST   = '1')
                            then
                                reg_IPV4_DST   <= intra_MI32_DWR;
                            end if;
                            if( we_reg_PROTOCOL   = '1')
                            then
                                reg_PROTOCOL   <= intra_MI32_DWR;
                            end if;
                            if( we_reg_PORT_SRC   = '1')
                            then
                                reg_PORT_SRC   <= intra_MI32_DWR;
                            end if;
                            if( we_reg_PORT_DST   = '1')
                            then
                                reg_PORT_DST   <= intra_MI32_DWR;
                            end if;
                        end if;
                    end if;
            end process;

    end architecture krabicka_pokus_3;
