SURF  1.0
IpV4EngineRx.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : IpV4EngineRx.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2015-08-12
5 -- Last update: 2016-09-16
6 -------------------------------------------------------------------------------
7 -- Description: IPv4 RX Engine Module
8 -- Note: IPv4 checksum checked in EthMac core
9 -------------------------------------------------------------------------------
10 -- This file is part of 'SLAC Firmware Standard Library'.
11 -- It is subject to the license terms in the LICENSE.txt file found in the
12 -- top-level directory of this distribution and at:
13 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
14 -- No part of 'SLAC Firmware Standard Library', including this file,
15 -- may be copied, modified, propagated, or distributed except according to
16 -- the terms contained in the LICENSE.txt file.
17 -------------------------------------------------------------------------------
18 
19 library ieee;
20 use ieee.std_logic_1164.all;
21 use ieee.std_logic_unsigned.all;
22 use ieee.std_logic_arith.all;
23 
24 use work.StdRtlPkg.all;
25 use work.AxiStreamPkg.all;
26 use work.SsiPkg.all;
27 use work.EthMacPkg.all;
28 
29 --! @see entity
30  --! @ingroup ethernet_IpV4Engine
31 entity IpV4EngineRx is
32  generic (
33  TPD_G : time := 1 ns;
34  SIM_ERROR_HALT_G : boolean := false;
35  PROTOCOL_SIZE_G : positive := 1;
36  PROTOCOL_G : Slv8Array := (0 => UDP_C);
37  VLAN_G : boolean := false);
38  port (
39  -- Interface to Ethernet Frame MUX/DEMUX
42  localhostMaster : in AxiStreamMasterType;
43  localhostSlave : out AxiStreamSlaveType;
44  -- Interface to Protocol Engine
47  -- Clock and Reset
48  clk : in sl;
49  rst : in sl);
50 end IpV4EngineRx;
51 
52 architecture rtl of IpV4EngineRx is
53 
54  type StateType is (
55  IDLE_S,
56  IPV4_HDR0_S,
57  IPV4_HDR1_S,
58  IPV4_HDR2_S,
59  MOVE_S,
60  LAST_S);
61 
62  type RegType is record
63  tLast : sl;
64  eofe : sl;
65  len : slv(15 downto 0);
66  protocol : slv(7 downto 0);
67  tKeep : slv(15 downto 0);
68  tData : slv(127 downto 0);
69  rxSlave : AxiStreamSlaveType;
70  txMaster : AxiStreamMasterType;
71  state : StateType;
72  end record RegType;
73  constant REG_INIT_C : RegType := (
74  tLast => '0',
75  eofe => '0',
76  len => (others => '0'),
77  protocol => (others => '0'),
78  tKeep => (others => '0'),
79  tData => (others => '0'),
80  rxSlave => AXI_STREAM_SLAVE_INIT_C,
81  txMaster => AXI_STREAM_MASTER_INIT_C,
82  state => IDLE_S);
83 
84  signal r : RegType := REG_INIT_C;
85  signal rin : RegType;
86 
87  signal rxMaster : AxiStreamMasterType;
88  signal rxSlave : AxiStreamSlaveType;
89  signal txSlave : AxiStreamSlaveType;
90 
91  -- attribute dont_touch : string;
92  -- attribute dont_touch of r : signal is "TRUE";
93 
94 begin
95 
96  U_Mux : entity work.AxiStreamMux
97  generic map (
98  TPD_G => TPD_G,
99  PIPE_STAGES_G => 0,
100  NUM_SLAVES_G => 2)
101  port map (
102  -- Clock and reset
103  axisClk => clk,
104  axisRst => rst,
105  -- Slaves
106  sAxisMasters(0) => ibIpv4Master,
107  sAxisMasters(1) => localhostMaster,
108  sAxisSlaves(0) => ibIpv4Slave,
109  sAxisSlaves(1) => localhostSlave,
110  -- Master
111  mAxisMaster => rxMaster,
112  mAxisSlave => rxSlave);
113 
114  comb : process (r, rst, rxMaster, txSlave) is
115  variable v : RegType;
116  variable i : natural;
117  begin
118  -- Latch the current value
119  v := r;
120 
121  -- Reset the flags
122  v.rxSlave := AXI_STREAM_SLAVE_INIT_C;
123  if (txSlave.tReady = '1') then
124  v.txMaster.tValid := '0';
125  v.txMaster.tLast := '0';
126  v.txMaster.tUser := (others => '0');
127  v.txMaster.tKeep := (others => '1');
128  end if;
129 
130  -- State Machine
131  case r.state is
132  ----------------------------------------------------------------------
133  when IDLE_S =>
134  -- Check for data
135  if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then
136  -- Accept the data
137  v.rxSlave.tReady := '1';
138  -- Check for SOF with no EOF
139  if (ssiGetUserSof(EMAC_AXIS_CONFIG_C, rxMaster) = '1') and (rxMaster.tLast = '0') then
140  -- Latch the remote MAC address
141  v.txMaster.tData(47 downto 0) := rxMaster.tData(95 downto 48);
142  -- Unused data field
143  v.txMaster.tData(63 downto 48) := (others => '0');
144  -- Next state
145  v.state := IPV4_HDR0_S;
146  end if;
147  end if;
148  ----------------------------------------------------------------------
149  when IPV4_HDR0_S =>
150  -- Check for data
151  if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then
152  -- Accept the data
153  v.rxSlave.tReady := '1';
154  -- Check for non-VLAN
155  if (VLAN_G = false) then
156  -- Calculate the IPV4 Pseudo Header length (in little Endian)
157  v.len(15 downto 8) := rxMaster.tData(7 downto 0); -- IPV4_Length(15 downto 8)
158  v.len(7 downto 0) := rxMaster.tData(15 downto 8); -- IPV4_Length(7 downto 0)
159  v.len := v.len - 20; -- IPV4 Pseudo Header's length = protocol length - 20 Bytes
160  -- Latch the protocol value
161  v.protocol := rxMaster.tData(63 downto 56);
162  -- Source IP Address(31 downto 0)
163  v.txMaster.tData(95 downto 64) := rxMaster.tData(111 downto 80);
164  -- Destination IP Address(31 downto 16)
165  v.txMaster.tData(111 downto 96) := rxMaster.tData(127 downto 112);
166  else
167  -- Calculate the IPV4 Pseudo Header length (in little Endian)
168  v.len(15 downto 8) := rxMaster.tData(39 downto 32); -- IPV4_Length(15 downto 8)
169  v.len(7 downto 0) := rxMaster.tData(47 downto 40); -- IPV4_Length(7 downto 0)
170  v.len := v.len - 20; -- IPV4 Pseudo Header's length = protocol length - 20 Bytes
171  -- Latch the protocol value
172  v.protocol := rxMaster.tData(95 downto 88);
173  -- Source IP Address(31 downto 16)
174  v.txMaster.tData(79 downto 64) := rxMaster.tData(127 downto 112);
175  end if;
176  -- Next state if protocol not detected during the "for loop"
177  v.state := IDLE_S;
178  -- Loop through the protocol buses
179  for i in (PROTOCOL_SIZE_G-1) downto 0 loop
180  if (v.protocol = PROTOCOL_G(i)) then
181  -- Latch the protocol bus pointer
182  v.txMaster.tDest := toSlv(i, 8);
183  -- Next state if protocol not detected
184  v.state := IPV4_HDR1_S;
185  end if;
186  end loop;
187  end if;
188  ----------------------------------------------------------------------
189  when IPV4_HDR1_S =>
190  -- Check for data
191  if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then
192  -- Move the data
193  v.txMaster.tValid := '1';
194  -- Set the SOF
195  ssiSetUserSof(EMAC_AXIS_CONFIG_C, v.txMaster, '1');
196  -- Check for non-VLAN
197  if (VLAN_G = false) then
198  -- Destination IP Address(15 downto 0)
199  v.txMaster.tData(127 downto 112) := rxMaster.tData(15 downto 0);
200  -- Track the leftovers
201  v.tData(7 downto 0) := x"00";
202  v.tData(15 downto 8) := r.protocol;
203  v.tData(23 downto 16) := r.len(15 downto 8);
204  v.tData(31 downto 24) := r.len(7 downto 0);
205  v.tData(127 downto 32) := rxMaster.tData(111 downto 16);
206  v.tKeep(3 downto 0) := "1111";
207  v.tKeep(15 downto 4) := rxMaster.tKeep(13 downto 2);
208  v.tLast := rxMaster.tLast;
209  v.eofe := ssiGetUserEofe(EMAC_AXIS_CONFIG_C, rxMaster);
210  -- Check for no remainder
211  if (rxMaster.tKeep(15 downto 14) = 0) then
212  -- Accept the data
213  v.rxSlave.tReady := '1';
214  -- Next state
215  v.state := LAST_S;
216  else
217  -- Next state
218  v.state := IPV4_HDR2_S;
219  end if;
220  else
221  -- Accept the data
222  v.rxSlave.tReady := '1';
223  -- Source IP Address(15 downto 0)
224  v.txMaster.tData(95 downto 80) := rxMaster.tData(15 downto 0);
225  -- Destination IP Address(31 downto 0)
226  v.txMaster.tData(127 downto 96) := rxMaster.tData(47 downto 16);
227  -- Track the leftovers
228  v.tData(7 downto 0) := x"00";
229  v.tData(15 downto 8) := r.protocol;
230  v.tData(23 downto 16) := r.len(15 downto 8);
231  v.tData(31 downto 24) := r.len(7 downto 0);
232  v.tData(111 downto 32) := rxMaster.tData(127 downto 48);
233  v.tKeep(3 downto 0) := "1111";
234  v.tKeep(13 downto 4) := rxMaster.tKeep(15 downto 6);
235  v.tKeep(15 downto 14) := "00";
236  v.tLast := rxMaster.tLast;
237  v.eofe := ssiGetUserEofe(EMAC_AXIS_CONFIG_C, rxMaster);
238  -- Check for EOF
239  if (rxMaster.tLast = '1') then
240  -- Check the leftovers
241  if (v.tKeep /= 0) then
242  -- Next state
243  v.state := LAST_S;
244  else
245  -- Set EOF and EOFE
246  v.txMaster.tLast := '1';
247  ssiSetUserEofe(EMAC_AXIS_CONFIG_C, v.txMaster, v.eofe);
248  -- Next state
249  v.state := IDLE_S;
250  end if;
251  else
252  -- Next state
253  v.state := MOVE_S;
254  end if;
255  end if;
256  end if;
257  ----------------------------------------------------------------------
258  when IPV4_HDR2_S =>
259  -- Check for data
260  if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then
261  -- Accept the data
262  v.rxSlave.tReady := '1';
263  -- Move the data
264  v.txMaster.tValid := '1';
265  v.txMaster.tData := r.tData;
266  v.txMaster.tKeep := r.tKeep;
267  -- Track the leftovers
268  v.tData(15 downto 0) := rxMaster.tData(127 downto 112);
269  v.tKeep(1 downto 0) := rxMaster.tKeep(15 downto 14);
270  v.tKeep(15 downto 2) := (others => '0');
271  v.tLast := rxMaster.tLast;
272  v.eofe := ssiGetUserEofe(EMAC_AXIS_CONFIG_C, rxMaster);
273  -- Check for EOF
274  if (rxMaster.tLast = '1') then
275  -- Check the leftovers
276  if (v.tKeep /= 0) then
277  -- Next state
278  v.state := LAST_S;
279  else
280  -- Set EOF and EOFE
281  v.txMaster.tLast := '1';
282  ssiSetUserEofe(EMAC_AXIS_CONFIG_C, v.txMaster, v.eofe);
283  -- Next state
284  v.state := IDLE_S;
285  end if;
286  else
287  -- Next state
288  v.state := MOVE_S;
289  end if;
290  end if;
291  ----------------------------------------------------------------------
292  when MOVE_S =>
293  -- Check for data
294  if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then
295  -- Accept the data
296  v.rxSlave.tReady := '1';
297  -- Move the data
298  v.txMaster.tValid := '1';
299  -- Check for non-VLAN
300  if (VLAN_G = false) then
301  -- Move the data
302  v.txMaster.tData(15 downto 0) := r.tData(15 downto 0);
303  v.txMaster.tData(127 downto 16) := rxMaster.tData(111 downto 0);
304  v.txMaster.tKeep(1 downto 0) := r.tKeep(1 downto 0);
305  v.txMaster.tKeep(15 downto 2) := rxMaster.tKeep(13 downto 0);
306  -- Track the leftovers
307  v.tData(15 downto 0) := rxMaster.tData(127 downto 112);
308  v.tKeep(1 downto 0) := rxMaster.tKeep(15 downto 14);
309  v.tLast := rxMaster.tLast;
310  v.eofe := ssiGetUserEofe(EMAC_AXIS_CONFIG_C, rxMaster);
311  else
312  -- Move the data
313  v.txMaster.tData(111 downto 0) := r.tData(111 downto 0);
314  v.txMaster.tData(127 downto 112) := rxMaster.tData(15 downto 0);
315  v.txMaster.tKeep(13 downto 0) := r.tKeep(13 downto 0);
316  v.txMaster.tKeep(15 downto 14) := rxMaster.tKeep(1 downto 0);
317  -- Track the leftovers
318  v.tData(111 downto 0) := rxMaster.tData(127 downto 16);
319  v.tKeep(13 downto 0) := rxMaster.tKeep(15 downto 2);
320  v.tLast := rxMaster.tLast;
321  v.eofe := ssiGetUserEofe(EMAC_AXIS_CONFIG_C, rxMaster);
322  end if;
323  -- Check for tLast
324  if (v.tLast = '1') then
325  -- Check the leftover tKeep is not empty
326  if (v.tKeep /= 0) then
327  -- Next state
328  v.state := LAST_S;
329  else
330  -- Set EOF and EOFE
331  v.txMaster.tLast := '1';
332  ssiSetUserEofe(EMAC_AXIS_CONFIG_C, v.txMaster, v.eofe);
333  -- Next state
334  v.state := IDLE_S;
335  end if;
336  end if;
337  end if;
338  ----------------------------------------------------------------------
339  when LAST_S =>
340  -- Check for data
341  if (v.txMaster.tValid = '0') then
342  -- Move the data
343  v.txMaster.tValid := '1';
344  v.txMaster.tData := r.tData;
345  v.txMaster.tKeep := r.tKeep;
346  v.txMaster.tLast := '1';
347  ssiSetUserEofe(EMAC_AXIS_CONFIG_C, v.txMaster, r.eofe);
348  -- Next state
349  v.state := IDLE_S;
350  end if;
351  ----------------------------------------------------------------------
352  end case;
353 
354  -- Reset
355  if (rst = '1') then
356  v := REG_INIT_C;
357  end if;
358 
359  -- Register the variable for next clock cycle
360  rin <= v;
361 
362  -- Outputs
363  rxSlave <= v.rxSlave;
364 
365  end process comb;
366 
367  seq : process (clk) is
368  begin
369  if rising_edge(clk) then
370  r <= rin after TPD_G;
371  end if;
372  end process seq;
373 
374  U_AxisMux : entity work.AxiStreamDeMux
375  generic map (
376  TPD_G => TPD_G,
377  PIPE_STAGES_G => 1,
379  port map (
380  -- Clock and reset
381  axisClk => clk,
382  axisRst => rst,
383  -- Slave
384  sAxisMaster => r.txMaster,
385  sAxisSlave => txSlave,
386  -- Masters
389 
390 end rtl;
PIPE_STAGES_Ginteger range 0 to 16:= 0
TPD_Gtime := 1 ns
array(natural range <> ) of AxiStreamSlaveType AxiStreamSlaveArray
out ibIpv4SlaveAxiStreamSlaveType
std_logic sl
Definition: StdRtlPkg.vhd:28
in ibIpv4MasterAxiStreamMasterType
out ibProtocolMastersAxiStreamMasterArray( PROTOCOL_SIZE_G- 1 downto 0)
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
sl eofe
Definition: SsiPkg.vhd:74
out mAxisMastersAxiStreamMasterArray( NUM_MASTERS_G- 1 downto 0)
slv( 15 downto 0) tKeep
_library_ ieeeieee
out sAxisSlaveAxiStreamSlaveType
SIM_ERROR_HALT_Gboolean := false
slv( 127 downto 0) tData
out mAxisMasterAxiStreamMasterType
NUM_SLAVES_Ginteger range 1 to 32:= 4
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
TPD_Gtime := 1 ns
in sAxisMasterAxiStreamMasterType
slv( 127 downto 0) tUser
VLAN_Gboolean := false
array(natural range <> ) of AxiStreamMasterType AxiStreamMasterArray
out localhostSlaveAxiStreamSlaveType
slv( 7 downto 0) tDest
in mAxisSlavesAxiStreamSlaveArray( NUM_MASTERS_G- 1 downto 0)
slv( 7 downto 0) := x"11" UDP_C
Definition: EthMacPkg.vhd:39
TPD_Gtime := 1 ns
PROTOCOL_SIZE_Gpositive := 1
array(natural range <> ) of slv( 7 downto 0) Slv8Array
Definition: StdRtlPkg.vhd:403
in localhostMasterAxiStreamMasterType
in mAxisSlaveAxiStreamSlaveType
NUM_MASTERS_Ginteger range 1 to 32:= 12
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
in ibProtocolSlavesAxiStreamSlaveArray( PROTOCOL_SIZE_G- 1 downto 0)
PROTOCOL_GSlv8Array :=( 0=> UDP_C)
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
PIPE_STAGES_Ginteger range 0 to 16:= 0