1 -------------------------------------------------------------------------------     2 -- File       : IpV4EngineRx.vhd     3 -- Company    : SLAC National Accelerator Laboratory     4 -- Created    : 2015-08-12     5 -- Last update: 2016-09-16     6 -------------------------------------------------------------------------------     7 -- Description: IPv4 RX Engine Module     8 -- Note: IPv4 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_IpV4Engine    39       -- Interface to Ethernet Frame MUX/DEMUX     42       localhostMaster   : 
in  AxiStreamMasterType;
    43       localhostSlave    : 
out AxiStreamSlaveType;
    44       -- Interface to Protocol Engine      62    type RegType is record    65       len      : slv(15 downto 0);
    66       protocol : slv(7 downto 0);
    73    constant REG_INIT_C : RegType := (    76       len      => (others => '0'),    77       protocol => (others => '0'),    78       tKeep    => (others => '0'),    79       tData    => (others => '0'),    84    signal r   : RegType := REG_INIT_C;
    91    -- attribute dont_touch              : string;    92    -- attribute dont_touch of r         : signal is "TRUE";   114    comb : 
process (r, 
rst, rxMaster, txSlave) 
is   115       variable v : RegType;
   118       -- Latch the current value   123       if (txSlave.tReady = '1') then   125          v.txMaster.tLast  := '0';
   126          v.txMaster.tUser  := (others => '0');
   127          v.txMaster.tKeep  := (others => '1');
   132          ----------------------------------------------------------------------   135             if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then   138                -- Check for SOF with no EOF   140                   -- Latch the remote MAC address   141                   v.txMaster.tData(47 downto 0)  := rxMaster.tData(95 downto 48);
   143                   v.txMaster.tData(63 downto 48) := (others => '0');
   145                   v.state                        := IPV4_HDR0_S;
   148          ----------------------------------------------------------------------   151             if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then   154                -- Check for non-VLAN                  156                   -- Calculate the IPV4 Pseudo Header length (in little Endian)   157                   v.len(15 downto 8)              := rxMaster.tData(7 downto 0);
  -- IPV4_Length(15 downto 8)   158                   v.len(7 downto 0)               := rxMaster.tData(15 downto 8);
  -- IPV4_Length(7 downto 0)   159                   v.len                           := v.len - 20;
  -- IPV4 Pseudo Header's length = protocol length - 20 Bytes                  160                   -- Latch the protocol value   161                   v.protocol                      := rxMaster.tData(63 downto 56);
   162                   -- Source IP Address(31 downto 0)   163                   v.txMaster.tData(95 downto 64)  := rxMaster.tData(111 downto 80);
   164                   -- Destination IP Address(31 downto 16)   165                   v.txMaster.tData(111 downto 96) := rxMaster.tData(127 downto 112);
   167                   -- Calculate the IPV4 Pseudo Header length (in little Endian)   168                   v.len(15 downto 8)             := rxMaster.tData(39 downto 32);
  -- IPV4_Length(15 downto 8)   169                   v.len(7 downto 0)              := rxMaster.tData(47 downto 40);
  -- IPV4_Length(7 downto 0)   170                   v.len                          := v.len - 20;
  -- IPV4 Pseudo Header's length = protocol length - 20 Bytes                  171                   -- Latch the protocol value   172                   v.protocol                     := rxMaster.tData(95 downto 88);
   173                   -- Source IP Address(31 downto 16)   174                   v.txMaster.tData(79 downto 64) := rxMaster.tData(127 downto 112);
   176                -- Next state if protocol not detected during the "for loop"   178                -- Loop through the protocol buses   181                      -- Latch the protocol bus pointer   182                      v.txMaster.tDest := toSlv(i, 8);
   183                      -- Next state if protocol not detected   184                      v.state          := IPV4_HDR1_S;
   188          ----------------------------------------------------------------------   191             if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then   196                -- Check for non-VLAN                        198                   -- Destination IP Address(15 downto 0)   199                   v.txMaster.tData(127 downto 112) := rxMaster.tData(15 downto 0);
   200                   -- Track the leftovers   201                   v.tData(7 downto 0)              := x"00";
   202                   v.tData(15 downto 8)             := r.protocol;
   203                   v.tData(23 downto 16)            := r.len(15 downto 8);
   204                   v.tData(31 downto 24)            := r.len(7 downto 0);
   205                   v.tData(127 downto 32)           := rxMaster.tData(111 downto 16);
   206                   v.tKeep(3 downto 0)              := "1111";
   207                   v.tKeep(15 downto 4)             := rxMaster.tKeep(13 downto 2);
   210                   -- Check for no remainder    211                   if (rxMaster.tKeep(15 downto 14) = 0) then   218                      v.state := IPV4_HDR2_S;
   223                   -- Source IP Address(15 downto 0)   224                   v.txMaster.tData(95 downto 80)  := rxMaster.tData(15 downto 0);
   225                   -- Destination IP Address(31 downto 0)   226                   v.txMaster.tData(127 downto 96) := rxMaster.tData(47 downto 16);
   227                   -- Track the leftovers   228                   v.tData(7 downto 0)             := x"00";
   229                   v.tData(15 downto 8)            := r.protocol;
   230                   v.tData(23 downto 16)           := r.len(15 downto 8);
   231                   v.tData(31 downto 24)           := r.len(7 downto 0);
   232                   v.tData(111 downto 32)          := rxMaster.tData(127 downto 48);
   233                   v.tKeep(3 downto 0)             := "1111";
   234                   v.tKeep(13 downto 4)            := rxMaster.tKeep(15 downto 6);
   235                   v.tKeep(15 downto 14)           := "00";
   239                   if (rxMaster.tLast = '1') then   240                      -- Check the leftovers   241                      if (v.tKeep /= 0) then   246                         v.txMaster.tLast := '1';
   257          ----------------------------------------------------------------------   260             if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then   267                -- Track the leftovers   268                v.tData(15 downto 0) := rxMaster.tData(127 downto 112);
   269                v.tKeep(1 downto 0)  := rxMaster.tKeep(15 downto 14);
   270                v.tKeep(15 downto 2) := (others => '0');
   274                if (rxMaster.tLast = '1') then   275                   -- Check the leftovers   276                   if (v.tKeep /= 0) then   281                      v.txMaster.tLast := '1';
   291          ----------------------------------------------------------------------   294             if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then   299                -- Check for non-VLAN    302                   v.txMaster.tData(15 downto 0)   := r.tData(15 downto 0);
   303                   v.txMaster.tData(127 downto 16) := rxMaster.tData(111 downto 0);
   304                   v.txMaster.tKeep(1 downto 0)    := r.tKeep(1 downto 0);
   305                   v.txMaster.tKeep(15 downto 2)   := rxMaster.tKeep(13 downto 0);
   306                   -- Track the leftovers                     307                   v.tData(15 downto 0)            := rxMaster.tData(127 downto 112);
   308                   v.tKeep(1 downto 0)             := rxMaster.tKeep(15 downto 14);
   313                   v.txMaster.tData(111 downto 0)   := r.tData(111 downto 0);
   314                   v.txMaster.tData(127 downto 112) := rxMaster.tData(15 downto 0);
   315                   v.txMaster.tKeep(13 downto 0)    := r.tKeep(13 downto 0);
   316                   v.txMaster.tKeep(15 downto 14)   := rxMaster.tKeep(1 downto 0);
   317                   -- Track the leftovers                     318                   v.tData(111 downto 0)            := rxMaster.tData(127 downto 16);
   319                   v.tKeep(13 downto 0)             := rxMaster.tKeep(15 downto 2);
   324                if (v.tLast = '1') then   325                   -- Check the leftover tKeep is not empty   326                   if (v.tKeep /= 0) then   331                      v.txMaster.tLast := '1';
   338          ----------------------------------------------------------------------   341             if (v.txMaster.tValid = '0') then   346                v.txMaster.tLast  := '1';
   351       ----------------------------------------------------------------------   359       -- Register the variable for next clock cycle   363       rxSlave <= v.rxSlave;
   367    seq : 
process (
clk) 
is   369       if rising_edge(clk) then   370          r <= rin after TPD_G;
 
PIPE_STAGES_Ginteger   range  0 to  16:= 0
 
array(natural range <> ) of AxiStreamSlaveType   AxiStreamSlaveArray
 
out ibIpv4SlaveAxiStreamSlaveType  
 
in ibIpv4MasterAxiStreamMasterType  
 
out ibProtocolMastersAxiStreamMasterArray(   PROTOCOL_SIZE_G- 1 downto  0)  
 
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
 
out mAxisMastersAxiStreamMasterArray(   NUM_MASTERS_G- 1 downto  0)  
 
out sAxisSlaveAxiStreamSlaveType  
 
SIM_ERROR_HALT_Gboolean  :=   false
 
out mAxisMasterAxiStreamMasterType  
 
NUM_SLAVES_Ginteger   range  1 to  32:= 4
 
AxiStreamSlaveType  :=(tReady  => '0') AXI_STREAM_SLAVE_INIT_C
 
in sAxisMasterAxiStreamMasterType  
 
array(natural range <> ) of AxiStreamMasterType   AxiStreamMasterArray
 
out localhostSlaveAxiStreamSlaveType  
 
in mAxisSlavesAxiStreamSlaveArray(   NUM_MASTERS_G- 1 downto  0)  
 
slv( 7 downto  0)  := x"11" UDP_C
 
PROTOCOL_SIZE_Gpositive  := 1
 
array(natural range <> ) of slv( 7 downto  0)   Slv8Array
 
in localhostMasterAxiStreamMasterType  
 
in mAxisSlaveAxiStreamSlaveType  
 
NUM_MASTERS_Ginteger   range  1 to  32:= 12
 
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
 
in ibProtocolSlavesAxiStreamSlaveArray(   PROTOCOL_SIZE_G- 1 downto  0)  
 
PROTOCOL_GSlv8Array  :=( 0=>   UDP_C)
 
PIPE_STAGES_Ginteger   range  0 to  16:= 0