--------------------------------------------------------------------------------
--
-- This VHDL file was generated by EASE/HDL 8.3 Revision 5 from HDL Works B.V.
--
-- Ease library  : design
-- HDL library   : work
-- Host name     : SERING
-- User name     : peterj
-- Time stamp    : Fri Nov 04 12:57:16 2016
--
-- Designed by   : 
-- Company       : HDL Works
-- Project info  : 
--
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
-- Object        : Entity design.TxStreamSel
-- Last modified : Wed May 11 13:21:29 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.V_ARRAY_Package.all;
use work.EMAC16bit_Package.all;

entity TxStreamSel is
  port (
    Clk           : in     std_logic;
    ConnectReq    : in     std_logic;
    Connected     : out    std_logic;
    Dout          : out    std_logic_vector(15 downto 0);
    EODout        : out    std_logic;
    Packet        : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    Packet_RdReq  : out    std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    RdReqOut      : out    std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    RdReqin       : in     std_logic;
    Rst           : in     std_logic;
    Stream        : out    natural range NUM_UDP_PRTS-1 downto 0;
    TXi           : in     dbus_type_array(NUM_UDP_PRTS-1 downto 0);
    TxStreamDebug : out    std_logic_vector(11 downto 0);
    Validin       : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    Validout      : out    std_logic);
end entity TxStreamSel;

--------------------------------------------------------------------------------
-- Object        : Architecture design.TxStreamSel.fsm
-- Last modified : Wed May 11 13:21:29 2016
--------------------------------------------------------------------------------


architecture fsm of TxStreamSel is

  type state_type is (Idle, SearchConnect, ReadUntilEOP, State_Connected) ;
  signal state : state_type  ;  -- Current State

  Signal StreamPointer: Natural Range NUM_UDP_PRTS - 1 Downto 0;

begin

  TxStreamDebug(3  downto  0) <= std_logic_vector(to_unsigned(2**StreamPointer,4));
  TxStreamDebug(4)            <= ConnectReq;
  TxStreamDebug(7  downto  5) <= (others => '0');
  TxStreamDebug(11 downto  8) <= packet;
  
   -- Pipeline between entity "TxFifos" and "TxBuffers/tx_data2buf"
   -- This will ease the timing of the system
   Process (Clk, Rst)
   Begin
      If Rst = '1' Then
         Stream <= 0;
         Dout <= (Others => '0');
         EODout <= '0';
         Validout <= '0';
      ElsIf Rising_Edge(Clk) Then
         -- Pipeline between entity "TxFifos" and "TxBuffers/tx_data2buf"
         -- This will ease the timing of the system
         Stream <= StreamPointer;
         Dout <= TXi(StreamPointer).D;
         EODout <= TXi(StreamPointer).EOD;
         If state = ReadUntilEOP Then
            If Validin(StreamPointer) = '0' Or RdReqin = '1' Then
               Validout <= Validin(StreamPointer);
            Else
               Validout <= '0';
            End If;
         Else
            Validout <= '0';
         End If;
      End If;
   End Process;
   
   process (state, StreamPointer)
   Begin
      -- By default, do not RdReqout any of the input FIFOs
      RdReqout <= (Others => '0');
      If state = ReadUntilEOP Then
         -- Overrule the RdReqout <= (Others => '0') above if needed:
         RdReqout(StreamPointer) <= '1';
      End If;
   End Process;

   state_decoding: Process (Clk, Rst) Is
   Begin
      If (Rst = '1') Then
         state <= Idle ;
         StreamPointer <= 0;
         Connected <= '0';
         Packet_RdReq <= (others => '0');
      ElsIf (rising_edge(Clk)) Then
         Case state Is
           When Idle =>
             -- One of the input pipelines contains data
             -- and the TxBuffer is ready to accept a connection
             If (Unsigned(Packet) /= 0 And ConnectReq = '1') Then
               state <= SearchConnect ;
               -- IncStreamPointer:
               -- Forcing a Stream Increment forces a round-
               -- robbin (otherwise the input fifo that keeps
               -- "not-empty" asserted, holds the stream)
               If StreamPointer = NUM_UDP_PRTS - 1 Then
                  StreamPointer <= 0;
               Else
                  StreamPointer <= StreamPointer + 1;
               End If;
             Else
               state <= Idle;
               Connected <= '0';
             End If ;

          When SearchConnect =>
             If (Packet(StreamPointer) = '1') Then
               state <= State_Connected;
               
               -- Read one entry from the fifo that keeps track of the amount of packets in the data fifo
               Packet_RdReq(StreamPointer) <= '1';
               Connected <= '1';

               -- The pointed input doesn't contain data
             Else
               state <= SearchConnect;
               -- IncStreamPointer:
               If StreamPointer = NUM_UDP_PRTS - 1 Then
                  StreamPointer <= 0;
               Else
                  StreamPointer <= StreamPointer + 1;
               End If;
             End If ;
             
           When State_Connected =>
             -- Signal "ConnectReq" is the handshake with the tx_data2buf state machine.
             -- If connect = 0 then the "tx_data2buf" machine advanced (i.e. it got out of
             -- the Idle state).
             Packet_RdReq(StreamPointer) <= '0';
             If (ConnectReq = '0') Then
               state <= ReadUntilEOP ;
               Connected <= '0';
             Else
               state <= State_Connected ;
               Connected <= '1';
             End If ;
             
           When ReadUntilEOP =>
             If (TXi(StreamPointer).EOD = '1') Then
               state <= Idle ;
               Connected <= '0';
             Else
               state <= ReadUntilEOP ;
               Connected <= '0';
             End If ;
             
         End Case ;
      End If ;
   End Process state_decoding ;

end architecture fsm ; -- of TxStreamSel

--------------------------------------------------------------------------------
-- Object        : Entity design.txfifos
-- Last modified : Thu May 12 14:43:16 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all;
use work.V_ARRAY_Package.all;
use work.EMAC16bit_Package.all;

entity txfifos is
  port (
    Flush        : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    Full         : out    std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    Packet       : out    std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    Packet_RdReq : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    PacketsDone  : out    std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    RdClk        : in     std_logic;
    RdReq        : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    Rst          : in     std_logic;
    TXi          : in     dbus_type_array(NUM_UDP_PRTS-1 downto 0);
    TXo          : out    dbus_type_array(NUM_UDP_PRTS-1 downto 0);
    Valid        : out    std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    WrClk        : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    WrReq        : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0));
end entity txfifos;

--------------------------------------------------------------------------------
-- Object        : Architecture design.txfifos.rtl
-- Last modified : Thu May 12 14:43:16 2016
--------------------------------------------------------------------------------


architecture rtl of txfifos is
  component Reg1En
    Port
    (
     Clk : in std_logic;
     En  : in std_logic;
     D   : in std_logic;
     Q   : out std_logic;
     Rst : in std_logic
    );
  end component ;
  
  constant fifo_size: natural := 8192;
  constant full_threshold: natural := fifo_size - 16;

  constant d_i_null: std_logic_vector(0 downto 0) := (others => '0');
  
  type std_logic_v9array is array ( natural range <> ) of std_logic_vector(8 downto 0);
  type std_logic_v18array is array ( natural range <> ) of std_logic_vector(17 downto 0);
  
  signal Din_Intern      : std_logic_v18array(NUM_UDP_PRTS-1 downto 0);
  signal Dout_Intern     : std_logic_v18array(NUM_UDP_PRTS-1 downto 0);
  signal Empty_Intern    : std_logic_vector(NUM_UDP_PRTS-1 downto 0);
  signal Valid_Intern    : std_logic_vector(NUM_UDP_PRTS-1 downto 0);
  signal NotEmpty_Intern : std_logic_vector(NUM_UDP_PRTS-1 downto 0);
  signal RdReq_Intern    : std_logic_vector(NUM_UDP_PRTS-1 downto 0);
  signal Rst_Intern      : std_logic_vector(NUM_UDP_PRTS-1 downto 0);
  signal Rst_Intern_n    : std_logic_vector(NUM_UDP_PRTS-1 downto 0);
  signal WrReq_EOD       : std_logic_vector(NUM_UDP_PRTS-1 downto 0);
  signal Empty_EOD       : std_logic_vector(NUM_UDP_PRTS-1 downto 0);
  signal Full_data       : std_logic_vector(NUM_UDP_PRTS-1 downto 0);
  signal Full_EOD        : std_logic_vector(NUM_UDP_PRTS-1 downto 0);

begin

  GenTxFifos: For i In 0 to NUM_UDP_PRTS-1 Generate
      
    Din_Intern(i)(17) <= '0';
    Din_Intern(i)(16) <= TXi(i).EOD;
    Din_Intern(i)(15 downto 0) <= TXi(i).D;
    TXo(i).EOD <= Dout_Intern(i)(16);
    TXo(i).D <= Dout_Intern(i)(15 downto 0);
    
    NotEmpty_Intern(i) <= Not Empty_Intern(i);
    RdReq_Intern(i) <= Not Valid_Intern(i) Or RdReq(i);
    Valid(i) <= Valid_Intern(i);
    Full(i) <= Full_data(i) Or Full_EOD(i);
    Rst_Intern(i)   <=     Flush(i) Or Rst;
    Rst_Intern_n(i) <= not(Flush(i) Or Rst);

    ValidReg: Reg1En
      Port Map
       (
         Clk       => RdClk,
         En        => RdReq_Intern(i),
         D         => NotEmpty_Intern(i),
         Q         => Valid_Intern(i),
         Rst       => Rst_Intern(i)
       );

    -- There are two FIFOs implemented for each channel:
    -- 1) tx_data_fifo that receives the packet payload data (in 16 bit words, plus an End Of Data bit)
    -- 2) tx_eod_fifo  is written only when an End Of Data is written to to tx_data_fifo
    -- The latter FIFO holds no actual data, rather the flag structure of the FIFO is used to signal
    -- that a complete packet (including EOD) was written to the data FIFO such that it is ready to be
    -- readout in one go.
    -- This avoids the situation where an input stream is serviced by IPMUX while the packet trailer (EOD)
    -- is still under way (which may take any time) thereby blocking transfers of any other IPMUX input streams.
    
    tx_data_fifo: generic_async_fifo
      generic map(
        g_data_width             => 18,
        g_size                   => fifo_size,
        g_with_rd_empty          => true,
        g_with_wr_almost_full    => true,
        g_almost_full_threshold  => full_threshold
      )
      port map
      (
        rst_n_i            => Rst_Intern_n(i),
        clk_wr_i           => WrClk(i),
        d_i                => Din_Intern(i),
        we_i               => WrReq(i),
        wr_empty_o         => open,
        wr_full_o          => open,
        wr_almost_empty_o  => open,
        wr_almost_full_o   => Full_data(i),
        wr_count_o         => open,
        clk_rd_i           => RdClk,
        q_o                => Dout_Intern(i),
        rd_i               => RdReq_Intern(i),
        rd_empty_o         => Empty_Intern(i),
        rd_full_o          => open,
        rd_almost_empty_o  => open,
        rd_almost_full_o   => open,
        rd_count_o         => open
      );

    WrReq_EOD(i) <= WrReq(i) And TXi(i).EOD;
    Packet(i) <= Not Empty_EOD(i);
    
    -- PacketsDone signals weather a stream is done with the transfer of a complete packet from it's tx_data_fifo to the packet buffer.
    -- so as soon as the tx_eod_fifo is not empty (Empty_EOD(i) = '0') then there is data to be shipped for the associated stream, until
    -- all data out of the tx_data_fifo was read, up to the EOD bit (Dout_Intern(i)(16) = '1')
    process (RdClk, Rst_Intern_n(i))
    begin
      if Rst_Intern_n(i) = '0' then
        PacketsDone(i) <= '1';
      elsif rising_edge(RdClk) then
        if Empty_EOD(i) = '0' then
          PacketsDone(i) <= '0';
        elsif Dout_Intern(i)(16) = '1' then
          PacketsDone(i) <= '1';
        end if;
      end if;
    end process;
    
      tx_eod_fifo: generic_async_fifo
      generic map(
        g_data_width             => 1,
        g_size                   => fifo_size,
        g_with_rd_empty          => true,
        g_with_wr_almost_full    => true,
        g_almost_full_threshold  => full_threshold
      )
      port map
      (
        rst_n_i            => Rst_Intern_n(i),
        clk_wr_i           => WrClk(i),
        d_i                => d_i_null,       -- Only FIFO flag functionality is used (no data input)
        we_i               => WrReq_EOD(i),   -- Write when EOD is signalled
        wr_empty_o         => open,
        wr_full_o          => open,
        wr_almost_empty_o  => open,
        wr_almost_full_o   => Full_EOD(i),
        wr_count_o         => open,
        clk_rd_i           => RdClk,
        q_o                => open,
        rd_i               => Packet_RdReq(i),
        rd_empty_o         => Empty_EOD(i),
        rd_full_o          => open,
        rd_almost_empty_o  => open,
        rd_almost_full_o   => open,
        rd_count_o         => open
      );
  End Generate GenTxFifos;
end architecture rtl ; -- of txfifos

--------------------------------------------------------------------------------
-- Object        : Entity design.rxfifos
-- Last modified : Wed May 11 13:18:09 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all;
use work.V_ARRAY_Package.all;
use work.EMAC16bit_Package.all;

entity rxfifos is
  port (
    Empty : out    std_logic_vector(NUM_UDP_PRTS downto 0);
    Flush : in     std_logic_vector(NUM_UDP_PRTS downto 0);
    Full  : out    std_logic_vector(NUM_UDP_PRTS downto 0);
    RXi   : in     dbus_type_array(NUM_UDP_PRTS downto 0);
    RXo   : out    dbus_type_array(NUM_UDP_PRTS downto 0);
    RdClk : in     std_logic_vector(NUM_UDP_PRTS downto 0);
    RdReq : in     std_logic_vector(NUM_UDP_PRTS downto 0);
    Rst   : in     std_logic;
    WrClk : in     std_logic;
    WrReq : in     std_logic_vector(NUM_UDP_PRTS downto 0));
end entity rxfifos;

--------------------------------------------------------------------------------
-- Object        : Architecture design.rxfifos.rtl
-- Last modified : Wed May 11 13:18:09 2016
--------------------------------------------------------------------------------


architecture rtl of rxfifos is

  type std_logic_v9array is array ( natural range <> ) of std_logic_vector(8 downto 0);
  type std_logic_v18array is array ( natural range <> ) of std_logic_vector(17 downto 0);
   
  Signal Din_Intern: std_logic_v18array(NUM_UDP_PRTS downto 0);
  Signal Dout_Intern: std_logic_v18array(NUM_UDP_PRTS downto 0);
  Signal Rst_Intern_n: std_logic_vector(NUM_UDP_PRTS downto 0);
   
begin

  GenRxFifos: For i In 0 to NUM_UDP_PRTS Generate
      
  Din_Intern(i)(17) <= '0';
  Din_Intern(i)(16) <= RXi(i).EOD;
  Din_Intern(i)(15 downto 0) <= RXi(i).D;
  RXo(i).EOD <= Dout_Intern(i)(16);
  RXo(i).D <= Dout_Intern(i)(15 downto 0);
  Rst_Intern_n(i) <= not(Flush(i) Or Rst);
      
  rxfifo: generic_async_fifo
    generic map(
      g_data_width             => 18,
      g_size                   => 8192,
      g_with_rd_empty          => true,
      g_with_wr_almost_full    => true,
      g_almost_full_threshold  => 8176
    )
    port map
    (
      rst_n_i            => Rst_Intern_n(i),
      clk_wr_i           => WrClk,
      d_i                => Din_Intern(i),
      we_i               => WrReq(i),
      wr_empty_o         => open,
      wr_full_o          => open,
      wr_almost_empty_o  => open,
      wr_almost_full_o   => Full(i),
      wr_count_o         => open,
      clk_rd_i          => RdClk(i),
      q_o               => Dout_Intern(i),
      rd_i              => RdReq(i),
      rd_empty_o        => Empty(i),
      rd_full_o         => open,
      rd_almost_empty_o => open,
      rd_almost_full_o  => open,
      rd_count_o        => open
    );
   End Generate GenRxFifos;
   
end architecture rtl ; -- of rxfifos

--------------------------------------------------------------------------------
-- Object        : Entity design.RxStreamSel
-- Last modified : Wed May 11 13:18:36 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.V_ARRAY_Package.all;
use work.EMAC16bit_Package.all;

