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