----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    15:06:14 02/25/2015 
-- Design Name: 
-- Module Name:    pp_udp_reply - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;


entity udp_packet is
	port (
		clk										: in  std_logic;
		tx_clk									: in  std_logic;
		udp_rx_pkt_id							: in  std_logic_vector(15 downto 0);
		udp_rx_frag_offset					: in  std_logic_vector(12 downto 0);
		udp_reply_mac_addr_0					: in  std_logic_vector(7 downto 0);
		udp_reply_mac_addr_1					: in  std_logic_vector(7 downto 0);
		udp_reply_mac_addr_2					: in  std_logic_vector(7 downto 0);
		udp_reply_mac_addr_3					: in  std_logic_vector(7 downto 0);
		udp_reply_mac_addr_4					: in  std_logic_vector(7 downto 0);
		udp_reply_mac_addr_5					: in  std_logic_vector(7 downto 0);
		udp_rx_hdw_src_addr_0				: in  std_logic_vector(7 downto 0);
		udp_rx_hdw_src_addr_1				: in  std_logic_vector(7 downto 0);
		udp_rx_hdw_src_addr_2				: in  std_logic_vector(7 downto 0);
		udp_rx_hdw_src_addr_3				: in  std_logic_vector(7 downto 0);
		udp_rx_hdw_src_addr_4				: in  std_logic_vector(7 downto 0);
		udp_rx_hdw_src_addr_5				: in  std_logic_vector(7 downto 0);
		udp_reply_ip_addr_0					: in  std_logic_vector(7 downto 0);
		udp_reply_ip_addr_1					: in  std_logic_vector(7 downto 0);
		udp_reply_ip_addr_2					: in  std_logic_vector(7 downto 0);
		udp_reply_ip_addr_3					: in  std_logic_vector(7 downto 0);
		udp_rx_src_ip_addr_0					: in  std_logic_vector(7 downto 0);
		udp_rx_src_ip_addr_1					: in  std_logic_vector(7 downto 0);
		udp_rx_src_ip_addr_2					: in  std_logic_vector(7 downto 0);
		udp_rx_src_ip_addr_3					: in  std_logic_vector(7 downto 0);
		udp_destination_port					: in  std_logic_vector(15 downto 0);
		packet_data_available				: in  std_logic;
		udp_packet_busy						: out std_logic;
		packet_data_num_bytes				: in  unsigned(10 downto 0);
		packet_data_fifo_rd_en				: out std_logic;
		packet_data_fifo_dout				: in  std_logic_vector(8 downto 0);
		udp_packet_fifo_rd_en				: in  std_logic;
		udp_packet_fifo_dout					: out std_logic_vector(8 downto 0);
		udp_packet_fifo_empty				: out std_logic
	);
end udp_packet;


