SURF  1.0
EthMacTxCsum.vhd
Go to the documentation of this file.
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 -------------------------------------------------------------------------------
18 
19 library ieee;
20 use ieee.std_logic_1164.all;
21 use ieee.std_logic_arith.all;
22 use ieee.std_logic_unsigned.all;
23 
24 use work.StdRtlPkg.all;
25 use work.AxiStreamPkg.all;
26 use work.EthMacPkg.all;
27 
28 --! @see entity
29  --! @ingroup ethernet_EthMacCore
30 entity EthMacTxCsum is
31  generic (
32  TPD_G : time := 1 ns;
33  DROP_ERR_PKT_G : boolean := true;
34  JUMBO_G : boolean := true;
35  VLAN_G : boolean := false;
36  VID_G : slv(11 downto 0) := x"001");
37  port (
38  -- Clock and Reset
39  ethClk : in sl;
40  ethRst : in sl;
41  -- Configurations
42  ipCsumEn : in sl;
43  tcpCsumEn : in sl;
44  udpCsumEn : in sl;
45  -- Outbound data to MAC
50 end EthMacTxCsum;
51 
52 architecture rtl of EthMacTxCsum is
53 
54  constant MAX_FRAME_SIZE_C : natural := ite(JUMBO_G, 9000, 1500);
55 
56  type StateType is (
57  IDLE_S,
58  IPV4_HDR0_S,
59  IPV4_HDR1_S,
60  MOVE_S,
61  BLOWOFF_S);
62 
63  type RegType is record
64  tranWr : sl;
65  fragDet : slv(EMAC_CSUM_PIPELINE_C+1 downto 0);
66  eofeDet : slv(EMAC_CSUM_PIPELINE_C+1 downto 0);
67  ipv4Det : slv(EMAC_CSUM_PIPELINE_C+1 downto 0);
68  udpDet : slv(EMAC_CSUM_PIPELINE_C+1 downto 0);
69  tcpDet : slv(EMAC_CSUM_PIPELINE_C+1 downto 0);
70  tcpFlag : sl;
71  ipv4Len : Slv16Array(EMAC_CSUM_PIPELINE_C+1 downto 0);
72  ipv4Csum : slv(15 downto 0);
73  protLen : Slv16Array(EMAC_CSUM_PIPELINE_C+1 downto 0);
74  protCsum : slv(15 downto 0);
75  ipv4Hdr : Slv8Array(19 downto 0);
76  calc : EthMacCsumAccumArray(1 downto 0);
77  len : slv(15 downto 0);
78  tKeep : slv(15 downto 0);
79  tData : slv(127 downto 0);
80  tranRd : sl;
81  mvCnt : natural range 0 to 4;
82  dbg : slv(5 downto 0);
83  rxSlave : AxiStreamSlaveType;
84  txMaster : AxiStreamMasterType;
85  mSlave : AxiStreamSlaveType;
86  sMaster : AxiStreamMasterType;
87  state : StateType;
88  end record RegType;
89  constant REG_INIT_C : RegType := (
90  tranWr => '0',
91  fragDet => (others => '0'),
92  eofeDet => (others => '0'),
93  ipv4Det => (others => '0'),
94  udpDet => (others => '0'),
95  tcpDet => (others => '0'),
96  tcpFlag => '0',
97  ipv4Len => (others => (others => '0')),
98  ipv4Csum => (others => '0'),
99  protLen => (others => (others => '0')),
100  protCsum => (others => '0'),
101  ipv4Hdr => (others => (others => '0')),
102  calc => (others => ETH_MAC_CSUM_ACCUM_INIT_C),
103  len => (others => '0'),
104  tKeep => (others => '0'),
105  tData => (others => '0'),
106  tranRd => '0',
107  mvCnt => 0,
108  dbg => (others => '0'),
109  rxSlave => AXI_STREAM_SLAVE_INIT_C,
110  txMaster => AXI_STREAM_MASTER_INIT_C,
111  mSlave => AXI_STREAM_SLAVE_INIT_C,
112  sMaster => AXI_STREAM_MASTER_INIT_C,
113  state => IDLE_S);
114 
115  signal r : RegType := REG_INIT_C;
116  signal rin : RegType;
117 
118  signal rxMaster : AxiStreamMasterType;
119  signal rxSlave : AxiStreamSlaveType;
120  signal sMaster : AxiStreamMasterType;
121  signal sSlave : AxiStreamSlaveType;
122  signal mMaster : AxiStreamMasterType;
123  signal mSlave : AxiStreamSlaveType;
124  signal txMaster : AxiStreamMasterType;
125  signal txSlave : AxiStreamSlaveType;
126 
127  signal tranPause : sl;
128  signal fragDet : sl;
129  signal eofeDet : sl;
130  signal ipv4Det : sl;
131  signal udpDet : sl;
132  signal tcpDet : 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;
138 
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";
153 
154 begin
155 
156  U_RxPipeline : entity work.AxiStreamPipeline
157  generic map (
158  TPD_G => TPD_G,
159  PIPE_STAGES_G => 0)
160  port map (
161  axisClk => ethClk,
162  axisRst => ethRst,
165  mAxisMaster => rxMaster,
166  mAxisSlave => rxSlave);
167 
168  comb : process (eofeDet, ethRst, fragDet, ipCsumEn, ipv4Csum, ipv4Det,
169  ipv4Len, mMaster, protCsum, protLen, r, rxMaster, sSlave,
170  tcpCsumEn, tcpDet, tranPause, tranValid, txSlave, udpCsumEn,
171  udpDet) is
172  variable v : RegType;
173  variable dummy : slv(1 downto 0);
174  begin
175  -- Latch the current value
176  v := r;
177 
178  -- Reset the flags
179  v.tranWr := '0';
180  v.tranRd := '0';
181  v.dbg := (others => '0');
182  v.tKeep := (others => '0');
183  v.rxSlave := AXI_STREAM_SLAVE_INIT_C;
184  if sSlave.tReady = '1' then
185  v.sMaster.tValid := '0';
186  end if;
187  v.mSlave := AXI_STREAM_SLAVE_INIT_C;
188  if txSlave.tReady = '1' then
189  v.txMaster.tValid := '0';
190  end if;
191 
192  GetEthMacCsum (
193  r.udpDet(EMAC_CSUM_PIPELINE_C),
194  r.tranWr,
195  r.ipv4Hdr,
196  r.tKeep,
197  r.tData,
198  r.len,
199  x"0000", -- Unused in TX CSUM
200  r.calc,
201  v.calc,
202  dummy(0), -- Unused in TX CSUM
203  v.ipv4Csum,
204  dummy(1), -- Unused in TX CSUM
205  v.protCsum);
206 
207  -- Pipeline alignment to GetEthMacCsum()
208  v.fragDet := r.fragDet(EMAC_CSUM_PIPELINE_C downto 0) & r.fragDet(0);
209  v.eofeDet := r.eofeDet(EMAC_CSUM_PIPELINE_C downto 0) & r.eofeDet(0);
210  v.ipv4Det := r.ipv4Det(EMAC_CSUM_PIPELINE_C downto 0) & r.ipv4Det(0);
211  v.udpDet := r.udpDet(EMAC_CSUM_PIPELINE_C downto 0) & r.udpDet(0);
212  v.tcpDet := r.tcpDet(EMAC_CSUM_PIPELINE_C downto 0) & r.tcpDet(0);
213  v.ipv4Len := r.ipv4Len(EMAC_CSUM_PIPELINE_C downto 0) & r.ipv4Len(0);
214  v.protLen := r.protLen(EMAC_CSUM_PIPELINE_C downto 0) & r.protLen(0);
215 
216  -- Check for UDP frame
217  if (r.udpDet(EMAC_CSUM_PIPELINE_C-1) = '1') then
218  -- Multiple length by 2 to combine UDP length and IPV4 Pseudo Header's length together
219  v.len := r.protLen(EMAC_CSUM_PIPELINE_C-2)(14 downto 0) & '0';
220  else
221  -- TCP only has IPV4 Pseudo Header's length together
222  v.len := r.protLen(EMAC_CSUM_PIPELINE_C-2);
223  end if;
224 
225  -- State Machine
226  case r.state is
227  ----------------------------------------------------------------------
228  when IDLE_S =>
229  -- Reset the flags
230  v.fragDet(0) := '0';
231  v.eofeDet(0) := '0';
232  v.ipv4Det(0) := '0';
233  v.udpDet(0) := '0';
234  v.tcpDet(0) := '0';
235  v.tcpFlag := '0';
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
241  -- Accept the data
242  v.rxSlave.tReady := '1';
243  -- Move data
244  v.sMaster := rxMaster;
245  -- Set the flag
246  v.fragDet(0) := axiStreamGetUserBit(EMAC_AXIS_CONFIG_C, rxMaster, EMAC_FRAG_BIT_C, 0);
247  -- Check for EOF
248  if (rxMaster.tLast = '1') then
249  -- Save the EOFE value
250  v.eofeDet(0) := axiStreamGetUserBit(EMAC_AXIS_CONFIG_C, rxMaster, EMAC_EOFE_BIT_C);
251  -- Write the transaction data
252  v.tranWr := '1';
253  else
254  -- Check if NON-VLAN
255  if (VLAN_G = false) then
256  -- Check for EtherType = IPV4 = 0x0800
257  if (rxMaster.tData(111 downto 96) = IPV4_TYPE_C) then
258  -- Set the flag
259  v.ipv4Det(0) := '1';
260  end if;
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
264  else
265  -- Add the IEEE 802.1Q header
266  v.sMaster.tData(111 downto 96) := VLAN_TYPE_C;
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);
269  end if;
270  -- Next state
271  v.state := IPV4_HDR0_S;
272  end if;
273  end if;
274  ----------------------------------------------------------------------
275  when IPV4_HDR0_S =>
276  -- Check if ready to move data
277  if (rxMaster.tValid = '1') and (v.sMaster.tValid = '0') and (tranPause = '0') then
278  -- Accept the data
279  v.rxSlave.tReady := '1';
280  -- Move data
281  v.sMaster := rxMaster;
282  -- Check for EOF
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
287  v.eofeDet(0) := '1';
288  else
289  -- Save the EOFE value
290  v.eofeDet(0) := axiStreamGetUserBit(EMAC_AXIS_CONFIG_C, rxMaster, EMAC_EOFE_BIT_C);
291  end if;
292  -- Write the transaction data
293  v.tranWr := '1';
294  -- Next state
295  v.state := IDLE_S;
296  else
297  -- Check if NON-VLAN
298  if (VLAN_G = false) then
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');
315  else
316  -- Check for EtherType = IPV4 = 0x0800
317  if (rxMaster.tData(15 downto 0) = IPV4_TYPE_C) then
318  -- Set the flag
319  v.ipv4Det(0) := '1';
320  end if;
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');
335  end if;
336  -- Check for UDP protocol
337  if (v.ipv4Hdr(9) = UDP_C) then
338  v.udpDet(0) := '1';
339  end if;
340  -- Check for TCP protocol
341  if (v.ipv4Hdr(9) = TCP_C) then
342  v.tcpDet(0) := '1';
343  end if;
344  -- Next state
345  v.state := IPV4_HDR1_S;
346  end if;
347  end if;
348  ----------------------------------------------------------------------
349  when IPV4_HDR1_S =>
350  -- Check if ready to move data
351  if (rxMaster.tValid = '1') and (v.sMaster.tValid = '0') and (tranPause = '0') then
352  -- Accept the data
353  v.rxSlave.tReady := '1';
354  -- Move data
355  v.sMaster := rxMaster;
356  -- Fill in the TCP/UDP checksum
357  v.tKeep := rxMaster.tKeep;
358  v.tData := rxMaster.tData;
359  -- Check if NON-VLAN
360  if (VLAN_G = false) then
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);
368  end if;
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;
372  else
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);
384  end if;
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;
388  end if;
389  -- Check for EOF
390  if (rxMaster.tLast = '1') then
391  -- Save the EOFE value
392  v.eofeDet(0) := axiStreamGetUserBit(EMAC_AXIS_CONFIG_C, rxMaster, EMAC_EOFE_BIT_C);
393  -- Write the transaction data
394  v.tranWr := '1';
395  -- Next state
396  v.state := IDLE_S;
397  else
398  -- Next state
399  v.state := MOVE_S;
400  end if;
401  end if;
402  ----------------------------------------------------------------------
403  when MOVE_S =>
404  -- Check if ready to move data
405  if (rxMaster.tValid = '1') and (v.sMaster.tValid = '0') and (tranPause = '0') then
406  -- Accept the data
407  v.rxSlave.tReady := '1';
408  -- Move data
409  v.sMaster := rxMaster;
410  -- Fill in the TCP/UDP checksum
411  v.tData := rxMaster.tData;
412  v.tKeep := rxMaster.tKeep;
413  -- Check for TCP data with inbound checksum
414  if (r.ipv4Det(0) = '1') and (r.tcpDet(0) = '1') and (r.tcpFlag = '0') then
415  -- Set the flag
416  v.tcpFlag := '1';
417  -- Check if NON-VLAN
418  if (VLAN_G = false) then
419  -- Mask off inbound TCP checksum
420  v.tData := rxMaster.tData(127 downto 32) & x"0000" & rxMaster.tData(15 downto 0);
421  else
422  -- Mask off inbound TCP checksum
423  v.tData := rxMaster.tData(127 downto 64) & x"0000" & rxMaster.tData(47 downto 0);
424  end if;
425  end if;
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);
429  -- Check for EOF
430  if (rxMaster.tLast = '1') or (v.ipv4Len(0) > MAX_FRAME_SIZE_C) then
431  -- Save the EOFE value
432  v.eofeDet(0) := axiStreamGetUserBit(EMAC_AXIS_CONFIG_C, rxMaster, EMAC_EOFE_BIT_C);
433  -- Check for overflow
434  if (rxMaster.tLast = '0') then
435  -- Error detect
436  v.eofeDet(0) := '1';
437  -- Write the transaction data
438  v.tranWr := '1';
439  -- Next state
440  v.state := BLOWOFF_S;
441  else
442  -- Write the transaction data
443  v.tranWr := '1';
444  -- Next state
445  v.state := IDLE_S;
446  end if;
447  end if;
448  end if;
449  ----------------------------------------------------------------------
450  when BLOWOFF_S =>
451  -- Check if ready to move data
452  if (rxMaster.tValid = '1') and (v.sMaster.tValid = '0') then
453  -- Accept the data
454  v.rxSlave.tReady := '1';
455  -- Check for EOF
456  if (rxMaster.tLast = '1') then
457  -- Next state
458  v.state := IDLE_S;
459  end if;
460  end if;
461  ----------------------------------------------------------------------
462  end case;
463 
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)
467 
468  -- Wait for the transaction data
469  if (tranValid = '1') and (r.tranRd = '0') then
470  -- Check for data
471  if (mMaster.tValid = '1') and (v.txMaster.tValid = '0') then
472  -- Accept the data
473  v.mSlave.tReady := '1';
474  -- Move data
475  v.txMaster := mMaster;
476  -- Check if not forwarding EOFE frames
477  if (DROP_ERR_PKT_G = true) and (eofeDet = '1') then
478  -- Do NOT move data
479  v.txMaster.tValid := '0';
480  end if;
481  -- Check the counter size
482  if (r.mvCnt /= 4) then
483  -- Increment the counter
484  v.mvCnt := r.mvCnt + 1;
485  end if;
486  -- Check for IPv4 checksum/length insertion
487  if (ipv4Det = '1') and (r.mvCnt = 1) then
488  -- Check if NON-VLAN
489  if (VLAN_G = false) then
490  -- Check if firmware checksum enabled
491  if (ipCsumEn = '1') then
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);
497  end if;
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
500  -- Set the flag
501  v.dbg(0) := '1';
502  end if;
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
505  -- Set the flag
506  v.dbg(1) := '1';
507  end if;
508  else
509  -- Check if firmware checksum enabled
510  if (ipCsumEn = '1') then
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);
516  end if;
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
519  -- Set the flag
520  v.dbg(0) := '1';
521  end if;
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
524  -- Set the flag
525  v.dbg(1) := '1';
526  end if;
527  end if;
528  end if;
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
531  -- Check if NON-VLAN
532  if (VLAN_G = false) then
533  -- Check if firmware checksum enabled
534  if (udpCsumEn = '1') then
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);
540  end if;
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
543  -- Set the flag
544  v.dbg(2) := '1';
545  end if;
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
548  -- Set the flag
549  v.dbg(3) := '1';
550  end if;
551  else
552  -- Check if firmware checksum enabled
553  if (udpCsumEn = '1') then
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);
559  end if;
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
562  -- Set the flag
563  v.dbg(2) := '1';
564  end if;
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
567  -- Set the flag
568  v.dbg(3) := '1';
569  end if;
570  end if;
571  end if;
572  -- Check for TCP checksum insertion and no fragmentation
573  if (ipv4Det = '1') and (tcpDet = '1') and (fragDet = '0') and (r.mvCnt = 3) then
574  -- Check if NON-VLAN
575  if (VLAN_G = false) then
576  -- Check if firmware checksum enabled
577  if (tcpCsumEn = '1') then
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);
581  end if;
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
584  -- Set the flag
585  v.dbg(4) := '1';
586  end if;
587  else
588  -- Check if firmware checksum enabled
589  if (tcpCsumEn = '1') then
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);
593  end if;
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
596  -- Set the flag
597  v.dbg(4) := '1';
598  end if;
599  end if;
600  end if;
601  -- Check for tLast
602  if (mMaster.tLast = '1') then
603  -- Reset the counter
604  v.mvCnt := 0;
605  -- Forward the EOFE
606  axiStreamSetUserBit(EMAC_AXIS_CONFIG_C, v.txMaster, EMAC_EOFE_BIT_C, eofeDet);
607  v.dbg(5) := eofeDet;
608  -- Accept the data
609  v.tranRd := '1';
610  end if;
611  end if;
612  end if;
613 
614  -- Reset
615  if (ethRst = '1') then
616  v := REG_INIT_C;
617  end if;
618 
619  -- Register the variable for next clock cycle
620  rin <= v;
621 
622  -- Outputs
623  rxSlave <= v.rxSlave;
624  sMaster <= r.sMaster;
625  mSlave <= v.mSlave;
626  txMaster <= r.txMaster;
627 
628  end process comb;
629 
630  seq : process (ethClk) is
631  begin
632  if rising_edge(ethClk) then
633  r <= rin after TPD_G;
634  end if;
635  end process seq;
636 
637  Fifo_Cache : entity work.AxiStreamFifoV2
638  generic map (
639  -- General Configurations
640  TPD_G => TPD_G,
641  INT_PIPE_STAGES_G => 0,
642  PIPE_STAGES_G => 1,
643  SLAVE_READY_EN_G => true,
644  VALID_THOLD_G => 1,
645  -- FIFO configurations
646  BRAM_EN_G => true,
647  USE_BUILT_IN_G => false,
648  GEN_SYNC_FIFO_G => true,
649  CASCADE_SIZE_G => ite(JUMBO_G, 2, 1),
650  FIFO_ADDR_WIDTH_G => 9, -- 8kB per FIFO
651  -- AXI Stream Port Configurations
654  port map (
655  -- Slave Port
656  sAxisClk => ethClk,
657  sAxisRst => ethRst,
658  sAxisMaster => sMaster,
659  sAxisSlave => sSlave,
660  -- Master Port
661  mAxisClk => ethClk,
662  mAxisRst => ethRst,
663  mAxisMaster => mMaster,
664  mAxisSlave => mSlave);
665 
666  Fifo_Trans : entity work.FifoSync
667  generic map (
668  TPD_G => TPD_G,
669  BRAM_EN_G => false,
670  FWFT_EN_G => true,
671  DATA_WIDTH_G => 69,
672  ADDR_WIDTH_G => 4,
673  FULL_THRES_G => 8)
674  port map (
675  clk => ethClk,
676  rst => ethRst,
677  --Write Ports (wr_clk domain)
678  wr_en => r.calc(0).step(EMAC_CSUM_PIPELINE_C),
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,
688  prog_full => tranPause,
689  --Read Ports (rd_clk domain)
690  rd_en => r.tranRd,
691  dout(68) => fragDet,
692  dout(67) => eofeDet,
693  dout(66) => ipv4Det,
694  dout(65) => udpDet,
695  dout(64) => tcpDet,
696  dout(63 downto 48) => ipv4Len,
697  dout(47 downto 32) => ipv4Csum,
698  dout(31 downto 16) => protLen,
699  dout(15 downto 0) => protCsum,
700  valid => tranValid);
701 
702  U_TxPipeline : entity work.AxiStreamPipeline
703  generic map (
704  TPD_G => TPD_G,
705  PIPE_STAGES_G => 1)
706  port map (
707  axisClk => ethClk,
708  axisRst => ethRst,
709  sAxisMaster => txMaster,
710  sAxisSlave => txSlave,
713 
714 end rtl;
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
Definition: FifoSync.vhd:40
in wr_ensl
Definition: FifoSync.vhd:47
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
Definition: FifoSync.vhd:45
slv( 7 downto 0) := x"06" TCP_C
Definition: EthMacPkg.vhd:40
std_logic sl
Definition: StdRtlPkg.vhd:28
slv( 15 downto 0) := x"0008" IPV4_TYPE_C
Definition: EthMacPkg.vhd:35
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
BRAM_EN_Gboolean := true
Definition: FifoSync.vhd:32
out prog_fullsl
Definition: FifoSync.vhd:56
SLAVE_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
out sAxisSlaveAxiStreamSlaveType
slv( 15 downto 0) tKeep
out validsl
Definition: FifoSync.vhd:53
SLAVE_READY_EN_Gboolean := true
in mAxisSlaveAxiStreamSlaveType
slv( EMAC_CSUM_PIPELINE_C downto 0) step
Definition: EthMacPkg.vhd:115
GEN_SYNC_FIFO_Gboolean := false
TPD_Gtime := 1 ns
Definition: FifoSync.vhd:29
VLAN_Gboolean := false
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
Definition: FifoSync.vhd:39
integer := 0 EMAC_FRAG_BIT_C
Definition: EthMacPkg.vhd:48
slv( 127 downto 0) tData
JUMBO_Gboolean := true
EthMacCsumAccumType :=(step =>( others => '0'),sum1 =>( others =>( others => '0')),sum3 =>( others => '0'),sum5 =>( others => '0')) ETH_MAC_CSUM_ACCUM_INIT_C
Definition: EthMacPkg.vhd:120
FULL_THRES_Ginteger range 1 to ( 2** 24):= 1
Definition: FifoSync.vhd:42
_library_ ieeeieee
INT_PIPE_STAGES_Gnatural range 0 to 16:= 0
natural := 3 EMAC_CSUM_PIPELINE_C
Definition: EthMacPkg.vhd:113
in sAxisMasterAxiStreamMasterType
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
in sAxisMasterAxiStreamMasterType
BRAM_EN_Gboolean := true
integer := 0 EMAC_EOFE_BIT_C
Definition: EthMacPkg.vhd:52
TPD_Gtime := 1 ns
DROP_ERR_PKT_Gboolean := true
out sAxisSlaveAxiStreamSlaveType
in clksl
Definition: FifoSync.vhd:46
out mAxisMasterAxiStreamMasterType
out sAxisSlaveAxiStreamSlaveType
array(natural range <> ) of slv( 15 downto 0) Slv16Array
Definition: StdRtlPkg.vhd:395
in rd_ensl
Definition: FifoSync.vhd:48
slv( 15 downto 0) := x"0081" VLAN_TYPE_C
Definition: EthMacPkg.vhd:36
in sAxisMasterAxiStreamMasterType
FWFT_EN_Gboolean := false
Definition: FifoSync.vhd:34
out mAxisMasterAxiStreamMasterType
slv( 7 downto 0) := x"11" UDP_C
Definition: EthMacPkg.vhd:39
in mAxisSlaveAxiStreamSlaveType
CASCADE_SIZE_Ginteger range 1 to ( 2** 24):= 1
USE_BUILT_IN_Gboolean := false
TPD_Gtime := 1 ns
array(natural range <> ) of slv( 7 downto 0) Slv8Array
Definition: StdRtlPkg.vhd:403
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
Definition: EthMacPkg.vhd:58
array(natural range <> ) of EthMacCsumAccumType EthMacCsumAccumArray
Definition: EthMacPkg.vhd:125
std_logic_vector slv
Definition: StdRtlPkg.vhd:29