----------------------------------------------------------------------------------
-- Company: CNRS
-- Engineer: CC
-- 
-- Create Date:    14:58:08 09/03/2015 
-- Design Name: 
-- Module Name:    udp_rx_fsm - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Revision 0.04 - add 64 bits rx & FIFO control
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use work.ipv4_types.all;
use work.data_IO.all;
use IEEE.NUMERIC_STD.ALL;


entity udp_rx_fsm is
	generic(
				g_data_rx_width  	: natural := 16);	
    Port ( 
			  rst_i 				: in  STD_LOGIC;
           clk_i 				: in  STD_LOGIC;
           udp_rx_start_i 	: in  STD_LOGIC;
           udp_rx_i 			: in  udp_rx_type;
			  -- Stored source addresses
			  src_addr_i 		: in src_addr_type;
           udp_rx_data_o 	: out  STD_LOGIC_VECTOR (g_data_rx_width-1 downto 0);
           data_valid_o 	: out  STD_LOGIC;
			  -- checked source addresses
			  src_addr_o 				: out src_addr_type
			  );
end udp_rx_fsm;

architecture Behavioral of udp_rx_fsm is

	TYPE STATE_TYPE IS (
			IDLE, 			-- initial stae - wait or Init
			RX,				--extract rx data
			DATA_OUT 		-- data are ready to be used
		);
	
	signal current_state : STATE_TYPE := IDLE;
	signal data_valid 	: STD_LOGIC;
	signal buffer_rx 		: std_logic_vector (g_data_rx_width-1 downto 0); 
	signal rx_count     	: unsigned (15 downto 0);
	 
begin
	-- Process MAE
   PROCESS(clk_i)		  
   BEGIN
	if rising_edge(clk_i) then
      if rst_i = '1' then
        current_state   <= IDLE;
		  rx_count 			<= x"0000";
		  buffer_Rx			<= (others => '0');
		  data_valid 		<= '0';
		  
		else
      
			CASE current_state IS 
	
			WHEN IDLE =>			
				--buffer_Rx 	<= (others=> '0');	
				data_valid 	<= '0';
				if (udp_rx_start_i = '1' and udp_rx_i.hdr.dst_port = x"D6E2") then	-- port 55010 UDP frame received and right destination port for config 
--					rx_count <= (unsigned(udp_rx_i.hdr.data_length))/2 - 1;
					-- check stored IP address
					if (src_addr_i.ip_addr = udp_rx_i.hdr.src_ip_addr) then 
						src_addr_o <= src_addr_i;
					end if;
					rx_count <= ('0' &(unsigned(udp_rx_i.hdr.data_length(15 downto 1)))) - 1;
					if (udp_rx_i.data.data_in_valid = '1') then
						buffer_Rx(15 downto 0) <= udp_rx_i.data.data_in; 							-- 16bits word received 
						current_state <= RX;
					else 
						current_state <= IDLE; 
					end if;				
				end if;
				
				WHEN	RX =>
				buffer_Rx(15 downto 0) <= udp_rx_i.data.data_in;
				if rx_count = X"0000" then 	--last data 
					buffer_rx 		<= buffer_rx;
					data_valid 		<= '1';
					current_state 	<= IDLE;	
				else 
					buffer_Rx(g_data_rx_width-1 downto 16) <= buffer_Rx(g_data_rx_width-16-1 downto 0);
					rx_count <= rx_count - 1;
					data_valid 		<= '0';
					current_state 	<= RX;
				end if;

			WHEN OTHERS =>
				 current_state <= IDLE;

			END CASE;	
		end if;
		end if;
	END PROCESS;


data_valid_o <= data_valid;
udp_rx_data_o <= buffer_rx;

end Behavioral;


