diff --git a/ethernet/UdpEngine/rtl/ArpIpTable.vhd b/ethernet/UdpEngine/rtl/ArpIpTable.vhd new file mode 100644 index 0000000000..d4e72f9dc3 --- /dev/null +++ b/ethernet/UdpEngine/rtl/ArpIpTable.vhd @@ -0,0 +1,371 @@ +------------------------------------------------------------------------------- +-- Company : SLAC National Accelerator Laboratory +------------------------------------------------------------------------------- +-- Description: Top-Level UDP/DHCP Module +------------------------------------------------------------------------------- +-- This file is part of 'SLAC Firmware Standard Library'. +-- It is subject to the license terms in the LICENSE.txt file found in the +-- top-level directory of this distribution and at: +-- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +-- No part of 'SLAC Firmware Standard Library', including this file, +-- may be copied, modified, propagated, or distributed except according to +-- the terms contained in the LICENSE.txt file. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.std_logic_arith.all; + + +library surf; +use surf.StdRtlPkg.all; + +entity ArpIpTable is + + generic ( + TPD_G : time := 1 ns; + CLK_FREQ_G : real := 156.25E+06; + COMM_TIMEOUT_G : positive := 30; + ENTRIES_G : positive range 1 to 255 := 4); + port ( + -- Clock and Reset + clk : in sl; + rst : in sl; + -- Read LUT + ipAddrIn : in slv(31 downto 0); + pos : in slv(7 downto 0); + found : out sl; + macAddr : out slv(47 downto 0); + ipAddrOut : out slv(31 downto 0); + -- Refresh LUT + clientRemoteDetIp : in slv(31 downto 0); + clientRemoteDetValid : in sl; + -- Write LUT + ipWrEn : in sl; + IpWrAddr : in slv(31 downto 0); + macWrEn : in sl; + macWrAddr : in slv(47 downto 0)); +end entity ArpIpTable; + +architecture rtl of ArpIpTable is + + -- Write stuff + type wRegType is record + ipLutTable : Slv32Array(ENTRIES_G-1 downto 0); + macLutTable : Slv48Array(ENTRIES_G-1 downto 0); + fifoRdEn : sl; + fifoValid : sl; + overwrite : boolean; + writingNewIp : boolean; + entryCount : slv(7 downto 0); + end record wRegType; + + constant W_REG_INIT_C : wRegType := ( + ipLutTable => (others => (others => '0')), + macLutTable => (others => (others => '0')), + fifoRdEn => '0', + fifoValid => '0', + overwrite => false, + writingNewIp => false, + entryCount => (others => '0') + ); + + signal wR : wRegType := W_REG_INIT_C; + signal wRin : wRegType; + + -- Read Stuff + signal matchArray : slv(ENTRIES_G-1 downto 0); + + -- Expire stuff + constant TIMER_1_SEC_C : natural := getTimeRatio(CLK_FREQ_G, 1.0); + type TimerArray is array (natural range <>) of natural range 0 to COMM_TIMEOUT_G; + type ExpStateType is ( + IDLE_S, + MONITOR_S, + EXPIRE_S + ); + type ExpStateArray is array (natural range <>) of ExpStateType; + + type eRegType is record + timerEn : sl; + state : ExpStateArray(ENTRIES_G-1 downto 0); + timer : natural range 0 to (TIMER_1_SEC_C-1); + arpTimers : TimerArray(ENTRIES_G-1 downto 0); + arbRequest : slv(ENTRIES_G-1 downto 0); + end record eRegType; + + constant E_REG_INIT_C : eRegType := + ( + timerEn => '0', + state => (others => IDLE_S), + timer => 0, + arpTimers => (others => 0), + arbRequest => (others => '0') + ); + + signal eR : eRegType := E_REG_INIT_C; + signal eRin : eRegType; + + -- Arbiter + signal arbSelected : slv(bitSize(ENTRIES_G-1)-1 downto 0); + signal arbSelectedResized : slv(7 downto 0); + signal arbValid : sl; + + -- FIFO + signal fifoData : slv(7 downto 0); + signal fifoValid : sl; + signal fifoEmpty : sl; + +begin -- architecture rtl + + -- Write process comb + wrComb : process (arbSelected, arbValid, fifoData, fifoEmpty, fifoValid, + ipWrAddr, ipWrEn, macWrAddr, macWrEn, rst, wR) is + variable v : wRegType; + variable wrAddInt : integer; + variable wrAddIntMac : integer; + begin + -- Latch the current value + v := wR; + + -- Update flags + v.overwrite := false; + v.fifoValid := '0'; + v.writingNewIp := false; + + -- Write IP to LUT + if ipWrEn = '1' or wR.overwrite then + wrAddInt := conv_integer(wR.entryCount); + if fifoEmpty = '0' and (not wR.overwrite) then + v.fifoRdEn := '1'; + elsif wrAddInt < ENTRIES_G then + v.ipLutTable(wrAddInt) := ipWrAddr; + v.writingNewIp := true; + wrAddIntMac := wrAddInt; + end if; + end if; + + -- Write MAC to LUT + if macWrEn = '1' then + -- wrAddInt := conv_integer(wR.entryCount); + -- if wrAddInt < ENTRIES_G then + v.macLutTable(wrAddIntMac) := macWrAddr; + -- end if; + + -- Update write LUT pointer + if wR.entryCount < ENTRIES_G - 1 then + v.entryCount := wr.entryCount + 1; + else + v.entryCount := (others => '0'); + end if; + end if; + + -- Overwrite LUT pointer if there are empty spaces + if fifoValid = '1' then + v.fifoValid := '1'; + v.fifoRdEn := '0'; + end if; + + if wR.fifoValid = '1' then + v.entryCount := fifoData; + v.overwrite := true; + end if; + + -- Remove entry from LUT + if arbValid = '1' then + wrAddInt := conv_integer(arbSelected); + v.macLutTable(wrAddInt) := (others => '0'); + v.ipLutTable(wrAddInt) := (others => '0'); + end if; + + -- Reset + if (rst = '1') then + v := W_REG_INIT_C; + end if; + + -- Register the variable for next clock cycle + wRin <= v; + + end process wrComb; + + wrSeq : process (clk) is + begin + if rising_edge(clk) then + wR <= wRin after TPD_G; + end if; + end process wrSeq; + + -- Read process + -- Check for a match + gen_compare : for i in 0 to ENTRIES_G-1 generate + matchArray(i) <= '1' when (wR.ipLutTable(i) = ipAddrIn) else '0'; + end generate; + + -- Encode the position based on the match_array + process(matchArray, pos, wr.macLutTable) + variable ipFound : sl := '0'; + variable posI : integer; + variable foundMacAddr : slv(47 downto 0); + variable foundIpAddr : slv(31 downto 0); + begin + ipFound := '0'; + foundMacAddr := (others => '0'); + foundIpAddr := (others => '0'); + if pos > 0 then + posI := conv_integer(pos-1); + if posI < ENTRIES_G then + foundMacAddr := wr.macLutTable(posI); + foundIpAddr := wr.ipLutTable(posI); + if uOr(foundMacAddr) = '0' or uOr(foundIpAddr) = '0' then + ipFound := '0'; + else + ipFound := '1'; + end if; + else + ipFound := '0'; + foundMacAddr := (others => '0'); + foundIpAddr := (others => '0'); + assert false report "Position in the LUT outside of bounds" severity error; + end if; + else + for i in 0 to ENTRIES_G-1 loop + if matchArray(i) = '1' then + foundMacAddr := wr.macLutTable(i); + ipFound := '1'; + exit; -- Exit as soon as a match is found + end if; + end loop; + end if; + found <= ipFound; + macAddr <= foundMacAddr; + ipAddrOut <= foundIpAddr; + end process; + + -- Expiration process + expComb : process (arbSelected, arbValid, clientRemoteDetIp, + clientRemoteDetValid, eR, rst, wR) is + variable v : eRegType; + begin -- process expComb + -- Latch the current value + v := eR; + + -- Reset the flags + v.timerEn := '0'; + + -- Increment the timer + if eR.timer = (TIMER_1_SEC_C-1) then + v.timer := 0; + v.timerEn := '1'; + else + v.timer := eR.timer + 1; + end if; + + -- Loop through the entries + for i in 0 to ENTRIES_G-1 loop + + -- Update the timers + if (eR.timerEn = '1') and (eR.arpTimers(i) /= 0) then + -- Decrement the timers + v.arpTimers(i) := eR.arpTimers(i) - 1; + end if; + + case eR.state(i) is + ------------------------------------------------------------------- + when IDLE_S => + if (uOr(wR.ipLutTable(i)) /= '0' and uOr(wR.macLutTable(i)) /= '0') then + -- Preset the timer + v.arpTimers(i) := COMM_TIMEOUT_G; + -- Next state + v.state(i) := MONITOR_S; + end if; + ---------------------------------------------------------------- + when MONITOR_S => + if clientRemoteDetValid = '1' and clientRemoteDetIp = wR.ipLutTable(i) then + -- Preset the timer + v.arpTimers(i) := COMM_TIMEOUT_G; + elsif wR.writingNewIp and conv_integer(wR.entryCount) = i then + -- Preset the timer + v.arpTimers(i) := COMM_TIMEOUT_G; + elsif eR.arpTimers(i) = 0 then + -- Next state + v.state(i) := EXPIRE_S; + end if; + if (uOr(wR.ipLutTable(i)) = '0' and uOr(wR.macLutTable(i)) = '0') then + -- Next state + v.state(i) := IDLE_S; + end if; + ---------------------------------------------------------------- + when EXPIRE_S => + -- Raise hand + v.arbRequest(i) := '1'; + if arbSelected = i and arbValid = '1' then + -- Lower hand + v.arbRequest(i) := '0'; + -- Next state + v.state(i) := IDLE_S; + end if; + ---------------------------------------------------------------- + when others => + -- Fallback on idle state + v.state(i) := IDLE_S; + ---------------------------------------------------------------- + end case; + + end loop; -- i + + -- Reset + if (rst = '1') then + v := E_REG_INIT_C; + end if; + + -- Register the variable for next clock cycle + eRin <= v; + + end process expComb; + + expSeq : process (clk) is + begin + if rising_edge(clk) then + eR <= eRin after TPD_G; + end if; + end process expSeq; + + -- Arbiter + U_Arbiter : entity surf.Arbiter + generic map ( + TPD_G => TPD_G, + REQ_SIZE_G => ENTRIES_G) + port map ( + clk => clk, + rst => rst, + req => eRin.arbRequest, + selected => arbSelected, + valid => arbValid, + ack => open); + + arbSelectedResized <= resize(arbSelected, 8); + + -- Empty spaces FIFO + U_ExpFifo : entity surf.Fifo + generic map ( + TPD_G => TPD_G, + GEN_SYNC_FIFO_G => true, + FWFT_EN_G => false, + DATA_WIDTH_G => 8, + ADDR_WIDTH_G => 8) + port map ( + rst => rst, + -- Write ports + wr_clk => clk, + wr_en => arbValid, + din => arbSelectedResized, + wr_ack => open, + -- Read ports + rd_clk => clk, + rd_en => wR.fifoRdEn, + dout => fifoData, + valid => fifoValid, + empty => fifoEmpty); + +end architecture rtl; diff --git a/ethernet/UdpEngine/rtl/UdpEngine.vhd b/ethernet/UdpEngine/rtl/UdpEngine.vhd index 7b7a26303d..8beef04c21 100644 --- a/ethernet/UdpEngine/rtl/UdpEngine.vhd +++ b/ethernet/UdpEngine/rtl/UdpEngine.vhd @@ -22,23 +22,25 @@ use surf.AxiStreamPkg.all; entity UdpEngine is generic ( -- Simulation Generics - TPD_G : time := 1 ns; + TPD_G : time := 1 ns; -- UDP Server Generics - SERVER_EN_G : boolean := true; - SERVER_SIZE_G : positive := 1; - SERVER_PORTS_G : PositiveArray := (0 => 8192); + SERVER_EN_G : boolean := true; + SERVER_SIZE_G : positive := 1; + SERVER_PORTS_G : PositiveArray := (0 => 8192); -- UDP Client Generics - CLIENT_EN_G : boolean := true; - CLIENT_SIZE_G : positive := 1; - CLIENT_PORTS_G : PositiveArray := (0 => 8193); + CLIENT_EN_G : boolean := true; + CLIENT_TAG_IP_IN_TUSER : boolean := false; + CLIENT_SIZE_G : positive := 1; + CLIENT_PORTS_G : PositiveArray := (0 => 8193); + ARP_TAB_ENTRIES_G : positive range 1 to 255 := 4; -- General UDP/IGMP/ARP/DHCP Generics - TX_FLOW_CTRL_G : boolean := true; -- True: Blow off the UDP TX data if link down, False: Backpressure until TX link is up - DHCP_G : boolean := false; - IGMP_G : boolean := false; - IGMP_GRP_SIZE : positive := 1; - CLK_FREQ_G : real := 156.25E+06; -- In units of Hz - COMM_TIMEOUT_G : positive := 30; -- In units of seconds, Client's Communication timeout before re-ARPing or DHCP discover/request - SYNTH_MODE_G : string := "inferred"); -- Synthesis mode for internal RAMs + TX_FLOW_CTRL_G : boolean := true; -- True: Blow off the UDP TX data if link down, False: Backpressure until TX link is up + DHCP_G : boolean := false; + IGMP_G : boolean := false; + IGMP_GRP_SIZE : positive := 1; + CLK_FREQ_G : real := 156.25E+06; -- In units of Hz + COMM_TIMEOUT_G : positive := 30; -- In units of seconds, Client's Communication timeout before re-ARPing or DHCP discover/request + SYNTH_MODE_G : string := "inferred"); -- Synthesis mode for internal RAMs port ( -- Local Configurations localMac : in slv(47 downto 0); -- big-Endian configuration @@ -77,8 +79,9 @@ end UdpEngine; architecture mapping of UdpEngine is - signal clientRemoteDet : slv(CLIENT_SIZE_G-1 downto 0); - signal clientRemoteMac : Slv48Array(CLIENT_SIZE_G-1 downto 0); + signal clientRemoteDetValid : slv(CLIENT_SIZE_G-1 downto 0); + signal clientRemoteDetIp : Slv32Array(CLIENT_SIZE_G-1 downto 0); + signal clientRemoteMac : Slv48Array(CLIENT_SIZE_G-1 downto 0); signal remotePort : Slv16Array(SERVER_SIZE_G-1 downto 0); signal remoteIp : Slv32Array(SERVER_SIZE_G-1 downto 0); @@ -95,6 +98,14 @@ architecture mapping of UdpEngine is signal localIp : slv(31 downto 0); + signal arpTabFound : slv(CLIENT_SIZE_G-1 downto 0); + signal arpTabMacAddr : Slv48Array(CLIENT_SIZE_G-1 downto 0); + signal arpTabIpAddr : Slv32Array(CLIENT_SIZE_G-1 downto 0); + signal arpTabIpWe : slv(CLIENT_SIZE_G-1 downto 0); + signal arpTabMacWe : slv(CLIENT_SIZE_G-1 downto 0); + signal arpTabMacAddrW : Slv48Array(CLIENT_SIZE_G-1 downto 0); + signal arpTabPos : Slv8Array(CLIENT_SIZE_G-1 downto 0); + begin assert ((SERVER_EN_G = true) or (CLIENT_EN_G = true)) report @@ -106,40 +117,42 @@ begin U_UdpEngineRx : entity surf.UdpEngineRx generic map ( - TPD_G => TPD_G, - DHCP_G => DHCP_G, - IGMP_G => IGMP_G, - IGMP_GRP_SIZE => IGMP_GRP_SIZE, - SERVER_EN_G => SERVER_EN_G, - SERVER_SIZE_G => SERVER_SIZE_G, - SERVER_PORTS_G => SERVER_PORTS_G, - CLIENT_EN_G => CLIENT_EN_G, - CLIENT_SIZE_G => CLIENT_SIZE_G, - CLIENT_PORTS_G => CLIENT_PORTS_G) + TPD_G => TPD_G, + DHCP_G => DHCP_G, + IGMP_G => IGMP_G, + IGMP_GRP_SIZE => IGMP_GRP_SIZE, + SERVER_EN_G => SERVER_EN_G, + SERVER_SIZE_G => SERVER_SIZE_G, + SERVER_PORTS_G => SERVER_PORTS_G, + CLIENT_EN_G => CLIENT_EN_G, + CLIENT_TAG_IP_IN_TUSER => CLIENT_TAG_IP_IN_TUSER, + CLIENT_SIZE_G => CLIENT_SIZE_G, + CLIENT_PORTS_G => CLIENT_PORTS_G) port map ( -- Local Configurations - localIp => localIp, - broadcastIp => broadcastIp, - igmpIp => igmpIp, + localIp => localIp, + broadcastIp => broadcastIp, + igmpIp => igmpIp, -- Interface to IPV4 Engine - ibUdpMaster => ibUdpMaster, - ibUdpSlave => ibUdpSlave, + ibUdpMaster => ibUdpMaster, + ibUdpSlave => ibUdpSlave, -- Interface to UDP Server engine(s) - serverRemotePort => remotePort, - serverRemoteIp => remoteIp, - serverRemoteMac => serverRemoteMac, - obServerMasters => obServerMasters, - obServerSlaves => obServerSlaves, + serverRemotePort => remotePort, + serverRemoteIp => remoteIp, + serverRemoteMac => serverRemoteMac, + obServerMasters => obServerMasters, + obServerSlaves => obServerSlaves, -- Interface to UDP Client engine(s) - clientRemoteDet => clientRemoteDet, - obClientMasters => obClientMasters, - obClientSlaves => obClientSlaves, + clientRemoteDetValid => clientRemoteDetValid, + clientRemoteDetIp => clientRemoteDetIp, + obClientMasters => obClientMasters, + obClientSlaves => obClientSlaves, -- Interface to DHCP Engine - ibDhcpMaster => ibDhcpMaster, - ibDhcpSlave => ibDhcpSlave, + ibDhcpMaster => ibDhcpMaster, + ibDhcpSlave => ibDhcpSlave, -- Clock and Reset - clk => clk, - rst => rst); + clk => clk, + rst => rst); GEN_DHCP : if (DHCP_G = true) generate @@ -206,6 +219,33 @@ begin GEN_CLIENT : if (CLIENT_EN_G = true) generate + GEN_ARP_TABLES : for i in 0 to CLIENT_SIZE_G-1 generate + ArpIpTable_1 : entity surf.ArpIpTable + generic map ( + TPD_G => TPD_G, + CLK_FREQ_G => CLK_FREQ_G, + COMM_TIMEOUT_G => COMM_TIMEOUT_G, + ENTRIES_G => ARP_TAB_ENTRIES_G) + port map ( + -- Clock and Reset + clk => clk, + rst => rst, + -- Read LUT + ipAddrIn => clientRemoteIp(i), + pos => arpTabPos(i), + found => arpTabFound(i), + macAddr => arpTabMacAddr(i), + ipAddrOut => arpTabIpAddr(i), + -- Refresh LUT + clientRemoteDetValid => clientRemoteDetValid(i), + clientRemoteDetIp => clientRemoteDetIp(i), + -- Write LUT + ipWrEn => arpTabIpWe(i), + IpWrAddr => clientRemoteIp(i), + macWrEn => arpTabMacWe(i), + macWrAddr => arpTabMacAddrW(i)); + end generate GEN_ARP_TABLES; + U_UdpEngineArp : entity surf.UdpEngineArp generic map ( TPD_G => TPD_G, @@ -214,19 +254,26 @@ begin COMM_TIMEOUT_G => COMM_TIMEOUT_G) port map ( -- Local Configurations - localIp => localIp, + localIp => localIp, -- Interface to ARP Engine - arpReqMasters => arpReqMasters, - arpReqSlaves => arpReqSlaves, - arpAckMasters => arpAckMasters, - arpAckSlaves => arpAckSlaves, + arpReqMasters => arpReqMasters, + arpReqSlaves => arpReqSlaves, + arpAckMasters => arpAckMasters, + arpAckSlaves => arpAckSlaves, + -- Interface to ARP Table + arpTabFound => arpTabFound, + arpTabMacAddr => arpTabMacAddr, + arpTabIpWe => arpTabIpWe, + arpTabMacWe => arpTabMacWe, + arpTabMacAddrW => arpTabMacAddrW, -- Interface to UDP Client engine(s) - clientRemoteDet => clientRemoteDet, - clientRemoteIp => clientRemoteIp, - clientRemoteMac => clientRemoteMac, + clientRemoteDetValid => clientRemoteDetValid, + clientRemoteDetIp => clientRemoteDetIp, + clientRemoteIp => clientRemoteIp, + clientRemoteMac => clientRemoteMac, -- Clock and Reset - clk => clk, - rst => rst); + clk => clk, + rst => rst); U_UdpEngineTx : entity surf.UdpEngineTx generic map ( @@ -236,19 +283,23 @@ begin PORT_G => CLIENT_PORTS_G) port map ( -- Interface to IPV4 Engine - obUdpMaster => obUdpMasters(1), - obUdpSlave => obUdpSlaves(1), + obUdpMaster => obUdpMasters(1), + obUdpSlave => obUdpSlaves(1), -- Interface to User Application - localMac => localMac, - localIp => localIp, - remotePort => clientRemotePort, - remoteIp => clientRemoteIp, - remoteMac => clientRemoteMac, - ibMasters => ibClientMasters, - ibSlaves => ibClientSlaves, + localMac => localMac, + localIp => localIp, + remotePort => clientRemotePort, + remoteIp => clientRemoteIp, + remoteMac => clientRemoteMac, + ibMasters => ibClientMasters, + ibSlaves => ibClientSlaves, + arpTabPos => arpTabPos, + arpTabFound => arpTabFound, + arpTabIpAddr => arpTabIpAddr, + arpTabMacAddr => arpTabMacAddr, -- Clock and Reset - clk => clk, - rst => rst); + clk => clk, + rst => rst); end generate; diff --git a/ethernet/UdpEngine/rtl/UdpEngineArp.vhd b/ethernet/UdpEngine/rtl/UdpEngineArp.vhd old mode 100755 new mode 100644 index 96f7a31e43..85dd7c77f5 --- a/ethernet/UdpEngine/rtl/UdpEngineArp.vhd +++ b/ethernet/UdpEngine/rtl/UdpEngineArp.vhd @@ -31,19 +31,26 @@ entity UdpEngineArp is RESP_TIMEOUT_G : positive := 5); port ( -- Local Configurations - localIp : in slv(31 downto 0); -- big-Endian configuration + localIp : in slv(31 downto 0); -- big-Endian configuration -- Interface to ARP Engine - arpReqMasters : out AxiStreamMasterArray(CLIENT_SIZE_G-1 downto 0); -- Request via IP address - arpReqSlaves : in AxiStreamSlaveArray(CLIENT_SIZE_G-1 downto 0); - arpAckMasters : in AxiStreamMasterArray(CLIENT_SIZE_G-1 downto 0); -- Respond with MAC address - arpAckSlaves : out AxiStreamSlaveArray(CLIENT_SIZE_G-1 downto 0); + arpReqMasters : out AxiStreamMasterArray(CLIENT_SIZE_G-1 downto 0); -- Request via IP address + arpReqSlaves : in AxiStreamSlaveArray(CLIENT_SIZE_G-1 downto 0); + arpAckMasters : in AxiStreamMasterArray(CLIENT_SIZE_G-1 downto 0); -- Respond with MAC address + arpAckSlaves : out AxiStreamSlaveArray(CLIENT_SIZE_G-1 downto 0); + -- Interface to ARP Table + arpTabFound : in slv(CLIENT_SIZE_G-1 downto 0); + arpTabMacAddr : in Slv48Array(CLIENT_SIZE_G-1 downto 0); + arpTabIpWe : out slv(CLIENT_SIZE_G-1 downto 0); + arpTabMacWe : out slv(CLIENT_SIZE_G-1 downto 0); + arpTabMacAddrW : out Slv48Array(CLIENT_SIZE_G-1 downto 0); -- Interface to UDP Client engine(s) - clientRemoteDet : in slv(CLIENT_SIZE_G-1 downto 0); - clientRemoteIp : in Slv32Array(CLIENT_SIZE_G-1 downto 0); - clientRemoteMac : out Slv48Array(CLIENT_SIZE_G-1 downto 0); + clientRemoteDetValid : in slv(CLIENT_SIZE_G-1 downto 0); + clientRemoteDetIp : in Slv32Array(CLIENT_SIZE_G-1 downto 0); + clientRemoteIp : in Slv32Array(CLIENT_SIZE_G-1 downto 0); + clientRemoteMac : out Slv48Array(CLIENT_SIZE_G-1 downto 0); -- Clock and Reset - clk : in sl; - rst : in sl); + clk : in sl; + rst : in sl); end UdpEngineArp; architecture rtl of UdpEngineArp is @@ -52,37 +59,44 @@ architecture rtl of UdpEngineArp is type TimerArray is array (natural range <>) of natural range 0 to COMM_TIMEOUT_G; type StateType is ( + CHECK_S, IDLE_S, WAIT_S, COMM_MONITOR_S); type StateArray is array (natural range <>) of StateType; type RegType is record - clientRemoteMac : Slv48Array(CLIENT_SIZE_G-1 downto 0); - arpAckSlaves : AxiStreamSlaveArray(CLIENT_SIZE_G-1 downto 0); - arpReqMasters : AxiStreamMasterArray(CLIENT_SIZE_G-1 downto 0); - timerEn : sl; - timer : natural range 0 to (TIMER_1_SEC_C-1); - arpTimers : TimerArray(CLIENT_SIZE_G-1 downto 0); - respTimers : TimerArray(CLIENT_SIZE_G-1 downto 0); - state : StateArray(CLIENT_SIZE_G-1 downto 0); + clientRemoteMac : Slv48Array(CLIENT_SIZE_G-1 downto 0); + clientRemoteMacWrEn : slv(CLIENT_SIZE_G-1 downto 0); + clientRemoteIpWrEn : slv(CLIENT_SIZE_G-1 downto 0); + arpAckSlaves : AxiStreamSlaveArray(CLIENT_SIZE_G-1 downto 0); + arpReqMasters : AxiStreamMasterArray(CLIENT_SIZE_G-1 downto 0); + timerEn : sl; + timer : natural range 0 to (TIMER_1_SEC_C-1); + arpTimers : TimerArray(CLIENT_SIZE_G-1 downto 0); + respTimers : TimerArray(CLIENT_SIZE_G-1 downto 0); + state : StateArray(CLIENT_SIZE_G-1 downto 0); end record RegType; constant REG_INIT_C : RegType := ( - clientRemoteMac => (others => (others => '0')), - arpAckSlaves => (others => AXI_STREAM_SLAVE_INIT_C), - arpReqMasters => (others => AXI_STREAM_MASTER_INIT_C), - timerEn => '0', - timer => 0, - arpTimers => (others => 0), - respTimers => (others => 0), - state => (others => IDLE_S)); + clientRemoteMac => (others => (others => '0')), + clientRemoteMacWrEn => (others => '0'), + clientRemoteIpWrEn => (others => '0'), + arpAckSlaves => (others => AXI_STREAM_SLAVE_INIT_C), + arpReqMasters => (others => AXI_STREAM_MASTER_INIT_C), + timerEn => '0', + timer => 0, + arpTimers => (others => 0), + respTimers => (others => 0), + state => (others => IDLE_S)); signal r : RegType := REG_INIT_C; signal rin : RegType; begin - comb : process (arpAckMasters, arpReqSlaves, clientRemoteDet, clientRemoteIp, r, rst) is + comb : process (arpAckMasters, arpReqSlaves, arpTabFound, arpTabMacAddr, + clientRemoteDetIp, clientRemoteDetValid, clientRemoteIp, r, + rst) is variable v : RegType; variable i : natural; begin @@ -90,7 +104,9 @@ begin v := r; -- Reset the flags - v.timerEn := '0'; + v.timerEn := '0'; + v.clientRemoteMacWrEn := (others => '0'); + v.clientRemoteIpWrEn := (others => '0'); for i in CLIENT_SIZE_G-1 downto 0 loop v.arpAckSlaves(i) := AXI_STREAM_SLAVE_INIT_C; if arpReqSlaves(i).tReady = '1' then @@ -120,24 +136,45 @@ begin v.respTimers(i) := r.respTimers(i) - 1; end if; - -- Update the IP address - v.arpReqMasters(i).tData(31 downto 0) := clientRemoteIp(i); - -- Check for dynamic change in IP address - if (r.arpReqMasters(i).tData(31 downto 0) /= clientRemoteIp(i)) or (clientRemoteIp(i) = 0) then + if (clientRemoteIp(i) = 0) then -- Stop any outstanding requests v.arpReqMasters(i).tValid := '0'; -- Reset the remote MAC address v.clientRemoteMac(i) := (others => '0'); -- Next state v.state(i) := IDLE_S; + elsif (r.arpReqMasters(i).tData(31 downto 0) /= clientRemoteIp(i)) then + -- Update the IP address + v.arpReqMasters(i).tData(31 downto 0) := clientRemoteIp(i); + -- Stop any outstanding requests + v.arpReqMasters(i).tValid := '0'; + -- Reset the remote MAC address + v.clientRemoteMac(i) := (others => '0'); + -- Next state + v.state(i) := CHECK_S; else -- State Machine case r.state(i) is ---------------------------------------------------------------------- + when CHECK_S => + if arpTabFound(i) = '1' then + -- Set found MAC addr + v.clientRemoteMac(i) := arpTabMacAddr(i); + -- Preset the timer + v.arpTimers(i) := COMM_TIMEOUT_G; + -- Next state + v.state(i) := COMM_MONITOR_S; + else + -- Write IP to ARP table + v.clientRemoteIpWrEn(i) := '1'; + -- Next state + v.state(i) := IDLE_S; + end if; + ---------------------------------------------------------------------- when IDLE_S => -- Reset the counter - v.arpTimers(i) := 0; + v.arpTimers(i) := 0; -- Check if we have a non-zero IP address to request if clientRemoteIp(i) /= 0 then -- Make an ARP request @@ -159,6 +196,8 @@ begin v.arpAckSlaves(i).tReady := '1'; -- Latch the MAC address value v.clientRemoteMac(i) := arpAckMasters(i).tData(47 downto 0); + -- Write to ARP table + v.clientRemoteMacWrEn(i) := '1'; -- Preset the timer v.arpTimers(i) := COMM_TIMEOUT_G; -- Next state @@ -167,7 +206,7 @@ begin ---------------------------------------------------------------------- when COMM_MONITOR_S => -- Check for inbound client communication - if clientRemoteDet(i) = '1' then + if clientRemoteDetValid(i) = '1' and clientRemoteDetIp(i) = clientRemoteIp(i) then -- Preset the timer v.arpTimers(i) := COMM_TIMEOUT_G; elsif r.arpTimers(i) = 0 then @@ -193,6 +232,9 @@ begin -- Registered Outputs arpReqMasters <= r.arpReqMasters; clientRemoteMac <= r.clientRemoteMac; + arpTabIpWe <= r.clientRemoteIpWrEn; + arpTabMacWe <= r.clientRemoteMacWrEn; + arpTabMacAddrW <= r.clientRemoteMac; end process comb; diff --git a/ethernet/UdpEngine/rtl/UdpEngineRx.vhd b/ethernet/UdpEngine/rtl/UdpEngineRx.vhd index fc5269c60b..882eb36d0b 100644 --- a/ethernet/UdpEngine/rtl/UdpEngineRx.vhd +++ b/ethernet/UdpEngine/rtl/UdpEngineRx.vhd @@ -27,43 +27,45 @@ use surf.EthMacPkg.all; entity UdpEngineRx is generic ( -- Simulation Generics - TPD_G : time := 1 ns; + TPD_G : time := 1 ns; -- UDP General Generic - DHCP_G : boolean := false; - IGMP_G : boolean := false; - IGMP_GRP_SIZE : positive := 1; + DHCP_G : boolean := false; + IGMP_G : boolean := false; + IGMP_GRP_SIZE : positive := 1; -- UDP Server Generics - SERVER_EN_G : boolean := true; - SERVER_SIZE_G : positive := 1; - SERVER_PORTS_G : PositiveArray := (0 => 8192); + SERVER_EN_G : boolean := true; + SERVER_SIZE_G : positive := 1; + SERVER_PORTS_G : PositiveArray := (0 => 8192); -- UDP Client Generics - CLIENT_EN_G : boolean := true; - CLIENT_SIZE_G : positive := 1; - CLIENT_PORTS_G : PositiveArray := (0 => 8193)); + CLIENT_EN_G : boolean := true; + CLIENT_TAG_IP_IN_TUSER : boolean := false; + CLIENT_SIZE_G : positive := 1; + CLIENT_PORTS_G : PositiveArray := (0 => 8193)); port ( -- Local Configurations - localIp : in slv(31 downto 0); -- big-Endian configuration - broadcastIp : in slv(31 downto 0); -- big-Endian configuration - igmpIp : in Slv32Array(IGMP_GRP_SIZE-1 downto 0); -- big-Endian configuration + localIp : in slv(31 downto 0); -- big-Endian configuration + broadcastIp : in slv(31 downto 0); -- big-Endian configuration + igmpIp : in Slv32Array(IGMP_GRP_SIZE-1 downto 0); -- big-Endian configuration -- Interface to IPV4 Engine - ibUdpMaster : in AxiStreamMasterType; - ibUdpSlave : out AxiStreamSlaveType; + ibUdpMaster : in AxiStreamMasterType; + ibUdpSlave : out AxiStreamSlaveType; -- Interface to UDP Server engine(s) - serverRemotePort : out Slv16Array(SERVER_SIZE_G-1 downto 0); - serverRemoteIp : out Slv32Array(SERVER_SIZE_G-1 downto 0); - serverRemoteMac : out Slv48Array(SERVER_SIZE_G-1 downto 0); - obServerMasters : out AxiStreamMasterArray(SERVER_SIZE_G-1 downto 0); - obServerSlaves : in AxiStreamSlaveArray(SERVER_SIZE_G-1 downto 0); + serverRemotePort : out Slv16Array(SERVER_SIZE_G-1 downto 0); + serverRemoteIp : out Slv32Array(SERVER_SIZE_G-1 downto 0); + serverRemoteMac : out Slv48Array(SERVER_SIZE_G-1 downto 0); + obServerMasters : out AxiStreamMasterArray(SERVER_SIZE_G-1 downto 0); + obServerSlaves : in AxiStreamSlaveArray(SERVER_SIZE_G-1 downto 0); -- Interface to UDP Client engine(s) - clientRemoteDet : out slv(CLIENT_SIZE_G-1 downto 0); - obClientMasters : out AxiStreamMasterArray(CLIENT_SIZE_G-1 downto 0); - obClientSlaves : in AxiStreamSlaveArray(CLIENT_SIZE_G-1 downto 0); + clientRemoteDetValid : out slv(CLIENT_SIZE_G-1 downto 0); + clientRemoteDetIp : out Slv32Array(CLIENT_SIZE_G-1 downto 0); + obClientMasters : out AxiStreamMasterArray(CLIENT_SIZE_G-1 downto 0); + obClientSlaves : in AxiStreamSlaveArray(CLIENT_SIZE_G-1 downto 0); -- Interface to DHCP Engine - ibDhcpMaster : out AxiStreamMasterType; - ibDhcpSlave : in AxiStreamSlaveType; + ibDhcpMaster : out AxiStreamMasterType; + ibDhcpSlave : in AxiStreamSlaveType; -- Clock and Reset - clk : in sl; - rst : in sl); + clk : in sl; + rst : in sl); end UdpEngineRx; architecture rtl of UdpEngineRx is @@ -84,40 +86,42 @@ architecture rtl of UdpEngineRx is LAST_S); type RegType is record - tDestServer : slv(7 downto 0); - tDestClient : slv(7 downto 0); - serverRemotePort : Slv16Array(SERVER_SIZE_G-1 downto 0); - serverRemoteIp : Slv32Array(SERVER_SIZE_G-1 downto 0); - serverRemoteMac : Slv48Array(SERVER_SIZE_G-1 downto 0); - clientRemoteDet : slv(CLIENT_SIZE_G-1 downto 0); - byteCnt : slv(15 downto 0); - tData : slv(127 downto 0); - sof : sl; - localHost : sl; - route : RouteType; - rxSlave : AxiStreamSlaveType; - dhcpMaster : AxiStreamMasterType; - serverMaster : AxiStreamMasterType; - clientMaster : AxiStreamMasterType; - state : StateType; + tDestServer : slv(7 downto 0); + tDestClient : slv(7 downto 0); + serverRemotePort : Slv16Array(SERVER_SIZE_G-1 downto 0); + serverRemoteIp : Slv32Array(SERVER_SIZE_G-1 downto 0); + serverRemoteMac : Slv48Array(SERVER_SIZE_G-1 downto 0); + clientRemoteDetValid : slv(CLIENT_SIZE_G-1 downto 0); + clientRemoteDetIp : Slv32Array(CLIENT_SIZE_G-1 downto 0); + byteCnt : slv(15 downto 0); + tData : slv(127 downto 0); + sof : sl; + localHost : sl; + route : RouteType; + rxSlave : AxiStreamSlaveType; + dhcpMaster : AxiStreamMasterType; + serverMaster : AxiStreamMasterType; + clientMaster : AxiStreamMasterType; + state : StateType; end record RegType; constant REG_INIT_C : RegType := ( - tDestServer => (others => '0'), - tDestClient => (others => '0'), - serverRemotePort => (others => (others => '0')), - serverRemoteIp => (others => (others => '0')), - serverRemoteMac => (others => (others => '0')), - clientRemoteDet => (others => '0'), - byteCnt => (others => '0'), - tData => (others => '0'), - sof => '1', - localHost => '0', - route => NULL_S, - rxSlave => AXI_STREAM_SLAVE_INIT_C, - dhcpMaster => AXI_STREAM_MASTER_INIT_C, - serverMaster => AXI_STREAM_MASTER_INIT_C, - clientMaster => AXI_STREAM_MASTER_INIT_C, - state => IDLE_S); + tDestServer => (others => '0'), + tDestClient => (others => '0'), + serverRemotePort => (others => (others => '0')), + serverRemoteIp => (others => (others => '0')), + serverRemoteMac => (others => (others => '0')), + clientRemoteDetValid => (others => '0'), + clientRemoteDetIp => (others => (others => '0')), + byteCnt => (others => '0'), + tData => (others => '0'), + sof => '1', + localHost => '0', + route => NULL_S, + rxSlave => AXI_STREAM_SLAVE_INIT_C, + dhcpMaster => AXI_STREAM_MASTER_INIT_C, + serverMaster => AXI_STREAM_MASTER_INIT_C, + clientMaster => AXI_STREAM_MASTER_INIT_C, + state => IDLE_S); signal r : RegType := REG_INIT_C; signal rin : RegType; @@ -156,8 +160,8 @@ begin v := r; -- Reset the flags - v.clientRemoteDet := (others => '0'); - v.rxSlave := AXI_STREAM_SLAVE_INIT_C; + v.clientRemoteDetValid := (others => '0'); + v.rxSlave := AXI_STREAM_SLAVE_INIT_C; if serverSlave.tReady = '1' then v.serverMaster.tValid := '0'; v.serverMaster.tLast := '0'; @@ -247,9 +251,13 @@ begin for i in (CLIENT_SIZE_G-1) downto 0 loop -- Check if port is defined if (v.route = NULL_S) and (rxMaster.tData(63 downto 48) = CLIENT_PORTS_C(i)) then - v.route := CLIENT_S; - v.tDestClient := toSlv(i, 8); - v.clientRemoteDet(i) := '1'; + v.route := CLIENT_S; + v.tDestClient := toSlv(i, 8); + v.clientRemoteDetValid(i) := '1'; + v.clientRemoteDetIp(i) := r.tData(95 downto 64); + if CLIENT_TAG_IP_IN_TUSER then + v.clientMaster.tUser(39 downto 8) := r.tData(95 downto 64); + end if; end if; end loop; end if; @@ -265,12 +273,12 @@ begin v.byteCnt := v.byteCnt - 8; -- Remove the RoCEv2 iCRC if rxMaster.tData(63 downto 48) = x"B712" then - v.byteCnt := v.byteCnt - 4; + v.byteCnt := v.byteCnt - 4; end if; -- Track the leftovers - v.tData(31 downto 0) := rxMaster.tData(127 downto 96); + v.tData(31 downto 0) := rxMaster.tData(127 downto 96); -- Set the flag - v.sof := '1'; + v.sof := '1'; -- Check if localhost if (localIp = r.tData(95 downto 64)) then v.localHost := '1'; @@ -496,10 +504,11 @@ begin rin <= v; -- Registered Outputs - serverRemotePort <= r.serverRemotePort; - serverRemoteIp <= r.serverRemoteIp; - serverRemoteMac <= r.serverRemoteMac; - clientRemoteDet <= r.clientRemoteDet; + serverRemotePort <= r.serverRemotePort; + serverRemoteIp <= r.serverRemoteIp; + serverRemoteMac <= r.serverRemoteMac; + clientRemoteDetValid <= r.clientRemoteDetValid; + clientRemoteDetIp <= r.clientRemoteDetIp; end process comb; diff --git a/ethernet/UdpEngine/rtl/UdpEngineTx.vhd b/ethernet/UdpEngine/rtl/UdpEngineTx.vhd index 7cc5938003..c3cac69e4b 100644 --- a/ethernet/UdpEngine/rtl/UdpEngineTx.vhd +++ b/ethernet/UdpEngine/rtl/UdpEngineTx.vhd @@ -31,27 +31,31 @@ entity UdpEngineTx is TPD_G : time := 1 ns; -- UDP General Generic SIZE_G : positive := 1; - TX_FLOW_CTRL_G : boolean := true; -- True: Blow off the UDP TX data if link down, False: Backpressure until TX link is up + TX_FLOW_CTRL_G : boolean := true; -- True: Blow off the UDP TX data if link down, False: Backpressure until TX link is up PORT_G : PositiveArray := (0 => 8192)); port ( -- Interface to IPV4 Engine - obUdpMaster : out AxiStreamMasterType; - obUdpSlave : in AxiStreamSlaveType; + obUdpMaster : out AxiStreamMasterType; + obUdpSlave : in AxiStreamSlaveType; -- Interface to User Application - linkUp : out slv(SIZE_G-1 downto 0); - localMac : in slv(47 downto 0); - localIp : in slv(31 downto 0); - remotePort : in Slv16Array(SIZE_G-1 downto 0); - remoteIp : in Slv32Array(SIZE_G-1 downto 0); - remoteMac : in Slv48Array(SIZE_G-1 downto 0); - ibMasters : in AxiStreamMasterArray(SIZE_G-1 downto 0); - ibSlaves : out AxiStreamSlaveArray(SIZE_G-1 downto 0); + linkUp : out slv(SIZE_G-1 downto 0); + localMac : in slv(47 downto 0); + localIp : in slv(31 downto 0); + remotePort : in Slv16Array(SIZE_G-1 downto 0); + remoteIp : in Slv32Array(SIZE_G-1 downto 0); + remoteMac : in Slv48Array(SIZE_G-1 downto 0); + ibMasters : in AxiStreamMasterArray(SIZE_G-1 downto 0); + ibSlaves : out AxiStreamSlaveArray(SIZE_G-1 downto 0); + arpTabPos : out Slv8Array(SIZE_G-1 downto 0); + arpTabFound : in slv(SIZE_G-1 downto 0) := (others => '0'); + arpTabIpAddr : in Slv32Array(SIZE_G-1 downto 0) := (others => (others => '0')); + arpTabMacAddr : in Slv48Array(SIZE_G-1 downto 0) := (others => (others => '0')); -- Interface to DHCP Engine - obDhcpMaster : in AxiStreamMasterType := AXI_STREAM_MASTER_INIT_C; - obDhcpSlave : out AxiStreamSlaveType; + obDhcpMaster : in AxiStreamMasterType := AXI_STREAM_MASTER_INIT_C; + obDhcpSlave : out AxiStreamSlaveType; -- Clock and Reset - clk : in sl; - rst : in sl); + clk : in sl; + rst : in sl); end UdpEngineTx; architecture rtl of UdpEngineTx is @@ -60,6 +64,7 @@ architecture rtl of UdpEngineTx is type StateType is ( IDLE_S, + ACC_ARP_TAB_S, DHCP_HDR_S, HDR_S, DHCP_BUFFER_S, @@ -74,6 +79,7 @@ architecture rtl of UdpEngineTx is eofe : sl; chPntr : natural range 0 to SIZE_G-1; index : natural range 0 to SIZE_G-1; + arpPos : Slv8Array(SIZE_G-1 downto 0); obDhcpSlave : AxiStreamSlaveType; ibSlaves : AxiStreamSlaveArray(SIZE_G-1 downto 0); txMaster : AxiStreamMasterType; @@ -87,6 +93,7 @@ architecture rtl of UdpEngineTx is eofe => '0', chPntr => 0, index => 0, + arpPos => (others => (others => '0')), obDhcpSlave => AXI_STREAM_SLAVE_INIT_C, ibSlaves => (others => AXI_STREAM_SLAVE_INIT_C), txMaster => AXI_STREAM_MASTER_INIT_C, @@ -105,8 +112,9 @@ begin comb : process (ibMasters, localIp, localMac, obDhcpMaster, r, remoteIp, remoteMac, remotePort, rst, txSlave) is - variable v : RegType; - variable i : natural; + variable v : RegType; + variable arpPosV : Slv8Array(SIZE_G-1 downto 0); + variable i : natural; begin -- Latch the current value v := r; @@ -123,12 +131,12 @@ begin for i in SIZE_G-1 downto 0 loop -- Check if link is up - if (localMac /= 0) and -- Non-zero local MAC address - (localIp /= 0) and -- Non-zero local IP address - (PORT_G(i) /= 0) and -- Non-zero local UDP port - (remoteMac(i) /= 0) and -- Non-zero remote MAC address - (remoteIp(i) /= 0) and -- Non-zero remote IP address - (remotePort(i) /= 0) then -- Non-zero remote UDP port + if (localMac /= 0) and -- Non-zero local MAC address + (localIp /= 0) and -- Non-zero local IP address + (PORT_G(i) /= 0) and -- Non-zero local UDP port + (remoteMac(i) /= 0) and -- Non-zero remote MAC address + (remoteIp(i) /= 0) and -- Non-zero remote IP address + (remotePort(i) /= 0) then -- Non-zero remote UDP port -- Link Up v.linkUp(i) := '1'; else @@ -156,7 +164,7 @@ begin -- Write the first header v.txMaster.tValid := '1'; v.txMaster.tData(47 downto 0) := (others => '1'); -- Destination MAC address - v.txMaster.tData(63 downto 48) := x"0000"; -- All 0s + v.txMaster.tData(63 downto 48) := x"0000"; -- All 0s v.txMaster.tData(95 downto 64) := (others => '0'); -- Source IP address v.txMaster.tData(127 downto 96) := (others => '1'); -- Destination IP address ssiSetUserSof(EMAC_AXIS_CONFIG_C, v.txMaster, '1'); @@ -168,31 +176,84 @@ begin end if; -- Check for data and remote MAC is non-zero elsif (ibMasters(r.index).tValid = '1') and (v.txMaster.tValid = '0') then + -- Check if need to access ARP Table + if ibMasters(r.index).tDest = x"00" then + -- Check if link down and blowing off the data + if (r.linkUp(r.index) = '0') and TX_FLOW_CTRL_G then + -- Blow off the data + v.ibSlaves(r.index).tReady := '1'; + -- Check for SOF + elsif (ssiGetUserSof(EMAC_AXIS_CONFIG_C, ibMasters(r.index)) = '1') then + -- Check if link up + if (r.linkUp(r.index) = '1') then + -- Latch the index + v.chPntr := r.index; + -- Write the first header + v.txMaster.tValid := '1'; + v.txMaster.tData(47 downto 0) := remoteMac(r.index); -- Destination MAC address + v.txMaster.tData(63 downto 48) := x"0000"; -- All 0s + v.txMaster.tData(95 downto 64) := localIp; -- Source IP address + v.txMaster.tData(127 downto 96) := remoteIp(r.index); -- Destination IP address + ssiSetUserSof(EMAC_AXIS_CONFIG_C, v.txMaster, '1'); + -- Next state + v.state := HDR_S; + end if; + else + -- Blow off the data + v.ibSlaves(r.index).tReady := '1'; + end if; + else + v.chPntr := r.index; + arpPosV(r.index) := ibMasters(r.index).tDest; + v.state := ACC_ARP_TAB_S; + end if; + end if; + ----------------------------------------------------------------------- + when ACC_ARP_TAB_S => + arpPosV(r.chPntr) := ibMasters(r.chPntr).tDest; + if arpTabFound(r.chPntr) = '0' then + v.linkUp(r.chPntr) := '0'; + -- Blow off the data.. + v.ibSlaves(r.chPntr).tReady := '1'; + -- ..until the last frame + if (ssiGetUserEofe(EMAC_AXIS_CONFIG_C, ibMasters(r.chPntr)) = '1' or ibMasters(r.chPntr).tLast = '1') then + v.state := IDLE_S; + end if; + else -- Check if link down and blowing off the data - if (r.linkUp(r.index) = '0') and TX_FLOW_CTRL_G then - -- Blow off the data - v.ibSlaves(r.index).tReady := '1'; + if (r.linkUp(r.chPntr) = '0') and TX_FLOW_CTRL_G then + -- Blow off the data.. + v.ibSlaves(r.chPntr).tReady := '1'; + -- ..until the last frame + if (ssiGetUserEofe(EMAC_AXIS_CONFIG_C, ibMasters(r.chPntr)) = '1' or ibMasters(r.chPntr).tLast = '1') then + v.state := IDLE_S; + end if; -- Check for SOF - elsif (ssiGetUserSof(EMAC_AXIS_CONFIG_C, ibMasters(r.index)) = '1') then + elsif (ssiGetUserSof(EMAC_AXIS_CONFIG_C, ibMasters(r.chPntr)) = '1') then -- Check if link up - if (r.linkUp(r.index) = '1') then + if (r.linkUp(r.chPntr) = '1') then -- Latch the index - v.chPntr := r.index; + v.chPntr := r.chPntr; -- Write the first header v.txMaster.tValid := '1'; - v.txMaster.tData(47 downto 0) := remoteMac(r.index); -- Destination MAC address + v.txMaster.tData(47 downto 0) := arpTabMacAddr(r.chPntr); -- Destination MAC address v.txMaster.tData(63 downto 48) := x"0000"; -- All 0s v.txMaster.tData(95 downto 64) := localIp; -- Source IP address - v.txMaster.tData(127 downto 96) := remoteIp(r.index); -- Destination IP address + v.txMaster.tData(127 downto 96) := arpTabIpAddr(r.chPntr); -- Destination IP address ssiSetUserSof(EMAC_AXIS_CONFIG_C, v.txMaster, '1'); -- Next state v.state := HDR_S; end if; else - -- Blow off the data - v.ibSlaves(r.index).tReady := '1'; + -- Blow off the data.. + v.ibSlaves(r.chPntr).tReady := '1'; + -- ..until the last frame + if (ssiGetUserEofe(EMAC_AXIS_CONFIG_C, ibMasters(r.chPntr)) = '1' or ibMasters(r.chPntr).tLast = '1') then + v.state := IDLE_S; + end if; end if; end if; + ------------------------------------------------ -- Notes: Non-Standard IPv4 Pseudo Header Format ------------------------------------------------ @@ -382,6 +443,7 @@ begin obDhcpSlave <= v.obDhcpSlave; txMaster <= r.txMaster; linkUp <= r.linkUp; + arpTabPos <= arpPosV; -- Reset if (rst = '1') then diff --git a/ethernet/UdpEngine/rtl/UdpEngineWrapper.vhd b/ethernet/UdpEngine/rtl/UdpEngineWrapper.vhd index 7763736090..5816c74423 100644 --- a/ethernet/UdpEngine/rtl/UdpEngineWrapper.vhd +++ b/ethernet/UdpEngine/rtl/UdpEngineWrapper.vhd @@ -26,26 +26,28 @@ use surf.EthMacPkg.all; entity UdpEngineWrapper is generic ( -- Simulation Generics - TPD_G : time := 1 ns; + TPD_G : time := 1 ns; -- UDP Server Generics - SERVER_EN_G : boolean := true; - SERVER_SIZE_G : positive := 1; - SERVER_PORTS_G : PositiveArray := (0 => 8192); + SERVER_EN_G : boolean := true; + SERVER_SIZE_G : positive := 1; + SERVER_PORTS_G : PositiveArray := (0 => 8192); -- UDP Client Generics - CLIENT_EN_G : boolean := true; - CLIENT_SIZE_G : positive := 1; - CLIENT_PORTS_G : PositiveArray := (0 => 8193); - CLIENT_EXT_CONFIG_G : boolean := false; + CLIENT_EN_G : boolean := true; + CLIENT_TAG_IP_IN_TUSER : boolean := false; + CLIENT_SIZE_G : positive := 1; + CLIENT_PORTS_G : PositiveArray := (0 => 8193); + CLIENT_EXT_CONFIG_G : boolean := false; + ARP_TAB_ENTRIES_G : positive range 1 to 255 := 4; -- General IPv4/IGMP/ICMP/ARP/DHCP Generics - TX_FLOW_CTRL_G : boolean := true; -- True: Blow off the UDP TX data if link down, False: Backpressure until TX link is up - DHCP_G : boolean := false; - IGMP_G : boolean := false; - IGMP_GRP_SIZE : positive range 1 to 8 := 1; - IGMP_INIT_G : Slv32Array := (0 => x"0000_0000"); - CLK_FREQ_G : real := 156.25E+06; -- In units of Hz - COMM_TIMEOUT_G : positive := 30; -- In units of seconds, Client's Communication timeout before re-ARPing or DHCP discover/request - TTL_G : slv(7 downto 0) := x"20"; -- IPv4's Time-To-Live (TTL) - SYNTH_MODE_G : string := "inferred"); -- Synthesis mode for internal RAMs + TX_FLOW_CTRL_G : boolean := true; -- True: Blow off the UDP TX data if link down, False: Backpressure until TX link is up + DHCP_G : boolean := false; + IGMP_G : boolean := false; + IGMP_GRP_SIZE : positive range 1 to 8 := 1; + IGMP_INIT_G : Slv32Array := (0 => x"0000_0000"); + CLK_FREQ_G : real := 156.25E+06; -- In units of Hz + COMM_TIMEOUT_G : positive := 30; -- In units of seconds, Client's Communication timeout before re-ARPing or DHCP discover/request + TTL_G : slv(7 downto 0) := x"20"; -- IPv4's Time-To-Live (TTL) + SYNTH_MODE_G : string := "inferred"); -- Synthesis mode for internal RAMs port ( -- Local Configurations localMac : in slv(47 downto 0); -- big-Endian configuration @@ -164,23 +166,25 @@ begin UdpEngine_Inst : entity surf.UdpEngine generic map ( -- Simulation Generics - TPD_G => TPD_G, - IGMP_G => IGMP_G, - IGMP_GRP_SIZE => IGMP_GRP_SIZE, + TPD_G => TPD_G, + IGMP_G => IGMP_G, + IGMP_GRP_SIZE => IGMP_GRP_SIZE, -- UDP Server Generics - SERVER_EN_G => SERVER_EN_G, - SERVER_SIZE_G => SERVER_SIZE_G, - SERVER_PORTS_G => SERVER_PORTS_G, + SERVER_EN_G => SERVER_EN_G, + SERVER_SIZE_G => SERVER_SIZE_G, + SERVER_PORTS_G => SERVER_PORTS_G, -- UDP Client Generics - CLIENT_EN_G => CLIENT_EN_G, - CLIENT_SIZE_G => CLIENT_SIZE_G, - CLIENT_PORTS_G => CLIENT_PORTS_G, + CLIENT_EN_G => CLIENT_EN_G, + CLIENT_TAG_IP_IN_TUSER => CLIENT_TAG_IP_IN_TUSER, + CLIENT_SIZE_G => CLIENT_SIZE_G, + CLIENT_PORTS_G => CLIENT_PORTS_G, + ARP_TAB_ENTRIES_G => ARP_TAB_ENTRIES_G, -- UDP ARP/DHCP Generics - TX_FLOW_CTRL_G => TX_FLOW_CTRL_G, - DHCP_G => DHCP_G, - CLK_FREQ_G => CLK_FREQ_G, - COMM_TIMEOUT_G => COMM_TIMEOUT_G, - SYNTH_MODE_G => SYNTH_MODE_G) + TX_FLOW_CTRL_G => TX_FLOW_CTRL_G, + DHCP_G => DHCP_G, + CLK_FREQ_G => CLK_FREQ_G, + COMM_TIMEOUT_G => COMM_TIMEOUT_G, + SYNTH_MODE_G => SYNTH_MODE_G) port map ( -- Local Configurations localMac => localMac, diff --git a/ethernet/UdpEngine/tb/UdpEngineTb.vhd b/ethernet/UdpEngine/tb/UdpEngineTb.vhd index cdd6f66700..8971eb9b99 100644 --- a/ethernet/UdpEngine/tb/UdpEngineTb.vhd +++ b/ethernet/UdpEngine/tb/UdpEngineTb.vhd @@ -22,280 +22,337 @@ use surf.StdRtlPkg.all; use surf.AxiStreamPkg.all; use surf.SsiPkg.all; use surf.EthMacPkg.all; +use surf.AxiLitePkg.all; entity UdpEngineTb is end UdpEngineTb; architecture testbed of UdpEngineTb is - - constant CLK_PERIOD_C : time := 6.4 ns; - constant TPD_G : time := (CLK_PERIOD_C/4); - - constant MAC_ADDR_C : Slv48Array(1 downto 0) := ( - 0 => x"010300564400", --00:44:56:00:03:01 - 1 => x"020300564400"); --00:44:56:00:03:02 - - constant IP_ADDR_C : Slv32Array(1 downto 0) := ( - 0 => x"0A02A8C0", -- 192.168.2.10 - 1 => x"0B02A8C0"); -- 192.168.2.11 - - type RegType is record - packetLength : slv(31 downto 0); - trig : sl; - txBusy : sl; - errorDet : sl; - end record RegType; - - constant REG_INIT_C : RegType := ( - packetLength => toSlv(0, 32), - trig => '0', - txBusy => '0', - errorDet => '0'); - - signal r : RegType := REG_INIT_C; - signal rin : RegType; - - signal clk : sl := '0'; - signal rst : sl := '0'; - - signal txMaster : AxiStreamMasterType := AXI_STREAM_MASTER_INIT_C; - signal txSlave : AxiStreamSlaveType := AXI_STREAM_SLAVE_INIT_C; - - signal obMacMasters : AxiStreamMasterArray(1 downto 0) := (others => AXI_STREAM_MASTER_INIT_C); - signal obMacSlaves : AxiStreamSlaveArray(1 downto 0) := (others => AXI_STREAM_SLAVE_INIT_C); - - signal ibMacMasters : AxiStreamMasterArray(1 downto 0) := (others => AXI_STREAM_MASTER_INIT_C); - signal ibMacSlaves : AxiStreamSlaveArray(1 downto 0) := (others => AXI_STREAM_SLAVE_INIT_C); - - signal ethConfig : EthMacConfigArray(1 downto 0) := (others => ETH_MAC_CONFIG_INIT_C); - signal phyD : Slv64Array(1 downto 0) := (others => (others => '0')); - signal phyC : Slv8Array(1 downto 0) := (others => (others => '0')); - - signal rxMaster : AxiStreamMasterType := AXI_STREAM_MASTER_INIT_C; - signal rxSlave : AxiStreamSlaveType := AXI_STREAM_SLAVE_INIT_C; - - signal phyReady : sl; - signal updatedResults : sl; - signal errorDet : sl; - signal rxBusy : sl; - signal txBusy : sl; + constant NUM_CLIENT_C : positive := 3; + constant CLK_PERIOD_C : time := 6.4 ns; + constant TPD_G : time := (CLK_PERIOD_C/4); + + constant MAC_ADDR_C : Slv48Array(3 downto 0) := ( + 0 => x"010300564400", --00:44:56:00:03:01 + 1 => x"020300564400", --00:44:56:00:03:02 + 2 => x"030300564400", --00:44:56:00:03:03 + 3 => x"040300564400" --00:44:56:00:03:04 + ); + constant IP_ADDR_C : Slv32Array(3 downto 0) := ( + 0 => x"0A02A8C0", -- 192.168.2.10 + 1 => x"0B02A8C0", -- 192.168.2.11 + 2 => x"0C02A8C0", -- 192.168.2.12 + 3 => x"0D02A8C0" -- 192.168.2.13 + ); + + type RegType is record + packetLength : slv(31 downto 0); + trig : sl; + txBusy : sl; + errorDet : sl; + end record RegType; + + constant REG_INIT_C : RegType := ( + packetLength => toSlv(0, 32), + trig => '0', + txBusy => '0', + errorDet => '0'); + + signal r : RegType := REG_INIT_C; + signal rin : RegType; + + signal clk : sl := '0'; + signal rst : sl := '0'; + + signal txMaster : AxiStreamMasterType := AXI_STREAM_MASTER_INIT_C; + signal txSlave : AxiStreamSlaveType := AXI_STREAM_SLAVE_INIT_C; + + signal obMacMasters : AxiStreamMasterArray((NUM_CLIENT_C-1)+1 downto 0) := (others => AXI_STREAM_MASTER_INIT_C); + signal obMacSlaves : AxiStreamSlaveArray((NUM_CLIENT_C-1)+1 downto 0) := (others => AXI_STREAM_SLAVE_INIT_C); + + signal ibMacMasters : AxiStreamMasterArray((NUM_CLIENT_C-1)+1 downto 0) := (others => AXI_STREAM_MASTER_INIT_C); + signal ibMacSlaves : AxiStreamSlaveArray((NUM_CLIENT_C-1)+1 downto 0) := (others => AXI_STREAM_SLAVE_INIT_C); + + signal ethConfig : EthMacConfigArray((NUM_CLIENT_C-1)+1 downto 0) := (others => ETH_MAC_CONFIG_INIT_C); + signal phyD : Slv64Array((NUM_CLIENT_C-1)+1 downto 0) := (others => (others => '0')); + signal phyC : Slv8Array((NUM_CLIENT_C-1)+1 downto 0) := (others => (others => '0')); + signal phyD_def : slv(63 downto 0); + signal phyC_def : slv(7 downto 0); + + signal rxMaster : AxiStreamMasterType := AXI_STREAM_MASTER_INIT_C; + signal rxSlave : AxiStreamSlaveType := AXI_STREAM_SLAVE_INIT_C; + + signal phyReady : sl; + signal updatedResults : sl; + signal errorDet : sl; + signal rxBusy : sl; + signal txBusy : sl; + + signal remoteIpAddr : slv(31 downto 0); + signal tDest : slv(7 downto 0); + + signal sel_phy : natural; + signal axilReadMaster : AxiLiteReadMasterType := AXI_LITE_READ_MASTER_INIT_C; + signal axilReadSlave : AxiLiteReadSlaveType; + signal axilWriteMaster : AxiLiteWriteMasterType := AXI_LITE_WRITE_MASTER_INIT_C; + signal axilWriteSlave : AxiLiteWriteSlaveType; begin - ClkRst_Inst : entity surf.ClkRst - generic map ( - CLK_PERIOD_G => CLK_PERIOD_C, - RST_START_DELAY_G => 0 ns, - RST_HOLD_TIME_G => 1000 ns) - port map ( - clkP => clk, - clkN => open, - rst => rst, - rstL => phyReady); - - ---------- - -- PRBS TX - ---------- - U_TX : entity surf.SsiPrbsTx + ClkRst_Inst : entity surf.ClkRst + generic map ( + CLK_PERIOD_G => CLK_PERIOD_C, + RST_START_DELAY_G => 0 ns, + RST_HOLD_TIME_G => 1000 ns) + port map ( + clkP => clk, + clkN => open, + rst => rst, + rstL => phyReady); + + ---------- + -- PRBS TX + ---------- + U_TX : entity surf.SsiPrbsTx + generic map ( + TPD_G => TPD_G, + AXI_EN_G => '0', + MASTER_AXI_STREAM_CONFIG_G => EMAC_AXIS_CONFIG_C) + port map ( + -- Master Port (mAxisClk) + mAxisClk => clk, + mAxisRst => rst, + mAxisMaster => txMaster, + mAxisSlave => txSlave, + -- AxiLite + axilReadMaster => axilReadMaster, + axilReadSlave => axilReadSlave, + axilWriteMaster => axilWriteMaster, + axilWriteSlave => axilWriteSlave, + -- Trigger Signal (locClk domain) + locClk => clk, + locRst => rst, + packetLength => r.packetLength, + tDest => tDest, + trig => r.trig, + busy => txBusy); + + ---------------------------------------------------------------------------- + -- Set Remote IP addr + ---------------------------------------------------------------------------- + process is + begin -- process + remoteIpAddr <= (others => '0'); + sel_phy <= 1; + wait for 1300 ns; + wait until rising_edge(clk); + remoteIpAddr <= IP_ADDR_C(1); + sel_phy <= 1; + wait for 16 us; + wait until rising_edge(clk); + remoteIpAddr <= IP_ADDR_C(2); + sel_phy <= 2; + wait for 4 us; + wait until rising_edge(clk); + -- remoteIpAddr <= IP_ADDR_C(3); + -- sel_phy <= 3; + -- wait for 4 us; + -- wait until rising_edge(clk); + -- remoteIpAddr <= IP_ADDR_C(1); + -- tDest = 1 + -- axiLiteBusSimWrite(clk, axilWriteMaster, axilWriteSlave, x"00000008", x"01"); + tDest <= x"01"; + sel_phy <= 1; + wait; + end process; + + phyD_def <= phyD(sel_phy); + phyC_def <= phyC(sel_phy); + + ---------------------- + -- IPv4/ARP/UDP Engine + ---------------------- + U_UDP_Client : entity surf.UdpEngineWrapper + generic map ( + -- Simulation Generics + TPD_G => TPD_G, + -- UDP Server Generics + SERVER_EN_G => false, + -- UDP Client Generics + CLIENT_EN_G => true, + CLIENT_SIZE_G => 1, + CLIENT_PORTS_G => (0 => 8193), + CLIENT_EXT_CONFIG_G => true) + port map ( + -- Local Configurations + localMac => MAC_ADDR_C(0), + localIp => IP_ADDR_C(0), + -- Remote Configurations + clientRemotePort(0) => x"0020", -- PORT = 8192 = 0x2000 (0x0020 in big endianness) + clientRemoteIp(0) => remoteIpAddr, + -- Interface to Ethernet Media Access Controller (MAC) + obMacMaster => obMacMasters(0), + obMacSlave => obMacSlaves(0), + ibMacMaster => ibMacMasters(0), + ibMacSlave => ibMacSlaves(0), + -- Interface to UDP Server engine(s) + obClientMasters => open, + obClientSlaves(0) => AXI_STREAM_SLAVE_FORCE_C, + ibClientMasters(0) => txMaster, + ibClientSlaves(0) => txSlave, + -- Clock and Reset + clk => clk, + rst => rst); + + -------------------- + -- Ethernet MAC core + -------------------- + U_MAC0 : entity surf.EthMacTop + generic map ( + TPD_G => TPD_G, + PHY_TYPE_G => "XGMII", + PRIM_CONFIG_G => EMAC_AXIS_CONFIG_C) + port map ( + -- DMA Interface + primClk => clk, + primRst => rst, + ibMacPrimMaster => ibMacMasters(0), + ibMacPrimSlave => ibMacSlaves(0), + obMacPrimMaster => obMacMasters(0), + obMacPrimSlave => obMacSlaves(0), + -- Ethernet Interface + ethClk => clk, + ethRst => rst, + ethConfig => ethConfig(0), + phyReady => phyReady, + -- XGMII PHY Interface + xgmiiTxd => phyD(0), + xgmiiTxc => phyC(0), + xgmiiRxd => phyD_def, + xgmiiRxc => phyC_def); + ethConfig(0).macAddress <= MAC_ADDR_C(0); + + GEN_RX_MACS : for i in 0 to NUM_CLIENT_C-1 generate + U_MAC1 : entity surf.EthMacTop generic map ( - TPD_G => TPD_G, - AXI_EN_G => '0', - MASTER_AXI_STREAM_CONFIG_G => EMAC_AXIS_CONFIG_C) + TPD_G => TPD_G, + PHY_TYPE_G => "XGMII", + PRIM_CONFIG_G => EMAC_AXIS_CONFIG_C) port map ( - -- Master Port (mAxisClk) - mAxisClk => clk, - mAxisRst => rst, - mAxisMaster => txMaster, - mAxisSlave => txSlave, - -- Trigger Signal (locClk domain) - locClk => clk, - locRst => rst, - packetLength => r.packetLength, - trig => r.trig, - busy => txBusy); - - ---------------------- - -- IPv4/ARP/UDP Engine - ---------------------- - U_UDP_Client : entity surf.UdpEngineWrapper + -- DMA Interface + primClk => clk, + primRst => rst, + ibMacPrimMaster => ibMacMasters(i+1), + ibMacPrimSlave => ibMacSlaves(i+1), + obMacPrimMaster => obMacMasters(i+1), + obMacPrimSlave => obMacSlaves(i+1), + -- Ethernet Interface + ethClk => clk, + ethRst => rst, + ethConfig => ethConfig(i+1), + phyReady => phyReady, + -- XGMII PHY Interface + xgmiiTxd => phyD(i+1), + xgmiiTxc => phyC(i+1), + xgmiiRxd => phyD(0), + xgmiiRxc => phyC(0)); + ethConfig(i+1).macAddress <= MAC_ADDR_C(i+1); + + ---------------------- + -- IPv4/ARP/UDP Engine + ---------------------- + U_UDP_Server : entity surf.UdpEngineWrapper generic map ( - -- Simulation Generics - TPD_G => TPD_G, - -- UDP Server Generics - SERVER_EN_G => false, - -- UDP Client Generics - CLIENT_EN_G => true, - CLIENT_SIZE_G => 1, - CLIENT_PORTS_G => (0 => 8193), - CLIENT_EXT_CONFIG_G => true) + -- Simulation Generics + TPD_G => TPD_G, + -- UDP Server Generics + SERVER_EN_G => true, + SERVER_SIZE_G => 1, + SERVER_PORTS_G => (0 => 8192), + -- UDP Client Generics + CLIENT_EN_G => false) port map ( - -- Local Configurations - localMac => MAC_ADDR_C(0), - localIp => IP_ADDR_C(0), - -- Remote Configurations - clientRemotePort(0) => x"0020", -- PORT = 8192 = 0x2000 (0x0020 in big endianness) - clientRemoteIp(0) => IP_ADDR_C(1), - -- Interface to Ethernet Media Access Controller (MAC) - obMacMaster => obMacMasters(0), - obMacSlave => obMacSlaves(0), - ibMacMaster => ibMacMasters(0), - ibMacSlave => ibMacSlaves(0), - -- Interface to UDP Server engine(s) - obClientMasters => open, - obClientSlaves(0) => AXI_STREAM_SLAVE_FORCE_C, - ibClientMasters(0) => txMaster, - ibClientSlaves(0) => txSlave, - -- Clock and Reset - clk => clk, - rst => rst); - - -------------------- - -- Ethernet MAC core - -------------------- - U_MAC0 : entity surf.EthMacTop - generic map ( - TPD_G => TPD_G, - PHY_TYPE_G => "XGMII", - PRIM_CONFIG_G => EMAC_AXIS_CONFIG_C) - port map ( - -- DMA Interface - primClk => clk, - primRst => rst, - ibMacPrimMaster => ibMacMasters(0), - ibMacPrimSlave => ibMacSlaves(0), - obMacPrimMaster => obMacMasters(0), - obMacPrimSlave => obMacSlaves(0), - -- Ethernet Interface - ethClk => clk, - ethRst => rst, - ethConfig => ethConfig(0), - phyReady => phyReady, - -- XGMII PHY Interface - xgmiiRxd => phyD(0), - xgmiiRxc => phyC(0), - xgmiiTxd => phyD(1), - xgmiiTxc => phyC(1)); - ethConfig(0).macAddress <= MAC_ADDR_C(0); - - U_MAC1 : entity surf.EthMacTop - generic map ( - TPD_G => TPD_G, - PHY_TYPE_G => "XGMII", - PRIM_CONFIG_G => EMAC_AXIS_CONFIG_C) - port map ( - -- DMA Interface - primClk => clk, - primRst => rst, - ibMacPrimMaster => ibMacMasters(1), - ibMacPrimSlave => ibMacSlaves(1), - obMacPrimMaster => obMacMasters(1), - obMacPrimSlave => obMacSlaves(1), - -- Ethernet Interface - ethClk => clk, - ethRst => rst, - ethConfig => ethConfig(1), - phyReady => phyReady, - -- XGMII PHY Interface - xgmiiRxd => phyD(1), - xgmiiRxc => phyC(1), - xgmiiTxd => phyD(0), - xgmiiTxc => phyC(0)); - ethConfig(1).macAddress <= MAC_ADDR_C(1); - - ---------------------- - -- IPv4/ARP/UDP Engine - ---------------------- - U_UDP_Server : entity surf.UdpEngineWrapper - generic map ( - -- Simulation Generics - TPD_G => TPD_G, - -- UDP Server Generics - SERVER_EN_G => true, - SERVER_SIZE_G => 1, - SERVER_PORTS_G => (0 => 8192), - -- UDP Client Generics - CLIENT_EN_G => false) - port map ( - -- Local Configurations - localMac => MAC_ADDR_C(1), - localIp => IP_ADDR_C(1), - -- Interface to Ethernet Media Access Controller (MAC) - obMacMaster => obMacMasters(1), - obMacSlave => obMacSlaves(1), - ibMacMaster => ibMacMasters(1), - ibMacSlave => ibMacSlaves(1), - -- Interface to UDP Server engine(s) - obServerMasters(0) => rxMaster, - obServerSlaves(0) => rxSlave, - ibServerMasters(0) => AXI_STREAM_MASTER_INIT_C, - ibServerSlaves => open, - -- Clock and Reset - clk => clk, - rst => rst); - - ---------- - -- PRBS RX - ---------- - U_RX : entity surf.SsiPrbsRx - generic map ( - TPD_G => TPD_G, - SLAVE_AXI_STREAM_CONFIG_G => EMAC_AXIS_CONFIG_C) - port map ( - -- Slave Port (sAxisClk) - sAxisClk => clk, - sAxisRst => rst, - sAxisMaster => rxMaster, - sAxisSlave => rxSlave, - -- Error Detection Signals (sAxisClk domain) - updatedResults => updatedResults, - errorDet => errorDet, - busy => rxBusy); - - comb : process (errorDet, r, rst, txBusy) is - variable v : RegType; - begin - -- Latch the current value - v := r; - - -- Keep delay copies - v.errorDet := errorDet; - v.txBusy := txBusy; - v.trig := not(r.txBusy); - - -- Check for the packet completion - if (txBusy = '1') and (r.txBusy = '0') then - -- Sweeping the packet size size - v.packetLength := r.packetLength + 1; - -- Check for Jumbo frame roll over - if (r.packetLength = (8192/4)-1) then - -- Reset the counter - v.packetLength := (others => '0'); - end if; - end if; - - -- Reset - if (rst = '1') then - v := REG_INIT_C; - end if; - - --------------------------------- - -- Simulation Error Self-checking - --------------------------------- - if r.errorDet = '1' then - assert false - report "Simulation Failed!" severity failure; - end if; - - -- Register the variable for next clock cycle - rin <= v; - - end process comb; - - seq : process (clk) is - begin - if (rising_edge(clk)) then - r <= rin after TPD_G; + -- Local Configurations + localMac => MAC_ADDR_C(i+1), + localIp => IP_ADDR_C(i+1), + -- Interface to Ethernet Media Access Controller (MAC) + obMacMaster => obMacMasters(i+1), + obMacSlave => obMacSlaves(i+1), + ibMacMaster => ibMacMasters(i+1), + ibMacSlave => ibMacSlaves(i+1), + -- Interface to UDP Server engine(s) + obServerMasters(0) => rxMaster, + obServerSlaves(0) => rxSlave, + ibServerMasters(0) => AXI_STREAM_MASTER_INIT_C, + ibServerSlaves => open, + -- Clock and Reset + clk => clk, + rst => rst); + end generate GEN_RX_MACS; + + ---------- + -- PRBS RX + ---------- + U_RX : entity surf.SsiPrbsRx + generic map ( + TPD_G => TPD_G, + SLAVE_AXI_STREAM_CONFIG_G => EMAC_AXIS_CONFIG_C) + port map ( + -- Slave Port (sAxisClk) + sAxisClk => clk, + sAxisRst => rst, + sAxisMaster => rxMaster, + sAxisSlave => rxSlave, + -- Error Detection Signals (sAxisClk domain) + updatedResults => updatedResults, + errorDet => errorDet, + busy => rxBusy); + + comb : process (errorDet, r, rst, txBusy) is + variable v : RegType; + begin + -- Latch the current value + v := r; + + -- Keep delay copies + v.errorDet := errorDet; + v.txBusy := txBusy; + v.trig := not(r.txBusy); + + -- Check for the packet completion + if (txBusy = '1') and (r.txBusy = '0') then + -- Sweeping the packet size size + v.packetLength := r.packetLength + 1; + -- Check for Jumbo frame roll over + if (r.packetLength = (8192/4)-1) then + -- Reset the counter + v.packetLength := (others => '0'); end if; - end process seq; + end if; + + -- Reset + if (rst = '1') then + v := REG_INIT_C; + end if; + + --------------------------------- + -- Simulation Error Self-checking + --------------------------------- + --if r.errorDet = '1' then + -- assert false + -- report "Simulation Failed!" severity failure; + --end if; + + -- Register the variable for next clock cycle + rin <= v; + + end process comb; + + seq : process (clk) is + begin + if (rising_edge(clk)) then + r <= rin after TPD_G; + end if; + end process seq; end testbed;