-------------------------------------------------------------------------------
--
-- Project name: UDP_100G_SWITCH
--
-- (C) Copyright 2019 DFC Design, s.r.o., Brno, Czech Republic
-- Author: Jakub Hadamek (j.hadamek@dfcdesign.cz)
--
-------------------------------------------------------------------------------
--
-------------------------------------------------------------------------------




library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

Library xpm;
use xpm.vcomponents.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 leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all; 

entity udp_100g_switch_2ports is
   port (
      -- Core clock and reset
      RESET                   : in  std_logic := '0';
      CLK                     : in  std_logic := '0';

      ------------   UDP 100G Interface    ---------
      -- RX Datapath --
      S_AXIS_UDP_TVALID       : in  std_logic := '0';
      S_AXIS_UDP_TREADY       : out std_logic := '0';
      S_AXIS_UDP_TLAST        : in  std_logic := '0';
      S_AXIS_UDP_TKEEP        : in  std_logic_vector(63 downto 0) := (others => '0');
      S_AXIS_UDP_TDATA        : in  std_logic_vector(511 downto 0) := (others => '0');
      -- RX net info
      RX_DST_UDP              : in std_logic_vector(15 downto 0) := (others => '0');
      RX_SRC_UDP              : in std_logic_vector(15 downto 0) := (others => '0');
      RX_SRC_IP               : in std_logic_vector(31 downto 0) := (others => '0');
      RX_SRC_MAC              : in std_logic_vector(47 downto 0) := (others => '0');
      RX_PACKET_LENGTH        : in std_logic_vector(15 downto 0) := (others => '0');
      -- TX Datapath --
      M_AXIS_UDP_TVALID       : out std_logic := '0';
      M_AXIS_UDP_TREADY       : in  std_logic := '0';
      M_AXIS_UDP_TLAST        : out std_logic := '0';
      M_AXIS_UDP_TKEEP        : out std_logic_vector(63 downto 0) := (others => '0');
      M_AXIS_UDP_TDATA        : out std_logic_vector(511 downto 0) := (others => '0');
      -- TX net info
      TX_SRC_UDP              : out  std_logic_vector(15 downto 0) := (others => '0');
      TX_DST_UDP              : out  std_logic_vector(15 downto 0) := (others => '0');
      TX_DST_IP               : out  std_logic_vector(31 downto 0) := (others => '0');
      TX_DST_MAC              : out  std_logic_vector(47 downto 0) := (others => '0');
      -- Packet divided user signal 
      PACKET_DIVIDED          : in  std_logic := '0';

      ------------   UDP Application 0    ---------
      -- TX Datapath
      APP0_S_AXIS_TVALID      : in  std_logic := '0';
      APP0_S_AXIS_TREADY      : out std_logic := '0';
      APP0_S_AXIS_TLAST       : in  std_logic := '0';
      APP0_S_AXIS_TKEEP       : in  std_logic_vector(63 downto 0) := (others => '0');
      APP0_S_AXIS_TDATA       : in  std_logic_vector(511 downto 0) := (others => '0');
      -- tx net infO
      APP0_TX_SRC_UDP         : in  std_logic_vector(15 downto 0) := (others => '0');
      APP0_TX_DST_UDP         : in  std_logic_vector(15 downto 0) := (others => '0');
      APP0_TX_DST_IP          : in  std_logic_vector(31 downto 0) := (others => '0');
      APP0_TX_DST_MAC         : in  std_logic_vector(47 downto 0) := (others => '0');
      -- Packet divided user signal 
      APP0_PACKET_DIVIDED     : out std_logic := '0';
      -- RX DatA
      APP0_M_AXIS_TVALID      : out std_logic := '0';
      APP0_M_AXIS_TREADY      : in  std_logic := '0';
      APP0_M_AXIS_TLAST       : out std_logic := '0';
      APP0_M_AXIS_TKEEP       : out std_logic_vector(63 downto 0) := (others => '0'); 
      APP0_M_AXIS_TDATA       : out std_logic_vector(511 downto 0) := (others => '0');
      -- RX net
      APP0_RX_DST_UDP         : in  std_logic_vector(15 downto 0) := (others => '0');
      APP0_RX_SRC_UDP         : out std_logic_vector(15 downto 0) := (others => '0');
      APP0_RX_SRC_IP          : out std_logic_vector(31 downto 0) := (others => '0');
      APP0_RX_SRC_MAC         : out std_logic_vector(47 downto 0) := (others => '0');
      APP0_RX_PACKET_LENGTH   : out std_logic_vector(15 downto 0) := (others => '0');
      APP0_DUPLICATE_PORT     : out std_logic := '0';

      ------------   UDP Application 0    ---------
      -- TX Datapath
      APP1_S_AXIS_TVALID      : in  std_logic := '0';
      APP1_S_AXIS_TREADY      : out std_logic := '0';
      APP1_S_AXIS_TLAST       : in  std_logic := '0';
      APP1_S_AXIS_TKEEP       : in  std_logic_vector(63 downto 0) := (others => '0');
      APP1_S_AXIS_TDATA       : in  std_logic_vector(511 downto 0) := (others => '0');
      -- tx net infO
      APP1_TX_SRC_UDP         : in  std_logic_vector(15 downto 0) := (others => '0');
      APP1_TX_DST_UDP         : in  std_logic_vector(15 downto 0) := (others => '0');
      APP1_TX_DST_IP          : in  std_logic_vector(31 downto 0) := (others => '0');
      APP1_TX_DST_MAC         : in  std_logic_vector(47 downto 0) := (others => '0');
      -- Packet divided user signal 
      APP1_PACKET_DIVIDED     : out std_logic := '0';
      -- RX DatA
      APP1_M_AXIS_TVALID      : out std_logic := '0';
      APP1_M_AXIS_TREADY      : in  std_logic := '0';
      APP1_M_AXIS_TLAST       : out std_logic := '0';
      APP1_M_AXIS_TKEEP       : out std_logic_vector(63 downto 0) := (others => '0'); 
      APP1_M_AXIS_TDATA       : out std_logic_vector(511 downto 0) := (others => '0');
      -- RX net
      APP1_RX_DST_UDP         : in  std_logic_vector(15 downto 0) := (others => '0');
      APP1_RX_SRC_UDP         : out std_logic_vector(15 downto 0) := (others => '0');
      APP1_RX_SRC_IP          : out std_logic_vector(31 downto 0) := (others => '0');
      APP1_RX_SRC_MAC         : out std_logic_vector(47 downto 0) := (others => '0');
      APP1_RX_PACKET_LENGTH   : out std_logic_vector(15 downto 0) := (others => '0');
      APP1_DUPLICATE_PORT     : out std_logic := '0'      
   );
