1 -------------------------------------------------------------------------------     2 -- File       : UdpEngineRx.vhd     3 -- Company    : SLAC National Accelerator Laboratory     4 -- Created    : 2015-08-20     5 -- Last update: 2017-05-22     6 -------------------------------------------------------------------------------     7 -- Description: UDP RX Engine Module     8 -- Note: UDP checksum checked in EthMac core     9 -------------------------------------------------------------------------------    10 -- This file is part of 'SLAC Firmware Standard Library'.    11 -- It is subject to the license terms in the LICENSE.txt file found in the     12 -- top-level directory of this distribution and at:     13 --    https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.     14 -- No part of 'SLAC Firmware Standard Library', including this file,     15 -- may be copied, modified, propagated, or distributed except according to     16 -- the terms contained in the LICENSE.txt file.    17 -------------------------------------------------------------------------------    20 use ieee.std_logic_1164.
all;
    21 use ieee.std_logic_unsigned.
all;
    22 use ieee.std_logic_arith.
all;
    30  --! @ingroup ethernet_UdpEngine    33       -- Simulation Generics    35       -- UDP General Generic    37       -- UDP Server Generics    41       -- UDP Client Generics    46       -- Local Configurations    47       localIp          : 
in  slv(
31 downto 0);  --  big-Endian 
configuration          48       -- Interface to IPV4 Engine      51       -- Interface to UDP Server engine(s)    57       -- Interface to UDP Client engine(s)    61       -- Interface to DHCP Engine    86    type RegType is record    91       byteCnt          : slv(15 downto 0);
   102    constant REG_INIT_C : RegType := (   107       byteCnt          => (others => '0'),   108       tData            => (others => '0'),   118    signal r   : RegType := REG_INIT_C;
   119    signal rin : RegType;
   128    -- attribute dont_touch      : string;   129    -- attribute dont_touch of r : signal is "TRUE";   145    comb : 
process (clientSlave, dhcpSlave, 
localIp, r, 
rst, rxMaster,
   147       variable v : RegType;
   150       -- Latch the current value   156       if serverSlave.tReady = '1' then   157          v.serverMaster.tValid := '0';
   158          v.serverMaster.tLast  := '0';
   159          v.serverMaster.tUser  := (others => '0');
   160          v.serverMaster.tKeep  := (others => '1');
   162       if clientSlave.tReady = '1' then   163          v.clientMaster.tValid := '0';
   164          v.clientMaster.tLast  := '0';
   165          v.clientMaster.tUser  := (others => '0');
   166          v.clientMaster.tKeep  := (others => '1');
   168       if (dhcpSlave.tReady) = '1' then   169          v.dhcpMaster.tValid := '0';
   170          v.dhcpMaster.tLast  := '0';
   171          v.dhcpMaster.tUser  := (others => '0');
   172          v.dhcpMaster.tKeep  := (others => '1');
   177          ----------------------------------------------------------------------   180             if (rxMaster.tValid = '1') then   183                -- Check for SOF with no EOF   185                   -- Latch the first header   188                   v.state := CHECK_PORT_S;
   191          ----------------------------------------------------------------------   194             if (rxMaster.tValid = '1') then   197                -- Set default route type   199                ------------------------------------------------   200                -- Notes: Non-Standard IPv4 Pseudo Header Format   201                ------------------------------------------------   202                -- tData[0][47:0]   = Remote MAC Address   203                -- tData[0][63:48]  = zeros   204                -- tData[0][95:64]  = Remote IP Address    205                -- tData[0][127:96] = Local IP address   206                -- tData[1][7:0]    = zeros   207                -- tData[1][15:8]   = Protocol Type = UDP   208                -- tData[1][31:16]  = IPv4 Pseudo header length   209                -- tData[1][47:32]  = Remote Port   210                -- tData[1][63:48]  = Local Port   211                -- tData[1][79:64]  = UDP Length   212                -- tData[1][95:80]  = UDP Checksum    213                -- tData[1][127:96] = UDP Datagram    214                ------------------------------------------------                  217                   -- Check if server engine(s) is enabled   220                         -- Check if port is defined   221                         if (v.route = NULL_S) and (rxMaster.tData(63 downto 48) = SERVER_PORTS_C(i)) then   223                            v.serverMaster.tDest  := toSlv(i, 8);
   230                   -- Check if clients engine(s) is enabled   233                         -- Check if port is defined   234                         if (v.route = NULL_S) and (rxMaster.tData(63 downto 48) = CLIENT_PORTS_C(i)) then   236                            v.clientMaster.tDest := toSlv(i, 8);
   242                -- Check if DHCP engine is enabled and DHCP packet   246                -- Get the UDP length = UDP HDR + UDP data   247                v.byteCnt(15 downto 8) := rxMaster.tData(71 downto 64);
   248                v.byteCnt(7 downto 0)  := rxMaster.tData(79 downto 72);
   249                -- Remove the 8 byte UDP header   250                v.byteCnt              := v.byteCnt - 8;
   251                -- Track the leftovers   252                v.tData(31 downto 0)   := rxMaster.tData(127 downto 96);
   255                -- Check if localhost   261                -- Check for non-NULL route type   262                if (v.route /= NULL_S) then   263                   -- Check for leftovers   264                   if (rxMaster.tLast = '1') or (v.byteCnt <= 4) then   276          ----------------------------------------------------------------------   278             -- Check the route type   280                ----------------------------------------------------------------------   282                   -- Check if ready to move data   283                   if (rxMaster.tValid = '1') and (v.serverMaster.tValid = '0') then   287                      v.serverMaster.tValid                   := '1';
   288                      v.serverMaster.tData(31 downto 0)       := r.tData(31 downto 0);
   289                      v.serverMaster.tData(127 downto 32)     := rxMaster.tData(95 downto 0);
   291                      -- Track the leftovers                                    292                      v.tData(31 downto 0)                    := rxMaster.tData(127 downto 96);
   295                      -- Decrement the counter   296                      v.byteCnt                               := r.byteCnt - 16;
   297                      -- Check for tLast or the byte counter   298                      if (rxMaster.tLast = '1') or (r.byteCnt <= 16) or (v.byteCnt <= 4) then   299                         -- Check if not localhost   300                         if (r.localHost = '0') then   301                            -- Check for leftovers   302                            if (v.byteCnt <= 4) and (r.byteCnt /= 16) then   306                               -- Terminate the packet   307                               v.serverMaster.tKeep := genTKeep(conv_integer(r.byteCnt));
   308                               v.serverMaster.tLast := '1';
   313                            -- Else localhost communication   314                            if (rxMaster.tKeep(15 downto 12) /= 0) then   315                               v.byteCnt := (x"00" & "000" & onesCount(x"000" & rxMaster.tKeep(15 downto 12)));
   319                               v.serverMaster.tKeep := rxMaster.tKeep(11 downto 0) & x"F";
   320                               v.serverMaster.tLast := '1';
   327                ----------------------------------------------------------------------   329                   -- Check if ready to move data   330                   if (rxMaster.tValid = '1') and (v.clientMaster.tValid = '0') then   334                      v.clientMaster.tValid                   := '1';
   335                      v.clientMaster.tData(31 downto 0)       := r.tData(31 downto 0);
   336                      v.clientMaster.tData(127 downto 32)     := rxMaster.tData(95 downto 0);
   338                      -- Track the leftovers                                    339                      v.tData(31 downto 0)                    := rxMaster.tData(127 downto 96);
   342                      -- Decrement the counter   343                      v.byteCnt                               := r.byteCnt - 16;
   344                      -- Check for tLast or the byte counter   345                      if (rxMaster.tLast = '1') or (r.byteCnt <= 16) or (v.byteCnt <= 4) then   346                         -- Check if not localhost   347                         if (r.localHost = '0') then   348                            -- Check for leftovers   349                            if (v.byteCnt <= 4) and (r.byteCnt /= 16) then   353                               -- Terminate the packet   354                               v.clientMaster.tKeep := genTKeep(conv_integer(r.byteCnt));
   355                               v.clientMaster.tLast := '1';
   360                            -- Else localhost communication   361                            if (rxMaster.tKeep(15 downto 12) /= 0) then   362                               v.byteCnt := (x"00" & "000" & onesCount(x"000" & rxMaster.tKeep(15 downto 12)));
   366                               v.clientMaster.tKeep := rxMaster.tKeep(11 downto 0) & x"F";
   367                               v.clientMaster.tLast := '1';
   374                ----------------------------------------------------------------------   376                   -- Check if ready to move data   377                   if (rxMaster.tValid = '1') and (v.dhcpMaster.tValid = '0') then   381                      v.dhcpMaster.tValid                     := '1';
   382                      v.dhcpMaster.tData(31 downto 0)         := r.tData(31 downto 0);
   383                      v.dhcpMaster.tData(127 downto 32)       := rxMaster.tData(95 downto 0);
   385                      -- Track the leftovers                                    386                      v.tData(31 downto 0)                    := rxMaster.tData(127 downto 96);
   389                      -- Decrement the counter   390                      v.byteCnt                               := r.byteCnt - 16;
   391                      -- Check for tLast or the byte counter   392                      if (rxMaster.tLast = '1') or (r.byteCnt <= 16) or (v.byteCnt <= 4) then   393                         -- Check for leftovers   394                         if (v.byteCnt <= 4) and (r.byteCnt /= 16) then   398                            -- Terminate the packet   399                            v.dhcpMaster.tKeep := genTKeep(conv_integer(r.byteCnt));
   400                            v.dhcpMaster.tLast := '1';
   406                ----------------------------------------------------------------------   410             ----------------------------------------------------------------------   412          ----------------------------------------------------------------------   414             -- Check the route type   416                ----------------------------------------------------------------------   418                   -- Check if ready to move data   419                   if (v.serverMaster.tValid = '0') then   421                      v.serverMaster.tValid := '1';
   423                      v.serverMaster.tKeep  := genTKeep(conv_integer(r.byteCnt));
   424                      v.serverMaster.tLast  := '1';
   429                ----------------------------------------------------------------------   431                   -- Check if ready to move data   432                   if (v.clientMaster.tValid = '0') then   434                      v.clientMaster.tValid := '1';
   436                      v.clientMaster.tKeep  := genTKeep(conv_integer(r.byteCnt));
   437                      v.clientMaster.tLast  := '1';
   442                ----------------------------------------------------------------------   444                   -- Check if ready to move data   445                   if (v.dhcpMaster.tValid = '0') then   447                      v.dhcpMaster.tValid := '1';
   449                      v.dhcpMaster.tKeep  := genTKeep(conv_integer(r.byteCnt));
   450                      v.dhcpMaster.tLast  := '1';
   455                ----------------------------------------------------------------------   459             ----------------------------------------------------------------------   461       ----------------------------------------------------------------------   469       -- Register the variable for next clock cycle   477       rxSlave          <= v.rxSlave;
   481    seq : 
process (
clk) 
is   483       if rising_edge(clk) then   484          r <= rin after TPD_G;
 
out serverRemoteMacSlv48Array(   SERVER_SIZE_G- 1 downto  0)  
 
PIPE_STAGES_Ginteger   range  0 to  16:= 0
 
PIPE_STAGES_Gnatural   range  0 to  16:= 0
 
out serverRemoteIpSlv32Array(   SERVER_SIZE_G- 1 downto  0)  
 
array(natural range <> ) of AxiStreamSlaveType   AxiStreamSlaveArray
 
SERVER_EN_Gboolean  :=   true
 
array(natural range <> ) of slv( 31 downto  0)   Slv32Array
 
out obServerMastersAxiStreamMasterArray(   SERVER_SIZE_G- 1 downto  0)  
 
slv( 15 downto  0)  := x"4300" DHCP_SPORT
 
CLIENT_PORTS_GPositiveArray  :=( 0=> 8193)
 
CLIENT_EN_Gboolean  :=   true
 
AxiStreamMasterType  :=(tValid  => '0',tData  =>( others => '0'),tStrb  =>( others => '1'),tKeep  =>( others => '1'),tLast  => '0',tDest  =>( others => '0'),tId  =>( others => '0'),tUser  =>( others => '0')) AXI_STREAM_MASTER_INIT_C
 
array(natural range <> ) of slv( 47 downto  0)   Slv48Array
 
in ibUdpMasterAxiStreamMasterType  
 
out mAxisMastersAxiStreamMasterArray(   NUM_MASTERS_G- 1 downto  0)  
 
out sAxisSlaveAxiStreamSlaveType  
 
in localIpslv( 31 downto  0)  
 
in mAxisSlaveAxiStreamSlaveType  
 
slv( 15 downto  0)  := x"4400" DHCP_CPORT
 
out sAxisSlaveAxiStreamSlaveType  
 
SERVER_SIZE_Gpositive  := 1
 
out clientRemoteDetslv(   CLIENT_SIZE_G- 1 downto  0)  
 
array(natural range <> ) of positive   PositiveArray
 
in sAxisMasterAxiStreamMasterType  
 
AxiStreamSlaveType  :=(tReady  => '0') AXI_STREAM_SLAVE_INIT_C
 
in sAxisMasterAxiStreamMasterType  
 
array(natural range <> ) of AxiStreamMasterType   AxiStreamMasterArray
 
out mAxisMasterAxiStreamMasterType  
 
CLIENT_SIZE_Gpositive  := 1
 
array(natural range <> ) of slv( 15 downto  0)   Slv16Array
 
out ibDhcpMasterAxiStreamMasterType  
 
in mAxisSlavesAxiStreamSlaveArray(   NUM_MASTERS_G- 1 downto  0)  
 
in obClientSlavesAxiStreamSlaveArray(   CLIENT_SIZE_G- 1 downto  0)  
 
SERVER_PORTS_GPositiveArray  :=( 0=> 8192)
 
in obServerSlavesAxiStreamSlaveArray(   SERVER_SIZE_G- 1 downto  0)  
 
NUM_MASTERS_Ginteger   range  1 to  32:= 12
 
in ibDhcpSlaveAxiStreamSlaveType  
 
AxiStreamConfigType  :=(TSTRB_EN_C  =>   false,TDATA_BYTES_C  => 16,TDEST_BITS_C  => 8,TID_BITS_C  => 0,TKEEP_MODE_C  =>   TKEEP_COMP_C,TUSER_BITS_C  => 4,TUSER_MODE_C  =>   TUSER_FIRST_LAST_C) EMAC_AXIS_CONFIG_C
 
out serverRemotePortSlv16Array(   SERVER_SIZE_G- 1 downto  0)  
 
out ibUdpSlaveAxiStreamSlaveType  
 
out obClientMastersAxiStreamMasterArray(   CLIENT_SIZE_G- 1 downto  0)