architecture Behavioral of udp_packet is

	signal udp_reply_ip_hdr_hdw_dst_addr_0		: std_logic_vector(7 downto 0) := (others => '0');
	signal udp_reply_ip_hdr_hdw_dst_addr_1		: std_logic_vector(7 downto 0) := (others => '0');
	signal udp_reply_ip_hdr_hdw_dst_addr_2		: std_logic_vector(7 downto 0) := (others => '0');
	signal udp_reply_ip_hdr_hdw_dst_addr_3		: std_logic_vector(7 downto 0) := (others => '0');
	signal udp_reply_ip_hdr_hdw_dst_addr_4		: std_logic_vector(7 downto 0) := (others => '0');
	signal udp_reply_ip_hdr_hdw_dst_addr_5		: std_logic_vector(7 downto 0) := (others => '0');
	
	signal udp_reply_ip_hdr_dst_addr_0			: std_logic_vector(7 downto 0) := (others => '0');
	signal udp_reply_ip_hdr_dst_addr_1			: std_logic_vector(7 downto 0) := (others => '0');
	signal udp_reply_ip_hdr_dst_addr_2			: std_logic_vector(7 downto 0) := (others => '0');
	signal udp_reply_ip_hdr_dst_addr_3			: std_logic_vector(7 downto 0) := (others => '0');
	
	component ip_checksum
	port (
		clk									: in  std_logic;
		calc_ip_reply_checksum			: in  std_logic;
		ip_reply_hdr_version				: in  std_logic_vector(3 downto 0);
		ip_reply_hdr_length				: in  std_logic_vector(3 downto 0);
		ip_reply_hdr_diff_services		: in  std_logic_vector(7 downto 0);
		ip_reply_hdr_total_length		: in  std_logic_vector(10 downto 0);
		ip_reply_hdr_pktid				: in  std_logic_vector(15 downto 0);
		ip_reply_hdr_flags				: in  std_logic_vector(2 downto 0);
		ip_reply_hdr_frag_offset		: in  std_logic_vector(12 downto 0);
		ip_reply_hdr_TTL					: in  std_logic_vector(7 downto 0);
		ip_reply_hdr_protocol			: in  std_logic_vector(7 downto 0);
		ip_reply_addr_0					: in  std_logic_vector(7 downto 0);
		ip_reply_addr_1					: in  std_logic_vector(7 downto 0);
		ip_reply_addr_2					: in  std_logic_vector(7 downto 0);
		ip_reply_addr_3					: in  std_logic_vector(7 downto 0);
		ip_reply_hdr_dst_addr_0			: in  std_logic_vector(7 downto 0);
		ip_reply_hdr_dst_addr_1			: in  std_logic_vector(7 downto 0);
		ip_reply_hdr_dst_addr_2			: in  std_logic_vector(7 downto 0);
		ip_reply_hdr_dst_addr_3			: in  std_logic_vector(7 downto 0);
		ip_reply_checksum					: out std_logic_vector(15 downto 0);
		ip_reply_checksum_valid			: out std_logic
	);
	end component;
	
--	signal udp_reply_ip_hdr_version				: std_logic_vector(3 downto 0) := (others => '0');
--	signal udp_reply_ip_hdr_length				: std_logic_vector(3 downto 0) := (others => '0');
--	signal udp_reply_ip_hdr_diff_services		: std_logic_vector(7 downto 0) := (others => '0');
	signal udp_reply_ip_hdr_total_length		: unsigned(10 downto 0) := (others => '0');
	signal udp_reply_ip_hdr_pktid					: std_logic_vector(15 downto 0) := (others => '0');
--	signal udp_reply_ip_hdr_flags					: std_logic_vector(2 downto 0) := (others => '0');
	signal udp_reply_ip_hdr_frag_offset			: std_logic_vector(12 downto 0) := (others => '0');
--	signal udp_reply_ip_hdr_TTL					: std_logic_vector(7 downto 0) := (others => '0');
--	signal udp_reply_ip_hdr_protocol				: std_logic_vector(7 downto 0) := (others => '0');
--	signal udp_reply_ip_hdr_dst_addr_0			: std_logic_vector(7 downto 0) := (others => '0');
--	signal udp_reply_ip_hdr_dst_addr_1			: std_logic_vector(7 downto 0) := (others => '0');
--	signal udp_reply_ip_hdr_dst_addr_2			: std_logic_vector(7 downto 0) := (others => '0');
--	signal udp_reply_ip_hdr_dst_addr_3			: std_logic_vector(7 downto 0) := (others => '0');
	
	signal udp_reply_ip_hdr_checksum_valid		: std_logic;
	signal udp_reply_ip_hdr_checksum				: std_logic_vector(15 downto 0);
	
	component udp_reply_fifo
	port (
		wr_clk			: in std_logic;
		rd_clk			: in std_logic;
		din				: in std_logic_vector(8 downto 0);
		wr_en				: in std_logic;
		rd_en				: in std_logic;
		dout				: out std_logic_vector(8 downto 0);
		full				: out std_logic;
		empty				: out std_logic
	);
	end component;

	signal udp_reply_fifo_din				: std_logic_vector(8 downto 0) := (others => '0');
	signal udp_reply_fifo_wr_en			: std_logic := '0';