end;

architecture Behavioral of udp_100g_switch_2ports is
   constant LC_PORTS_CNT      : natural := 2;

      ------------   USER Interface    ---------
      -- tx datapath
      signal app_s_axis_tvalid       : std_logic_vector(LC_PORTS_CNT - 1 downto 0) := (others => '0');
      signal app_s_axis_tready       : std_logic_vector(LC_PORTS_CNT - 1 downto 0) := (others => '0');
      signal app_s_axis_tlast        : std_logic_vector(LC_PORTS_CNT - 1 downto 0) := (others => '0');
      signal app_s_axis_tkeep        : std_logic_vector(64 * LC_PORTS_CNT - 1 downto 0) := (others => '0');
      signal app_s_axis_tdata        : std_logic_vector(512 * LC_PORTS_CNT - 1 downto 0) := (others => '0');
      -- tx net info
      signal app_tx_src_udp          : std_logic_vector(LC_PORTS_CNT * 16 - 1 downto 0) := (others => '0');
      signal app_tx_dst_udp          : std_logic_vector(LC_PORTS_CNT * 16 - 1 downto 0) := (others => '0');
      signal app_tx_dst_ip           : std_logic_vector(LC_PORTS_CNT * 32 - 1 downto 0) := (others => '0');
      signal app_tx_dst_mac          : std_logic_vector(LC_PORTS_CNT * 48 - 1 downto 0) := (others => '0');
      -- packet divided user signal 
      signal app_packet_divided      : std_logic_vector(LC_PORTS_CNT - 1 downto 0) := (others => '0');
      -- rx datapath
      signal app_m_axis_tvalid       : std_logic_vector(LC_PORTS_CNT - 1 downto 0) := (others => '0');
      signal app_m_axis_tready       : std_logic_vector(LC_PORTS_CNT - 1 downto 0) := (others => '0');
      signal app_m_axis_tlast        : std_logic_vector(LC_PORTS_CNT - 1 downto 0) := (others => '0');
      signal app_m_axis_tkeep        : std_logic_vector(64 * LC_PORTS_CNT - 1 downto 0) := (others => '0'); 
      signal app_m_axis_tdata        : std_logic_vector(512 * LC_PORTS_CNT - 1 downto 0) := (others => '0');
      -- rx net info
      signal app_rx_dst_udp          : std_logic_vector(LC_PORTS_CNT * 16 - 1 downto 0) := (others => '0');
      signal app_rx_src_udp          : std_logic_vector(LC_PORTS_CNT * 16 - 1 downto 0) := (others => '0');
      signal app_rx_src_ip           : std_logic_vector(LC_PORTS_CNT * 32 - 1 downto 0) := (others => '0');
      signal app_rx_src_mac          : std_logic_vector(LC_PORTS_CNT * 48 - 1 downto 0) := (others => '0');
      signal app_rx_packet_length    : std_logic_vector(LC_PORTS_CNT * 16 - 1 downto 0) := (others => '0');

      ------------   COMMON status    ---------
      signal duplicate_ports         : std_logic_vector(LC_PORTS_CNT - 1 downto 0);


   
