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)