1 -------------------------------------------------------------------------------     2 -- File       : IpV4EngineTx.vhd     3 -- Company    : SLAC National Accelerator Laboratory     4 -- Created    : 2015-08-12     5 -- Last update: 2016-09-16     6 -------------------------------------------------------------------------------     7 -- Description: IPv4 TX 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       -- Local Configurations    40       localMac          : 
in  slv(
47 downto 0);  --  big-Endian 
configuration     41       -- Interface to Ethernet Frame MUX/DEMUX     44       localhostMaster   : 
out AxiStreamMasterType;
    45       localhostSlave    : 
in  AxiStreamSlaveType;
    46       -- Interface to Protocol Engine      64    type RegType is record    69       id       : slv(15 downto 0);
    74    constant REG_INIT_C : RegType := (    76       tKeep    => (others => '0'),    77       tData    => (others => '0'),    78       tDest    => (others => '0'),    79       id       => (others => '0'),    84    signal r   : RegType := REG_INIT_C;
    96    -- attribute dont_touch              : string;    97    -- attribute dont_touch of r         : signal is "TRUE";      117    comb : 
process (
localMac, r, 
rst, rxMaster, txSlave) 
is   118       variable v : RegType;
   121       -- Latch the current value   126       if txSlave.tReady = '1' then   128          v.txMaster.tLast  := '0';
   129          v.txMaster.tUser  := (others => '0');
   130          v.txMaster.tKeep  := (others => '1');
   135          ----------------------------------------------------------------------   137             -- Check if ready to move data   138             if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then   143                -- Check for SOF with no EOF   145                   -- Send the RAW Ethernet header   149                   -- Setup the tDest routing   152                      v.txMaster.tDest := x"01";
   155                      v.txMaster.tDest := x"00";
   157                   -- Set the DST MAC and SRC MAC   158                   v.txMaster.tData(47 downto 0)  := rxMaster.tData(47 downto 0);
   160                   -- Check for non-VLAN   163                      v.txMaster.tData(119 downto 112) := x"45";
  -- IPVersion = 4,Header length = 5   164                      v.txMaster.tData(127 downto 120) := x"00";
  --- DSCP and ECN   166                      -- Set the EtherType = VLAN Type   168                      -- VID = 0x0 here because it gets overwritten in the MAC                  169                      v.txMaster.tData(127 downto 112) := (others => '0');
   171                   -- Track the leftovers   172                   v.tData(63 downto 0) := rxMaster.tData(127 downto 64);
   174                   v.state              := IPV4_HDR0_S;
   177          ----------------------------------------------------------------------   180             if (v.txMaster.tValid = '0') then   181                -- Send the IPV4 header   183                -- Check for non-VLAN   185                   v.txMaster.tData(7 downto 0)     := x"00";
  -- IPV4_Length(15 downto 8) Note: Calculated in EthMac core    186                   v.txMaster.tData(15 downto 8)    := x"00";
  -- IPV4_Length(7 downto 0)  Note: Calculated in EthMac core    187                   v.txMaster.tData(23 downto 16)   := r.id(15 downto 8);
     -- IPV4_ID(15 downto 8)   188                   v.txMaster.tData(31 downto 24)   := r.id(7 downto 0);
      -- IPV4_ID(7 downto 0)   189                   v.txMaster.tData(39 downto 32)   := x"40";
  -- Flags(2 downto 0) =  Don't Fragment (DF) and Fragment_Offsets(12 downto 8) = 0x0   190                   v.txMaster.tData(47 downto 40)   := x"00";
  -- Fragment_Offsets(7 downto 0) = 0x0   191                   v.txMaster.tData(55 downto 48)   := TTL_G;
  -- Time-To-Live (number of hops before packet is discarded)   193                   v.txMaster.tData(71 downto 64)   := x"00";
  -- IPV4_Checksum(15 downto 8)  Note: Filled in next state   194                   v.txMaster.tData(79 downto 72)   := x"00";
  -- IPV4_Checksum(7 downto 0)   Note: Filled in next state   195                   v.txMaster.tData(111 downto 80)  := r.tData(31 downto 0);
  -- Source IP Address(31 downto 0)   196                   v.txMaster.tData(127 downto 112) := r.tData(47 downto 32);
  -- Destination IP Address(31 downto 16)   199                   v.txMaster.tData(23 downto 16)   := x"45";
  -- IPVersion = 4,Header length = 5   200                   v.txMaster.tData(31 downto 24)   := x"00";
  -- DSCP and ECN   201                   v.txMaster.tData(39 downto 32)   := x"00";
  -- IPV4_Length(15 downto 8) Note: Calculated in EthMac core    202                   v.txMaster.tData(47 downto 40)   := x"00";
  -- IPV4_Length(7 downto 0)  Note: Calculated in EthMac core    203                   v.txMaster.tData(55 downto 48)   := r.id(15 downto 8);
     -- IPV4_ID(15 downto 8)   204                   v.txMaster.tData(63 downto 56)   := r.id(7 downto 0);
      -- IPV4_ID(7 downto 0)   205                   v.txMaster.tData(71 downto 64)   := x"40";
  -- Flags(2 downto 0) =  Don't Fragment (DF) and Fragment_Offsets(12 downto 8) = 0x0   206                   v.txMaster.tData(79 downto 72)   := x"00";
  -- Fragment_Offsets(7 downto 0) = 0x0   207                   v.txMaster.tData(87 downto 80)   := TTL_G;
  -- Time-To-Live (number of hops before packet is discarded)   209                   v.txMaster.tData(103 downto 96)  := x"00";
  -- IPV4_Checksum(15 downto 8)  Note: Calculated in EthMac core    210                   v.txMaster.tData(111 downto 104) := x"00";
  -- IPV4_Checksum(7 downto 0)   Note: Calculated in EthMac core    211                   v.txMaster.tData(127 downto 112) := r.tData(15 downto 0);
  -- Source IP Address(31 downto 16)   213                -- Increment the counter   216                v.state := IPV4_HDR1_S;
   218          ----------------------------------------------------------------------   220             -- Check if ready to move data   221             if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then   224                -- Check for non-VLAN   226                   -- Update the tData bus   227                   v.txMaster.tData(15 downto 0)   := r.tData(63 downto 48);
  -- Destination IP Address(15 downto 0)   228                   v.txMaster.tData(111 downto 16) := rxMaster.tData(127 downto 32);
   229                   -- Update the tKeep bus   230                   v.txMaster.tKeep(1 downto 0)    := (others => '1');
   231                   v.txMaster.tKeep(13 downto 2)   := rxMaster.tKeep(15 downto 4);
   232                   v.txMaster.tKeep(15 downto 14)  := (others => '0');
   236                   if (rxMaster.tLast = '1') then   239                      -- Set the tLast flag   240                      v.txMaster.tLast  := '1';
   247                      v.state := IPV4_HDR2_S;
   252                   -- Update the tData bus   253                   v.txMaster.tData(15 downto 0)   := r.tData(31 downto 16);
  -- Source IP Address(15 downto 0)   254                   v.txMaster.tData(47 downto 16)  := r.tData(63 downto 32);
  -- Destination IP Address(31 downto 0)   255                   v.txMaster.tData(127 downto 48) := rxMaster.tData(111 downto 32);
   256                   -- Update the tKeep bus   257                   v.txMaster.tKeep(5 downto 0)    := (others => '1');
   258                   v.txMaster.tKeep(15 downto 6)   := rxMaster.tKeep(13 downto 4);
   259                   -- Track the leftovers   260                   v.tData(15 downto 0)            := rxMaster.tData(127 downto 112);
   261                   v.tKeep(1 downto 0)             := rxMaster.tKeep(15 downto 14);
   265                   if (rxMaster.tLast = '1') then   266                      -- Check the leftover tKeep is not empty   267                      if (v.tKeep /= 0) then   272                         v.txMaster.tLast := '1';
   283          ----------------------------------------------------------------------   286             if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then   291                v.txMaster.tData(127 downto 112) := rxMaster.tData(15 downto 0);
   292                v.txMaster.tKeep(13 downto 0)    := (others => '1');
   293                v.txMaster.tKeep(15 downto 14)   := rxMaster.tKeep(1 downto 0);
   294                -- Track the leftovers   295                v.tData(111 downto 0)            := rxMaster.tData(127 downto 16);
   296                v.tKeep(13 downto 0)             := rxMaster.tKeep(15 downto 2);
   300                if (rxMaster.tLast = '1') then   301                   -- Check the leftover tKeep is not empty   302                   if (v.tKeep /= 0) then   307                      v.txMaster.tLast := '1';
   317          ----------------------------------------------------------------------   320             if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then   325                -- Check for non-VLAN   328                   v.txMaster.tData(111 downto 0)   := r.tData(111 downto 0);
   329                   v.txMaster.tData(127 downto 112) := rxMaster.tData(15 downto 0);
   330                   v.txMaster.tKeep(13 downto 0)    := r.tKeep(13 downto 0);
   331                   v.txMaster.tKeep(15 downto 14)   := rxMaster.tKeep(1 downto 0);
   332                   -- Track the leftovers   333                   v.tData(111 downto 0)            := rxMaster.tData(127 downto 16);
   334                   v.tKeep(13 downto 0)             := rxMaster.tKeep(15 downto 2);
   338                   if (rxMaster.tLast = '1') then   339                      -- Check the leftover tKeep is not empty   340                      if (v.tKeep /= 0) then   345                         v.txMaster.tLast := '1';
   353                   v.txMaster.tData(15 downto 0)   := r.tData(15 downto 0);
   354                   v.txMaster.tData(127 downto 16) := rxMaster.tData(111 downto 0);
   355                   v.txMaster.tKeep(1 downto 0)    := r.tKeep(1 downto 0);
   356                   v.txMaster.tKeep(15 downto 2)   := rxMaster.tKeep(13 downto 0);
   357                   -- Track the leftovers                     358                   v.tData(15 downto 0)            := rxMaster.tData(127 downto 112);
   359                   v.tKeep(1 downto 0)             := rxMaster.tKeep(15 downto 14);
   363                   if (rxMaster.tLast = '1') then   364                      -- Check the leftover tKeep is not empty   365                      if (v.tKeep /= 0) then   370                         v.txMaster.tLast := '1';
   378          ----------------------------------------------------------------------   381             if (v.txMaster.tValid = '0') then   386                v.txMaster.tLast  := '1';
   391       ----------------------------------------------------------------------   399       -- Register the variable for next clock cycle   403       rxSlave  <= v.rxSlave;
   404       txMaster <= r.txMaster;
   408    seq : 
process (
clk) 
is   410       if rising_edge(clk) then   411          r <= rin after TPD_G;
 
PIPE_STAGES_Ginteger   range  0 to  16:= 0
 
PIPE_STAGES_Gnatural   range  0 to  16:= 0
 
array(natural range <> ) of AxiStreamSlaveType   AxiStreamSlaveArray
 
slv( 15 downto  0)  := x"0008" IPV4_TYPE_C
 
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 sAxisSlaveAxiStreamSlaveType  
 
in obProtocolMastersAxiStreamMasterArray(   PROTOCOL_SIZE_G- 1 downto  0)  
 
in mAxisSlaveAxiStreamSlaveType  
 
in localMacslv( 47 downto  0)  
 
out sAxisSlaveAxiStreamSlaveType  
 
out localhostMasterAxiStreamMasterType  
 
in localhostSlaveAxiStreamSlaveType  
 
out mAxisMasterAxiStreamMasterType  
 
NUM_SLAVES_Ginteger   range  1 to  32:= 4
 
in sAxisMasterAxiStreamMasterType  
 
AxiStreamSlaveType  :=(tReady  => '0') AXI_STREAM_SLAVE_INIT_C
 
in sAxisMastersAxiStreamMasterArray(   NUM_SLAVES_G- 1 downto  0)  
 
in sAxisMasterAxiStreamMasterType  
 
array(natural range <> ) of AxiStreamMasterType   AxiStreamMasterArray
 
out sAxisSlavesAxiStreamSlaveArray(   NUM_SLAVES_G- 1 downto  0)  
 
out mAxisMasterAxiStreamMasterType  
 
slv( 15 downto  0)  := x"0081" VLAN_TYPE_C
 
out obIpv4MasterAxiStreamMasterType  
 
TTL_Gslv( 7 downto  0)  := x"20"
 
out obProtocolSlavesAxiStreamSlaveArray(   PROTOCOL_SIZE_G- 1 downto  0)  
 
slv( 7 downto  0)  := x"11" UDP_C
 
PROTOCOL_GSlv8Array  :=( 0=>   UDP_C)
 
array(natural range <> ) of slv( 7 downto  0)   Slv8Array
 
PROTOCOL_SIZE_Gpositive  := 1
 
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 obIpv4SlaveAxiStreamSlaveType  
 
PIPE_STAGES_Ginteger   range  0 to  16:= 0