1 ------------------------------------------------------------------------------- 2 -- File : UdpEngineDhcp.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2016-08-12 5 -- Last update: 2017-05-10 6 ------------------------------------------------------------------------------- 7 -- Description: DHCP Engine 8 ------------------------------------------------------------------------------- 9 -- This file is part of 'SLAC Firmware Standard Library'. 10 -- It is subject to the license terms in the LICENSE.txt file found in the 11 -- top-level directory of this distribution and at: 12 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. 13 -- No part of 'SLAC Firmware Standard Library', including this file, 14 -- may be copied, modified, propagated, or distributed except according to 15 -- the terms contained in the LICENSE.txt file. 16 ------------------------------------------------------------------------------- 19 use ieee.std_logic_1164.
all;
20 use ieee.std_logic_unsigned.
all;
21 use ieee.std_logic_arith.
all;
29 --! @ingroup ethernet_UdpEngine 32 -- Simulation Generics 34 -- UDP ARP/DHCP Generics 38 -- Local Configurations 39 localMac :
in slv(
47 downto 0); -- big-Endian
configuration 40 localIp :
in slv(
31 downto 0); -- big-Endian
configuration 41 dhcpIp : out slv(31 downto 0);
-- big-Endian configuration 42 -- Interface to DHCP Engine 55 constant TIMER_1_SEC_C : := getTimeRatio(CLK_FREQ_G, 1.
0);
56 constant CLIENT_HDR_C : slv(31 downto 0) := x"00060101";
-- 0x01010600 57 constant SERVER_HDR_C : slv(31 downto 0) := x"00060102";
-- 0x02010600 58 constant MAGIC_COOKIE_C : slv(31 downto 0) := x"63538263";
-- 0x63825363 73 type RegType is record 76 timer : range 0 to (TIMER_1_SEC_C-1);
77 commCnt : range 0 to COMM_TIMEOUT_C;
78 renewCnt : slv(30 downto 0);
79 leaseCnt : slv(31 downto 0);
80 leaseTime : slv(31 downto 0);
81 remoteMac : slv(47 downto 0);
82 remoteIp : slv(31 downto 0);
85 xid : slv(31 downto 0);
86 yiaddr : slv(31 downto 0);
87 siaddr : slv(31 downto 0);
88 yiaddrTemp : slv(31 downto 0);
89 siaddrTemp : slv(31 downto 0);
92 opCode : slv(7 downto 0);
93 len : slv(7 downto 0);
94 msgType : slv(7 downto 0);
100 constant REG_INIT_C : RegType := ( 104 commCnt => 3, -- Default to 3 seconds after bootup 105 renewCnt => (others => '0'), 106 leaseCnt => (others => '0'), 107 leaseTime => (others => '0'), 108 remoteMac => (others => '1'), -- Broadcast MAC Address 109 remoteIp => (others => '1'), -- Broadcast IP Address 110 dhcpIP => (others => '0'), 112 xid => (others => '0'), 113 yiaddr => (others => '0'), 114 siaddr => (others => '0'), 115 yiaddrTemp => (others => '0'), 116 siaddrTemp => (others => '0'), 118 valid => (others => '0'), 119 opCode => (others => '0'), 120 len => (others => '0'), 121 msgType => (others => '0'), 127 signal r : RegType := REG_INIT_C;
128 signal rin : RegType;
135 -- attribute dont_touch : string; 136 -- attribute dont_touch of r : signal is "TRUE"; 142 -- General Configurations 148 -- FIFO configurations 154 -- AXI Stream Port Configurations 170 variable v : RegType;
174 -- Latch the current value 180 if txSlave.tReady = '1' then 182 v.txMaster.tLast := '0';
183 v.txMaster.tUser := (others => '0');
186 -- Check 1 second heartbeat timeout 187 if r.timer = (TIMER_1_SEC_C-1) then 190 -- Set the timeout flag 193 -- Increment the counter 194 v.timer := r.timer + 1;
197 -- Check for heart beat 198 if (r.heartbeat = '1') then 199 -- Check Communication timer 200 if (r.commCnt /= 0) then 201 -- Decrement the counter 202 v.commCnt := r.commCnt - 1;
204 -- Check DHCP renewal timer 205 if (r.renewCnt /= 0) then 206 -- Decrement the counter 207 v.renewCnt := r.renewCnt - 1;
209 -- Check DHCP lease timer 210 if (r.leaseCnt /= 0) then 211 -- Decrement the counter 212 v.leaseCnt := r.leaseCnt - 1;
213 -- Check for DHCP lease expire event 214 if (r.leaseCnt = 1) then 217 -- Reset the renewal counter 218 v.renewCnt := (others => '0');
219 -- Broadcast the MAC/IP addresses 220 v.remoteMac := (others => '1');
221 v.remoteIp := (others => '1');
224 -- Set DHCP IP address to local value 229 -- Update the variables 230 tData := rxMaster.tData((8*r.index)+7 downto (8*r.index));
235 ---------------------------------------------------------------------- 237 -- Check for inbound data 238 if (rxMaster.tValid = '1') then 241 -- Check for SOF with no EOF 242 if (ssiGetUserSof(DHCP_CONFIG_C, rxMaster) = '1') and (rxMaster.tLast = '0') then 243 -- Check for valid DHCP server OP/HTYPE/HLEN/HOPS 244 if rxMaster.tData(31 downto 0) = SERVER_HDR_C then 245 -- Preset the counter 252 -- Check DHCP renewal timer 253 if (r.renewCnt = 0) then 254 -- Check for communication timeout 255 if r.commCnt = 0 then 258 -- Increment the counter 265 ---------------------------------------------------------------------- 267 -- Check if ready to move data 268 if v.txMaster.tValid = '0' then 269 -- Set the default value 271 v.txMaster.tData(31 downto 0) := (others => '0');
272 -- Increment the counter 276 -- OP/HTYPE/HLEN/HOPS 278 v.txMaster.tData(31 downto 0) := CLIENT_HDR_C;
279 ssiSetUserSof(DHCP_CONFIG_C, v.txMaster, '1');
282 -- Save the XID as big Endian 283 v.txMaster.tData(31 downto 24) := r.xid(7 downto 0);
284 v.txMaster.tData(23 downto 16) := r.xid(15 downto 8);
285 v.txMaster.tData(15 downto 8) := r.xid(23 downto 16);
286 v.txMaster.tData(7 downto 0) := r.xid(31 downto 24);
289 v.txMaster.tData(31 downto 0) := x"00080000";
292 -- Check for DHCP request 293 if r.dhcpReq = '1' then 294 v.txMaster.tData(31 downto 0) := r.siaddr;
304 v.txMaster.tData(31 downto 0) := MAGIC_COOKIE_C;
307 -- Check for DHCP Discover 308 if r.dhcpReq = '0' then 309 v.txMaster.tData(7 downto 0) := toSlv(53, 8);
-- code = DHCP Message Type 310 v.txMaster.tData(15 downto 8) := x"01";
-- len = 1 byte 311 v.txMaster.tData(23 downto 16) := x"01";
-- DHCP Discover = 0x1 312 v.txMaster.tLast := '1';
313 -- Start the communication timer 314 v.commCnt := COMM_TIMEOUT_C;
320 v.txMaster.tData(7 downto 0) := toSlv(53, 8);
-- code = DHCP Message Type 321 v.txMaster.tData(15 downto 8) := x"01";
-- len = 1 byte 322 v.txMaster.tData(23 downto 16) := x"03";
-- DHCP request = 0x3 324 -- Requested IP address[15:0] 326 v.txMaster.tData(7 downto 0) := toSlv(50, 8);
-- code = Requested IP address 327 v.txMaster.tData(15 downto 8) := x"04";
-- len = 4 byte 328 v.txMaster.tData(31 downto 16) := r.yiaddr(15 downto 0);
-- YIADDR[15:0] 329 -- Requested IP address[32:16] 331 v.txMaster.tData(15 downto 0) := r.yiaddr(31 downto 16);
-- YIADDR[31:16] 332 -- Server Identifier[15:0] 334 v.txMaster.tData(7 downto 0) := toSlv(54, 8);
-- code = Server Identifier 335 v.txMaster.tData(15 downto 8) := x"04";
-- len = 4 byte 336 v.txMaster.tData(31 downto 16) := r.siaddr(15 downto 0);
-- SIADDR[15:0] 337 -- Server Identifier[32:16] 339 v.txMaster.tData(15 downto 0) := r.siaddr(31 downto 16);
-- SIADDR[31:16] 340 v.txMaster.tLast := '1';
341 -- Start the communication timer 342 v.commCnt := COMM_TIMEOUT_C;
351 ---------------------------------------------------------------------- 353 -- Check for request data 354 if (rxMaster.tValid = '1') then 357 -- Increment the counter 363 -- Check if XID doesn't match 364 if (rxMaster.tData(31 downto 24) /= r.xid(7 downto 0)) 365 or (rxMaster.tData(23 downto 16) /= r.xid(15 downto 8)) 366 or (rxMaster.tData(15 downto 8) /= r.xid(23 downto 16)) 367 or (rxMaster.tData(7 downto 0) /= r.xid(31 downto 24)) then 373 v.yiaddrTemp := rxMaster.tData(31 downto 0);
376 v.siaddrTemp := rxMaster.tData(31 downto 0);
379 -- Check if CHADDR[31:0] doesn't match 386 -- Check if CHADDR[47:32] doesn't match 387 if rxMaster.tData(15 downto 0) /= localMac(47 downto 32) then 393 -- Check if Magic cookie doesn't match 394 if rxMaster.tData(31 downto 0) /= MAGIC_COOKIE_C then 399 v.valid := (others => '0');
408 -- Check for early packet termination 409 if (rxMaster.tLast = '1') then 414 ---------------------------------------------------------------------- 416 -- Check for request data 417 if (rxMaster.tValid = '1') then 418 -- Decode State Machine 420 ---------------------------------------------------------------- 422 -- Save the OP-code value 424 -- Check for not "PAD" and not "End" OP-code 429 ---------------------------------------------------------------- 433 -- Check for non-zero length 437 else -- Error detected 441 ---------------------------------------------------------------- 443 -- Decrement the counter 445 -- Check for last byte 451 if (r.opCode = 53) then -- Note: Assuming zero padding 452 -- Check for DHCP Message Type 460 -- Check for IP address Lease Time 461 elsif (r.opcode = 51) then 465 v.leaseTime(31 downto 24) := tData;
469 v.leaseTime(23 downto 16) := tData;
473 v.leaseTime(15 downto 8) := tData;
477 v.leaseTime(7 downto 0) := tData;
481 ---------------------------------------------------------------- 490 v.index := r.index + 1;
492 -- Check for last transfer 493 if (rxMaster.tLast = '1') and (getTKeep(tKeep) = (r.index+1)) then 495 if ssiGetUserEofe(DHCP_CONFIG_C, rxMaster) = '0' then 504 ---------------------------------------------------------------------- 507 if uAnd(r.valid) = '1' then 509 v.yiaddr := r.yiaddrTemp;
510 v.siaddr := r.siaddrTemp;
511 -- Check for "DHCP Discover" request and "DHCP Offer" reply 512 if (r.dhcpReq = '0') and (r.msgType = 2) then 515 -- Reset counter to immediately start the "DHCP request" 517 -- Check for "DHCP request" request and "DHCP ACK" reply 518 elsif (r.dhcpReq = '1') and (r.msgType = 5) then 519 -- Set the DHCP address 521 -- Clients begin to attempt to renew their leases 522 -- once half the lease interval has expired. 523 v.renewCnt := r.leaseTime(31 downto 1);
524 v.leaseCnt := r.leaseTime;
529 ---------------------------------------------------------------------- 537 -- Register the variable for next clock cycle 541 rxSlave <= v.rxSlave;
542 txMaster <= r.txMaster;
547 seq :
process (
clk)
is 549 if rising_edge(clk) then 550 r <= rin after TPD_G;
556 -- General Configurations 562 -- FIFO configurations 568 -- AXI Stream Port Configurations
FIFO_ADDR_WIDTH_Ginteger range 4 to 48:= 9
out dhcpIpslv( 31 downto 0)
in ibDhcpMasterAxiStreamMasterType
PIPE_STAGES_Gnatural range 0 to 16:= 1
out obDhcpMasterAxiStreamMasterType
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
SLAVE_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
SLAVE_READY_EN_Gboolean := true
GEN_SYNC_FIFO_Gboolean := false
out ibDhcpSlaveAxiStreamSlaveType
in localIpslv( 31 downto 0)
in localMacslv( 47 downto 0)
INT_PIPE_STAGES_Gnatural range 0 to 16:= 0
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
CLK_FREQ_Greal := 156.25E+06
out sAxisSlaveAxiStreamSlaveType
COMM_TIMEOUT_Gpositive := 30
in sAxisMasterAxiStreamMasterType
out mAxisMasterAxiStreamMasterType
in mAxisSlaveAxiStreamSlaveType
CASCADE_SIZE_Ginteger range 1 to ( 2** 24):= 1
USE_BUILT_IN_Gboolean := false
VALID_THOLD_Ginteger range 0 to ( 2** 24):= 1
MASTER_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
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 obDhcpSlaveAxiStreamSlaveType