entity RxStreamSel is
  port (
    Din     : in     std_logic_vector(15 downto 0);
    EODin   : in     std_logic;
    EOFin   : in     std_logic;
    Full    : in     std_logic_vector(NUM_UDP_PRTS downto 0);
    Fullout : out    std_logic;
    RXo     : out    dbus_type_array(NUM_UDP_PRTS downto 0);
    SODin   : in     std_logic;
    Stream  : in     std_logic_vector(NUM_UDP_PRTS downto 0);
    WrReq   : out    std_logic_vector(NUM_UDP_PRTS downto 0);
    WrReqin : in     std_logic);
end entity RxStreamSel;

--------------------------------------------------------------------------------
-- Object        : Architecture design.RxStreamSel.rtl
-- Last modified : Wed May 11 13:18:36 2016
--------------------------------------------------------------------------------


architecture rtl of RxStreamSel is

begin
   Process (Full, Din, EOFin, EODin, Stream, WrReqin)
--   Process (Full, Din, EOFin, EODin, SODin, Stream, WrReqin)
   Begin       
      -- Default is all zero
      Fullout <= '0';
      For i In NUM_UDP_PRTS downto 0 Loop
         RXo(i).D <= (Others => '0');
--         RXo(i).SOD <= '0';
         RXo(i).EOD <= '0';
         WrReq(i) <= '0';
      End Loop;

      -- Now connect the selected stream
      For i In Stream'Range Loop
         If Stream(i) = '1' Then
            RXo(i).D <= Din;
            -- On the data link layer, where the transactions with the MAC take place, a “frame” is defined
            -- as all data that are signaled “rx_data_valid” by the MAC. These data range from the first byte
            -- after the Start of Frame Delimiter (SFD) to the last data byte before the first Frame Control
            -- Sequence (FCS).
            -- Note that for Ethernet v2 framing (see also: http://en.wikipedia.org/wiki/EtherType) this
            -- also includes padded data that might have been inserted to ensure that the frame length is
            -- at least 64 bytes.
            -- Start and End of Data are asserted at the start and end of the 
            -- payload data of the mac frame (without padded data)
--            RXo(i).SOD <= SODin;
            RXo(i).EOD <= EODin;
            WrReq(i) <= WrReqin;
            Fullout <= Full(i);
         End If;
      End Loop;
      -- The exception is the CPU stream where the End Of Frame Signalling from the MAC is routed directly to
      -- the EOD of the CPU channel. There is no other means to know the end of a Frame since unknown Frames
      -- are not decoded.
      RXo(NUM_UDP_PRTS).EOD <= EOFin;
   End Process;

end architecture rtl ; -- of RxStreamSel
--------------------------------------------------------------------------------
-- Object        : Entity design.rx_buf2data
-- Last modified : Wed May 11 13:16:26 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.V_ARRAY_Package.all;
use work.EMAC16bit_Package.all;

entity rx_buf2data is
  generic(
    abits : integer := 15);
  port (
    Clk             : in     std_logic;
    Din             : in     std_logic_vector(15 downto 0);
    EODout          : out    std_logic;
    EOFin           : in     std_logic;
    Empty           : in     std_logic;
    FragID          : out    std_logic_vector(15 downto 0);
    FragOff         : out    std_logic_vector(11 downto 0);
    Full            : in     std_logic;
    MoreFrags       : out    std_logic;
    PktRdPtr        : out    std_logic_vector(abits-1 downto 0);
    RdAddr          : out    std_logic_vector(abits-1 downto 0);
    Rst             : in     std_logic;
    SODout          : out    std_logic;
    Stream          : out    std_logic_vector(NUM_UDP_PRTS downto 0);
    UDP_CheckSumErr : out    std_logic;
    WrReq           : out    std_logic;
    eth_regs_i      : in     eth_regs_type);
end entity rx_buf2data;

--------------------------------------------------------------------------------
-- Object        : Architecture design.rx_buf2data.fsm
-- Last modified : Wed May 11 13:16:26 2016
--------------------------------------------------------------------------------

architecture fsm of rx_buf2data is

  -- State Machine Options:
  --  Clock : Clk (Rising edge).
  --  State assignment : Enumerate.
  --  State decoding : Case construct.
  --  Actions on transitions : Clocked.
  --  Actions on states : Clocked.

  type state_type is (Idle, StartMemAcc, ReadHeader, HeaderChecks, StatusOut, 
            TransferData, TransferOtherData) ;
  signal state : state_type ;  -- Current State
  Signal Offset: Integer Range 0 to MAX_RESERV_PKT_BUF;
  Signal PktPtr: Unsigned(abits-1 downto 0);
  Signal ErrorVector: Unsigned(7 downto 0);
  Signal WrReqIntern: Std_Logic;
  Signal SOD_Intern: Std_Logic;
  Signal StreamIntern: Std_Logic_Vector(NUM_UDP_PRTS downto 0);


begin
    --It takes MEM_ACC_TICKS pipeline stages to fetch
    --the data, henche "Idx - MEM_ACC_TICKS"
    ---- One may want to check if EOF is set at the proper location
    ---- Although this is equal to checking THIS implementation.
    ---- EOF should be set on address "Offset <= IP_HDR + To_Integer(IP_Length/2) - 1;"
    ---- Note: IP_Length is in bytes, NOT in 16 bit words!
    ---- Also note that for Ethernet v2 framing EOF is signalled including padded data
    ---- that might have been added to the MAC frame to ensure that the frame length is
    ---- at least 64 bytes! In such case EOF does not correspond to
    ---- "IP_HDR + To_Integer(IP_Length/2) - 1;"
    --Note 1:
    --During "TransferData" or "TransferOtherData"
    --a Packet may be padded with zeros. Buffer
    --reading should be done until EOP occus but
    --WrReq should only be asserted during valid
    --Payload data.
    --
    --Note 2:
    --The UDP_CheckSum is calculated during
    --"TransferData" and NOT during "TransferOtherData"
    --(which may be used by other protocols). 
    --Mind the Full situation while the last word
    --is transferred...
    --Leave "TransferData" only when the last
    --WrRequest is asserted due to Payload_Length = 0
    --(thus WrReqIntern = '1').
    --With padded packets wait for the MAC to signal
    --EOFin (Payload_Length got 0 earlier).
    --
    --Mind the Full situation while the last word
    --is transferred...
    --Leave "TransferOtherData" only when the last
    --WrRequest is asserted due to EOFin = '1' and
    --WrReqIntern = '1'.
    --
    RdAddr <= Std_Logic_Vector(PktPtr + To_Unsigned(Offset,RX_PKT_BUF_ADRSIZE));
    PktRdPtr <= Std_Logic_Vector(PktPtr);
    WrReq <= WrReqIntern;
    SODout <= SOD_Intern;
    Stream <= StreamIntern;


  state_decoding: process (Clk, Rst) is
      Variable Packet_HeaderRegFile: std_logic_v16array(MAC_HDR_CNT + IP_HDR_CNT + UDP_HDR_CNT -1 downto 0);
      Variable IP_Length: Unsigned(15 downto 0);
      Variable Payload_Length: Unsigned(15 downto 0);
      Variable IP_CheckSum : Unsigned(31 downto 0);
      Variable UDP_CheckSum : Unsigned(31 downto 0);
      Variable Idx: Integer Range 0 to 31;
      Constant MEM_ACC_TICKS : Positive := 1;

  begin
    if (Rst = '1') then
      state <= Idle ;
      -- Initialize:
      For i In Packet_HeaderRegFile'Range Loop
         Packet_HeaderRegFile(i) := (Others => '0');
      End Loop;
      Idx := 0;
      Offset <= MAC_HDR + Idx;
      WrReqIntern <= '0';
      IP_CheckSum := (Others => '0');
      UDP_CheckSum := (Others => '0');
      IP_Length := (Others => '0');
      Payload_Length := (Others => '0');
      ErrorVector <= (Others => '0');
      FragID <= (Others => '0');
      MoreFrags <= '0';
      FragOff <= (Others => '0');
      StreamIntern <= (NUM_UDP_PRTS => '1', Others =>'0');
      SOD_Intern <= '0';
      EODout <= '0';
      PktPtr <= (Others => '0');
      UDP_CheckSumErr <= '0';
    elsif (rising_edge(Clk)) then
      lbl_state : case state is
        when Idle =>
          if (Empty = '0') then
            state <= StartMemAcc ;
            Idx := Idx + 1;
            Offset <= MAC_HDR + Idx;
            UDP_CheckSumErr <= '0';

          else
            state <= Idle ;
            -- Initialize:
            For i In Packet_HeaderRegFile'Range Loop
               Packet_HeaderRegFile(i) := (Others => '0');
            End Loop;
            Idx := 0;
            Offset <= MAC_HDR + Idx;
            WrReqIntern <= '0';
            IP_CheckSum := (Others => '0');
            UDP_CheckSum := (Others => '0');
            IP_Length := (Others => '0');
            Payload_Length := (Others => '0');
            ErrorVector <= (Others => '0');
            FragID <= (Others => '0');
            MoreFrags <= '0';
            FragOff <= (Others => '0');
            StreamIntern <= (NUM_UDP_PRTS => '1', Others =>'0');
            SOD_Intern <= '0';
            EODout <= '0';
          end if ;
        when StartMemAcc =>
          if (Idx = MEM_ACC_TICKS) then
            state <= ReadHeader ;
            Packet_HeaderRegFile(Idx - MEM_ACC_TICKS) := Din;
            If (Idx - MEM_ACC_TICKS) >= IP_HDR and (Idx - MEM_ACC_TICKS) < UDP_HDR Then
               IP_CheckSum := IP_CheckSum + Unsigned(Din);
            End If;
            If (Idx - MEM_ACC_TICKS) >= UDP_HDR and (Idx - MEM_ACC_TICKS) < PAYLOAD Then
               UDP_CheckSum := UDP_CheckSum + Unsigned(Din);
            End If;
            Idx := Idx + 1;
            Offset <= MAC_HDR + Idx;

          else
            state <= StartMemAcc ;
            Idx := Idx + 1;
            Offset <= MAC_HDR + Idx;
            UDP_CheckSumErr <= '0';

          end if ;
        when ReadHeader =>
          if (Idx = MEM_ACC_TICKS + PAYLOAD) then
            state <= HeaderChecks ;
            IP_CheckSum (15 Downto 0) := Not(IP_CheckSum(31 downto 16) + IP_CheckSum(15 downto 0));
            IP_Length := Unsigned(Packet_HeaderRegFile(IP_HDR + IP_IDX_LEN));

            -- "The Default Stream"
            StreamIntern <= (NUM_UDP_PRTS => '1', Others =>'0'); 
            Offset <= 0;
            Payload_Length := (IP_Length / 2) + MAC_HDR_CNT;
            --

            If Packet_HeaderRegFile(MAC_HDR + MAC_IDX_LEN) /= ETH_TYPE_II Then ErrorVector (0) <= '1'; End If;
            If IP_CheckSum (15 Downto 0) /= 0 Then ErrorVector (1) <= '1'; End If;
            If Packet_HeaderRegFile(IP_HDR + IP_IDX_VER_LEN_TOS)(IP_VER_LEN'Range) /= IP_VER_LEN Then ErrorVector (2) <= '1'; End If;
            If Packet_HeaderRegFile(IP_HDR + IP_IDX_TTL_PROT)(IP_PROT_UDP'Range) /= IP_PROT_UDP Then ErrorVector (3) <= '1'; End If;

            SOD_Intern <= '1';
          else
            state <= ReadHeader ;
            Packet_HeaderRegFile(Idx - MEM_ACC_TICKS) := Din;
            If (Idx - MEM_ACC_TICKS) >= IP_HDR and (Idx - MEM_ACC_TICKS) < UDP_HDR Then
               IP_CheckSum := IP_CheckSum + Unsigned(Din);
            End If;
            If (Idx - MEM_ACC_TICKS) >= UDP_HDR and (Idx - MEM_ACC_TICKS) < PAYLOAD Then
               UDP_CheckSum := UDP_CheckSum + Unsigned(Din);
            End If;
            Idx := Idx + 1;
            Offset <= MAC_HDR + Idx;

          end if ;
        when HeaderChecks =>
          if (ErrorVector /= 0) then
            state <= TransferOtherData ;
            If Full = '0' Then
               Offset <= Offset + 1;
               If SOD_intern = '1' And WrReqIntern = '1' Then
                  SOD_intern <= '0';
               End If;
               WrReqIntern <= '1';
            Else
               WrReqIntern <= '0';
            End If;
          else
            state <= StatusOut ;
            FragID <= Packet_HeaderRegFile(IP_HDR + IP_IDX_ID);
            MoreFrags <= Packet_HeaderRegFile(IP_HDR + IP_IDX_FLAGS_FRAGOFF)(IP_FLAGS_MOREFRAGS_INDEX);
            FragOff <= Packet_HeaderRegFile(IP_HDR + IP_IDX_FLAGS_FRAGOFF)(IP_FRAGOFF_RANGE);

            -- "The Default Stream"
            StreamIntern <= (NUM_UDP_PRTS => '1', Others =>'0'); 
            Offset <= 0;
            Payload_Length := (IP_Length / 2) + MAC_HDR_CNT;
            --

            For i In NUM_UDP_PRTS - 1 downto 0 Loop
               If Unsigned(eth_regs_i.UDP_ModPrt(i)) = Unsigned(Packet_HeaderRegFile(UDP_HDR + UDP_IDX_DSTPRT)) Then
                  StreamIntern(i) <= '1';
                  Offset <= PAYLOAD;
                  Payload_Length := (IP_Length / 2) - IP_HDR_CNT - UDP_HDR_CNT;
                  StreamIntern(NUM_UDP_PRTS) <= '0';
               End If;
            End Loop;

            -- PrepareUDP_CheckSum:
            -- For UDP Checksum calculation the items in the UDP header (UDP Source Port,
            -- UDP Destination Port, UDP Length and UDP Checksum) were already collected
            -- during header reading.
            -- Add the UDP Pseudo-Header that contains:
            --   IP Source address
            --   IP Destination address
            --   x"00" & Protocol
            --   UDP_Length  (note that actually the UDP_Length is calculated twice!) 
            UDP_CheckSum := UDP_CheckSum + 
               (x"0000" & Unsigned(Packet_HeaderRegFile(IP_HDR + IP_IDX_IP_SRC))) +
               (x"0000" & Unsigned(Packet_HeaderRegFile(IP_HDR + IP_IDX_IP_SRC + 1))) +
               (x"0000" & Unsigned(Packet_HeaderRegFile(IP_HDR + IP_IDX_IP_DST))) +
               (x"0000" & Unsigned(Packet_HeaderRegFile(IP_HDR + IP_IDX_IP_DST + 1))) +
               (x"0000" & x"00" & Unsigned(Packet_HeaderRegFile(IP_HDR + IP_IDX_TTL_PROT)(7 downto 0))) +
               (x"0000" & Unsigned(Packet_HeaderRegFile(UDP_HDR + UDP_IDX_LEN)));
          end if ;
        when StatusOut =>
          if (StreamIntern(NUM_UDP_PRTS) = '1') then
            state <= TransferOtherData ;
            If Full = '0' Then
               Offset <= Offset + 1;
               If SOD_intern = '1' And WrReqIntern = '1' Then
                  SOD_intern <= '0';
               End If;
               WrReqIntern <= '1';
            Else
               WrReqIntern <= '0';
            End If;
          else
            state <= TransferData ;
            If Full = '0' Then
               Offset <= Offset + 1;
               If SOD_intern = '1' And WrReqIntern = '1' Then
                  SOD_intern <= '0';
               End If;
               If Payload_Length = 1 Then
                  EODout <= '1';
               Else
                  EODout <= '0';
               End If;
               If Payload_Length > 0 Then
                  Payload_Length := Payload_Length - 1;
                  WrReqIntern <= '1';
                  UDP_CheckSum := UDP_CheckSum + (x"0000" & Unsigned(Din));
               Else
                  WrReqIntern <= '0';
               End If;
            Else
               WrReqIntern <= '0';
            End If;
          end if ;
        when TransferData =>
          if (EOFin = '1' And Payload_Length = 0) then
            state <= Idle ;
            PktPtr <= PktPtr + To_Unsigned(Offset,RX_PKT_BUF_ADRSIZE);
            -- FinalizeUDP_CheckSum:
            -- Add the last data word
            If WrReqIntern = '1' Then
               UDP_CheckSum := UDP_CheckSum + (x"0000" & Unsigned(Din));
            End If;

            UDP_CheckSum (15 Downto 0) := Not(UDP_CheckSum(31 downto 16) + UDP_CheckSum(15 downto 0));
            If UDP_CheckSum (15 Downto 0) /= 0 Then
               UDP_CheckSumErr <= '1';
            Else
               UDP_CheckSumErr <= '0';
            End If;

            -- Initialize:
            For i In Packet_HeaderRegFile'Range Loop
               Packet_HeaderRegFile(i) := (Others => '0');
            End Loop;
            Idx := 0;
            Offset <= MAC_HDR + Idx;
            WrReqIntern <= '0';
            IP_CheckSum := (Others => '0');
            UDP_CheckSum := (Others => '0');
            IP_Length := (Others => '0');
            Payload_Length := (Others => '0');
            ErrorVector <= (Others => '0');
            FragID <= (Others => '0');
            MoreFrags <= '0';
            FragOff <= (Others => '0');
            StreamIntern <= (NUM_UDP_PRTS => '1', Others =>'0');
            SOD_Intern <= '0';
            EODout <= '0';
          else
            state <= TransferData ;
            If Full = '0' Then
               Offset <= Offset + 1;
               If SOD_intern = '1' And WrReqIntern = '1' Then
                  SOD_intern <= '0';
               End If;
               If Payload_Length = 1 Then
                  EODout <= '1';
               Else
                  EODout <= '0';
               End If;
               If Payload_Length > 0 Then
                  Payload_Length := Payload_Length - 1;
                  WrReqIntern <= '1';
                  UDP_CheckSum := UDP_CheckSum + (x"0000" & Unsigned(Din));
               Else
                  WrReqIntern <= '0';
               End If;
            Else
               WrReqIntern <= '0';
            End If;
          end if ;
        when TransferOtherData =>
          if (EOFin = '1' And WrReqIntern = '1') then
            state <= Idle ;
            PktPtr <= PktPtr + To_Unsigned(Offset,RX_PKT_BUF_ADRSIZE);
            -- Initialize:
            For i In Packet_HeaderRegFile'Range Loop
               Packet_HeaderRegFile(i) := (Others => '0');
            End Loop;
            Idx := 0;
            Offset <= MAC_HDR + Idx;
            WrReqIntern <= '0';
            IP_CheckSum := (Others => '0');
            UDP_CheckSum := (Others => '0');
            IP_Length := (Others => '0');
            Payload_Length := (Others => '0');
            ErrorVector <= (Others => '0');
            FragID <= (Others => '0');
            MoreFrags <= '0';
            FragOff <= (Others => '0');
            StreamIntern <= (NUM_UDP_PRTS => '1', Others =>'0');
            SOD_Intern <= '0';
            EODout <= '0';
          else
            state <= TransferOtherData ;
            If Full = '0' Then
               Offset <= Offset + 1;
               If SOD_intern = '1' And WrReqIntern = '1' Then
                  SOD_intern <= '0';
               End If;
               WrReqIntern <= '1';
            Else
               WrReqIntern <= '0';
            End If;
          end if ;
      end case lbl_state ;
    end if ; --  Reset & Clock
  end process state_decoding ;

end architecture fsm ; -- of rx_buf2data

--------------------------------------------------------------------------------
-- Object        : Entity design.PauseReqLogic
-- Last modified : Thu Nov 14 15:46:58 2013
--------------------------------------------------------------------------------



library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity PauseReqLogic is
  port (
    Clk           : in     std_logic;
    PauseAck      : in     std_logic;
    PauseReq      : out    std_logic;
    PauseVal      : out    std_logic_vector(15 downto 0);
    Rst           : in     std_logic;
    WaterMarkHigh : in     std_logic;
    WaterMarkLow  : in     std_logic);
end entity PauseReqLogic;

--------------------------------------------------------------------------------
-- Object        : Architecture design.PauseReqLogic.rtl
-- Last modified : Thu Nov 14 15:46:58 2013
--------------------------------------------------------------------------------


architecture rtl of PauseReqLogic is
begin
   Process (Clk, Rst)
      Variable WaterMarkLow_del: Std_logic;
      Variable WaterMarkHigh_del: Std_logic;
   Begin
      If Rst = '1' Then
         WaterMarkLow_del := '1';
         WaterMarkHigh_del := '0';
         PauseReq <= '0';
         PauseVal <= x"0000";
      ElsIf Rising_Edge(Clk) Then
        -- Remove any pending Pause Request when Ack
	    If PauseAck = '1' Then
            PauseReq <= '0';
            PauseVal <= x"0000";
         -- If Rising_Edge(WaterMarkLow) Then "Cancel" Pause Request
		 -- note that PauseVal may be updated to the current value when a former PauseReq is still pending
         ElsIf WaterMarkLow = '1' and WaterMarkLow_del = '0' Then
            PauseReq <= '1';
            PauseVal <= x"0000";
         -- If Rising_Edge(WaterMarkHigh) Then Pause Request 65535
         -- Pause_Quantas (= 512 bit times)
         -- is 65535 * 512 * 800 ps (for 1 Gbit Ethernet) = ~26.8 ms
         -- See IEEE802.3-2005 Annex 31B
		 -- note that PauseVal may be updated to the current value when a former PauseReq is still pending
         ElsIf WaterMarkHigh = '1' and WaterMarkHigh_del = '0' Then
            PauseReq <= '1';
            PauseVal <= x"FFFF";
         End If;
         -- Pipeline
         WaterMarkLow_del := WaterMarkLow;
         WaterMarkHigh_del := WaterMarkHigh;
      End If;
   End Process;
   
end architecture rtl ; -- of PauseReqLogic

--------------------------------------------------------------------------------
-- Object        : Entity design.PacketBuffer
-- Last modified : Wed May 11 13:15:44 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all;

entity PacketBuffer is
  generic(
    abits : integer := 15;
    dbits : integer := 8);
  port (
    AddrA : in     std_logic_vector(abits-1 downto 0);
    AddrB : in     std_logic_vector(abits-1 downto 0);
    Clk   : in     std_logic;
    Din   : in     std_logic_vector(dbits-1 downto 0);
    Q     : out    std_logic_vector(dbits-1 downto 0);
    Rst   : in     std_logic;
    WeA   : in     std_logic);
end entity PacketBuffer;

--------------------------------------------------------------------------------
-- Object        : Architecture design.PacketBuffer.rtl
-- Last modified : Wed May 11 13:15:44 2016
--------------------------------------------------------------------------------


architecture rtl of PacketBuffer is

  signal rst_n: Std_Logic;
   
begin
  
  rst_n <= not Rst;

  u0: generic_dpram
    generic map (
      g_data_width => 17,
      g_size       => 2**abits,
      g_dual_clock => false)
    port map (
      rst_n_i => rst_n,
      clka_i  => Clk,
      bwea_i  => "111",
      wea_i   => Wea,
      aa_i    => AddrA,
      da_i    => Din,
      qa_o    => open,
      clkb_i  => '0',
      bweb_i  => "000",
      web_i   => '0',
      ab_i    => AddrB,
      db_i    => "00000000000000000",
      qb_o    => Q
      );   

end architecture rtl ; -- of PacketBuffer

--------------------------------------------------------------------------------
-- Object        : Entity design.Calc_UDP_PseudoHeader
-- Last modified : Wed May 11 13:12:27 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.V_ARRAY_Package.all;
use work.EMAC16bit_Package.all;

entity Calc_UDP_PseudoHeader is
  port (
    Clk          : in     std_logic;
    PseudoHeader : out    std_logic_vector(31 downto 0);
    Rst          : in     std_logic;
    eth_regs_i   : in     eth_regs_type);
end entity Calc_UDP_PseudoHeader;

--------------------------------------------------------------------------------
-- Object        : Architecture design.Calc_UDP_PseudoHeader.a0
-- Last modified : Wed May 11 13:12:27 2016
--------------------------------------------------------------------------------


architecture a0 of Calc_UDP_PseudoHeader is

begin
   Process (Clk, Rst)
      Variable PseudoHdr : Unsigned(31 downto 0);
   Begin
      If Rst = '1' Then 
         PseudoHdr := (Others => '0');
      ElsIf Rising_Edge(Clk) Then
         -- The UDP CheckSum is calculated using an UDP Pseudo-Header that contains:
         -- IP Source address
         -- IP Destination address
         -- x"00" & Protocol
         -- UDP_Length
         -- Note: UDP Length is to be added when this value is known
         PseudoHdr := 
            (x"0000" & Unsigned(eth_regs_i.IP_Mod(31 downto 16))) +
            (x"0000" & Unsigned(eth_regs_i.IP_Mod(15 downto 0))) +
            (x"0000" & Unsigned(eth_regs_i.IP_Srv(31 downto 16))) +
            (x"0000" & Unsigned(eth_regs_i.IP_Srv(15 downto 0))) +
            (x"0000" & x"0011");
      End If;
      PseudoHeader <= Std_Logic_Vector(PseudoHdr);
   End Process;
end architecture a0 ; -- of Calc_UDP_PseudoHeader

--------------------------------------------------------------------------------
-- Object        : Entity design.tx_data2buf
-- Last modified : Wed May 11 13:19:58 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.V_ARRAY_Package.all;
use work.EMAC16bit_Package.all;

entity tx_data2buf is
  generic(
    abits : integer := 15);
  port (
    CPU_AccGnt   : out    std_logic;
    CPU_Tx       : in     ipmux_cpu_in_type;
    Clk          : in     std_logic;
    ConnectReq   : out    std_logic;
    Connected    : in     std_logic;
    Dout         : out    std_logic_vector(15 downto 0);
    EOPout       : out    std_logic;
    FragID       : in     std_logic_vector(15 downto 0);
    FragOff      : in     std_logic_vector(11 downto 0);
    Full         : in     std_logic;
    MoreFrag     : in     std_logic;
    PktWrPtr     : out    std_logic_vector(abits-1 downto 0);
    PseudoHeader : in     std_logic_vector(31 downto 0);
    Rst          : in     std_logic;
    SelSm        : out    std_logic;
    Stream       : in     natural range NUM_UDP_PRTS-1 downto 0;
    TX_LL_DATA   : in     std_logic_vector(15 downto 0);
    TX_LL_EOP    : in     std_logic;
    TX_LL_RDREQ  : out    std_logic;
    TX_LL_VALID  : in     std_logic;
    WrAddr       : out    std_logic_vector(abits-1 downto 0);
    WrEn         : out    std_logic;
    eth_regs_i   : in     eth_regs_type);
end entity tx_data2buf;

--------------------------------------------------------------------------------
-- Object        : Architecture design.tx_data2buf.fsm
-- Last modified : Wed May 11 13:19:58 2016
--------------------------------------------------------------------------------

architecture fsm of tx_data2buf is

  -- State Machine Options:
  --  Clock : Clk (Rising edge).
  --  State assignment : Enumerate.
  --  State decoding : Case construct.
  --  Actions on transitions : Clocked.
  --  Actions on states : Clocked.

  type state_type is (Idle, More_Data, UDP_WriteHeader, IP_WriteHeader, 
            IP_WriteCheckSum, MAC_WriteHeader, AccessByCPU) ;
  signal state : state_type ;  -- Current State
  Signal Offset: Integer Range 0 to MAX_RESERV_PKT_BUF;
  Signal PktPtr: Unsigned(abits-1 downto 0);
  Signal Pkt_End: Unsigned(abits-1 downto 0);
  Signal RdReq: Std_Logic;
  Signal ConnectReq_Intern: Std_Logic;



begin
    --Packet Buffer Full Flag is only checked once.
    --If Full = False then there is at least place
    --to store one packet (size PKT_LEN + PAYLOAD).
    --It is the responsibility of the input *NOT* to
    --exceed this maximum; Overfglow is not checked!
    WrAddr <= Std_Logic_Vector(PktPtr + To_Unsigned(Offset,TX_PKT_BUF_ADRSIZE));
    PktWrPtr <= Std_Logic_Vector(PktPtr);
    -- Asynchronously avoid a new TX_LL_RDREQ when the Packet Buffer becomes Full
    TX_LL_RDREQ <= RdReq And Not Full;
    ConnectReq <= ConnectReq_Intern;


  state_decoding: process (Clk, Rst) is
      Variable MAC_HeaderRegFile: std_logic_v16array(MAC_HDR_CNT-1 downto 0);
      Variable IP_HeaderRegFile: std_logic_v16array(IP_HDR_CNT-1 downto 0);
      Variable IP_Length: Unsigned(15 downto 0);
      Variable UDP_HeaderRegFile: std_logic_v16array(UDP_HDR_CNT-1 downto 0);
      Variable UDP_Length: Unsigned(15 downto 0);
      Variable CheckSum : Unsigned(31 downto 0);
      Variable Idx: Integer Range 0 to 31;

  begin
    if (Rst = '1') then
      state <= Idle ;
      -- Initialize:
      ConnectReq_Intern <= '1';
      PktPtr <= (Others => '0');
      Pkt_End <= (Others => '0');
      Offset <= PAYLOAD;
      RdReq <= '1';
      SelSm <= '0';
      WrEn <= '0';
      CPU_AccGnt <= '0';
      Dout <= (Others => '0');
      Idx := 0;
      CheckSum := (Others => '0');
      EOPout <= '0';
    elsif (rising_edge(Clk)) then
      lbl_state : case state is
        when Idle =>
          if (Full = '0' And CPU_Tx.Request = '1') then
            state <= AccessByCPU ;
            Offset <= To_Integer(Unsigned(CPU_Tx.Addr));
            RdReq <= '0';
            SelSm <= '1';
            WrEn <= CPU_Tx.WrEn;
            CPU_AccGnt <= '1';
            Dout <= CPU_Tx.D;
            EOPout <= CPU_Tx.EOP;
            If CPU_Tx.EOP = '1' and CPU_Tx.WrEn = '1' Then
              Pkt_End <= Unsigned(CPU_Tx.Addr);
            End If;
            ConnectReq_Intern <= '0';
          elsif (
            Full = '0' And
            Connected = '1'
            ) then
            state <= More_Data ;
            RdReq <= '1';
            SelSm <= '0';
            WrEn <= '1';
            CPU_AccGnt <= '0';
            If TX_LL_VALID = '1' And ConnectReq_Intern = '0' Then 
               Offset <= Offset + 1;
               CheckSum := CheckSum + (x"0000" & Unsigned(TX_LL_DATA));
            End If;

            ConnectReq_Intern <= '0';
          else
            state <= Idle ;
            Offset <= PAYLOAD;
            If CPU_Tx.Request = '0' Then
               RdReq <= '1';
               ConnectReq_Intern <= '1';
            Else
               RdReq <= '0';
               ConnectReq_Intern <= '0';
            End If;
            SelSm <= '1';
            WrEn <= '0';
            CPU_AccGnt <= '0';
            EOPout <= '0';
            -- InitHregFile:
            -- MAC Destination Address
            MAC_HeaderRegFile(MAC_IDX_DST)                  := eth_regs_i.MAC_Srv (47 downto 32);
            MAC_HeaderRegFile(MAC_IDX_DST + 1)              := eth_regs_i.MAC_Srv (31 downto 16);
            MAC_HeaderRegFile(MAC_IDX_DST + 2)              := eth_regs_i.MAC_Srv (15 downto 0);
            -- MAC Source Address
            MAC_HeaderRegFile(MAC_IDX_SRC)                  := eth_regs_i.MAC_Mod (47 downto 32);
            MAC_HeaderRegFile(MAC_IDX_SRC + 1)              := eth_regs_i.MAC_Mod (31 downto 16);
            MAC_HeaderRegFile(MAC_IDX_SRC + 2)              := eth_regs_i.MAC_Mod (15 downto 0);
            -- Type/Length (EtherType is Internet Protocol Version 4 (0x0800)
            MAC_HeaderRegFile(MAC_IDX_LEN)                  := x"0800";

            -- IP Version / Header Length / Type Of Service
            IP_HeaderRegFile(IP_IDX_VER_LEN_TOS)            := x"4500";
            -- IP Length (assigned later according to input stream)
            IP_HeaderRegFile(IP_IDX_LEN)                    := x"0000";
            -- IP ID (assigned later according to FragID input)
            IP_HeaderRegFile(IP_IDX_ID)                     := x"0000";
            -- IP Flags / Fragment Offset (assigned later according to MoreFrag and FragOff input)
            IP_HeaderRegFile(IP_IDX_FLAGS_FRAGOFF)          := x"0000";
            -- IP Time To Live (128), PROT: UDP = 17
            IP_HeaderRegFile(IP_IDX_TTL_PROT)               := x"8011";
            -- IP Header CheckSum. Initially set to 0x0000 for
            -- Checksum calculation (assigned later according to input stream)
            IP_HeaderRegFile(IP_IDX_CHECKS)                 := x"0000";
            -- IP Source Address
            IP_HeaderRegFile(IP_IDX_IP_SRC)                 := eth_regs_i.IP_Mod(31 downto 16);
            IP_HeaderRegFile(IP_IDX_IP_SRC + 1)             := eth_regs_i.IP_Mod(15 downto 0);
            -- IP Destination Address
            IP_HeaderRegFile(IP_IDX_IP_DST)                 := eth_regs_i.IP_Srv(31 downto 16);
            IP_HeaderRegFile(IP_IDX_IP_DST + 1)             := eth_regs_i.IP_Srv(15 downto 0);

            -- UDP Source Port (assigned later according to input stream)
            UDP_HeaderRegFile(UDP_IDX_SRCPRT)               := x"0000";
            -- UDP Destination Port (assigned later according to input stream)
            UDP_HeaderRegFile(UDP_IDX_DSTPRT)               := x"0000";
            -- UDP Length
            UDP_HeaderRegFile(UDP_IDX_LEN)                  := x"0000";
            -- UDP CheckSum
            -- CheckSum is optional. If it is not calculated then
            -- it should be set to 0x0000.
            UDP_HeaderRegFile(UDP_IDX_CHECKS)               := x"0000";

            -- The UDP CheckSum is calculated using an UDP Pseudo-Header that contains:
            -- IP Source address
            -- IP Destination address
            -- x"00" & Protocol
            -- UDP_Length
            -- Note: UDP Length is to be added when this value is known

            --CheckSum := 
            --   (x"0000" & Unsigned(IP_HeaderRegFile(IP_IDX_IP_SRC))) +
            --   (x"0000" & Unsigned(IP_HeaderRegFile(IP_IDX_IP_SRC + 1))) +
            --   (x"0000" & Unsigned(IP_HeaderRegFile(IP_IDX_IP_DST))) +
            --   (x"0000" & Unsigned(IP_HeaderRegFile(IP_IDX_IP_DST + 1))) +
            --   (x"0000" & x"00" & Unsigned(IP_HeaderRegFile(IP_IDX_TTL_PROT)(7 downto 0)));

            -- Note that due timing issues between "eth_regs_i.IP_Src" and "CheckSum" which occured
            -- during place&route it was decided to pre-calculate the content of the pseudo header.
            CheckSum := Unsigned(PseudoHeader);

          end if ;
        when More_Data =>
          if (TX_LL_EOP = '1' And TX_LL_VALID = '1') then
            state <= UDP_WriteHeader ;
            -- Write_UDP_Ports_Length_and_CheckSum_To_HregFile:
            -- UDP Source Port
            UDP_HeaderRegFile(UDP_IDX_SRCPRT)               := eth_regs_i.UDP_ModPrt(Stream);
            -- UDP Destination Port
            UDP_HeaderRegFile(UDP_IDX_DSTPRT)               := eth_regs_i.UDP_SrvPrt(Stream);

            -- UDP Length is the length of the UDP header and 
            -- the data (= offset + 1 - PAYLOAD) in 16 bit words
            -- henche "2*" to calculate bytes.
            UDP_Length := To_Unsigned((2*(UDP_HDR_CNT + Offset + 1 - PAYLOAD)),16);
            UDP_HeaderRegFile(UDP_IDX_LEN)     := Std_Logic_Vector(UDP_Length);

            -- UDP CRC is the sum over the Pseudo Header and all the data words.
            -- Don't forget to add the last dataword here
            -- The Pseudo Header was pre-calculated in "InitHregFile" but the UDP Length
            -- was not yet known at that time. So it must be added here as well twice,
            -- since the UDP Length is part of the Pseudo Header *AND* part of the UDP Header!
            CheckSum := CheckSum + (x"0000" & Unsigned(TX_LL_DATA)) + (x"000" & "000" & UDP_Length & '0');

            -- Add the the UDP Source and Destination Ports to the Checksum 
            CheckSum := CheckSum + 
               (x"0000" & Unsigned(UDP_HeaderRegFile(UDP_IDX_SRCPRT))) +
               (x"0000" & Unsigned(UDP_HeaderRegFile(UDP_IDX_DSTPRT)));

            CheckSum (16 Downto 0) := ('0' & CheckSum(31 downto 16)) + ('0' & CheckSum(15 downto 0));
            -- Note that two 16 bit additions may lead to overflow
            -- for example 0xffff + 0xffff = 0x1fffe
            -- need to add overflow bit (16) to (15 downto 0)
            CheckSum (15 Downto 0) := ("0000000" & CheckSum(16)) + CheckSum(15 downto 0);
            UDP_HeaderRegFile(UDP_IDX_CHECKS) := Not Std_Logic_Vector(CheckSum(15 downto 0));
            Pkt_End <= To_Unsigned(Offset,TX_PKT_BUF_ADRSIZE);
            Idx := 0;
            RdReq <= '0';
            SelSm <= '1';
            WrEn <= '1';
            CPU_AccGnt <= '0';
            Dout <= UDP_HeaderRegFile(Idx);
            Offset <= UDP_HDR + Idx;
            Idx := Idx + 1;

            ConnectReq_Intern <= '0';
          else
            state <= More_Data ;
            RdReq <= '1';
            SelSm <= '0';
            WrEn <= '1';
            CPU_AccGnt <= '0';
            If TX_LL_VALID = '1' And ConnectReq_Intern = '0' Then 
               Offset <= Offset + 1;
               CheckSum := CheckSum + (x"0000" & Unsigned(TX_LL_DATA));
            End If;

            ConnectReq_Intern <= '0';
          end if ;
        when UDP_WriteHeader =>
          if (Idx = UDP_HDR_CNT) then
            state <= IP_WriteHeader ;
            -- Write_IP_Length_To_HregFile:
            -- IP Length is the length of the IP header and 
            -- the data. Note that IP_HDR_CNT is in 16 bit words
            -- henche "2*" to calculate bytes.
            IP_Length := To_Unsigned(2 * IP_HDR_CNT,16) + UDP_Length;
            IP_HeaderRegFile(IP_IDX_LEN) := Std_Logic_Vector(IP_Length);

            -- IP Fragment ID
            IP_HeaderRegFile(IP_IDX_ID) := FragID;
            -- IP Flags / Fragment Offset
            IP_HeaderRegFile(IP_IDX_FLAGS_FRAGOFF) := "00" & MoreFrag & '0' & FragOff;
            Idx := 0;
            CheckSum := (Others => '0');

            RdReq <= '0';
            SelSm <= '1';
            WrEn <= '1';
            CPU_AccGnt <= '0';
            Dout <= IP_HeaderRegFile(Idx);
            CheckSum := CheckSum + (x"0000" & Unsigned(IP_HeaderRegFile(Idx)));
            Offset <= IP_HDR + Idx;
            Idx := Idx + 1;

            ConnectReq_Intern <= '0';
          else
            state <= UDP_WriteHeader ;
            RdReq <= '0';
            SelSm <= '1';
            WrEn <= '1';
            CPU_AccGnt <= '0';
            Dout <= UDP_HeaderRegFile(Idx);
            Offset <= UDP_HDR + Idx;
            Idx := Idx + 1;

            ConnectReq_Intern <= '0';
          end if ;
        when IP_WriteHeader =>
          if (Idx = IP_HDR_CNT) then
            state <= IP_WriteCheckSum ;
            CheckSum (16 Downto 0) := ('0' & CheckSum(31 downto 16)) + ('0' & CheckSum(15 downto 0));
            -- Note that two 16 bit additions may lead to overflow
            -- for example 0xffff + 0xffff = 0x1fffe
            -- need to add overflow bit (16) to (15 downto 0)
            CheckSum (15 Downto 0) := ("0000000" & CheckSum(16)) + CheckSum(15 downto 0);
            RdReq <= '0';
            SelSm <= '1';
            WrEn <= '1';
            CPU_AccGnt <= '0';
            Dout <= Not Std_Logic_Vector(CheckSum(15 downto 0));
            Offset <= IP_HDR + IP_IDX_CHECKS;
            ConnectReq_Intern <= '0';
          else
            state <= IP_WriteHeader ;
            RdReq <= '0';
            SelSm <= '1';
            WrEn <= '1';
            CPU_AccGnt <= '0';
            Dout <= IP_HeaderRegFile(Idx);
            CheckSum := CheckSum + (x"0000" & Unsigned(IP_HeaderRegFile(Idx)));
            Offset <= IP_HDR + Idx;
            Idx := Idx + 1;

            ConnectReq_Intern <= '0';
          end if ;
        when IP_WriteCheckSum =>
            state <= MAC_WriteHeader ;
            Idx := 0;
            -- Write_MAC_Length_To_HregFile:
            -- MAC Length is equal to the IP_Length
            -- Add the Legth value to the EtherType that is
            -- already initialized in MAC_HeaderRegFile(MAC_IDX_LEN)

            -- MAC_HeaderRegFile(MAC_IDX_LEN)     := Std_Logic_Vector(Unsigned(MAC_HeaderRegFile(MAC_IDX_LEN)) + IP_Length);

            RdReq <= '0';
            SelSm <= '1';
            WrEn <= '1';
            CPU_AccGnt <= '0';
            Dout <= MAC_HeaderRegFile(Idx);
            Offset <= MAC_HDR + Idx;
            Idx := Idx + 1;

            ConnectReq_Intern <= '0';
        when MAC_WriteHeader =>
          if (Idx = MAC_HDR_CNT) then
            state <= Idle ;
            PktPtr <= PktPtr + Pkt_End + 1;
            Offset <= PAYLOAD;
            If CPU_Tx.Request = '0' Then
               RdReq <= '1';
               ConnectReq_Intern <= '1';
            Else
               RdReq <= '0';
               ConnectReq_Intern <= '0';
            End If;
            SelSm <= '1';
            WrEn <= '0';
            CPU_AccGnt <= '0';
            EOPout <= '0';
            -- InitHregFile:
            -- MAC Destination Address
            MAC_HeaderRegFile(MAC_IDX_DST)                  := eth_regs_i.MAC_Srv (47 downto 32);
            MAC_HeaderRegFile(MAC_IDX_DST + 1)              := eth_regs_i.MAC_Srv (31 downto 16);
            MAC_HeaderRegFile(MAC_IDX_DST + 2)              := eth_regs_i.MAC_Srv (15 downto 0);
            -- MAC Source Address
            MAC_HeaderRegFile(MAC_IDX_SRC)                  := eth_regs_i.MAC_Mod (47 downto 32);
            MAC_HeaderRegFile(MAC_IDX_SRC + 1)              := eth_regs_i.MAC_Mod (31 downto 16);
            MAC_HeaderRegFile(MAC_IDX_SRC + 2)              := eth_regs_i.MAC_Mod (15 downto 0);
            -- Type/Length (EtherType is Internet Protocol Version 4 (0x0800)
            MAC_HeaderRegFile(MAC_IDX_LEN)                  := x"0800";

            -- IP Version / Header Length / Type Of Service
            IP_HeaderRegFile(IP_IDX_VER_LEN_TOS)            := x"4500";
            -- IP Length (assigned later according to input stream)
            IP_HeaderRegFile(IP_IDX_LEN)                    := x"0000";
            -- IP ID (assigned later according to FragID input)
            IP_HeaderRegFile(IP_IDX_ID)                     := x"0000";
            -- IP Flags / Fragment Offset (assigned later according to MoreFrag and FragOff input)
            IP_HeaderRegFile(IP_IDX_FLAGS_FRAGOFF)          := x"0000";
            -- IP Time To Live (128), PROT: UDP = 17
            IP_HeaderRegFile(IP_IDX_TTL_PROT)               := x"8011";
            -- IP Header CheckSum. Initially set to 0x0000 for
            -- Checksum calculation (assigned later according to input stream)
            IP_HeaderRegFile(IP_IDX_CHECKS)                 := x"0000";
            -- IP Source Address
            IP_HeaderRegFile(IP_IDX_IP_SRC)                 := eth_regs_i.IP_Mod(31 downto 16);
            IP_HeaderRegFile(IP_IDX_IP_SRC + 1)             := eth_regs_i.IP_Mod(15 downto 0);
            -- IP Destination Address
            IP_HeaderRegFile(IP_IDX_IP_DST)                 := eth_regs_i.IP_Srv(31 downto 16);
            IP_HeaderRegFile(IP_IDX_IP_DST + 1)             := eth_regs_i.IP_Srv(15 downto 0);

            -- UDP Source Port (assigned later according to input stream)
            UDP_HeaderRegFile(UDP_IDX_SRCPRT)               := x"0000";
            -- UDP Destination Port (assigned later according to input stream)
            UDP_HeaderRegFile(UDP_IDX_DSTPRT)               := x"0000";
            -- UDP Length
            UDP_HeaderRegFile(UDP_IDX_LEN)                  := x"0000";
            -- UDP CheckSum
            -- CheckSum is optional. If it is not calculated then
            -- it should be set to 0x0000.
            UDP_HeaderRegFile(UDP_IDX_CHECKS)               := x"0000";

            -- The UDP CheckSum is calculated using an UDP Pseudo-Header that contains:
            -- IP Source address
            -- IP Destination address
            -- x"00" & Protocol
            -- UDP_Length
            -- Note: UDP Length is to be added when this value is known

            --CheckSum := 
            --   (x"0000" & Unsigned(IP_HeaderRegFile(IP_IDX_IP_SRC))) +
            --   (x"0000" & Unsigned(IP_HeaderRegFile(IP_IDX_IP_SRC + 1))) +
            --   (x"0000" & Unsigned(IP_HeaderRegFile(IP_IDX_IP_DST))) +
            --   (x"0000" & Unsigned(IP_HeaderRegFile(IP_IDX_IP_DST + 1))) +
            --   (x"0000" & x"00" & Unsigned(IP_HeaderRegFile(IP_IDX_TTL_PROT)(7 downto 0)));

            -- Note that due timing issues between "eth_regs_i.IP_Src" and "CheckSum" which occured
            -- during place&route it was decided to pre-calculate the content of the pseudo header.
            CheckSum := Unsigned(PseudoHeader);

          else
            state <= MAC_WriteHeader ;
            RdReq <= '0';
            SelSm <= '1';
            WrEn <= '1';
            CPU_AccGnt <= '0';
            Dout <= MAC_HeaderRegFile(Idx);
            Offset <= MAC_HDR + Idx;
            Idx := Idx + 1;

            ConnectReq_Intern <= '0';
          end if ;
        when AccessByCPU =>
          if (CPU_Tx.Request = '0') then
            state <= Idle ;
            PktPtr <= PktPtr + Pkt_End + 1;
            Offset <= PAYLOAD;
            If CPU_Tx.Request = '0' Then
               RdReq <= '1';
               ConnectReq_Intern <= '1';
            Else
               RdReq <= '0';
               ConnectReq_Intern <= '0';
            End If;
            SelSm <= '1';
            WrEn <= '0';
            CPU_AccGnt <= '0';
            EOPout <= '0';
            -- InitHregFile:
            -- MAC Destination Address
            MAC_HeaderRegFile(MAC_IDX_DST)                  := eth_regs_i.MAC_Srv (47 downto 32);
            MAC_HeaderRegFile(MAC_IDX_DST + 1)              := eth_regs_i.MAC_Srv (31 downto 16);
            MAC_HeaderRegFile(MAC_IDX_DST + 2)              := eth_regs_i.MAC_Srv (15 downto 0);
            -- MAC Source Address
            MAC_HeaderRegFile(MAC_IDX_SRC)                  := eth_regs_i.MAC_Mod (47 downto 32);
            MAC_HeaderRegFile(MAC_IDX_SRC + 1)              := eth_regs_i.MAC_Mod (31 downto 16);
            MAC_HeaderRegFile(MAC_IDX_SRC + 2)              := eth_regs_i.MAC_Mod (15 downto 0);
            -- Type/Length (EtherType is Internet Protocol Version 4 (0x0800)
            MAC_HeaderRegFile(MAC_IDX_LEN)                  := x"0800";

            -- IP Version / Header Length / Type Of Service
            IP_HeaderRegFile(IP_IDX_VER_LEN_TOS)            := x"4500";
            -- IP Length (assigned later according to input stream)
            IP_HeaderRegFile(IP_IDX_LEN)                    := x"0000";
            -- IP ID (assigned later according to FragID input)
            IP_HeaderRegFile(IP_IDX_ID)                     := x"0000";
            -- IP Flags / Fragment Offset (assigned later according to MoreFrag and FragOff input)
            IP_HeaderRegFile(IP_IDX_FLAGS_FRAGOFF)          := x"0000";
            -- IP Time To Live (128), PROT: UDP = 17
            IP_HeaderRegFile(IP_IDX_TTL_PROT)               := x"8011";
            -- IP Header CheckSum. Initially set to 0x0000 for
            -- Checksum calculation (assigned later according to input stream)
            IP_HeaderRegFile(IP_IDX_CHECKS)                 := x"0000";
            -- IP Source Address
            IP_HeaderRegFile(IP_IDX_IP_SRC)                 := eth_regs_i.IP_Mod(31 downto 16);
            IP_HeaderRegFile(IP_IDX_IP_SRC + 1)             := eth_regs_i.IP_Mod(15 downto 0);
            -- IP Destination Address
            IP_HeaderRegFile(IP_IDX_IP_DST)                 := eth_regs_i.IP_Srv(31 downto 16);
            IP_HeaderRegFile(IP_IDX_IP_DST + 1)             := eth_regs_i.IP_Srv(15 downto 0);

            -- UDP Source Port (assigned later according to input stream)
            UDP_HeaderRegFile(UDP_IDX_SRCPRT)               := x"0000";
            -- UDP Destination Port (assigned later according to input stream)
            UDP_HeaderRegFile(UDP_IDX_DSTPRT)               := x"0000";
            -- UDP Length
            UDP_HeaderRegFile(UDP_IDX_LEN)                  := x"0000";
            -- UDP CheckSum
            -- CheckSum is optional. If it is not calculated then
            -- it should be set to 0x0000.
            UDP_HeaderRegFile(UDP_IDX_CHECKS)               := x"0000";

            -- The UDP CheckSum is calculated using an UDP Pseudo-Header that contains:
            -- IP Source address
            -- IP Destination address
            -- x"00" & Protocol
            -- UDP_Length
            -- Note: UDP Length is to be added when this value is known

            --CheckSum := 
            --   (x"0000" & Unsigned(IP_HeaderRegFile(IP_IDX_IP_SRC))) +
            --   (x"0000" & Unsigned(IP_HeaderRegFile(IP_IDX_IP_SRC + 1))) +
            --   (x"0000" & Unsigned(IP_HeaderRegFile(IP_IDX_IP_DST))) +
            --   (x"0000" & Unsigned(IP_HeaderRegFile(IP_IDX_IP_DST + 1))) +
            --   (x"0000" & x"00" & Unsigned(IP_HeaderRegFile(IP_IDX_TTL_PROT)(7 downto 0)));

            -- Note that due timing issues between "eth_regs_i.IP_Src" and "CheckSum" which occured
            -- during place&route it was decided to pre-calculate the content of the pseudo header.
            CheckSum := Unsigned(PseudoHeader);

          else
            state <= AccessByCPU ;
            Offset <= To_Integer(Unsigned(CPU_Tx.Addr));
            RdReq <= '0';
            SelSm <= '1';
            WrEn <= CPU_Tx.WrEn;
            CPU_AccGnt <= '1';
            Dout <= CPU_Tx.D;
            EOPout <= CPU_Tx.EOP;
            If CPU_Tx.EOP = '1' and CPU_Tx.WrEn = '1' Then
              Pkt_End <= Unsigned(CPU_Tx.Addr);
            End If;
            ConnectReq_Intern <= '0';
          end if ;
      end case lbl_state ;
    end if ; --  Reset & Clock
  end process state_decoding ;

end architecture fsm ; -- of tx_data2buf

--------------------------------------------------------------------------------
-- Object        : Entity design.PktBufFlags
-- Last modified : Thu May 12 11:00:53 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.V_ARRAY_Package.all;
use work.EMAC16bit_Package.all;

entity PktBufFlags is
  generic(
    abits : integer := 15);
  port (
    Empty         : out    std_logic;
    Full          : out    std_logic;
    PktRdPtr      : in     std_logic_vector(abits-1 downto 0);
    PktWrPtr      : in     std_logic_vector(abits-1 downto 0);
    WaterMarkHigh : out    std_logic;
    WaterMarkLow  : out    std_logic);
end entity PktBufFlags;

--------------------------------------------------------------------------------
-- Object        : Architecture design.PktBufFlags.rtl
-- Last modified : Thu May 12 11:00:53 2016
--------------------------------------------------------------------------------


architecture rtl of PktBufFlags is
   
   -- Note:
   -- A buffer size of 32678 (16 bit) words (abits = 15) can contain 65536 bytes which
   -- corresponds to 7 jumbo frames.
   -- A High Water Mark set to 50% means that a pause request is issued after four jumbo frames were received
   -- (the fifth on it's way...; place left to store 5, 6 and 7)
   -- Recall hat 50% of 65536 is 32678 is more than three and less than four jumbo frames of 9014 bytes. Flag
   -- behavior acts upon the Packet Read and Write pointers (not the actual read and write address pointers!)
   -- since packets may be signaled as "bad" and therefore will not occupy buffer space...
   
   -- Jumbo	   Number of   % of abits = 14   % of abits = 15   % of abits = 16
   --          Bytes       (= 32678 Bytes)   (= 65536 Bytes)   (= 131072 Bytes)
   -- 1        9014        27,51%	         13,75%	         6,88%
   -- 2	      18028	      55,02%	         27,51%	         13,75%
   -- 3	      27042	      82,53%	         41,26%	         20,63%
   -- 4	      36056	      110,03%	         55,02%	         27,51%
   -- 5	      45070		                     68,77%	         34,39%
   -- 6	      54084		                     82,53%	         41,26%
   -- 7	      63098		                     96,28%	         48,14%
   -- 8	      72112		                     110,03%	         55,02%
   -- 9	      81126		                                       61,89%
   -- 10	      90140		                                       68,77%
   -- 11	      99154		                                       75,65%
   -- 12	      108168		                                    82,53%
   -- 13	      117182		                                    89,40%
   -- 14	      126196		                                    96,28%
   -- 15	      135210		                                    103,16%
   
   Constant LowLevelPerc: Integer := 30;
   Constant HighLevelPerc: Integer := 50;
begin

   Process (PktRdPtr, PktWrPtr)
   Begin
      If PktRdPtr = PktWrPtr Then
         Empty <= '1';
      Else
         Empty <= '0';
      End If;
      
      -- Signal Low WaterMark
      If (Unsigned(PktWrPtr) - Unsigned(PktRdPtr)) < To_Unsigned((2**abits * LowLevelPerc)/100, abits) Then
         WaterMarkLow <= '1';
      Else
         WaterMarkLow <= '0';
      End If;

      -- Signal High WaterMark
      If (Unsigned(PktWrPtr) - Unsigned(PktRdPtr)) > To_Unsigned((2**abits * HighLevelPerc)/100, abits) And
         PktRdPtr /= PktWrPtr Then
         WaterMarkHigh <= '1';
      Else
         WaterMarkHigh <= '0';
      End If;

      -- Signal Full, as soon as there is no room left for a complete (Jumbo) packet
      If (Unsigned(PktRdPtr) - Unsigned(PktWrPtr)) <= To_Unsigned(MAX_RESERV_PKT_BUF, abits) And
         PktRdPtr /= PktWrPtr Then
         Full <= '1';
      Else
         Full <= '0';
      End If;
   End Process;
end architecture rtl ; -- of PktBufFlags

--------------------------------------------------------------------------------
-- Object        : Entity design.TxWrDataSrcSel
-- Last modified : Thu May 12 13:48:23 2016
--------------------------------------------------------------------------------



library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity TxWrDataSrcSel is
  port (
    Dout        : out    std_logic_vector(15 downto 0);
    EOPin       : in     std_logic;
    EOPout      : out    std_logic;
    SelSm       : in     std_logic;
    SmDin       : in     std_logic_vector(15 downto 0);
    TX_LL_DATA  : in     std_logic_vector(15 downto 0);
    TX_LL_EOP   : in     std_logic;
    TX_LL_VALID : in     std_logic;
    WrEn        : out    std_logic;
    WrEnIn      : in     std_logic);
end entity TxWrDataSrcSel;

--------------------------------------------------------------------------------
-- Object        : Architecture design.TxWrDataSrcSel.rtl
-- Last modified : Thu May 12 13:48:23 2016
--------------------------------------------------------------------------------


architecture rtl of TxWrDataSrcSel is

begin
   WrEn <= WrEnIn When SelSm = '1' Else TX_LL_VALID;
   Dout <= SmDin When SelSm = '1' Else TX_LL_DATA;
   EOPout <= EOPin When SelSm = '1' Else TX_LL_EOP;
end architecture rtl ; -- of TxWrDataSrcSel

--------------------------------------------------------------------------------
-- Object        : Entity design.ipmux_regs_and_rxtxcpu
-- Last modified : Wed May 11 13:15:26 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.V_ARRAY_Package.all;
use work.EMAC16bit_Package.all;
use work.wishbone_pkg.all;

entity ipmux_regs_and_rxtxcpu is
  port (
    CPU_AccGnt       : in     std_logic;
    CPU_Tx           : out    ipmux_cpu_in_type;
    Clk              : in     std_logic;
    Flush            : out    std_logic_vector(NUM_UDP_PRTS downto 0);
    PacketsDone      : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    Rst              : in     std_logic;
    Rx_Empty         : in     std_logic_vector(NUM_UDP_PRTS downto 0);
    TxStreamDebug    : in     std_logic_vector(11 downto 0);
    Tx_Full          : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    cpu_rdreq        : out    std_logic;
    cpu_rx           : in     dbus_type;
    div_ratio        : out    std_logic_vector(31 downto 0);
    eth_regs_o       : out    eth_regs_type;
    numpackets       : out    std_logic_vector(9 downto 0);
    numwords         : out    std_logic_vector(13 downto 0);
    udptstctrl       : out    std_logic_vector(2 downto 0);
    wb_ipmux_reg_i   : in     t_wishbone_slave_in;
    wb_ipmux_reg_o   : out    t_wishbone_slave_out;
    wb_ipmux_rx_tx_i : in     t_wishbone_slave_in;
    wb_ipmux_rx_tx_o : out    t_wishbone_slave_out);
end entity ipmux_regs_and_rxtxcpu;

--------------------------------------------------------------------------------
-- Object        : Architecture design.ipmux_regs_and_rxtxcpu.rtl
-- Last modified : Wed May 11 13:15:26 2016
--------------------------------------------------------------------------------


architecture rtl of ipmux_regs_and_rxtxcpu is

  signal ack_reg: std_logic;   -- internal acknowledeg for wb_ipmux_reg
  signal wr_reg: std_logic;    -- internal write
  signal rd_reg: std_logic;    -- internal read

  signal ack_txrx: std_logic;  -- internal acknowledeg for wb_ipmux_rx_tx
  signal rd_rx: std_logic;     -- internal read
  signal wr_tx: std_logic;     -- internal read

  
  -- actual wishbone registers 
  signal MAC_Mod            : std_logic_vector(47 downto 0);					-- Module MAC address
  signal MAC_Srv            : std_logic_vector(47 downto 0);					-- Server MAC address
  signal IP_Mod             : std_logic_vector(31 downto 0);					-- Module IP address
  signal IP_Srv             : std_logic_vector(31 downto 0);					-- Server IP address
  signal UDP_SrvPrt         : std_logic_v16array(NUM_UDP_PRTS-1 downto 0);     -- Server Port
  signal UDP_ModPrt         : std_logic_v16array(NUM_UDP_PRTS-1 downto 0);     -- Module Port
  
  signal reg_flush          : std_logic_vector(4 downto 0);                    -- Access Control Status Register -> Flush
  signal reg_tx_request     : std_logic;       	                            -- Access Control Status Register -> Tx_Request

  signal reg_div_ratio      : std_logic_vector(31 downto 0);                   -- packet test generator: divide ratio (counts * 16 ns ticks)
  signal reg_numwords       : std_logic_vector(13 downto 0);                   -- packet test generator: number of words per packet 
  signal reg_numpackets     : std_logic_vector( 9 downto 0);                   -- packet test generator: number of packets per burst
  signal reg_udptstcntr     : std_logic_vector( 2 downto 0);                   -- packet test generator: control register (continuously or trigger)
   
begin
-- ==============================================================================
-- Implement IPMUX Register acces via wb_ipmux_reg_i and wb_ipmux_reg_o
-- ==============================================================================
	
  -- generate acknowledge output signal
  gen_ack_reg : process(Clk, Rst)
  begin
      if Rst = '1' then
	 ack_reg <= '0';
	elsif rising_edge(Clk) then
          ack_reg <= wb_ipmux_reg_i.cyc and wb_ipmux_reg_i.stb and not ack_reg;         -- because timing is always honored
      end if;
  end process gen_ack_reg;
  wb_ipmux_reg_o.ack <= ack_reg;
  
  -- generate other wishbone signals
  wb_ipmux_reg_o.err <= '0';
  wb_ipmux_reg_o.rty <= '0';
  wb_ipmux_reg_o.stall <= '0';
  wb_ipmux_reg_o.int <= '0';
  
  -- generate wishbone write and read access signal
  wr_reg <= wb_ipmux_reg_i.cyc and wb_ipmux_reg_i.stb and wb_ipmux_reg_i.we;
  rd_reg <= wb_ipmux_reg_i.cyc and wb_ipmux_reg_i.stb and not wb_ipmux_reg_i.we;
  
  -- assign wishbone data output
  wb_read_reg : process(Clk, Rst)
	begin
    if Rst = '1' then
      wb_ipmux_reg_o.dat <= (others => '0');
    elsif rising_edge(Clk) then
      if (rd_reg = '1') then
        case to_integer(unsigned(wb_ipmux_reg_i.adr(7 downto 2))) is
          when 16#00# => wb_ipmux_reg_o.dat <= MAC_Srv(31 downto 0);
          when 16#01# => wb_ipmux_reg_o.dat <= x"0000" & MAC_Srv(47 downto 32);
          when 16#02# => wb_ipmux_reg_o.dat <= MAC_Mod(31 downto 0);
          when 16#03# => wb_ipmux_reg_o.dat <= x"0000" & MAC_Mod(47 downto 32);
          when 16#04# => wb_ipmux_reg_o.dat <= IP_Srv;
          when 16#05# => wb_ipmux_reg_o.dat <= IP_Mod;
          when 16#06# => wb_ipmux_reg_o.dat <= UDP_SrvPrt(0) & UDP_ModPrt(0);
          when 16#07# => wb_ipmux_reg_o.dat <= UDP_SrvPrt(1) & UDP_ModPrt(1);
          when 16#08# => wb_ipmux_reg_o.dat <= UDP_SrvPrt(2) & UDP_ModPrt(2);
          when 16#09# => wb_ipmux_reg_o.dat <= UDP_SrvPrt(3) & UDP_ModPrt(3);
          when 16#0A# => wb_ipmux_reg_o.dat <= "0000" & Tx_Full & "000" & Rx_Empty & "000" & reg_flush & "000000" & CPU_AccGnt & reg_tx_request;
    
          when 16#10# => wb_ipmux_reg_o.dat <= reg_div_ratio;
          when 16#11# => wb_ipmux_reg_o.dat <= x"0000" & "00" & reg_numwords;
          when 16#12# => wb_ipmux_reg_o.dat <= x"00000" & "00" & reg_numpackets;
          when 16#13# => wb_ipmux_reg_o.dat <= x"0000000" & '0' & reg_udptstcntr;
          when 16#14# => wb_ipmux_reg_o.dat <= x"0000" & PacketsDone & TxStreamDebug;
          when others => wb_ipmux_reg_o.dat <= (others => '0');
                         report ("### IPMUX_Registers: Illegal read address");
        end case;
      end if;
    end if;
  end process wb_read_reg;

   -- assign the registers with wishbone data input
  wb_write_reg: process(Clk, Rst)
  begin
    if (Rst = '1') then
      MAC_Mod <= (others => '0');
      MAC_Srv <= (others => '0');
      IP_Mod <= (others => '0');
      IP_Srv <= (others => '0');
      for i in 0 to (NUM_UDP_PRTS-1) loop
        UDP_SrvPrt(i) <= (others => '0');
        UDP_ModPrt(i) <= (others => '0');
      end loop;

      reg_tx_request <= '0';
      reg_flush <= (others => '0');
      reg_div_ratio  <= std_logic_vector(to_unsigned(2422,32));  -- default = 1 / (2422 * 16 ns) = 25,8 KHz
      reg_numwords   <= std_logic_vector(to_unsigned(4,14));     -- default = 4 words payload  per UDP packet (gives minimum size Ethernet packets of 60 bytes)
      reg_numpackets <= std_logic_vector(to_unsigned(16,10));    -- default = bunches of 16 packets
      reg_udptstcntr <= (others => '0');                         -- default = no continuous, no trigger

    elsif rising_edge(Clk) then
      if (wr_reg = '1') then
        case to_integer(unsigned(wb_ipmux_reg_i.adr(7 downto 2))) is
          when 16#00# => MAC_Srv(31 downto 0)  <= wb_ipmux_reg_i.dat;
          when 16#01# => MAC_Srv(47 downto 32) <= wb_ipmux_reg_i.dat(15 downto 0);
          when 16#02# => MAC_Mod(31 downto 0)  <= wb_ipmux_reg_i.dat;
          when 16#03# => MAC_Mod(47 downto 32) <= wb_ipmux_reg_i.dat(15 downto 0);
          when 16#04# => IP_Srv                <= wb_ipmux_reg_i.dat;
          when 16#05# => IP_Mod                <= wb_ipmux_reg_i.dat;
          when 16#06# => UDP_SrvPrt(0)         <= wb_ipmux_reg_i.dat(31 downto 16);
                         UDP_ModPrt(0)         <= wb_ipmux_reg_i.dat(15 downto 0);
          when 16#07# => UDP_SrvPrt(1)         <= wb_ipmux_reg_i.dat(31 downto 16);
                         UDP_ModPrt(1)         <= wb_ipmux_reg_i.dat(15 downto 0);
          when 16#08# => UDP_SrvPrt(2)         <= wb_ipmux_reg_i.dat(31 downto 16);
                         UDP_ModPrt(2)         <= wb_ipmux_reg_i.dat(15 downto 0);
          when 16#09# => UDP_SrvPrt(3)         <= wb_ipmux_reg_i.dat(31 downto 16);
                         UDP_ModPrt(3)         <= wb_ipmux_reg_i.dat(15 downto 0);
          when 16#0A# => reg_tx_request        <= wb_ipmux_reg_i.dat(0);             -- Tx Request
                         reg_flush             <= wb_ipmux_reg_i.dat(12 downto 8);   -- Flush
          when 16#10# => reg_div_ratio         <= wb_ipmux_reg_i.dat;
          when 16#11# => reg_numwords          <= wb_ipmux_reg_i.dat(13 downto 0);
          when 16#12# => reg_numpackets        <= wb_ipmux_reg_i.dat( 9 downto 0);
          when 16#13# => reg_udptstcntr        <= wb_ipmux_reg_i.dat( 2 downto 0);
        --when 16#14# =>                                                             -- Read Only
          when others => report ("### IPMUX_Registers: Illegal write address");
        end case;
      end if;
    end if;
  end process wb_write_reg;

  -- assign the registers to the output pins
  eth_regs_o.MAC_Mod    <= MAC_Mod;
  eth_regs_o.MAC_Srv    <= MAC_Srv;
  eth_regs_o.IP_Mod     <= IP_Mod;
  eth_regs_o.IP_Srv     <= IP_Srv;
  eth_regs_o.UDP_SrvPrt <= UDP_SrvPrt;
  eth_regs_o.UDP_ModPrt <= UDP_ModPrt;
  
  div_ratio             <= reg_div_ratio;
  numwords              <= reg_numwords;
  numpackets            <= reg_numpackets;
  udptstctrl            <= reg_udptstcntr;
  
  CPU_Tx.Request        <= reg_tx_request;
  Flush                 <= reg_flush;

-- ==============================================================================
-- Implement IPMUX Tx/Rx CPU interface via wb_ipmux_rx_tx_i and wb_ipmux_rx_tx_o
-- ==============================================================================

  -- generate acknowledge output signal
  gen_ack_txrx : process(Clk, Rst)
  begin
    if Rst = '1' then
	    ack_txrx <= '0';
	  elsif rising_edge(Clk) then
      ack_txrx <= wb_ipmux_rx_tx_i.cyc and wb_ipmux_rx_tx_i.stb and not ack_txrx;         -- because timing is always honoured
    end if;
  end process gen_ack_txrx;
  wb_ipmux_rx_tx_o.ack <= ack_txrx;

  -- generate other wishbone signals
  wb_ipmux_rx_tx_o.err <= '0';
  wb_ipmux_rx_tx_o.rty <= '0';
  wb_ipmux_rx_tx_o.stall <= '0';
  wb_ipmux_rx_tx_o.int <= '0';

  -- generate wishbone write and read access signal
  wr_tx <= wb_ipmux_rx_tx_i.cyc and wb_ipmux_rx_tx_i.stb and wb_ipmux_rx_tx_i.we;
  rd_rx <= wb_ipmux_rx_tx_i.cyc and wb_ipmux_rx_tx_i.stb and not wb_ipmux_rx_tx_i.we;

  cpu_rdreq <= rd_rx;
  wb_ipmux_rx_tx_o.dat <= x"000" & "000" & cpu_rx.EOD & cpu_rx.D;     -- assign wishbone data output

	-- Check for address range
  addr_range_check: process(wb_ipmux_rx_tx_i.adr, wr_tx, rd_rx, cpu_rx)
	  Constant AddrRange: integer := TX_PKT_BUF_ADRSIZE-1;
	  Variable Addr: std_logic_vector (TX_PKT_BUF_ADRSIZE-1 downto 0);
  begin
    Addr(Addr'left downto AddrRange) := (others => '0');
    -- In case TX_PKT_BUF_ADRSIZE = 14 then Range 0x0000-0x7FFC (14 downto 2) = 0x0000-0x1FFF (12 downto 0)
	  Addr(AddrRange - 1 downto 0) := wb_ipmux_rx_tx_i.adr(AddrRange + 1 downto 2);
	  case to_integer(unsigned(Addr)) is
      when 16#0000# to MAX_RESERV_PKT_BUF => CPU_TX.Addr <= Addr;
                                             CPU_Tx.WrEn <= wr_tx;
		  when others                         => CPU_TX.Addr <= (others => '0');
                                             CPU_Tx.WrEn <= '0';
    	                                       report ("### IPMUX_CPU_RX_TX: Illegal address");
      end case;
  end process addr_range_check;

  CPU_Tx.D    <= wb_ipmux_rx_tx_i.dat(15 downto 0);
  CPU_Tx.EOP  <= wb_ipmux_rx_tx_i.dat(16);
	
end architecture rtl ; -- of ipmux_regs_and_rxtxcpu

--------------------------------------------------------------------------------
-- Object        : Entity design.rx_mac2buf
-- Last modified : Wed May 11 13:17:33 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wr_fabric_pkg.all;
use work.V_ARRAY_Package.all;
use work.EMAC16bit_Package.all;

entity rx_mac2buf is
  generic(
    abits : integer := 15);
  port (
    Clk      : in     std_logic;
    Dout     : out    std_logic_vector(15 downto 0);
    EOF      : out    std_logic;
    Full     : in     std_logic;
    OverFlow : out    std_logic;
    PktWrPtr : out    std_logic_vector(abits-1 downto 0);
    Rst      : in     std_logic;
    We       : out    std_logic;
    WrAddr   : out    std_logic_vector(abits-1 downto 0);
    snk_i    : in     t_wrf_sink_in;
    snk_o    : out    t_wrf_sink_out);
end entity rx_mac2buf;

--------------------------------------------------------------------------------
-- Object        : Architecture design.rx_mac2buf.rtl
-- Last modified : Wed May 11 13:17:33 2016
--------------------------------------------------------------------------------


architecture rtl of rx_mac2buf is

-- general signals
  signal rd_req         : std_logic;
  signal q_data_p1      : std_logic_vector(15 downto 0);
  signal q_valid_p1     : std_logic;
  signal q_adr_p1       : std_logic_vector(1 downto 0);

  signal snk_valid      : std_logic;
  signal eocycle        : std_logic;
  signal adr_change     : std_logic;
  signal snk_cyc_d0     : std_logic;

  signal snk_out        : t_wrf_sink_out;
  signal stall_int      : std_logic;
  signal shift_pipeline : std_logic;

  Signal Offset         : Integer Range 0 to MAX_RESERV_PKT_BUF;
  Signal PktPtr         : Unsigned(abits-1 downto 0);
  Signal We_Int         : Std_Logic;   
  Signal good_frame     : Std_Logic;
  Signal bad_frame      : Std_Logic;

begin
  -- IPmux should always be capable to store at leaste one jumbo packet.
  -- Backpressure is not implemented using "rd_req" but by sending Ethernet Pause Frames.
  -- Therefore rd_req ia always asserted.
  rd_req <= '1';
  
  p_detect_frame : process(Clk, Rst)
  begin
    if rising_edge(Clk) then
      if Rst = '1' then
        snk_cyc_d0 <= '0';
      else
        snk_cyc_d0 <= snk_i.cyc;
      end if;
    end if;
  end process;

  eocycle   <= snk_cyc_d0 and not snk_i.cyc;
  snk_valid <= (snk_i.cyc and snk_i.stb and snk_i.we) and not stall_int;
  shift_pipeline <= '1' when snk_valid = '1' or adr_change = '1' or eocycle = '1' else '0';

  adr_change <= '1' when (q_adr_p1 = c_WRF_DATA and snk_i.adr /= c_WRF_DATA) else '0';

  p_pipeline : process (Clk, Rst)
  begin  -- process
    if rising_edge(Clk) then
      if(Rst = '1') then
        q_data_p1  <= (others => '0');
        q_adr_p1   <= (others => '0');
        q_valid_p1 <= '0';
      else
	    if(shift_pipeline = '1') then
          q_data_p1     <= snk_i.dat;
		  q_adr_p1		<= snk_i.adr;
          if snk_i.adr = c_WRF_DATA then
		    q_valid_p1 <= snk_valid;
          else
            q_valid_p1 <= '0';
		  end if;
        end if;
      end if;
    end if;
  end process;

  Dout  <= q_data_p1;
  EOF   <= eocycle Or adr_change;

  stall_int <= not (rd_req);
  snk_out.stall <= stall_int;
  snk_out.err <= '0';
  snk_out.rty <= '0';

  p_gen_ack : process(Clk, Rst)
  begin
    if(Rst = '1') then
      snk_out.ack <= '0';
    elsif rising_edge(Clk) then
      snk_out.ack <= snk_valid;
    end if;
  end process;
  
  snk_o <= snk_out;
  
  -- Good and Bad Frame need at least one pipeline since they musn't co-incide with "We_Int"
  -- Note that in our case (connecting to White Rabbit PTP Core) we never have a bad-frame!
  p_frame_pipeline : process(Clk, Rst)
  begin
    if(Rst = '1') then
      good_frame <= '0';
      bad_frame  <= '0';
    elsif rising_edge(Clk) then
      good_frame <= eocycle;
      bad_frame  <= '0';
    end if;
  end process;
  
  WrAddr <= Std_Logic_Vector(PktPtr + To_Unsigned(Offset,RX_PKT_BUF_ADRSIZE));
  PktWrPtr <= Std_Logic_Vector(PktPtr);
  We_Int <= shift_pipeline when q_valid_p1 = '1' and Full = '0' else '0';
  Overflow <= shift_pipeline when q_valid_p1 = '1' and Full = '1' else '0';
  We <= We_Int;

  RxPktBufPointers: Process (Clk, Rst)
  Begin
    If Rst = '1' Then
      Offset <= 0;
      PktPtr <= (Others => '0');
    ElsIf Rising_Edge(Clk) Then
      If We_Int = '1' Then
        Offset <= Offset + 1;
      -- When "Good Frame" then increment the Packet Pointer
      ElsIf good_frame = '1' Then
        PktPtr <= PktPtr + To_Unsigned(Offset,RX_PKT_BUF_ADRSIZE);
        Offset <= 0;
      -- When "Bad Frame" then leave the Packet Pointer thus overwriting
      -- the bad frame in the buffer memory with the next frame.
      ElsIf bad_frame = '1' Then
         Offset <= 0;
      End If;
    End If;
  End Process RxPktBufPointers;

end architecture rtl ; -- of rx_mac2buf

--------------------------------------------------------------------------------
-- Object        : Entity design.RxBuffers
-- Last modified : Wed May 11 13:22:13 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wr_fabric_pkg.all;
use work.V_ARRAY_Package.all;
use work.EMAC16bit_Package.all;

entity RxBuffers is
  port (
    FragID          : out    std_logic_vector(15 downto 0);
    FragOff         : out    std_logic_vector(11 downto 0);
    Full            : in     std_logic_vector(NUM_UDP_PRTS downto 0);
    MoreFrags       : out    std_logic;
    PauseAck        : in     std_logic;
    PauseReq        : out    std_logic;
    PauseVal        : out    std_logic_vector(15 downto 0);
    RXo             : out    dbus_type_array(NUM_UDP_PRTS downto 0);
    UDP_CheckSumErr : out    std_logic;
    WrReq           : out    std_logic_vector(NUM_UDP_PRTS downto 0);
    eth_regs_i      : in     eth_regs_type;
    rx_clk          : in     std_logic;
    rx_reset        : in     std_logic;
    snk_i           : in     t_wrf_sink_in;
    snk_o           : out    t_wrf_sink_out);
end entity RxBuffers;

--------------------------------------------------------------------------------
-- Object        : Architecture design.RxBuffers.structure
-- Last modified : Wed May 11 13:22:13 2016
--------------------------------------------------------------------------------

architecture structure of RxBuffers is

  signal Din0          : std_logic_vector(16 downto 0);
  signal We            : std_logic;
  signal PktWrPtr      : std_logic_vector(RX_PKT_BUF_ADRSIZE-1 downto 0);
  signal WrAddr        : std_logic_vector(RX_PKT_BUF_ADRSIZE-1 downto 0);
  signal LowThrs       : std_logic;
  signal HighThrs      : std_logic;
  signal Empty0        : std_logic;
  signal PktRdPtr0     : std_logic_vector(RX_PKT_BUF_ADRSIZE-1 downto 0);
  signal RdAddr        : std_logic_vector(RX_PKT_BUF_ADRSIZE-1 downto 0);
  signal Net_3         : std_logic_vector(16 downto 0);
  signal Stream        : std_logic_vector(NUM_UDP_PRTS downto 0);
  signal Full_net      : std_logic;
  signal Fullout       : std_logic;
  signal Tst_WrReq_net : std_logic;
  signal SODout_net    : std_logic;
  signal EODout_net    : std_logic;

  component rx_mac2buf
    generic(
      abits : integer := 15);
    port (
      Clk      : in     std_logic;
      Dout     : out    std_logic_vector(15 downto 0);
      EOF      : out    std_logic;
      Full     : in     std_logic;
      OverFlow : out    std_logic;
      PktWrPtr : out    std_logic_vector(abits-1 downto 0);
      Rst      : in     std_logic;
      We       : out    std_logic;
      WrAddr   : out    std_logic_vector(abits-1 downto 0);
      snk_i    : in     t_wrf_sink_in;
      snk_o    : out    t_wrf_sink_out);
  end component rx_mac2buf;

  component PktBufFlags
    generic(
      abits : integer := 15);
    port (
      Empty         : out    std_logic;
      Full          : out    std_logic;
      PktRdPtr      : in     std_logic_vector(abits-1 downto 0);
      PktWrPtr      : in     std_logic_vector(abits-1 downto 0);
      WaterMarkHigh : out    std_logic;
      WaterMarkLow  : out    std_logic);
  end component PktBufFlags;

  component PauseReqLogic
    port (
      Clk           : in     std_logic;
      PauseAck      : in     std_logic;
      PauseReq      : out    std_logic;
      PauseVal      : out    std_logic_vector(15 downto 0);
      Rst           : in     std_logic;
      WaterMarkHigh : in     std_logic;
      WaterMarkLow  : in     std_logic);
  end component PauseReqLogic;

  component rx_buf2data
    generic(
      abits : integer := 15);
    port (
      Clk             : in     std_logic;
      Din             : in     std_logic_vector(15 downto 0);
      EODout          : out    std_logic;
      EOFin           : in     std_logic;
      Empty           : in     std_logic;
      FragID          : out    std_logic_vector(15 downto 0);
      FragOff         : out    std_logic_vector(11 downto 0);
      Full            : in     std_logic;
      MoreFrags       : out    std_logic;
      PktRdPtr        : out    std_logic_vector(abits-1 downto 0);
      RdAddr          : out    std_logic_vector(abits-1 downto 0);
      Rst             : in     std_logic;
      SODout          : out    std_logic;
      Stream          : out    std_logic_vector(NUM_UDP_PRTS downto 0);
      UDP_CheckSumErr : out    std_logic;
      WrReq           : out    std_logic;
      eth_regs_i      : in     eth_regs_type);
  end component rx_buf2data;

  component RxStreamSel
    port (
      Din     : in     std_logic_vector(15 downto 0);
      EODin   : in     std_logic;
      EOFin   : in     std_logic;
      Full    : in     std_logic_vector(NUM_UDP_PRTS downto 0);
      Fullout : out    std_logic;
      RXo     : out    dbus_type_array(NUM_UDP_PRTS downto 0);
      SODin   : in     std_logic;
      Stream  : in     std_logic_vector(NUM_UDP_PRTS downto 0);
      WrReq   : out    std_logic_vector(NUM_UDP_PRTS downto 0);
      WrReqin : in     std_logic);
  end component RxStreamSel;

  component PacketBuffer
    generic(
      abits : integer := 15;
      dbits : integer := 8);
    port (
      AddrA : in     std_logic_vector(abits-1 downto 0);
      AddrB : in     std_logic_vector(abits-1 downto 0);
      Clk   : in     std_logic;
      Din   : in     std_logic_vector(dbits-1 downto 0);
      Q     : out    std_logic_vector(dbits-1 downto 0);
      Rst   : in     std_logic;
      WeA   : in     std_logic);
  end component PacketBuffer;

begin
  --MAC Interface (White Rabbit PTP Core; WRPC)
  --Local Link Interface
  --EOF signals the End Of MAC Frame. The MAC frame ranges from the first
  --byte after the Start of Frame Delimiter (SFD) to the last data byte
  --before the first Frame Control Sequence (FCS). Note however that for
  --Ethernet v2 framing this *also* includes padded data that might have
  --been inserted to ensure that the frame length is at least 64 bytes!
  --
  --Entity "rx_buf2data" generates Start and End Of Data (SOD and EOD) to
  --signal the first and last data byte of the UDP packet (or the CPU packet)
  --without including padded data bytes.
  --
  --The exception is the CPU stream where the End Of Frame Signalling from
  --the MAC is routed directly to the EOD of the CPU channel (see entity
  --RxStreamSel). There is no other means to know the end of a Frame since
  --unknown Frames are not decoded.
  --
  --UDP CheckSum Error is signalled after a packet is
  --transferred to the output fifo and is de-asserted
  --when the state machine (re)starts for receiving
  --another packet. For monitorring purposes one may
  --want to count the rising edges of this signal in
  --order to track the amount of UDP checksum errors.
  --Overflow occurs when Full ='1' while
  --the MAC wants to write a frame into
  --the buffer memory.
  --Signal is pulsed?

  u1: rx_mac2buf
    generic map(
      abits => RX_PKT_BUF_ADRSIZE)
    port map(
      Clk      => rx_clk,
      Dout     => Din0(15 downto 0),
      EOF      => Din0(16),
      Full     => Full_net,
      OverFlow => open,
      PktWrPtr => PktWrPtr,
      Rst      => rx_reset,
      We       => We,
      WrAddr   => WrAddr,
      snk_i    => snk_i,
      snk_o    => snk_o);

  u4: PktBufFlags
    generic map(
      abits => RX_PKT_BUF_ADRSIZE)
    port map(
      Empty         => Empty0,
      Full          => Full_net,
      PktRdPtr      => PktRdPtr0,
      PktWrPtr      => PktWrPtr,
      WaterMarkHigh => HighThrs,
      WaterMarkLow  => LowThrs);

  u2: PauseReqLogic
    port map(
      Clk           => rx_clk,
      PauseAck      => PauseAck,
      PauseReq      => PauseReq,
      PauseVal      => PauseVal,
      Rst           => rx_reset,
      WaterMarkHigh => HighThrs,
      WaterMarkLow  => LowThrs);

  u5: rx_buf2data
    generic map(
      abits => RX_PKT_BUF_ADRSIZE)
    port map(
      Clk             => rx_clk,
      Din             => Net_3(15 downto 0),
      EODout          => EODout_net,
      EOFin           => Net_3(16),
      Empty           => Empty0,
      FragID          => FragID,
      FragOff         => FragOff,
      Full            => Fullout,
      MoreFrags       => MoreFrags,
      PktRdPtr        => PktRdPtr0,
      RdAddr          => RdAddr,
      Rst             => rx_reset,
      SODout          => SODout_net,
      Stream          => Stream,
      UDP_CheckSumErr => UDP_CheckSumErr,
      WrReq           => Tst_WrReq_net,
      eth_regs_i      => eth_regs_i);

  u3: RxStreamSel
    port map(
      Din     => Net_3(15 downto 0),
      EODin   => EODout_net,
      EOFin   => Net_3(16),
      Full    => Full,
      Fullout => Fullout,
      RXo     => RXo,
      SODin   => SODout_net,
      Stream  => Stream,
      WrReq   => WrReq,
      WrReqin => Tst_WrReq_net);

  u0: PacketBuffer
    generic map(
      abits => RX_PKT_BUF_ADRSIZE,
      dbits => 17)
    port map(
      AddrA => WrAddr,
      AddrB => RdAddr,
      Clk   => rx_clk,
      Din   => Din0,
      Q     => Net_3,
      Rst   => rx_reset,
      WeA   => We);
end architecture structure ; -- of RxBuffers

--------------------------------------------------------------------------------
-- Object        : Entity design.tx_pkt2mac
-- Last modified : Wed May 11 13:20:18 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wr_fabric_pkg.all;
use work.V_ARRAY_Package.all;
use work.EMAC16bit_Package.all;

entity tx_pkt2mac is
  generic(
    abits : integer := 15);
  port (
    Clk      : in     std_logic;
    Din      : in     std_logic_vector(15 downto 0);
    EOP      : in     std_logic;
    Empty    : in     std_logic;
    PktRdPtr : out    std_logic_vector(abits-1 downto 0);
    RdAddr   : out    std_logic_vector(abits-1 downto 0);
    Rst      : in     std_logic;
    src_i    : in     t_wrf_source_in;
    src_o    : out    t_wrf_source_out);
end entity tx_pkt2mac;

--------------------------------------------------------------------------------
-- Object        : Architecture design.tx_pkt2mac.rtl
-- Last modified : Wed May 11 13:20:18 2016
--------------------------------------------------------------------------------


architecture rtl of tx_pkt2mac is
  -- State Machine Options:
  --  Clock : Clk (Rising edge).
  --  State assignment : Enumerate.
  --  State decoding : Case construct.
  --  Actions on transitions : Clocked.
  --  Actions on states : Clocked.

  type state_type is (Idle, wrf_status, Frame, Stall, EndCycle) ;
  signal state : state_type  ;  -- Current State
  Signal Offset: Integer Range 0 to MAX_RESERV_PKT_BUF;
  Signal PktPtr: Unsigned(abits-1 downto 0);

begin
  RdAddr <= Std_Logic_Vector(PktPtr + To_Unsigned(Offset,TX_PKT_BUF_ADRSIZE));
  PktRdPtr <= Std_Logic_Vector(PktPtr);
  src_o.adr <= c_WRF_STATUS when state = wrf_status else c_WRF_DATA;
  src_o.dat <= x"0204" when state = wrf_status else Din; -- Status word derived from figure 7 (wrpc_hdl.pdf)
  src_o.we  <= '1'; -- source is writing by definition
  src_o.sel <= (others => '1'); -- we live in a 16 bit domain
  
  state_decoding: process (Clk, Rst) is
  begin
    if (Rst = '1') then
      state <= Idle ;
      -- Initialize:
      PktPtr <= (Others => '0');
      -- Pkt_Str <= (Others => '0');
      Offset <= 0;
	  src_o.cyc <= '0';
	  src_o.stb <= '0';
    elsif (rising_edge(Clk)) then
      case state is
        when Idle =>
          src_o.cyc <= '0';
          src_o.stb <= '0';
          Offset <= 0;
          if (Empty = '0') then
            state <= wrf_status ;
            src_o.cyc <= '1';
            src_o.stb <= '1';
          else
            state <= Idle ;
          end if ;
		  
        when wrf_status =>
          if (src_i.stall = '0') then
            src_o.stb <= '1';
            state <= Frame ;
            Offset <= Offset + 1; -- read in advance (it takes data one cycle to e available)
          else
            state <= wrf_status ;
          end if ;

        when Frame =>
          state <= Frame;
		  if (src_i.stall = '1') then  -- stall then take back the pipeline data pointer
            Offset <= Offset - 1;
            state <= Stall;
            src_o.stb <= '0';
		  elsif (src_i.stall = '0') then
            if (EOP = '1') then
              state <= EndCycle ;
              src_o.stb <= '0';
              PktPtr <= PktPtr +To_Unsigned(Offset,TX_PKT_BUF_ADRSIZE);
              Offset <= 0;
            else
              src_o.stb <= '1';
              Offset <= Offset + 1;
			end if;
          end if ;

        when Stall =>
          src_o.stb <= '0';
          if (src_i.stall = '0') then
            src_o.stb <= '1';
            state <= Frame ;
            Offset <= Offset + 1; -- read in advance (it takes data one cycle to e available)
          end if ;
		  
        when EndCycle =>
          src_o.stb <= '0';
          if (src_i.stall = '0') then
           state <= Idle;
           src_o.cyc <= '0';  -- cyc should only be '0' after ack_i was seen (which equals to stall = '0')
		  else
           state <= EndCycle ;
 		  end if;
      end case ;
    end if ; --  Reset & Clock
  end process state_decoding ;

end architecture rtl ; -- of tx_pkt2mac

--------------------------------------------------------------------------------
-- Object        : Entity design.TxBuffers
-- Last modified : Wed May 11 13:22:13 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wr_fabric_pkg.all;
use work.V_ARRAY_Package.all;
use work.EMAC16bit_Package.all;

entity TxBuffers is
  port (
    CPU_AccGnt    : out    std_logic;
    CPU_Tx        : in     ipmux_cpu_in_type;
    Connect       : out    std_logic;
    Connected     : in     std_logic;
    FragID        : in     std_logic_vector(15 downto 0);
    FragOff       : in     std_logic_vector(11 downto 0);
    MoreFrag      : in     std_logic;
    Stream        : in     natural range NUM_UDP_PRTS-1 downto 0;
    TX_LL_DATA    : in     std_logic_vector(15 downto 0);
    TX_LL_EOP     : in     std_logic;
    TX_LL_RDREQ   : out    std_logic;
    TX_LL_VALID   : in     std_logic;
    eth_regs_i    : in     eth_regs_type;
    src_i         : in     t_wrf_source_in;
    src_o         : out    t_wrf_source_out;
    tx_clk        : in     std_logic;
    tx_collision  : in     std_logic;
    tx_overflow   : out    std_logic;
    tx_reset      : in     std_logic;
    tx_retransmit : in     std_logic;
    tx_underrun   : out    std_logic);
end entity TxBuffers;

--------------------------------------------------------------------------------
-- Object        : Architecture design.TxBuffers.rtl
-- Last modified : Wed May 11 13:22:13 2016
--------------------------------------------------------------------------------

architecture rtl of TxBuffers is

  signal Q            : std_logic_vector(16 downto 0);
  signal Dout         : std_logic_vector(16 downto 0);
  signal SelSm        : std_logic;
  signal WrEn0        : std_logic;
  signal Dout0        : std_logic_vector(15 downto 0);
  signal PktWrPtr     : std_logic_vector(TX_PKT_BUF_ADRSIZE-1 downto 0);
  signal PktRdPtr0    : std_logic_vector(TX_PKT_BUF_ADRSIZE-1 downto 0);
  signal WrAddr0      : std_logic_vector(TX_PKT_BUF_ADRSIZE-1 downto 0);
  signal Full         : std_logic;
  signal Empty        : std_logic;
  signal WrEn         : std_logic;
  signal WrAddr       : std_logic_vector(TX_PKT_BUF_ADRSIZE-1 downto 0);
  signal EOPout       : std_logic;
  signal PseudoHeader : std_logic_vector(31 downto 0);

  component TxWrDataSrcSel
    port (
      Dout        : out    std_logic_vector(15 downto 0);
      EOPin       : in     std_logic;
      EOPout      : out    std_logic;
      SelSm       : in     std_logic;
      SmDin       : in     std_logic_vector(15 downto 0);
      TX_LL_DATA  : in     std_logic_vector(15 downto 0);
      TX_LL_EOP   : in     std_logic;
      TX_LL_VALID : in     std_logic;
      WrEn        : out    std_logic;
      WrEnIn      : in     std_logic);
  end component TxWrDataSrcSel;

  component PktBufFlags
    generic(
      abits : integer := 15);
    port (
      Empty         : out    std_logic;
      Full          : out    std_logic;
      PktRdPtr      : in     std_logic_vector(abits-1 downto 0);
      PktWrPtr      : in     std_logic_vector(abits-1 downto 0);
      WaterMarkHigh : out    std_logic;
      WaterMarkLow  : out    std_logic);
  end component PktBufFlags;

  component tx_pkt2mac
    generic(
      abits : integer := 15);
    port (
      Clk      : in     std_logic;
      Din      : in     std_logic_vector(15 downto 0);
      EOP      : in     std_logic;
      Empty    : in     std_logic;
      PktRdPtr : out    std_logic_vector(abits-1 downto 0);
      RdAddr   : out    std_logic_vector(abits-1 downto 0);
      Rst      : in     std_logic;
      src_i    : in     t_wrf_source_in;
      src_o    : out    t_wrf_source_out);
  end component tx_pkt2mac;

  component tx_data2buf
    generic(
      abits : integer := 15);
    port (
      CPU_AccGnt   : out    std_logic;
      CPU_Tx       : in     ipmux_cpu_in_type;
      Clk          : in     std_logic;
      ConnectReq   : out    std_logic;
      Connected    : in     std_logic;
      Dout         : out    std_logic_vector(15 downto 0);
      EOPout       : out    std_logic;
      FragID       : in     std_logic_vector(15 downto 0);
      FragOff      : in     std_logic_vector(11 downto 0);
      Full         : in     std_logic;
      MoreFrag     : in     std_logic;
      PktWrPtr     : out    std_logic_vector(abits-1 downto 0);
      PseudoHeader : in     std_logic_vector(31 downto 0);
      Rst          : in     std_logic;
      SelSm        : out    std_logic;
      Stream       : in     natural range NUM_UDP_PRTS-1 downto 0;
      TX_LL_DATA   : in     std_logic_vector(15 downto 0);
      TX_LL_EOP    : in     std_logic;
      TX_LL_RDREQ  : out    std_logic;
      TX_LL_VALID  : in     std_logic;
      WrAddr       : out    std_logic_vector(abits-1 downto 0);
      WrEn         : out    std_logic;
      eth_regs_i   : in     eth_regs_type);
  end component tx_data2buf;

  component Calc_UDP_PseudoHeader
    port (
      Clk          : in     std_logic;
      PseudoHeader : out    std_logic_vector(31 downto 0);
      Rst          : in     std_logic;
      eth_regs_i   : in     eth_regs_type);
  end component Calc_UDP_PseudoHeader;

  component PacketBuffer
    generic(
      abits : integer := 15;
      dbits : integer := 8);
    port (
      AddrA : in     std_logic_vector(abits-1 downto 0);
      AddrB : in     std_logic_vector(abits-1 downto 0);
      Clk   : in     std_logic;
      Din   : in     std_logic_vector(dbits-1 downto 0);
      Q     : out    std_logic_vector(dbits-1 downto 0);
      Rst   : in     std_logic;
      WeA   : in     std_logic);
  end component PacketBuffer;

begin
  --32 KB buffer can store at least
  --3 jumbo frames (9000 bytes each)
  --Local Link Interface
  --MAC Interface
  --A complete paket is always accumelated
  --in the buffer before a transmit is started,
  --so an underrun can never occur.
  --Note that due timing issues between "eth_regs.IP_Src" and "tx_data2buf/CheckSum"
  --which occured during place&route it was decided to pre-calculate the content of
  --the pseudo header in order to avoid timing problems.
  --
  tx_overflow <= '0';
  tx_underrun <= '0';

  u2: TxWrDataSrcSel
    port map(
      Dout        => Dout(15 downto 0),
      EOPin       => EOPout,
      EOPout      => Dout(16),
      SelSm       => SelSm,
      SmDin       => Dout0,
      TX_LL_DATA  => TX_LL_DATA,
      TX_LL_EOP   => TX_LL_EOP,
      TX_LL_VALID => TX_LL_VALID,
      WrEn        => WrEn0,
      WrEnIn      => WrEn);

  u4: PktBufFlags
    generic map(
      abits => TX_PKT_BUF_ADRSIZE)
    port map(
      Empty         => Empty,
      Full          => Full,
      PktRdPtr      => PktRdPtr0,
      PktWrPtr      => PktWrPtr,
      WaterMarkHigh => open,
      WaterMarkLow  => open);

  u3: tx_pkt2mac
    generic map(
      abits => TX_PKT_BUF_ADRSIZE)
    port map(
      Clk      => tx_clk,
      Din      => Q(15 downto 0),
      EOP      => Q(16),
      Empty    => Empty,
      PktRdPtr => PktRdPtr0,
      RdAddr   => WrAddr0,
      Rst      => tx_reset,
      src_i    => src_i,
      src_o    => src_o);

  u1: tx_data2buf
    generic map(
      abits => TX_PKT_BUF_ADRSIZE)
    port map(
      CPU_AccGnt   => CPU_AccGnt,
      CPU_Tx       => CPU_Tx,
      Clk          => tx_clk,
      ConnectReq   => Connect,
      Connected    => Connected,
      Dout         => Dout0,
      EOPout       => EOPout,
      FragID       => FragID,
      FragOff      => FragOff,
      Full         => Full,
      MoreFrag     => MoreFrag,
      PktWrPtr     => PktWrPtr,
      PseudoHeader => PseudoHeader,
      Rst          => tx_reset,
      SelSm        => SelSm,
      Stream       => Stream,
      TX_LL_DATA   => TX_LL_DATA,
      TX_LL_EOP    => TX_LL_EOP,
      TX_LL_RDREQ  => TX_LL_RDREQ,
      TX_LL_VALID  => TX_LL_VALID,
      WrAddr       => WrAddr,
      WrEn         => WrEn,
      eth_regs_i   => eth_regs_i);

  u6: Calc_UDP_PseudoHeader
    port map(
      Clk          => tx_clk,
      PseudoHeader => PseudoHeader,
      Rst          => tx_reset,
      eth_regs_i   => eth_regs_i);

  u0: PacketBuffer
    generic map(
      abits => TX_PKT_BUF_ADRSIZE,
      dbits => 17)
    port map(
      AddrA => WrAddr,
      AddrB => WrAddr0,
      Clk   => tx_clk,
      Din   => Dout,
      Q     => Q,
      Rst   => tx_reset,
      WeA   => WrEn0);
end architecture rtl ; -- of TxBuffers

--------------------------------------------------------------------------------
-- Object        : Entity design.ipmux
-- Last modified : Thu May 12 14:43:14 2016
--------------------------------------------------------------------------------



library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.V_ARRAY_Package.all;
use work.wr_fabric_pkg.all;
use work.EMAC16bit_Package.all;
use work.wishbone_pkg.all;

entity ipmux is
  port (
    CPU_Gnt          : out    std_logic;
    CPU_Req          : out    std_logic;
    ConnectReq       : out    std_logic;
    Empty            : out    std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    Full             : out    std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    PauseAck         : in     std_logic;
    PauseReq         : out    std_logic;
    PauseVal         : out    std_logic_vector(15 downto 0);
    RdClk            : in     std_logic_vector(NUM_UDP_PRTS downto 0);
    RdReq            : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    Rst              : in     std_logic;
    Rx               : out    dbus_type_array(NUM_UDP_PRTS-1 downto 0);
    Stream           : out    natural range NUM_UDP_PRTS-1 downto 0;
    Tx               : in     dbus_type_array(NUM_UDP_PRTS-1 downto 0);
    WrClk            : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    WrReq            : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
    div_ratio        : out    std_logic_vector(31 downto 0);
    numpackets       : out    std_logic_vector(9 downto 0);
    numwords         : out    std_logic_vector(13 downto 0);
    snk_i            : in     t_wrf_sink_in;
    snk_o            : out    t_wrf_sink_out;
    src_i            : in     t_wrf_source_in;
    src_o            : out    t_wrf_source_out;
    tx_clk           : in     std_logic;
    tx_reset         : in     std_logic;
    udptstctrl       : out    std_logic_vector(2 downto 0);
    wb_ipmux_reg_i   : in     t_wishbone_slave_in;
    wb_ipmux_reg_o   : out    t_wishbone_slave_out;
    wb_ipmux_rx_tx_i : in     t_wishbone_slave_in;
    wb_ipmux_rx_tx_o : out    t_wishbone_slave_out);
end entity ipmux;

--------------------------------------------------------------------------------
-- Object        : Architecture design.ipmux.rtl
-- Last modified : Thu May 12 14:43:14 2016
--------------------------------------------------------------------------------

architecture rtl of ipmux is

  signal CPU_Gnt_net    : std_logic;
  signal Full_net       : std_logic_vector(NUM_UDP_PRTS downto 0);
  signal Full_net0      : std_logic_vector(NUM_UDP_PRTS-1 downto 0);
  signal RdReqOut       : std_logic_vector(NUM_UDP_PRTS-1 downto 0);
  signal Valid          : std_logic_vector(NUM_UDP_PRTS-1 downto 0);
  signal Dout1          : std_logic_vector(15 downto 0);
  signal EOPout         : std_logic;
  signal TX_LL_RDREQ0   : std_logic;
  signal Validinout     : std_logic;
  signal Empty_net      : std_logic_vector(NUM_UDP_PRTS downto 0);
  signal u7_RdReq       : std_logic_vector(NUM_UDP_PRTS downto 0);
  signal WrReq_net      : std_logic_vector(NUM_UDP_PRTS downto 0);
  signal Rx_net0        : dbus_type_array(NUM_UDP_PRTS downto 0);
  signal TXo            : dbus_type_array(NUM_UDP_PRTS-1 downto 0);
  signal RX_net         : dbus_type_array(NUM_UDP_PRTS downto 0);
  signal u4_eth_regs_o  : eth_regs_type;
  signal CPU_Tx         : ipmux_cpu_in_type;
  signal u4_Flush       : std_logic_vector(NUM_UDP_PRTS downto 0);
  signal ConnectReq_net : std_logic;
  signal Stream_net     : natural range NUM_UDP_PRTS-1 downto 0;
  signal u1_Connected   : std_logic;
  signal Packet         : std_logic_vector(NUM_UDP_PRTS-1 downto 0);
  signal Packet_RdReq   : std_logic_vector(NUM_UDP_PRTS-1 downto 0);
  signal TxStreamDebug  : std_logic_vector(11 downto 0);
  signal PacketsDone    : std_logic_vector(NUM_UDP_PRTS-1 downto 0);

  component TxBuffers
    port (
      CPU_AccGnt    : out    std_logic;
      CPU_Tx        : in     ipmux_cpu_in_type;
      Connect       : out    std_logic;
      Connected     : in     std_logic;
      FragID        : in     std_logic_vector(15 downto 0);
      FragOff       : in     std_logic_vector(11 downto 0);
      MoreFrag      : in     std_logic;
      Stream        : in     natural range NUM_UDP_PRTS-1 downto 0;
      TX_LL_DATA    : in     std_logic_vector(15 downto 0);
      TX_LL_EOP     : in     std_logic;
      TX_LL_RDREQ   : out    std_logic;
      TX_LL_VALID   : in     std_logic;
      eth_regs_i    : in     eth_regs_type;
      src_i         : in     t_wrf_source_in;
      src_o         : out    t_wrf_source_out;
      tx_clk        : in     std_logic;
      tx_collision  : in     std_logic;
      tx_overflow   : out    std_logic;
      tx_reset      : in     std_logic;
      tx_retransmit : in     std_logic;
      tx_underrun   : out    std_logic);
  end component TxBuffers;

  component RxBuffers
    port (
      FragID          : out    std_logic_vector(15 downto 0);
      FragOff         : out    std_logic_vector(11 downto 0);
      Full            : in     std_logic_vector(NUM_UDP_PRTS downto 0);
      MoreFrags       : out    std_logic;
      PauseAck        : in     std_logic;
      PauseReq        : out    std_logic;
      PauseVal        : out    std_logic_vector(15 downto 0);
      RXo             : out    dbus_type_array(NUM_UDP_PRTS downto 0);
      UDP_CheckSumErr : out    std_logic;
      WrReq           : out    std_logic_vector(NUM_UDP_PRTS downto 0);
      eth_regs_i      : in     eth_regs_type;
      rx_clk          : in     std_logic;
      rx_reset        : in     std_logic;
      snk_i           : in     t_wrf_sink_in;
      snk_o           : out    t_wrf_sink_out);
  end component RxBuffers;

  component rxfifos
    port (
      Empty : out    std_logic_vector(NUM_UDP_PRTS downto 0);
      Flush : in     std_logic_vector(NUM_UDP_PRTS downto 0);
      Full  : out    std_logic_vector(NUM_UDP_PRTS downto 0);
      RXi   : in     dbus_type_array(NUM_UDP_PRTS downto 0);
      RXo   : out    dbus_type_array(NUM_UDP_PRTS downto 0);
      RdClk : in     std_logic_vector(NUM_UDP_PRTS downto 0);
      RdReq : in     std_logic_vector(NUM_UDP_PRTS downto 0);
      Rst   : in     std_logic;
      WrClk : in     std_logic;
      WrReq : in     std_logic_vector(NUM_UDP_PRTS downto 0));
  end component rxfifos;

  component txfifos
    port (
      Flush        : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
      Full         : out    std_logic_vector(NUM_UDP_PRTS-1 downto 0);
      Packet       : out    std_logic_vector(NUM_UDP_PRTS-1 downto 0);
      Packet_RdReq : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
      PacketsDone  : out    std_logic_vector(NUM_UDP_PRTS-1 downto 0);
      RdClk        : in     std_logic;
      RdReq        : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
      Rst          : in     std_logic;
      TXi          : in     dbus_type_array(NUM_UDP_PRTS-1 downto 0);
      TXo          : out    dbus_type_array(NUM_UDP_PRTS-1 downto 0);
      Valid        : out    std_logic_vector(NUM_UDP_PRTS-1 downto 0);
      WrClk        : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
      WrReq        : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0));
  end component txfifos;

  component TxStreamSel
    port (
      Clk           : in     std_logic;
      ConnectReq    : in     std_logic;
      Connected     : out    std_logic;
      Dout          : out    std_logic_vector(15 downto 0);
      EODout        : out    std_logic;
      Packet        : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
      Packet_RdReq  : out    std_logic_vector(NUM_UDP_PRTS-1 downto 0);
      RdReqOut      : out    std_logic_vector(NUM_UDP_PRTS-1 downto 0);
      RdReqin       : in     std_logic;
      Rst           : in     std_logic;
      Stream        : out    natural range NUM_UDP_PRTS-1 downto 0;
      TXi           : in     dbus_type_array(NUM_UDP_PRTS-1 downto 0);
      TxStreamDebug : out    std_logic_vector(11 downto 0);
      Validin       : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
      Validout      : out    std_logic);
  end component TxStreamSel;

  component ipmux_regs_and_rxtxcpu
    port (
      CPU_AccGnt       : in     std_logic;
      CPU_Tx           : out    ipmux_cpu_in_type;
      Clk              : in     std_logic;
      Flush            : out    std_logic_vector(NUM_UDP_PRTS downto 0);
      PacketsDone      : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
      Rst              : in     std_logic;
      Rx_Empty         : in     std_logic_vector(NUM_UDP_PRTS downto 0);
      TxStreamDebug    : in     std_logic_vector(11 downto 0);
      Tx_Full          : in     std_logic_vector(NUM_UDP_PRTS-1 downto 0);
      cpu_rdreq        : out    std_logic;
      cpu_rx           : in     dbus_type;
      div_ratio        : out    std_logic_vector(31 downto 0);
      eth_regs_o       : out    eth_regs_type;
      numpackets       : out    std_logic_vector(9 downto 0);
      numwords         : out    std_logic_vector(13 downto 0);
      udptstctrl       : out    std_logic_vector(2 downto 0);
      wb_ipmux_reg_i   : in     t_wishbone_slave_in;
      wb_ipmux_reg_o   : out    t_wishbone_slave_out;
      wb_ipmux_rx_tx_i : in     t_wishbone_slave_in;
      wb_ipmux_rx_tx_o : out    t_wishbone_slave_out);
  end component ipmux_regs_and_rxtxcpu;

begin
  --Application Clock domain
  --MAC Clock domain
  --There are NUM_UDP_PRTS + 1 Receive Fifos.
  --The Default Stream (= CPU; index = NUM_UDP_PRTS)
  --is handled in a similar way as the UDP receive streams.
  --Wishbone connection
  --to IPMUX registers
  --Wishbone connection
  --to CPU Rx/Tx Interface
  --Debugging:
  CPU_Gnt <= CPU_Gnt_net;
  Full <= Full_net0;
  u7_RdReq(NUM_UDP_PRTS-1 downto 0) <= RdReq;
  Rx <= Rx_net0(NUM_UDP_PRTS-1 downto 0);
  Empty <= Empty_net(NUM_UDP_PRTS-1 downto 0);
  ConnectReq <= ConnectReq_net;
  Stream <= Stream_net;

  u0: TxBuffers
    port map(
      CPU_AccGnt    => CPU_Gnt_net,
      CPU_Tx        => CPU_Tx,
      Connect       => ConnectReq_net,
      Connected     => u1_Connected,
      FragID        => x"0000",
      FragOff       => x"000",
      MoreFrag      => '0',
      Stream        => Stream_net,
      TX_LL_DATA    => Dout1,
      TX_LL_EOP     => EOPout,
      TX_LL_RDREQ   => TX_LL_RDREQ0,
      TX_LL_VALID   => Validinout,
      eth_regs_i    => u4_eth_regs_o,
      src_i         => src_i,
      src_o         => src_o,
      tx_clk        => tx_clk,
      tx_collision  => '0',
      tx_overflow   => open,
      tx_reset      => tx_reset,
      tx_retransmit => '0',
      tx_underrun   => open);

  u6: RxBuffers
    port map(
      FragID          => open,
      FragOff         => open,
      Full            => Full_net,
      MoreFrags       => open,
      PauseAck        => PauseAck,
      PauseReq        => PauseReq,
      PauseVal        => PauseVal,
      RXo             => RX_net,
      UDP_CheckSumErr => open,
      WrReq           => WrReq_net,
      eth_regs_i      => u4_eth_regs_o,
      rx_clk          => tx_clk,
      rx_reset        => tx_reset,
      snk_i           => snk_i,
      snk_o           => snk_o);

  u7: rxfifos
    port map(
      Empty => Empty_net,
      Flush => u4_Flush,
      Full  => Full_net,
      RXi   => RX_net,
      RXo   => Rx_net0,
      RdClk => RdClk,
      RdReq => u7_RdReq,
      Rst   => Rst,
      WrClk => tx_clk,
      WrReq => WrReq_net);

  u8: txfifos
    port map(
      Flush        => u4_Flush(NUM_UDP_PRTS-1 downto 0),
      Full         => Full_net0,
      Packet       => Packet,
      Packet_RdReq => Packet_RdReq,
      PacketsDone  => PacketsDone,
      RdClk        => tx_clk,
      RdReq        => RdReqOut,
      Rst          => Rst,
      TXi          => Tx,
      TXo          => TXo,
      Valid        => Valid,
      WrClk        => WrClk,
      WrReq        => WrReq);

  u1: TxStreamSel
    port map(
      Clk           => tx_clk,
      ConnectReq    => ConnectReq_net,
      Connected     => u1_Connected,
      Dout          => Dout1,
      EODout        => EOPout,
      Packet        => Packet,
      Packet_RdReq  => Packet_RdReq,
      RdReqOut      => RdReqOut,
      RdReqin       => TX_LL_RDREQ0,
      Rst           => tx_reset,
      Stream        => Stream_net,
      TXi           => TXo,
      TxStreamDebug => TxStreamDebug,
      Validin       => Valid,
      Validout      => Validinout);

  u4: ipmux_regs_and_rxtxcpu
    port map(
      CPU_AccGnt       => CPU_Gnt_net,
      CPU_Tx           => CPU_Tx,
      Clk              => tx_clk,
      Flush            => u4_Flush,
      PacketsDone      => PacketsDone,
      Rst              => Rst,
      Rx_Empty         => Empty_net,
      TxStreamDebug    => TxStreamDebug,
      Tx_Full          => Full_net0,
      cpu_rdreq        => u7_RdReq(NUM_UDP_PRTS),
      cpu_rx           => Rx_net0(NUM_UDP_PRTS),
      div_ratio        => div_ratio,
      eth_regs_o       => u4_eth_regs_o,
      numpackets       => numpackets,
      numwords         => numwords,
      udptstctrl       => udptstctrl,
      wb_ipmux_reg_i   => wb_ipmux_reg_i,
      wb_ipmux_reg_o   => wb_ipmux_reg_o,
      wb_ipmux_rx_tx_i => wb_ipmux_rx_tx_i,
      wb_ipmux_rx_tx_o => wb_ipmux_rx_tx_o);
  CPU_Req <= CPU_Tx.Request;
end architecture rtl ; -- of ipmux

