URL
https://opencores.org/ocsvn/xenie/xenie/trunk
Subversion Repositories xenie
[/] [xenie/] [trunk/] [examples/] [Eth_example/] [src/] [hdl/] [udp_ip_10g_test_app.vhd] - Rev 10
Go to most recent revision | Compare with Previous | Blame | View Log
------------------------------------------------------------------------------- -- -- (C) Copyright 2017 DFC Design, s.r.o., Brno, Czech Republic -- Author: Marek Kvas (m.kvas@dspfpga.com) -- ------------------------------------------------------------------------------- -- This file is part of Xenia Ethernet Example project. -- -- Xenia Ethernet Example project is free software: you can -- redistribute it and/or modify it under the terms of -- the GNU Lesser General Public License as published by the Free -- Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- Xenia Ethernet Example project is distributed in the hope that -- it will be useful, but WITHOUT ANY WARRANTY; without even -- the implied warranty of MERCHANTABILITY or FITNESS FOR A -- PARTICULAR PURPOSE. See the GNU Lesser General Public License -- for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with Xenia Ethernet Example project. If not, -- see <http://www.gnu.org/licenses/>. ------------------------------------------------------------------------------- -- -- This is core demonstrates usage of udp_ip_10g core. There are two functions -- integrated here. -- -- When data come to udp port g_loopback_port. Packet is looped back with -- source info used as a destination info. -- -- When frame comes to udp port g_test_port, first 4 bytes are checked for -- magic number. If it matches and length is higher than minimal length for -- test packet, response packet is sent. Response starts with magic number and -- next 4 bytes copied from incomming frame - user can use this feature to -- identify response frames. 64 bit timestamp and packet counters follow. -- Packet has this structure -- 7 6 5 4 3 2 1 0 -- User ID | Magic number -- 64 bit long timestamp -- test pkt cnt | loopback pkt cnt -- accepted tst cnt | unknown port pkt cnt -- Padding to the size of request packet -- -- ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity udp_ip_10g_test_app is generic ( g_loopback_port : std_logic_vector(15 downto 0) := x"DFC0"; g_test_port : std_logic_vector(15 downto 0) := x"DFC1"; g_net_info_port : std_logic_vector(15 downto 0) := x"DFCC" ); port ( RST : in std_logic; CLK : in std_logic; -- Host information user interface HOST_MAC : in std_logic_vector(47 downto 0); HOST_IP : in std_logic_vector(31 downto 0); HOST_IP_NETMASK : in std_logic_vector(31 downto 0); -- TX user interface TX_DST_MAC : out std_logic_vector(47 downto 0); TX_DST_IP : out std_logic_vector(31 downto 0); TX_SRC_UDP : out std_logic_vector(15 downto 0); TX_DST_UDP : out std_logic_vector(15 downto 0); TX_FRAME_VALID : out std_logic; TX_FRAME_RDY : in std_logic; TX_FRAME_LAST : out std_logic; TX_FRAME_BE : out std_logic_vector(7 downto 0); TX_FRAME_DATA : out std_logic_vector(63 downto 0); -- RX user interface RX_SRC_MAC : in std_logic_vector(47 downto 0); RX_SRC_IP : in std_logic_vector(31 downto 0); RX_SRC_UDP : in std_logic_vector(15 downto 0); RX_DST_UDP : in std_logic_vector(15 downto 0); RX_FRAME_VALID : in std_logic; RX_FRAME_RDY : out std_logic; RX_FRAME_LAST : in std_logic; RX_FRAME_BE : in std_logic_vector(7 downto 0); RX_FRAME_DATA : in std_logic_vector(63 downto 0); RX_FRAME_LENGTH : in std_logic_vector(15 downto 0) ); end entity; architecture synthesis of udp_ip_10g_test_app is constant LC_TEST_MAGIC : std_logic_vector(31 downto 0) := x"DFCDFC01"; constant LC_TEST_MIN_PKT : integer := 32; type main_fsm_type is (M_IDLE, M_LOOPBACK, M_TEST, M_TEST_RESP_DATA, M_NET_INFO, M_DISCARD); signal main_fsm_cur : main_fsm_type; signal main_fsm_next : main_fsm_type; signal tx_frame_valid_i : std_logic; signal rx_frame_rdy_i : std_logic; signal tx_frame_data_i : std_logic_vector(TX_FRAME_DATA'range); signal tx_frame_be_i : std_logic_vector(TX_FRAME_BE'range); signal tx_frame_last_i : std_logic; signal loopback_pkt_cnt_inc : std_logic; signal test_pkt_cnt_inc : std_logic; signal unknown_port_pkt_cnt_inc : std_logic; signal test_pkt_accept_cnt_inc : std_logic; signal loopback_pkt_cnt : std_logic_vector(31 downto 0); signal test_pkt_cnt : std_logic_vector(31 downto 0); signal unknown_port_pkt_cnt : std_logic_vector(31 downto 0); signal test_pkt_accept_cnt : std_logic_vector(31 downto 0); signal tstmp64_cnt : std_logic_vector(63 downto 0); signal test_pkt_prepare : std_logic; signal test_pkt_last : std_logic; signal test_pkt_last_d : std_logic; signal test_pkt_shift : std_logic; signal net_info_pkt_prepare : std_logic; signal net_info_pkt_last : std_logic; signal net_info_pkt_shift : std_logic; signal data_out_reg : std_logic_vector(TX_FRAME_DATA'range); signal data_out_be_reg : std_logic_vector(TX_FRAME_BE'range); type test_pkt_fsm_type is (TP_LPBK_TEST_CNTS, TP_UNKNOW_TST_ACCEPT_CNTS); signal test_pkt_fsm : test_pkt_fsm_type; type net_info_pkt_fsm_type is (NI_MAC_ADDR, NI_IP_INFO); signal net_info_pkt_fsm : net_info_pkt_fsm_type; begin TX_DST_MAC <= RX_SRC_MAC; TX_DST_IP <= RX_SRC_IP; TX_DST_UDP <= RX_SRC_UDP; TX_SRC_UDP <= RX_DST_UDP; main_fsm_adv_proc : process(CLK) begin if rising_edge(CLK) then if RST = '1' then main_fsm_cur <= M_IDLE; else main_fsm_cur <= main_fsm_next; end if; end if; end process; main_fsm_transout_proc : process(main_fsm_cur, RX_FRAME_VALID, RX_DST_UDP, RX_FRAME_DATA, RX_FRAME_BE, RX_FRAME_LAST, TX_FRAME_RDY, data_out_reg, data_out_be_reg, test_pkt_last, test_pkt_last_d, RX_FRAME_LENGTH, net_info_pkt_last) begin main_fsm_next <= main_fsm_cur; tx_frame_valid_i <= '0'; rx_frame_rdy_i <= '0'; tx_frame_data_i <= RX_FRAME_DATA; tx_frame_be_i <= RX_FRAME_BE; tx_frame_last_i <= RX_FRAME_LAST; loopback_pkt_cnt_inc <= '0'; test_pkt_cnt_inc <= '0'; unknown_port_pkt_cnt_inc <= '0'; test_pkt_accept_cnt_inc <= '0'; test_pkt_prepare <= '0'; test_pkt_shift <= '0'; net_info_pkt_prepare <= '0'; net_info_pkt_shift <= '0'; case main_fsm_cur is when M_IDLE => if RX_FRAME_VALID = '1' then case RX_DST_UDP is when g_loopback_port => main_fsm_next <= M_LOOPBACK; loopback_pkt_cnt_inc <= '1'; when g_test_port => if RX_FRAME_DATA(31 downto 0) = LC_TEST_MAGIC and unsigned(RX_FRAME_LENGTH) >= LC_TEST_MIN_PKT then test_pkt_accept_cnt_inc <= '1'; main_fsm_next <= M_TEST; else main_fsm_next <= M_DISCARD; end if; test_pkt_cnt_inc <= '1'; when g_net_info_port => main_fsm_next <= M_NET_INFO; net_info_pkt_prepare <= '1'; when others => main_fsm_next <= M_DISCARD; unknown_port_pkt_cnt_inc <= '1'; end case; end if; when M_LOOPBACK => tx_frame_valid_i <= '1'; -- RX is guaranteed to have all data ready rx_frame_rdy_i <= TX_FRAME_RDY; if RX_FRAME_LAST = '1' and TX_FRAME_RDY = '1' then -- last word was accepted by tx main_fsm_next <= M_IDLE; end if; when M_TEST => -- Copy magic and user id to response tx_frame_valid_i <= '1'; if TX_FRAME_RDY = '1' then rx_frame_rdy_i <= '1'; main_fsm_next <= M_TEST_RESP_DATA; test_pkt_prepare <= '1'; end if; when M_TEST_RESP_DATA => -- We can be sure that RX data are longer than inserted header -- as we tested it in IDLE state if test_pkt_last = '0' or test_pkt_last_d = '0' then tx_frame_data_i <= data_out_reg; -- send data from temporary register else tx_frame_data_i <= RX_FRAME_DATA; -- send data from request end if; tx_frame_be_i <= RX_FRAME_BE; tx_frame_valid_i <= '1'; -- we have always data ready tx_frame_last_i <= RX_FRAME_LAST; rx_frame_rdy_i <= TX_FRAME_RDY; -- drain unused rx data test_pkt_shift <= TX_FRAME_RDY; -- Sent frame shall be of the same length as the received one if TX_FRAME_RDY = '1' and RX_FRAME_LAST = '1' then main_fsm_next <= M_IDLE; end if; when M_NET_INFO => tx_frame_data_i <= data_out_reg; -- send data from temporary register tx_frame_be_i <= data_out_be_reg; tx_frame_valid_i <= '1'; tx_frame_last_i <= net_info_pkt_last; net_info_pkt_shift <= TX_FRAME_RDY; if TX_FRAME_RDY = '1' and net_info_pkt_last = '1' then -- Discard request packet main_fsm_next <= M_DISCARD; end if; when M_DISCARD => rx_frame_rdy_i <= RX_FRAME_VALID; if RX_FRAME_LAST = '1' or RX_FRAME_VALID = '0' then main_fsm_next <= M_IDLE; end if; end case; end process; test_net_info_pkt_build_proc : process(CLK) begin if rising_edge(CLK) then if test_pkt_prepare = '1' then test_pkt_last <= '0'; data_out_reg <= tstmp64_cnt; data_out_be_reg <= (others => '1'); test_pkt_fsm <= TP_LPBK_TEST_CNTS; elsif test_pkt_shift = '1' then case test_pkt_fsm is when TP_LPBK_TEST_CNTS => data_out_reg <= test_pkt_cnt & loopback_pkt_cnt; test_pkt_fsm <= TP_UNKNOW_TST_ACCEPT_CNTS; when TP_UNKNOW_TST_ACCEPT_CNTS => data_out_reg <= test_pkt_accept_cnt & unknown_port_pkt_cnt; test_pkt_last <= '1'; end case; test_pkt_last_d <= test_pkt_last; end if; if net_info_pkt_prepare = '1' then net_info_pkt_last <= '0'; data_out_reg <= tstmp64_cnt; data_out_be_reg <= (others => '1'); net_info_pkt_fsm <= NI_MAC_ADDR; elsif net_info_pkt_shift = '1' then case net_info_pkt_fsm is when NI_MAC_ADDR => data_out_reg <= x"0000" & HOST_MAC; net_info_pkt_fsm <= NI_IP_INFO; when NI_IP_INFO => data_out_reg <= HOST_IP_NETMASK & HOST_IP; net_info_pkt_last <= '1'; end case; end if; end if; end process; counters_proc : process(CLK) begin if rising_edge(CLK) then if loopback_pkt_cnt_inc = '1' then loopback_pkt_cnt <= std_logic_vector(unsigned(loopback_pkt_cnt) + 1); end if; if test_pkt_cnt_inc = '1' then test_pkt_cnt <= std_logic_vector(unsigned(test_pkt_cnt) + 1); end if; if unknown_port_pkt_cnt_inc = '1' then unknown_port_pkt_cnt <= std_logic_vector(unsigned( unknown_port_pkt_cnt) + 1); end if; if test_pkt_accept_cnt_inc = '1' then test_pkt_accept_cnt <= std_logic_vector(unsigned( test_pkt_accept_cnt) + 1); end if; -- timestamp counter tstmp64_cnt <= std_logic_vector(unsigned(tstmp64_cnt) + 1); if RST = '1' then tstmp64_cnt <= (others => '0'); test_pkt_accept_cnt <= (others => '0'); unknown_port_pkt_cnt <= (others => '0'); test_pkt_cnt <= (others => '0'); loopback_pkt_cnt <= (others => '0'); end if; end if; end process; TX_FRAME_VALID <= tx_frame_valid_i; TX_FRAME_LAST <= tx_frame_last_i; TX_FRAME_BE <= tx_frame_be_i; TX_FRAME_DATA <= tx_frame_data_i; RX_FRAME_RDY <= rx_frame_rdy_i; end architecture;
Go to most recent revision | Compare with Previous | Blame | View Log