--	signal udp_packet_fifo_rd_en			: std_logic := '0';
--	signal udp_packet_fifo_dout				: std_logic_vector(8 downto 0);
--	signal udp_packet_fifo_empty			: std_logic;
	
	signal udp_reply_rx_data_length		: unsigned(10 downto 0) := (others => '0');

	signal udp_reply_udp_data_counter	: unsigned(10 downto 0) := (others => '0');

	type   udp_reply_type is (idle, waitCountersSet, waitIPHeaderSet, setDstHdwAddr_0, setDstHdwAddr_1,
										setDstHdwAddr_2, setDstHdwAddr_3, setDstHdwAddr_4, setDstHdwAddr_5,
											setSrcHdwAddr_0, setSrcHdwAddr_1, setSrcHdwAddr_2, setSrcHdwAddr_3,
												setSrcHdwAddr_4, setSrcHdwAddr_5, setEthertype_0, setEthertype_1,
													setIPHdr_0, setIPHdrDiffServices, setIPHdrPktLength_0, setIPHdrPktLength_1,
														setIPHdrPktID_0, setIPHdrPktID_1, setIPHdrFlgFrag_0, setIPHdrFlgFrag_1,
															setIPHdrTTL, setIPHdrProtocol, setIPHdrChecksum_0, setIPHdrChecksum_1,
																setIPHdrSrcIPAddr_0, setIPHdrSrcIPAddr_1, setIPHdrSrcIPAddr_2, setIPHdrSrcIPAddr_3,
																	setIPHdrDstIPAddr_0, setIPHdrDstIPAddr_1, setIPHdrDstIPAddr_2, setIPHdrDstIPAddr_3,
																		setUDPHdrSrcPort_0, setUDPHdrSrcPort_1, setUDPHdrDstPort_0, setUDPHdrDstPort_1,
																			setUDPHdrDataLength_0, setUDPHdrDataLength_1, setUDPHdrChecksum_0, setUDPHdrChecksum_1,
																				loadUDPReplyFifo_Data);
	signal udp_reply_state					: udp_reply_type := idle;
--	signal udp_send_busy_i					: std_logic := '0';
--	signal udp_calc_udp_checksum			: std_logic := '0';
	signal udp_calc_ip_reply_checksum	: std_logic := '0';
	signal udp_reply_set_data_counter	: std_logic := '0';
	signal udp_reply_dec_data_counter	: std_logic := '0';
	signal udp_reply_set_ip_header		: std_logic := '0';

