1 ------------------------------------------------------------------------------- 2 -- File : EthMacTxCsum.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2016-09-08 5 -- Last update: 2017-02-22 6 ------------------------------------------------------------------------------- 7 -- Description: TX Checksum Hardware Offloading Engine 8 -- https://docs.google.com/spreadsheets/d/1_1M1keasfq8RLmRYHkO0IlRhMq5YZTgJ7OGrWvkib8I/edit?usp=sharing 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_arith.
all;
22 use ieee.std_logic_unsigned.
all;
29 --! @ingroup ethernet_EthMacCore 45 -- Outbound data to MAC 54 constant MAX_FRAME_SIZE_C : := ite(JUMBO_G, 9000, 1500);
63 type RegType is record 72 ipv4Csum : slv(15 downto 0);
74 protCsum : slv(15 downto 0);
77 len : slv(15 downto 0);
82 dbg : slv(5 downto 0);
89 constant REG_INIT_C : RegType := ( 91 fragDet => (others => '0'), 92 eofeDet => (others => '0'), 93 ipv4Det => (others => '0'), 94 udpDet => (others => '0'), 95 tcpDet => (others => '0'), 97 ipv4Len => (others => (others => '0')), 98 ipv4Csum => (others => '0'), 99 protLen => (others => (others => '0')), 100 protCsum => (others => '0'), 101 ipv4Hdr => (others => (others => '0')), 103 len => (others => '0'), 104 tKeep => (others => '0'), 105 tData => (others => '0'), 108 dbg => (others => '0'), 115 signal r : RegType := REG_INIT_C;
116 signal rin : RegType;
127 signal tranPause : sl;
133 signal ipv4Len : slv(15 downto 0);
134 signal ipv4Csum : slv(15 downto 0);
135 signal protLen : slv(15 downto 0);
136 signal protCsum : slv(15 downto 0);
137 signal tranValid : sl;
139 -- attribute dont_touch : string; 140 -- attribute dont_touch of r : signal is "TRUE"; 141 -- attribute dont_touch of fragDet : signal is "TRUE"; 142 -- attribute dont_touch of eofeDet : signal is "TRUE"; 143 -- attribute dont_touch of ipv4Det : signal is "TRUE"; 144 -- attribute dont_touch of udpDet : signal is "TRUE"; 145 -- attribute dont_touch of tcpDet : signal is "TRUE"; 146 -- attribute dont_touch of ipv4Len : signal is "TRUE"; 147 -- attribute dont_touch of ipv4Csum : signal is "TRUE"; 148 -- attribute dont_touch of protLen : signal is "TRUE"; 149 -- attribute dont_touch of protCsum : signal is "TRUE"; 150 -- attribute dont_touch of tranValid : signal is "TRUE"; 151 -- attribute dont_touch of mMaster : signal is "TRUE"; 152 -- attribute dont_touch of mSlave : signal is "TRUE"; 168 comb :
process (eofeDet,
ethRst, fragDet,
ipCsumEn, ipv4Csum, ipv4Det,
169 ipv4Len, mMaster, protCsum, protLen, r, rxMaster, sSlave,
172 variable v : RegType;
173 variable dummy : slv(1 downto 0);
175 -- Latch the current value 181 v.dbg := (others => '0');
182 v.tKeep := (others => '0');
184 if sSlave.tReady = '1' then 188 if txSlave.tReady = '1' then 199 x"0000", -- Unused in TX CSUM 202 dummy(0), -- Unused in TX CSUM 204 dummy(1), -- Unused in TX CSUM 207 -- Pipeline alignment to GetEthMacCsum() 216 -- Check for UDP frame 218 -- Multiple length by 2 to combine UDP length and IPV4 Pseudo Header's length together 221 -- TCP only has IPV4 Pseudo Header's length together 227 ---------------------------------------------------------------------- 236 -- Reset accumulators 237 v.ipv4Len(0) := toSlv(20, 16);
238 v.protLen(0) := (others => '0');
239 -- Check if ready to move data 240 if (rxMaster.tValid = '1') and (v.sMaster.tValid = '0') and (tranPause = '0') then 244 v.sMaster := rxMaster;
248 if (rxMaster.tLast = '1') then 249 -- Save the EOFE value 251 -- Write the transaction data 256 -- Check for EtherType = IPV4 = 0x0800 261 -- Fill in the IPv4 header checksum 262 v.ipv4Hdr(0) := rxMaster.tData(119 downto 112);
-- IPVersion + Header length 263 v.ipv4Hdr(1) := rxMaster.tData(127 downto 120);
-- DSCP and ECN 265 -- Add the IEEE 802.1Q header 267 v.sMaster.tData(119 downto 112) := x"0" & VID_G(11 downto 8);
268 v.sMaster.tData(127 downto 120) := VID_G(7 downto 0);
271 v.state := IPV4_HDR0_S;
274 ---------------------------------------------------------------------- 276 -- Check if ready to move data 277 if (rxMaster.tValid = '1') and (v.sMaster.tValid = '0') and (tranPause = '0') then 281 v.sMaster := rxMaster;
283 if (rxMaster.tLast = '1') then 284 -- if IPv4 detected, ETH frame too short 285 if (r.ipv4Det(0) = '1') then 286 -- Set the error flag 289 -- Save the EOFE value 292 -- Write the transaction data 299 -- Fill in the IPv4 header checksum 300 v.ipv4Hdr(4) := rxMaster.tData(23 downto 16);
-- IPV4_ID(15 downto 8) 301 v.ipv4Hdr(5) := rxMaster.tData(31 downto 24);
-- IPV4_ID(7 downto 0) 302 v.ipv4Hdr(6) := rxMaster.tData(39 downto 32);
-- Flags(2 downto 0) and Fragment Offsets(12 downto 8) 303 v.ipv4Hdr(7) := rxMaster.tData(47 downto 40);
-- Fragment Offsets(7 downto 0) 304 v.ipv4Hdr(8) := rxMaster.tData(55 downto 48);
-- Time-To-Live 305 v.ipv4Hdr(9) := rxMaster.tData(63 downto 56);
-- Protocol 306 v.ipv4Hdr(12) := rxMaster.tData(87 downto 80);
-- Source IP Address 307 v.ipv4Hdr(13) := rxMaster.tData(95 downto 88);
-- Source IP Address 308 v.ipv4Hdr(14) := rxMaster.tData(103 downto 96);
-- Source IP Address 309 v.ipv4Hdr(15) := rxMaster.tData(111 downto 104);
-- Source IP Address 310 v.ipv4Hdr(16) := rxMaster.tData(119 downto 112);
-- Destination IP Address 311 v.ipv4Hdr(17) := rxMaster.tData(127 downto 120);
-- Destination IP Address 312 -- Fill in the TCP/UDP checksum 313 v.tData(63 downto 0) := rxMaster.tData(127 downto 80) & rxMaster.tData(63 downto 56) & x"00";
314 v.tKeep(7 downto 0) := (others => '1');
316 -- Check for EtherType = IPV4 = 0x0800 321 -- Fill in the IPv4 header checksum 322 v.ipv4Hdr(0) := rxMaster.tData(23 downto 16);
-- IPVersion + Header length 323 v.ipv4Hdr(1) := rxMaster.tData(31 downto 24);
-- DSCP and ECN 324 v.ipv4Hdr(4) := rxMaster.tData(55 downto 48);
-- IPV4_ID(15 downto 8) 325 v.ipv4Hdr(5) := rxMaster.tData(63 downto 56);
-- IPV4_ID(7 downto 0) 326 v.ipv4Hdr(6) := rxMaster.tData(71 downto 64);
-- Flags(2 downto 0) and Fragment Offsets(12 downto 8) 327 v.ipv4Hdr(7) := rxMaster.tData(79 downto 72);
-- Fragment Offsets(7 downto 0) 328 v.ipv4Hdr(8) := rxMaster.tData(87 downto 80);
-- Time-To-Live 329 v.ipv4Hdr(9) := rxMaster.tData(95 downto 88);
-- Protocol 330 v.ipv4Hdr(12) := rxMaster.tData(119 downto 112);
-- Source IP Address 331 v.ipv4Hdr(13) := rxMaster.tData(127 downto 120);
-- Source IP Address 332 -- Fill in the TCP/UDP checksum 333 v.tData(31 downto 0) := rxMaster.tData(127 downto 119) & rxMaster.tData(95 downto 88) & x"00";
334 v.tKeep(3 downto 0) := (others => '1');
336 -- Check for UDP protocol 337 if (v.ipv4Hdr(9) = UDP_C) then 340 -- Check for TCP protocol 341 if (v.ipv4Hdr(9) = TCP_C) then 345 v.state := IPV4_HDR1_S;
348 ---------------------------------------------------------------------- 350 -- Check if ready to move data 351 if (rxMaster.tValid = '1') and (v.sMaster.tValid = '0') and (tranPause = '0') then 355 v.sMaster := rxMaster;
356 -- Fill in the TCP/UDP checksum 361 -- Fill in the IPv4 header checksum 362 v.ipv4Hdr(18) := rxMaster.tData(7 downto 0);
-- Destination IP Address 363 v.ipv4Hdr(19) := rxMaster.tData(15 downto 8);
-- Destination IP Address 364 -- Check for UDP data with inbound length/checksum 365 if (r.ipv4Det(0) = '1') and (r.udpDet(0) = '1') then 366 -- Mask off inbound UDP length/checksum 367 v.tData := rxMaster.tData(127 downto 80) & x"00000000" & rxMaster.tData(47 downto 0);
369 -- Track the number of bytes 370 v.ipv4Len(0) := r.ipv4Len(0) + getTKeep(rxMaster.tKeep) - 2;
371 v.protLen(0) := r.protLen(0) + getTKeep(rxMaster.tKeep) - 2;
373 -- Fill in the IPv4 header checksum 374 v.ipv4Hdr(14) := rxMaster.tData(7 downto 0);
-- Source IP Address 375 v.ipv4Hdr(15) := rxMaster.tData(15 downto 8);
-- Source IP Address 376 v.ipv4Hdr(16) := rxMaster.tData(23 downto 16);
-- Destination IP Address 377 v.ipv4Hdr(17) := rxMaster.tData(31 downto 24);
-- Destination IP Address 378 v.ipv4Hdr(18) := rxMaster.tData(39 downto 32);
-- Destination IP Address 379 v.ipv4Hdr(19) := rxMaster.tData(47 downto 40);
-- Destination IP Address 380 -- Check for UDP data with inbound length/checksum 381 if (r.ipv4Det(0) = '1') and (r.udpDet(0) = '1') then 382 -- Mask off inbound UDP length/checksum 383 v.tData := rxMaster.tData(127 downto 112) & x"00000000" & rxMaster.tData(79 downto 0);
385 -- Track the number of bytes 386 v.ipv4Len(0) := r.ipv4Len(0) + getTKeep(rxMaster.tKeep) - 6;
387 v.protLen(0) := r.protLen(0) + getTKeep(rxMaster.tKeep) - 6;
390 if (rxMaster.tLast = '1') then 391 -- Save the EOFE value 393 -- Write the transaction data 402 ---------------------------------------------------------------------- 404 -- Check if ready to move data 405 if (rxMaster.tValid = '1') and (v.sMaster.tValid = '0') and (tranPause = '0') then 409 v.sMaster := rxMaster;
410 -- Fill in the TCP/UDP checksum 413 -- Check for TCP data with inbound checksum 414 if (r.ipv4Det(0) = '1') and (r.tcpDet(0) = '1') and (r.tcpFlag = '0') then 419 -- Mask off inbound TCP checksum 420 v.tData := rxMaster.tData(127 downto 32) & x"0000" & rxMaster.tData(15 downto 0);
422 -- Mask off inbound TCP checksum 423 v.tData := rxMaster.tData(127 downto 64) & x"0000" & rxMaster.tData(47 downto 0);
426 -- Track the number of bytes 427 v.ipv4Len(0) := r.ipv4Len(0) + getTKeep(rxMaster.tKeep);
428 v.protLen(0) := r.protLen(0) + getTKeep(rxMaster.tKeep);
430 if (rxMaster.tLast = '1') or (v.ipv4Len(0) > MAX_FRAME_SIZE_C) then 431 -- Save the EOFE value 433 -- Check for overflow 434 if (rxMaster.tLast = '0') then 437 -- Write the transaction data 440 v.state := BLOWOFF_S;
442 -- Write the transaction data 449 ---------------------------------------------------------------------- 451 -- Check if ready to move data 452 if (rxMaster.tValid = '1') and (v.sMaster.tValid = '0') then 456 if (rxMaster.tLast = '1') then 461 ---------------------------------------------------------------------- 464 -- Fill in the IPv4 header 465 v.ipv4Hdr(2) := v.ipv4Len(0)(15 downto 8);
-- IPV4_Length(15 downto 8) 466 v.ipv4Hdr(3) := v.ipv4Len(0)(7 downto 0);
-- IPV4_Length(7 downto 0) 468 -- Wait for the transaction data 469 if (tranValid = '1') and (r.tranRd = '0') then 471 if (mMaster.tValid = '1') and (v.txMaster.tValid = '0') then 475 v.txMaster := mMaster;
476 -- Check if not forwarding EOFE frames 481 -- Check the counter size 482 if (r.mvCnt /= 4) then 483 -- Increment the counter 484 v.mvCnt := r.mvCnt + 1;
486 -- Check for IPv4 checksum/length insertion 487 if (ipv4Det = '1') and (r.mvCnt = 1) then 490 -- Check if firmware checksum enabled 492 -- Overwrite the data field 493 v.txMaster.tData(7 downto 0) := ipv4Len(15 downto 8);
494 v.txMaster.tData(15 downto 8) := ipv4Len(7 downto 0);
495 v.txMaster.tData(71 downto 64) := ipv4Csum(15 downto 8);
496 v.txMaster.tData(79 downto 72) := ipv4Csum(7 downto 0);
498 -- Check for mismatch between firmware/software IPv4 length 499 if (ipv4Len(15 downto 8) /= mMaster.tData(7 downto 0)) or (ipv4Len(7 downto 0) /= mMaster.tData(15 downto 8)) then 503 -- Check for mismatch between firmware/software IPv4 checksum 504 if (ipv4Csum(15 downto 8) /= mMaster.tData(71 downto 64)) or (ipv4Csum(7 downto 0) /= mMaster.tData(79 downto 72)) then 509 -- Check if firmware checksum enabled 511 -- Overwrite the data field 512 v.txMaster.tData(39 downto 32) := ipv4Len(15 downto 8);
513 v.txMaster.tData(47 downto 40) := ipv4Len(7 downto 0);
514 v.txMaster.tData(103 downto 96) := ipv4Csum(15 downto 8);
515 v.txMaster.tData(111 downto 104) := ipv4Csum(7 downto 0);
517 -- Check for mismatch between firmware/software IPv4 length 518 if (ipv4Len(15 downto 8) /= mMaster.tData(39 downto 32)) or (ipv4Len(7 downto 0) /= mMaster.tData(47 downto 40)) then 522 -- Check for mismatch between firmware/software IPv4 checksum 523 if (ipv4Csum(15 downto 8) /= mMaster.tData(103 downto 96)) or (ipv4Csum(7 downto 0) /= mMaster.tData(111 downto 104)) then 529 -- Check for UDP checksum/length insertion and no fragmentation 530 if (ipv4Det = '1') and (udpDet = '1') and (fragDet = '0') and (r.mvCnt = 2) then 533 -- Check if firmware checksum enabled 535 -- Overwrite the data field 536 v.txMaster.tData(55 downto 48) := protLen(15 downto 8);
537 v.txMaster.tData(63 downto 56) := protLen(7 downto 0);
538 v.txMaster.tData(71 downto 64) := protCsum(15 downto 8);
539 v.txMaster.tData(79 downto 72) := protCsum(7 downto 0);
541 -- Check for mismatch between firmware/software UDP length 542 if (protLen(15 downto 8) /= mMaster.tData(55 downto 48)) or (protLen(7 downto 0) /= mMaster.tData(63 downto 56)) then 546 -- Check for mismatch between firmware/software UDP checksum 547 if (protCsum(15 downto 8) /= mMaster.tData(71 downto 64)) or (protCsum(7 downto 0) /= mMaster.tData(79 downto 72)) then 552 -- Check if firmware checksum enabled 554 -- Overwrite the data field 555 v.txMaster.tData(87 downto 80) := protLen(15 downto 8);
556 v.txMaster.tData(95 downto 88) := protLen(7 downto 0);
557 v.txMaster.tData(103 downto 96) := protCsum(15 downto 8);
558 v.txMaster.tData(111 downto 104) := protCsum(7 downto 0);
560 -- Check for mismatch between firmware/software UDP length 561 if (protLen(15 downto 8) /= mMaster.tData(87 downto 80)) or (protLen(7 downto 0) /= mMaster.tData(95 downto 88)) then 565 -- Check for mismatch between firmware/software UDP checksum 566 if (protCsum(15 downto 8) /= mMaster.tData(103 downto 96)) or (protCsum(7 downto 0) /= mMaster.tData(111 downto 104)) then 572 -- Check for TCP checksum insertion and no fragmentation 573 if (ipv4Det = '1') and (tcpDet = '1') and (fragDet = '0') and (r.mvCnt = 3) then 576 -- Check if firmware checksum enabled 578 -- Overwrite the data field 579 v.txMaster.tData(23 downto 16) := protCsum(15 downto 8);
580 v.txMaster.tData(31 downto 24) := protCsum(7 downto 0);
582 -- Check for mismatch between firmware/software TCP checksum 583 if (protCsum(15 downto 8) /= mMaster.tData(23 downto 16)) or (protCsum(7 downto 0) /= mMaster.tData(31 downto 24)) then 588 -- Check if firmware checksum enabled 590 -- Overwrite the data field 591 v.txMaster.tData(55 downto 48) := protCsum(15 downto 8);
592 v.txMaster.tData(63 downto 56) := protCsum(7 downto 0);
594 -- Check for mismatch between firmware/software TCP checksum 595 if (protCsum(15 downto 8) /= mMaster.tData(55 downto 48)) or (protCsum(7 downto 0) /= mMaster.tData(63 downto 56)) then 602 if (mMaster.tLast = '1') then 619 -- Register the variable for next clock cycle 623 rxSlave <= v.rxSlave;
624 sMaster <= r.sMaster;
626 txMaster <= r.txMaster;
632 if rising_edge(ethClk) then 633 r <= rin after TPD_G;
639 -- General Configurations 645 -- FIFO configurations 651 -- AXI Stream Port Configurations 677 --Write Ports (wr_clk domain) 679 din
(68) => r.fragDet
(EMAC_CSUM_PIPELINE_C+1
),
680 din
(67) => r.eofeDet
(EMAC_CSUM_PIPELINE_C+1
),
681 din
(66) => r.ipv4Det
(EMAC_CSUM_PIPELINE_C+1
),
682 din
(65) => r.udpDet
(EMAC_CSUM_PIPELINE_C+1
),
683 din
(64) => r.tcpDet
(EMAC_CSUM_PIPELINE_C+1
),
684 din
(63 downto 48) => r.ipv4Len
(EMAC_CSUM_PIPELINE_C+1
),
685 din
(47 downto 32) => r.ipv4Csum,
686 din
(31 downto 16) => r.protLen
(EMAC_CSUM_PIPELINE_C+1
),
687 din
(15 downto 0) => r.protCsum,
689 --Read Ports (rd_clk domain) 696 dout
(63 downto 48) => ipv4Len,
697 dout
(47 downto 32) => ipv4Csum,
698 dout
(31 downto 16) => protLen,
699 dout
(15 downto 0) => protCsum,
FIFO_ADDR_WIDTH_Ginteger range 4 to 48:= 9
PIPE_STAGES_Gnatural range 0 to 16:= 0
ADDR_WIDTH_Ginteger range 4 to 48:= 4
out mAxisMasterAxiStreamMasterType
in mAxisSlaveAxiStreamSlaveType
VID_Gslv( 11 downto 0) := x"001"
PIPE_STAGES_Gnatural range 0 to 16:= 1
in rstsl :=not RST_POLARITY_G
slv( 7 downto 0) := x"06" TCP_C
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
SLAVE_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
out sAxisSlaveAxiStreamSlaveType
SLAVE_READY_EN_Gboolean := true
in mAxisSlaveAxiStreamSlaveType
slv( EMAC_CSUM_PIPELINE_C downto 0) step
GEN_SYNC_FIFO_Gboolean := false
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
integer := 0 EMAC_FRAG_BIT_C
EthMacCsumAccumType :=(step =>( others => '0'),sum1 =>( others =>( others => '0')),sum3 =>( others => '0'),sum5 =>( others => '0')) ETH_MAC_CSUM_ACCUM_INIT_C
FULL_THRES_Ginteger range 1 to ( 2** 24):= 1
INT_PIPE_STAGES_Gnatural range 0 to 16:= 0
natural := 3 EMAC_CSUM_PIPELINE_C
in sAxisMasterAxiStreamMasterType
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
in sAxisMasterAxiStreamMasterType
integer := 0 EMAC_EOFE_BIT_C
DROP_ERR_PKT_Gboolean := true
out sAxisSlaveAxiStreamSlaveType
out mAxisMasterAxiStreamMasterType
out sAxisSlaveAxiStreamSlaveType
array(natural range <> ) of slv( 15 downto 0) Slv16Array
slv( 15 downto 0) := x"0081" VLAN_TYPE_C
in sAxisMasterAxiStreamMasterType
FWFT_EN_Gboolean := false
out mAxisMasterAxiStreamMasterType
slv( 7 downto 0) := x"11" UDP_C
in mAxisSlaveAxiStreamSlaveType
CASCADE_SIZE_Ginteger range 1 to ( 2** 24):= 1
USE_BUILT_IN_Gboolean := false
array(natural range <> ) of slv( 7 downto 0) Slv8Array
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
array(natural range <> ) of EthMacCsumAccumType EthMacCsumAccumArray