begin

   udp_switch_inst: entity work.udp_100g_switch
   generic map(
      g_ports_cnt             => LC_PORTS_CNT
           )
   port map(
      -- Core reset
      RESET                   => RESET,
      CLK                     => CLK,

      ------------   UDP 100G Interface    ---------
--      -- Host net info
--      HOST_MAC                => HOST_MAC,     
--      HOST_IP                 => HOST_IP,      
--      HOST_NET_MASK           => HOST_NET_MASK, 
      -- RX Datapath                    
      S_AXIS_UDP_TVALID       => S_AXIS_UDP_TVALID, 
      S_AXIS_UDP_TREADY       => S_AXIS_UDP_TREADY, 
      S_AXIS_UDP_TLAST        => S_AXIS_UDP_TLAST, 
      S_AXIS_UDP_TKEEP        => S_AXIS_UDP_TKEEP, 
      S_AXIS_UDP_TDATA        => S_AXIS_UDP_TDATA, 
      -- RX net info           
      RX_DST_UDP              => RX_DST_UDP,       
      RX_SRC_UDP              => RX_SRC_UDP,       
      RX_SRC_IP               => RX_SRC_IP,        
      RX_SRC_MAC              => RX_SRC_MAC,        
      RX_PACKET_LENGTH        => RX_PACKET_LENGTH,
      -- TX Datapath           
      M_AXIS_UDP_TVALID       => M_AXIS_UDP_TVALID,
      M_AXIS_UDP_TREADY       => M_AXIS_UDP_TREADY, 
      M_AXIS_UDP_TLAST        => M_AXIS_UDP_TLAST, 
      M_AXIS_UDP_TKEEP        => M_AXIS_UDP_TKEEP, 
      M_AXIS_UDP_TDATA        => M_AXIS_UDP_TDATA, 
      -- TX net info            
      TX_SRC_UDP              => TX_SRC_UDP,       
      TX_DST_UDP              => TX_DST_UDP,       
      TX_DST_IP               => TX_DST_IP,       
      TX_DST_MAC              => TX_DST_MAC,       
      -- Packet divided user signal
      PACKET_DIVIDED          => PACKET_DIVIDED,    

      ------------   USER Interface    ---------
      -- TX Datapath
      APP_S_AXIS_TVALID       => app_s_axis_tvalid,    
      APP_S_AXIS_TREADY       => app_s_axis_tready,    
      APP_S_AXIS_TLAST        => app_s_axis_tlast,     
      APP_S_AXIS_TKEEP        => app_s_axis_tkeep,     
      APP_S_AXIS_TDATA        => app_s_axis_tdata,     
      -- tx net info            
      APP_TX_SRC_UDP          => app_tx_src_udp,       
      APP_TX_DST_UDP          => app_tx_dst_udp,       
      APP_TX_DST_IP           => app_tx_dst_ip,        
      APP_TX_DST_MAC          => app_tx_dst_mac,       
      -- Packet divided user signals
      APP_PACKET_DIVIDED      => app_packet_divided,   
      -- RX Datapath                                   
      APP_M_AXIS_TVALID       => app_m_axis_tvalid,    
      APP_M_AXIS_TREADY       => app_m_axis_tready,    
      APP_M_AXIS_TLAST        => app_m_axis_tlast,     
      APP_M_AXIS_TKEEP        => app_m_axis_tkeep,     
      APP_M_AXIS_TDATA        => app_m_axis_tdata,     
      -- RX net info                                   
      APP_RX_DST_UDP          => app_rx_dst_udp,       
      APP_RX_SRC_UDP          => app_rx_src_udp,       
      APP_RX_SRC_IP           => app_rx_src_ip,        
      APP_RX_SRC_MAC          => app_rx_src_mac,       
      APP_RX_PACKET_LENGTH    => app_rx_packet_length, 
                                                 
      ------------   COMMON signals ------------   
      DUPLICATE_PORTS         => duplicate_ports     
   );


      ------------   UDP Application 0    ---------
      -- TX Datapath
      app_s_axis_tvalid(0) <= APP0_S_AXIS_TVALID;    
      APP0_S_AXIS_TREADY   <= app_s_axis_tready(0);    
      app_s_axis_tlast(0)  <= APP0_S_AXIS_TLAST;     
      app_s_axis_tkeep(APP0_S_AXIS_TKEEP'length - 1 downto 0)  <= APP0_S_AXIS_TKEEP;     
      app_s_axis_tdata(APP0_S_AXIS_TDATA'length - 1 downto 0)  <= APP0_S_AXIS_TDATA;     
      app_tx_src_udp(APP0_TX_SRC_UDP'length - 1 downto 0)      <= APP0_TX_SRC_UDP;       
      app_tx_dst_udp(APP0_TX_DST_UDP'length - 1 downto 0)      <= APP0_TX_DST_UDP;       
      app_tx_dst_ip(APP0_TX_DST_IP'length - 1 downto 0)        <= APP0_TX_DST_IP ;        
      app_tx_dst_mac(APP0_TX_DST_MAC'length - 1 downto 0)      <= APP0_TX_DST_MAC;       
      APP0_PACKET_DIVIDED <= app_packet_divided(0);   
      -- RX Datapath                                   
      APP0_M_AXIS_TVALID  <= app_m_axis_tvalid(0);    
      app_m_axis_tready(0) <= APP0_M_AXIS_TREADY;    
      APP0_M_AXIS_TLAST   <= app_m_axis_tlast(0);     
      APP0_M_AXIS_TKEEP   <= app_m_axis_tkeep(APP0_M_AXIS_TKEEP'length - 1 downto 0);     
      APP0_M_AXIS_TDATA   <= app_m_axis_tdata(APP0_M_AXIS_TDATA'length - 1 downto 0);     
      app_rx_dst_udp(APP0_RX_DST_UDP'length - 1 downto 0) <= APP0_RX_DST_UDP;       
      APP0_RX_SRC_UDP     <= app_rx_src_udp(APP0_RX_SRC_UDP'length - 1 downto 0);       
      APP0_RX_SRC_IP      <= app_rx_src_ip(APP0_RX_SRC_IP'length - 1 downto 0);        
      APP0_RX_SRC_MAC     <= app_rx_src_mac(APP0_RX_SRC_MAC'length - 1 downto 0);       
      APP0_RX_PACKET_LENGTH <= app_rx_packet_length(APP0_RX_PACKET_LENGTH'length - 1 downto 0); 
      -- common
      APP0_DUPLICATE_PORT <= duplicate_ports(0);   

      ------------   UDP Application 1    ---------
      -- TX Datapath
      app_s_axis_tvalid(1) <= APP1_S_AXIS_TVALID;    
      APP1_S_AXIS_TREADY   <= app_s_axis_tready(1);    
      app_s_axis_tlast(1)  <= APP1_S_AXIS_TLAST;     
      app_s_axis_tkeep(2*APP1_S_AXIS_TKEEP'length - 1 downto APP1_S_AXIS_TKEEP'length) <= APP1_S_AXIS_TKEEP;     
      app_s_axis_tdata(2*APP1_S_AXIS_TDATA'length - 1 downto APP1_S_AXIS_TDATA'length) <= APP1_S_AXIS_TDATA;     
      app_tx_src_udp(2*APP1_TX_SRC_UDP'length - 1 downto APP1_TX_SRC_UDP'length)       <= APP1_TX_SRC_UDP;       
      app_tx_dst_udp(2*APP1_TX_DST_UDP'length - 1 downto APP1_TX_DST_UDP'length)       <= APP1_TX_DST_UDP;       
      app_tx_dst_ip(2*APP1_TX_DST_IP'length - 1 downto APP1_TX_DST_IP'length)          <= APP1_TX_DST_IP ;        
      app_tx_dst_mac(2*APP1_TX_DST_MAC'length - 1 downto APP1_TX_DST_MAC'length)       <= APP1_TX_DST_MAC;       
      APP1_PACKET_DIVIDED <= app_packet_divided(1);   
      -- RX Datapath                                   
      APP1_M_AXIS_TVALID  <= app_m_axis_tvalid(1);    
      app_m_axis_tready(1) <= APP1_M_AXIS_TREADY;    
      APP1_M_AXIS_TLAST   <= app_m_axis_tlast(1);     
      APP1_M_AXIS_TKEEP   <= app_m_axis_tkeep(2*APP1_M_AXIS_TKEEP'length - 1 downto APP1_M_AXIS_TKEEP'length);     
      APP1_M_AXIS_TDATA   <= app_m_axis_tdata(2*APP1_M_AXIS_TDATA'length - 1 downto APP1_M_AXIS_TDATA'length);     
      app_rx_dst_udp(2*APP1_RX_DST_UDP'length - 1 downto APP1_RX_DST_UDP'length) <= APP1_RX_DST_UDP;       
      APP1_RX_SRC_UDP     <= app_rx_src_udp(2*APP1_RX_SRC_UDP'length - 1 downto APP1_RX_SRC_UDP'length);       
      APP1_RX_SRC_IP      <= app_rx_src_ip(2*APP1_RX_SRC_IP'length - 1 downto APP1_RX_SRC_IP'length);        
      APP1_RX_SRC_MAC     <= app_rx_src_mac(2*APP1_RX_SRC_MAC'length - 1 downto APP1_RX_SRC_MAC'length);       
      APP1_RX_PACKET_LENGTH <= app_rx_packet_length(2*APP1_RX_PACKET_LENGTH'length - 1 downto APP1_RX_PACKET_LENGTH'length); 
      -- common
      APP1_DUPLICATE_PORT <= duplicate_ports(1);   

end;
