OpenCores
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 4

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;
 
 
 
 
 
 
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.