begin

	udp_reply_set_ip_header_proc : process (clk)
	begin
		if rising_edge(clk) then
			if (udp_reply_set_ip_header = '1') then
				udp_reply_ip_hdr_pktid <= udp_rx_pkt_id;
				udp_reply_ip_hdr_frag_offset <= udp_rx_frag_offset;
				udp_reply_ip_hdr_hdw_dst_addr_0 <= udp_rx_hdw_src_addr_0;
				udp_reply_ip_hdr_hdw_dst_addr_1 <= udp_rx_hdw_src_addr_1;
				udp_reply_ip_hdr_hdw_dst_addr_2 <= udp_rx_hdw_src_addr_2;
				udp_reply_ip_hdr_hdw_dst_addr_3 <= udp_rx_hdw_src_addr_3;
				udp_reply_ip_hdr_hdw_dst_addr_4 <= udp_rx_hdw_src_addr_4;
				udp_reply_ip_hdr_hdw_dst_addr_5 <= udp_rx_hdw_src_addr_5;
				udp_reply_ip_hdr_dst_addr_0 <= udp_rx_src_ip_addr_0;
				udp_reply_ip_hdr_dst_addr_1 <= udp_rx_src_ip_addr_1;
				udp_reply_ip_hdr_dst_addr_2 <= udp_rx_src_ip_addr_2;
				udp_reply_ip_hdr_dst_addr_3 <= udp_rx_src_ip_addr_3;
			end if;
		end if;
	end process udp_reply_set_ip_header_proc;


	udp_ip_checksum: ip_checksum
	port map (
		clk								=> clk,
		calc_ip_reply_checksum		=> udp_calc_ip_reply_checksum,
		ip_reply_hdr_version			=> "0100",
		ip_reply_hdr_length			=> "0101",
		ip_reply_hdr_diff_services	=> x"00",
		ip_reply_hdr_total_length	=> std_logic_vector(udp_reply_ip_hdr_total_length),
		ip_reply_hdr_pktid			=> udp_reply_ip_hdr_pktid,
		ip_reply_hdr_flags			=> "010",
		ip_reply_hdr_frag_offset	=> udp_reply_ip_hdr_frag_offset,
		ip_reply_hdr_TTL				=> x"80",
		ip_reply_hdr_protocol		=> x"11",
		ip_reply_addr_0 				=> udp_reply_ip_addr_0,
		ip_reply_addr_1 				=> udp_reply_ip_addr_1,
		ip_reply_addr_2 				=> udp_reply_ip_addr_2,
		ip_reply_addr_3 				=> udp_reply_ip_addr_3,
		ip_reply_hdr_dst_addr_0		=> udp_reply_ip_hdr_dst_addr_0,
		ip_reply_hdr_dst_addr_1		=> udp_reply_ip_hdr_dst_addr_1,
		ip_reply_hdr_dst_addr_2		=> udp_reply_ip_hdr_dst_addr_2,
		ip_reply_hdr_dst_addr_3		=> udp_reply_ip_hdr_dst_addr_3,
		ip_reply_checksum				=> udp_reply_ip_hdr_checksum,
		ip_reply_checksum_valid		=> udp_reply_ip_hdr_checksum_valid
	);


	udp_reply_fifo_0 : udp_reply_fifo
	port map (
		wr_clk			=> clk,
		rd_clk			=> tx_clk,
		din				=> udp_reply_fifo_din,
		wr_en				=> udp_reply_fifo_wr_en,
		rd_en				=> udp_packet_fifo_rd_en,
		dout				=> udp_packet_fifo_dout,
		full				=> open,
		empty				=> udp_packet_fifo_empty
	);


	udp_reply_calc_IPlength : process (clk)
	begin
		if rising_edge(clk) then
			if (udp_reply_set_data_counter = '1') then
				udp_reply_ip_hdr_total_length <= packet_data_num_bytes + 28;
			end if;
		end if;
	end process udp_reply_calc_IPlength;


	udp_reply_calc_UDPlength : process (clk)
	begin
		if rising_edge(clk) then
			if (udp_reply_set_data_counter = '1') then
				udp_reply_rx_data_length <= packet_data_num_bytes + 8;
			end if;
		end if;
	end process udp_reply_calc_UDPlength;


	udp_reply_data_counter_proc : process (clk)
	begin
		if rising_edge(clk) then
			if (udp_reply_set_data_counter = '1') then
				udp_reply_udp_data_counter <= packet_data_num_bytes;
			elsif (udp_reply_dec_data_counter = '1') then
				udp_reply_udp_data_counter <= udp_reply_udp_data_counter - 1;
			end if;
		end if;
	end process udp_reply_data_counter_proc;


--udp_packet_busy <= udp_send_busy_i;

	udp_reply : process (clk)
	begin
		if rising_edge(clk) then
			packet_data_fifo_rd_en <= '0';
--			udp_calc_udp_checksum <= '0';
			udp_calc_ip_reply_checksum <= '0';
			udp_reply_set_data_counter <= '0';
			udp_reply_dec_data_counter <= '0';
			udp_reply_set_ip_header <= '0';
			
			case udp_reply_state is
				when idle =>
					if (packet_data_available = '1') then
						udp_reply_set_ip_header <= '1';
						udp_packet_busy <= '1';
--						udp_calc_udp_checksum <= '1';
						udp_reply_set_data_counter <= '1';
						udp_reply_state <= waitCountersSet;
					else
						udp_reply_state <= idle;
						udp_packet_busy <= '0';
						udp_reply_fifo_wr_en <= '0';
					end if;
				
				when waitCountersSet =>
					udp_reply_set_ip_header <= '1';
					udp_reply_state <= waitIPHeaderSet;
				
				when waitIPHeaderSet =>
					udp_calc_ip_reply_checksum <= '1';
					udp_reply_state <= setDstHdwAddr_0;
				
--				when waitCheckSumValid =>
--					if (udp_reply_checksum_valid = '1') then
--						udp_reply_state <= waitUDPReplyFifoEmpty;
--					else
--						udp_reply_state <= waitCheckSumValid;
--					end if;
--				
--				when waitUDPReplyFifoEmpty =>
--					if (udp_packet_fifo_empty = '1') then
--						udp_reply_state <= setDstHdwAddr_0;
--					else
--						udp_reply_state <= waitUDPReplyFifoEmpty;
--					end if;
					
				when setDstHdwAddr_0 =>
					udp_reply_fifo_wr_en <= '1';
					udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_hdw_dst_addr_0;
					udp_reply_state <= setDstHdwAddr_1;
					
				when setDstHdwAddr_1 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_hdw_dst_addr_1;
					udp_reply_state <= setDstHdwAddr_2;
					
				when setDstHdwAddr_2 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_hdw_dst_addr_2;
					udp_reply_state <= setDstHdwAddr_3;
					
				when setDstHdwAddr_3 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_hdw_dst_addr_3;
					udp_reply_state <= setDstHdwAddr_4;
					
				when setDstHdwAddr_4 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_hdw_dst_addr_4;
					udp_reply_state <= setDstHdwAddr_5;
					
				when setDstHdwAddr_5 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_hdw_dst_addr_5;
					udp_reply_state <= setSrcHdwAddr_0;
					
				when setSrcHdwAddr_0 =>
					udp_reply_fifo_din <= '0' & udp_reply_mac_addr_0;
					udp_reply_state <= setSrcHdwAddr_1;
					
				when setSrcHdwAddr_1 =>
					udp_reply_fifo_din <= '0' & udp_reply_mac_addr_1;
					udp_reply_state <= setSrcHdwAddr_2;
					
				when setSrcHdwAddr_2 =>
					udp_reply_fifo_din <= '0' & udp_reply_mac_addr_2;
					udp_reply_state <= setSrcHdwAddr_3;
					
				when setSrcHdwAddr_3 =>
					udp_reply_fifo_din <= '0' & udp_reply_mac_addr_3;
					udp_reply_state <= setSrcHdwAddr_4;
					
				when setSrcHdwAddr_4 =>
					udp_reply_fifo_din <= '0' & udp_reply_mac_addr_4;
					udp_reply_state <= setSrcHdwAddr_5;
					
				when setSrcHdwAddr_5 =>
					udp_reply_fifo_din <= '0' & udp_reply_mac_addr_5;
					udp_reply_state <= setEthertype_0;
					
				when setEthertype_0 =>									-- is IP
					udp_reply_fifo_din <= '0' & x"08";
					udp_reply_state <= setEthertype_1;
					
				when setEthertype_1 =>
					udp_reply_fifo_din <= '0' & x"00";
					udp_reply_state <= setIPHdr_0;
							
				when setIPHdr_0 =>										-- v4 hdrlen 20
					udp_reply_fifo_din <= '0' & "0100" & "0101";
					udp_reply_state <= setIPHdrDiffServices;
							
				when setIPHdrDiffServices =>							-- diff services
					udp_reply_fifo_din <= '0' & x"00";
					udp_reply_state <= setIPHdrPktLength_0;
				
				when setIPHdrPktLength_0 =>
					udp_reply_fifo_din <= '0' & "00000" & std_logic_vector(udp_reply_ip_hdr_total_length(10 downto 8));
					udp_reply_state <= setIPHdrPktLength_1;
				
				when setIPHdrPktLength_1 =>
					udp_reply_fifo_din <= '0' & std_logic_vector(udp_reply_ip_hdr_total_length(7 downto 0));
					udp_reply_state <= setIPHdrPktID_0;
				
				when setIPHdrPktID_0 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_pktid(15 downto 8);
					udp_reply_state <= setIPHdrPktID_1;
				
				when setIPHdrPktID_1 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_pktid(7 downto 0);
					udp_reply_state <= setIPHdrFlgFrag_0;
						
				when setIPHdrFlgFrag_0 =>
					udp_reply_fifo_din <= '0' & "010" & udp_reply_ip_hdr_frag_offset(12 downto 8);
					udp_reply_state <= setIPHdrFlgFrag_1;
						
				when setIPHdrFlgFrag_1 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_frag_offset(7 downto 0);
					udp_reply_state <= setIPHdrTTL;
						
				when setIPHdrTTL =>
					udp_reply_fifo_din <= '0' & x"80";
					udp_reply_state <= setIPHdrProtocol;
						
				when setIPHdrProtocol =>
					udp_reply_fifo_din <= '0' & x"11";
					udp_reply_state <= setIPHdrChecksum_0;
						
				when setIPHdrChecksum_0 =>
					if (udp_reply_ip_hdr_checksum_valid = '1') then
						udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_checksum(15 downto 8);
					else
						udp_reply_fifo_din <= '0' & x"00";
					end if;
					udp_reply_state <= setIPHdrChecksum_1;
						
				when setIPHdrChecksum_1 =>
					if (udp_reply_ip_hdr_checksum_valid = '1') then
						udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_checksum(7 downto 0);
					else
						udp_reply_fifo_din <= '0' & x"00";
					end if;
					udp_reply_state <= setIPHdrSrcIPAddr_0;
						
				when setIPHdrSrcIPAddr_0 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_addr_0;
					udp_reply_state <= setIPHdrSrcIPAddr_1;
						
				when setIPHdrSrcIPAddr_1 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_addr_1;
					udp_reply_state <= setIPHdrSrcIPAddr_2;
						
				when setIPHdrSrcIPAddr_2 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_addr_2;
					udp_reply_state <= setIPHdrSrcIPAddr_3;
						
				when setIPHdrSrcIPAddr_3 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_addr_3;
					udp_reply_state <= setIPHdrDstIPAddr_0;
						
				when setIPHdrDstIPAddr_0 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_dst_addr_0;
					udp_reply_state <= setIPHdrDstIPAddr_1;
						
				when setIPHdrDstIPAddr_1 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_dst_addr_1;
					udp_reply_state <= setIPHdrDstIPAddr_2;
						
				when setIPHdrDstIPAddr_2 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_dst_addr_2;
					udp_reply_state <= setIPHdrDstIPAddr_3;
						
				when setIPHdrDstIPAddr_3 =>
					udp_reply_fifo_din <= '0' & udp_reply_ip_hdr_dst_addr_3;
					udp_reply_state <= setUDPHdrSrcPort_0;
						
				when setUDPHdrSrcPort_0 =>															-- UDP header start
					udp_reply_fifo_din <= '0' & udp_destination_port(15 downto 8);
					udp_reply_state <= setUDPHdrSrcPort_1;
						
				when setUDPHdrSrcPort_1 =>
					udp_reply_fifo_din <= '0' & udp_destination_port(7 downto 0);
					udp_reply_state <= setUDPHdrDstPort_0;
						
				when setUDPHdrDstPort_0 =>
					udp_reply_fifo_din <= '0' & udp_destination_port(15 downto 8);
					udp_reply_state <= setUDPHdrDstPort_1;
						
				when setUDPHdrDstPort_1 =>
					udp_reply_fifo_din <= '0' & udp_destination_port(7 downto 0);
					udp_reply_state <= setUDPHdrDataLength_0;
						
				when setUDPHdrDataLength_0 =>
					udp_reply_fifo_din <= '0' & "00000" & std_logic_vector(udp_reply_rx_data_length(10 downto 8));
					udp_reply_state <= setUDPHdrDataLength_1;
						
				when setUDPHdrDataLength_1 =>
					udp_reply_fifo_din <= '0' & std_logic_vector(udp_reply_rx_data_length(7 downto 0));
					udp_reply_state <= setUDPHdrChecksum_0;
						
				when setUDPHdrChecksum_0 =>													-- UDP checksum
--					if (udp_reply_checksum_valid = '1') then
--						udp_reply_fifo_din <= '0' & udp_reply_checksum(15 downto 8);
--					else
						udp_reply_fifo_din <= '0' & "00000000";
--					end if;
					packet_data_fifo_rd_en <= '1';
					udp_reply_state <= setUDPHdrChecksum_1;
						
					when setUDPHdrChecksum_1 =>
--						if (udp_reply_checksum_valid = '1') then
--							udp_reply_fifo_din <= '0' & udp_reply_checksum(7 downto 0);
--						else
							udp_reply_fifo_din <= '0' & "00000000";
--						end if;
					packet_data_fifo_rd_en <= '1';
					udp_reply_state <= loadUDPReplyFifo_Data;
				
				
				when loadUDPReplyFifo_Data =>
					udp_reply_dec_data_counter <= '1';
					packet_data_fifo_rd_en <= '1';
					udp_reply_fifo_din <= packet_data_fifo_dout;
					
					if (udp_reply_udp_data_counter = 1) then
						udp_reply_state <= idle;
					else
						udp_reply_state <= loadUDPReplyFifo_Data;
					end if;
			end case;
		end if;
	end process udp_reply;

end Behavioral;

