AMC13
Firmwares for the different applications of the AMC13 uTCA board made at Boston University
 All Classes Variables
EMAC_Rx_if.vhd
1 ----------------------------------------------------------------------------------
2 -- Company:
3 -- Engineer:
4 --
5 -- Create Date: 16:09:48 08/05/2010
6 -- Design Name:
7 -- Module Name: GE_in - Behavioral
8 -- Project Name:
9 -- Target Devices:
10 -- Tool versions:
11 -- Description:
12 --
13 -- Dependencies:
14 --
15 -- Revision:
16 -- Revision 0.01 - File Created
17 -- Additional Comments:
18 -- Dout(17 downto 16) = "01" for header or ARP data
19 -- Dout(17 downto 16) = "11" for IP data
20 -- Dout(17 downto 16) = "10" for IP data last word which has odd number of bytes
21 ----------------------------------------------------------------------------------
22 library IEEE;
23 use IEEE.STD_LOGIC_1164.ALL;
24 use IEEE.STD_LOGIC_ARITH.ALL;
25 use IEEE.STD_LOGIC_UNSIGNED.ALL;
26 use IEEE.std_logic_misc.all;
27 use work.amc13_pack.all;
28 
29 -- Uncomment the following library declaration if using
30 -- arithmetic functions with Signed or Unsigned values
31 --use IEEE.NUMERIC_STD.ALL;
32 
33 -- Uncomment the following library declaration if instantiating
34 -- any Xilinx primitives in this code.
35 library UNISIM;
36 use UNISIM.VComponents.all;
37 Library UNIMACRO;
38 use UNIMACRO.vcomponents.all;
39 
40 entity EMAC_Rx_if is
41  Port ( clk : in STD_LOGIC;
42  reset : in STD_LOGIC;
43  rstCntr : IN std_logic;
44  no_TCP_DATA : in STD_LOGIC; -- if set, TCP data are not output
45  EMAC_RxD : in STD_LOGIC_VECTOR (31 downto 0);
46  EMAC_RxDVLD : in STD_LOGIC_VECTOR (3 downto 0);
47  EMAC_RxGoodFrame : in STD_LOGIC;
48  EMAC_RxBadFrame : in STD_LOGIC;
49  MY_IP : in STD_LOGIC_VECTOR (31 downto 0); -- my IP address
50  MY_ETH : in STD_LOGIC_VECTOR (47 downto 0); -- my Ethernet address
51  en_Dout : in STD_LOGIC;
52  Dout_avl : out STD_LOGIC := '0';
53  Dout_type : out STD_LOGIC_VECTOR (1 downto 0):= "00"; -- 00 TCP, 01 ICMP, 10 ARP reply, 11 ARP request
54  Dout : out STD_LOGIC_VECTOR (35 downto 0) := (others => '0');
55  last_word : out STD_LOGIC := '0';
56  Dout_valid : out STD_LOGIC := '0';
57  ipb_addr : in STD_LOGIC_VECTOR(31 downto 0);
58  ipb_rdata : out STD_LOGIC_VECTOR(31 downto 0);
59  csa : out STD_LOGIC_VECTOR (135 downto 0);
60  csb : out STD_LOGIC_VECTOR (135 downto 0)
61  );
62 end EMAC_Rx_if;
63 
64 architecture Behavioral of EMAC_Rx_if is
65 COMPONENT checksum
66  PORT(
67  c : IN std_logic;
68  r : IN std_logic;
69  r_value : IN std_logic_vector(15 downto 0);
70  ce : IN std_logic;
71  d : IN std_logic_vector(16 downto 0);
72  bad_chksum : OUT std_logic;
73  s : OUT std_logic_vector(15 downto 0)
74  );
75 END COMPONENT;
76 constant ETHTYPE_IP4 : std_logic_vector(31 downto 0) := x"08004500";
77 constant ETHTYPE_ARP : std_logic_vector(31 downto 0) := x"08060001";
78 constant PROTOCAL_TCP : std_logic_vector(7 downto 0) := x"06";
79 constant PROTOCAL_ICMP : std_logic_vector(7 downto 0) := x"01";
80 type state is (IDLE, ET_HDR, ARP, IP_HDR, IP_DATA, DROP);
81 signal in_state : state;
82 signal goto_DROP : std_logic_vector(11 downto 0) := (others => '0');
83 signal buf_di : std_logic_vector(35 downto 0) := (others => '0');
84 signal buf_do : std_logic_vector(35 downto 0) := (others => '0');
85 signal buf_dout : std_logic_vector(35 downto 0) := (others => '0');
86 signal EMAC_RxD_q : std_logic_vector(31 downto 0) := (others => '0');
87 signal EMAC_RxD_q2 : std_logic_vector(31 downto 0) := (others => '0');
88 signal EMAC_RxD_q3 : std_logic_vector(31 downto 0) := (others => '0');
89 signal EMAC_RxD_q4 : std_logic_vector(31 downto 0) := (others => '0');
90 signal EMAC_RxDVLD_q : std_logic := '0';
91 signal reset_ext : std_logic := '0';
92 signal en_Rx : std_logic := '0';
93 signal wea : std_logic := '0';
94 signal buf_space : std_logic_vector(8 downto 0) := (others => '0');
95 signal waddr : std_logic_vector(8 downto 0) := (others => '0');
96 signal start_waddr : std_logic_vector(8 downto 0) := (others => '0');
97 signal last_waddr : std_logic_vector(8 downto 0) := (others => '0');
98 signal raddr : std_logic_vector(8 downto 0) := (others => '0');
99 signal wc : std_logic_vector(8 downto 0) := (others => '0');
100 signal byte_cnt : std_logic_vector(1 downto 0) := (others => '0');
101 signal ec_raddr : std_logic := '0';
102 signal is_ARP : std_logic := '0';
103 signal IS_Request : std_logic := '0';
104 signal is_TCP : std_logic := '0';
105 signal is_ICMP : std_logic := '0';
106 signal cut_TCP_DATA : std_logic := '0';
107 signal cut_TCP_DATA_r : std_logic := '0';
108 signal IPHDR_data : std_logic := '0';
109 signal IPHDR_data_dl : std_logic_vector(1 downto 0) := (others => '0');
110 signal IHDL : std_logic_vector(3 downto 0) := (others => '0');
111 signal IP_Length : std_logic_vector(11 downto 0) := (others => '0');
112 signal TCP_Length : std_logic_vector(15 downto 0) := (others => '0');
113 signal IP_Length_offset : std_logic_vector(9 downto 0) := (others => '0');
114 signal bad_Length : std_logic := '0';
115 signal rst_IP_chksum : std_logic := '0';
116 signal rst_IPHDR_chksum : std_logic := '0';
117 signal bad_IPHDR_chksum : std_logic := '0';
118 signal IPHDR_chksum_in : std_logic_vector(16 downto 0) := (others => '0');
119 signal IP_chksum_in : std_logic_vector(16 downto 0) := (others => '0');
120 signal bad_IP_chksum : std_logic := '0';
121 signal ipdata_end: std_logic := '0';
122 signal chk_IP_chksum : std_logic := '0';
123 signal chk_IPHDR_chksum : std_logic := '0';
124 signal ICMP_check : std_logic := '0';
125 signal ICMP_ECHO : std_logic := '0';
126 signal ICMP_chksum : std_logic := '0';
127 signal ICMP_newchksum : std_logic_vector(16 downto 0) := (others => '0');
128 signal swap_ETH_ADDR: std_logic := '0';
129 signal swap_IP_ADDR: std_logic := '0';
130 signal swap_TCP_PORT: std_logic := '0';
131 --signal swap_TCP_PORT_dl: std_logic_vector(1 downto 0) := (others => '0');
132 signal cut_TCP_DATA_dl : std_logic_vector(4 downto 0) := (others => '0');
133 signal SOURCE_IP : std_logic_vector(31 downto 0) := (others => '0');
134 signal SOURCE_ADDR : std_logic_vector(31 downto 0) := (others => '0');
135 signal Frame_end_dl : std_logic_vector(3 downto 0) := (others => '0');
136 signal EMAC_RxGoodFrame_dl : std_logic := '0';
137 signal Dout_valid_i: std_logic := '0';
138 signal Dout_avl_i: std_logic := '0';
139 signal we_queue: std_logic := '0';
140 signal re_queue: std_logic := '0';
141 signal queue_empty: std_logic := '0';
142 signal queue_full: std_logic := '0';
143 signal queue_a : std_logic_vector(4 downto 0) := (others => '0');
144 signal queue_in : std_logic_vector(10 downto 0) := (others => '0');
145 signal queue_out : std_logic_vector(10 downto 0) := (others => '0');
146 signal queue_o : std_logic_vector(10 downto 0) := (others => '0');
147 signal buf_rden : std_logic := '0';
148 signal buf_dout_vld : std_logic := '0';
149 signal rd_buf : std_logic := '0';
150 signal is_MY_ETH: std_logic := '0';
151 signal is_broadcast_ETH: std_logic := '0';
152 signal in_states : std_logic_vector(2 downto 0) := (others => '0');
153 signal was_DROP : std_logic := '0';
154 signal GoodCntr : std_logic_vector(31 downto 0) := (others => '0');
155 signal BadCntr : std_logic_vector(31 downto 0) := (others => '0');
156 signal DROPCntr : array12x32 := (others => (others => '0'));
157 begin
158 csa(129) <= emac_rxbadframe;
159 csa(128) <= emac_rxdvld(3);
160 csa(127 downto 117) <= queue_out;
161 csa(116 downto 112) <= queue_a;
162 csa(111 downto 106) <= raddr(5 downto 0);
163 csa(105) <= ec_raddr;
164 csa(104) <= buf_dout_vld;
165 csa(103) <= buf_rden;
166 csa(102) <= rd_buf;
167 csa(101) <= is_broadcast_ETH;
168 csa(100) <= is_MY_ETH;
169 csa(99) <= queue_full;
170 csa(98) <= queue_empty;
171 csa(97) <= cut_tcp_data;
172 csa(96) <= '1' when in_state = drop else '0';
173 csa(95) <= '1' when in_state = ip_data else '0';
174 csa(94) <= '1' when in_state = ip_hdr else '0';
175 csa(93) <= '1' when in_state = arp else '0';
176 csa(92) <= '1' when in_state = et_hdr else '0';
177 csa(91) <= '1' when in_state = idle else '0';
178 csa(90) <= en_dout;
179 csa(89) <= emac_rxbadframe;
180 csa(88) <= emac_rxgoodframe;
181 csa(87) <= bad_iphdr_chksum;
182 csa(86) <= chk_iphdr_chksum;
183 csa(85) <= bad_ip_chksum;
184 csa(84) <= chk_ip_chksum;
185 csa(83) <= is_ICMP;
186 csa(82) <= is_TCP;
187 csa(81) <= is_ARP;
188 csa(80) <= en_Rx;
189 csa(79) <= wea;
190 csa(78) <= re_queue;
191 csa(77) <= we_queue;
192 csa(76 downto 65) <= goto_drop;
193 csa(64 downto 56) <= start_waddr;
194 csa(55 downto 47) <= waddr;
195 csa(46 downto 36) <= queue_in;
196 csa(35 downto 32) <= emac_rxdvld;
197 csa(31 downto 0) <= emac_rxd;
198 Dout_type <= queue_out(10 downto 9);
199 --Dout_length <= queue_out(8 downto 0);
200 Dout <= buf_dout;
201 Dout_valid <= Dout_valid_i;
202 Dout_avl <= Dout_avl_i;
203 -- bit 35 marks start of frame, bit 34 marks next to last word of the frame
204 -- bit 33-32 are number of valid bytes of buf_dout:
205 -- when "00" buf_dout(31 downto 0) are valid
206 -- when "01" buf_dout(31 downto 24) are valid
207 -- when "10" buf_dout(31 downto 16) are valid
208 -- when "11" buf_dout(31 downto 8) are valid
209 i_buf : BRAM_SDP_MACRO
210  generic map (
211  BRAM_SIZE => "18Kb", -- Target BRAM, "18Kb" or "36Kb"
212  DEVICE => "7SERIES", -- Target device: "VIRTEX5", "VIRTEX6", "7SERIES", "SPARTAN6"
213  WRITE_WIDTH => 36, -- Valid values are 1-72 (37-72 only valid when BRAM_SIZE="36Kb")
214  READ_WIDTH => 36, -- Valid values are 1-72 (37-72 only valid when BRAM_SIZE="36Kb")
215  DO_REG => 0, -- Optional output register (0 or 1)
216  INIT_FILE => "NONE",
217  SIM_COLLISION_CHECK => "NONE") -- Collision check enable "ALL", "WARNING_ONLY",
218  -- "GENERATE_X_ONLY" or "NONE"
219  port map (
220  DO => buf_do, -- Output read data port, width defined by READ_WIDTH parameter
221  DI => buf_di, -- Input write data port, width defined by WRITE_WIDTH parameter
222  RDADDR => raddr, -- Input read address, width defined by read port depth
223  RDCLK => clk, -- 1-bit input read clock
224  RDEN => buf_rden, -- 1-bit input read port enable
225  REGCE => '1', -- 1-bit input read output register enable
226  RST => '0', -- 1-bit input reset
227  WE => x"f", -- Input write enable, width defined by write port depth
228  WRADDR => waddr, -- Input write address, width defined by write port depth
229  WRCLK => clk, -- 1-bit input write clock
230  WREN => wea -- 1-bit input write port enable
231  );
232 g_SOURCE_ADDR: for i in 0 to 15 generate
233  i_SOURCE_ADDR_h : SRL16E
234  port map (
235  Q => SOURCE_ADDR(i+16), -- SRL data output
236  A0 => '0', -- Select[0] input
237  A1 => '1', -- Select[1] input
238  A2 => '0', -- Select[2] input
239  A3 => '0', -- Select[3] input
240  CE => '1', -- Clock enable input
241  CLK => clk, -- Clock input
242  D => EMAC_RxD_q(i) -- SRL data input
243  );
244  i_SOURCE_ADDR_l : SRL16E
245  port map (
246  Q => SOURCE_ADDR(i), -- SRL data output
247  A0 => '1', -- Select[0] input
248  A1 => '0', -- Select[1] input
249  A2 => '0', -- Select[2] input
250  A3 => '0', -- Select[3] input
251  CE => '1', -- Clock enable input
252  CLK => clk, -- Clock input
253  D => EMAC_RxD_q(i+16) -- SRL data input
254  );
255 end generate;
256 g_buf_di: for i in 0 to 1 generate
257  i_buf_di : SRL16E
258  port map (
259  Q => buf_di(32+i), -- SRL data output
260  A0 => '1', -- Select[0] input
261  A1 => '1', -- Select[1] input
262  A2 => '0', -- Select[2] input
263  A3 => '0', -- Select[3] input
264  CE => '1', -- Clock enable input
265  CLK => clk, -- Clock input
266  D => byte_cnt(i) -- SRL data input
267  );
268 end generate;
269 i_wea : SRL16E
270  port map (
271  Q => wea, -- SRL data output
272  A0 => '0', -- Select[0] input
273  A1 => '1', -- Select[1] input
274  A2 => '0', -- Select[2] input
275  A3 => '0', -- Select[3] input
276  CE => '1', -- Clock enable input
277  CLK => clk, -- Clock input
278  D => en_Rx -- SRL data input
279  );
280 i_chk_IP_chksum : SRL16E
281  port map (
282  Q => chk_IP_chksum, -- SRL data output
283  A0 => '0', -- Select[0] input
284  A1 => '1', -- Select[1] input
285  A2 => '0', -- Select[2] input
286  A3 => '0', -- Select[3] input
287  CE => '1', -- Clock enable input
288  CLK => clk, -- Clock input
289  D => ipdata_end -- SRL data input
290  );
291 process(clk)
292 begin
293  if(clk'event and clk = '1')then
294  if(reset = '1')then
295  reset_ext <= '1';
296  elsif(EMAC_RxDVLD(3) = '0')then
297  reset_ext <= '0';
298  end if;
299  case EMAC_RxDVLD is
300  when x"f" => EMAC_RxD_q <= EMAC_RxD;
301  when x"e" => EMAC_RxD_q <= EMAC_RxD(31 downto 8) & x"00";
302  when x"c" => EMAC_RxD_q <= EMAC_RxD(31 downto 16) & x"0000";
303  when x"8" => EMAC_RxD_q <= EMAC_RxD(31 downto 24) & x"000000";
304  when others => EMAC_RxD_q <= x"00000000";
305  end case;
306  if(IS_ARP = '1' and wc(3 downto 0) = x"9")then
307  byte_cnt <= "10";
308  else
309  case EMAC_RxDVLD is
310  when x"f" => byte_cnt <= "00";
311  when x"e" => byte_cnt <= "11";
312  when x"c" => byte_cnt <= "10";
313  when x"8" => byte_cnt <= "01";
314  when others => byte_cnt <= "00";
315  end case;
316  end if;
317 -- swap_TCP_port_dl <= swap_TCP_port_dl(0) & swap_TCP_port;
318  if(reset = '1')then
319  cut_TCP_DATA_dl <= (others => '0');
320  elsif(chk_iphdr_chksum = '1' and is_TCP = '1')then
321  cut_TCP_DATA_dl(4) <= '1';
322  cut_TCP_DATA_dl(3) <= EMAC_RxD_q(15) xnor EMAC_RxD_q(14);
323  cut_TCP_DATA_dl(2) <= not EMAC_RxD_q(14);
324  cut_TCP_DATA_dl(1 downto 0) <= EMAC_RxD_q(13 downto 12);
325  elsif(cut_TCP_DATA_dl(4) = '1')then
326  cut_TCP_DATA_dl <= cut_TCP_DATA_dl - 1;
327  end if;
328  if(cut_TCP_DATA_dl = "10000")then
329  cut_TCP_DATA <= '1';
330  else
331  cut_TCP_DATA <= '0';
332  end if;
333  cut_TCP_DATA_r <= cut_TCP_DATA;
334  if(reset_ext = '1' or Frame_end_dl(0) = '1')then
335  wc <= (others => '0');
336  elsif(EMAC_RxDVLD_q = '1')then
337  wc <= wc + 1;
338  end if;
339  if(reset_ext = '1' or EMAC_RxDVLD_q = '0' or (is_ARP = '1' and wc(3 downto 0) = x"b") or (cut_TCP_DATA = '1' and no_TCP_DATA = '1'))then
340  en_Rx <= '0';
341  elsif(in_state = ET_HDR)then
342  en_Rx <= '1';
343  end if;
344  if(IS_ARP = '0' and EMAC_RxDVLD(3) = '0' and EMAC_RxDVLD_q = '1' and ipdata_end = '0')then
345  ipdata_end <= '1';
346  else
347  ipdata_end <= '0';
348  end if;
349  buf_di(35) <= cut_TCP_DATA_r;
350  if(IS_ARP = '1')then
351  case wc(3 downto 0) is
352  when x"5" => EMAC_RxD_q2 <= x"0002" & MY_ETH(47 downto 32);
353  when x"6" => EMAC_RxD_q2 <= MY_ETH(31 downto 0);
354  when x"7" => EMAC_RxD_q2 <= MY_IP;
355  when x"8" | x"9" | x"a" | x"b" => EMAC_RxD_q2 <= SOURCE_ADDR;
356  when others => EMAC_RxD_q2 <= EMAC_RxD_q;
357  end case;
358  elsif(swap_TCP_port = '1')then
359  EMAC_RxD_q2 <= EMAC_RxD_q2(15 downto 0) & EMAC_RxD_q(15 downto 0);-- this does not affect IP_chksum_in for TCP header
360  else
361  EMAC_RxD_q2 <= EMAC_RxD_q;
362  end if;
363  if(in_state = IP_HDR and wc(3 downto 0) = X"7" and is_ICMP = '1')then
364  ICMP_check <= '1';
365  else
366  ICMP_check <= '0';
367  end if;
368  ICMP_ECHO <= ICMP_check;
369  ICMP_chksum <= ICMP_ECHO;
370  if(ICMP_check = '1')then
371  ICMP_newchksum(16 downto 11) <= ('0' & EMAC_RxD(31 downto 27)) + 1;
372  ICMP_newchksum(10 downto 0) <= EMAC_RxD(26 downto 16);
373  elsif(ICMP_newchksum(16) = '1')then
374  ICMP_newchksum <= '0' & (ICMP_newchksum(15 downto 0) + 1);
375  end if;
376  if(ICMP_ECHO = '1')then
377  EMAC_RxD_q3 <= EMAC_RxD_q2(31 downto 16) & x"0000"; -- change to ECHO reply
378  elsif(ICMP_chksum = '1')then
379  EMAC_RxD_q3 <= ICMP_newchksum(15 downto 0) & EMAC_RxD_q2(15 downto 0); -- change to ECHO reply
380  elsif(swap_TCP_port = '1')then
381  EMAC_RxD_q3 <= EMAC_RxD_q2(31 downto 16) & EMAC_RxD_q(31 downto 16);
382  else
383  EMAC_RxD_q3 <= EMAC_RxD_q2;
384  end if;
385  buf_di(31 downto 0) <= EMAC_RxD_q4;
386  if(in_state /= ET_HDR)then
387  swap_ETH_ADDR <= '0';
388  elsif(wc(0) = '1')then
389  swap_ETH_ADDR <= '1';
390  end if;
391  if(is_TCP = '1' and in_state = IP_HDR and IHDL = x"1")then
392  swap_TCP_port <= '1';
393  else
394  swap_TCP_port <= '0';
395  end if;
396 -- swap_TCP_port(1) <= swap_TCP_port(0);
397  if(in_state = IP_HDR and wc(3 downto 0) = x"7")then
398  SOURCE_IP <= EMAC_RxD_q2(15 downto 0) & EMAC_RxD_q(31 downto 16);
399  swap_IP_ADDR <= '1';
400  elsif(wc(1) = '1')then
401  swap_IP_ADDR <= '0';
402  end if;
403  if(swap_ETH_ADDR = '1')then
404  case wc(1 downto 0) is
405  when "10" => EMAC_RxD_q4 <= EMAC_RxD_q2(15 downto 0) & EMAC_RxD_q(31 downto 16);
406  when "11" => EMAC_RxD_q4 <= EMAC_RxD_q2(15 downto 0) & MY_ETH(47 downto 32);
407  when others => EMAC_RxD_q4 <= MY_ETH(31 downto 0);
408  end case;
409  elsif(swap_IP_ADDR = '1')then
410  case wc(1 downto 0) is
411  when "00" => EMAC_RxD_q4 <= EMAC_RxD_q3(31 downto 16) & EMAC_RxD_q2(15 downto 0);
412  when "01" => EMAC_RxD_q4 <= EMAC_RxD_q2(31 downto 16) & SOURCE_IP(31 downto 16);
413  when others => EMAC_RxD_q4 <= SOURCE_IP(15 downto 0) & EMAC_RxD_q3(15 downto 0);
414  end case;
415  else
416  EMAC_RxD_q4 <= EMAC_RxD_q3;
417  end if;
418  EMAC_RxDVLD_q <= EMAC_RxDVLD(3);
419  buf_space <= raddr - waddr - 1;
420  if(reset_ext = '1' or EMAC_RxBadFrame = '1' or EMAC_RxGoodFrame = '1')then
421  in_state <= IDLE;
422  goto_DROP <= (others => '0');
423  else
424  case in_state is
425  when IDLE =>
426  if(EMAC_RxDVLD(3) = '1')then
427  if(queue_full = '1' or or_reduce(buf_space(8 downto 5)) = '0')then
428  goto_DROP(0) <= '1';
429  in_state <= DROP;
430  else
431  in_state <= ET_HDR;
432  end if;
433  end if;
434  IHDL <= x"f";
435  is_MY_ETH <= '1';
436  is_broadcast_ETH <= '1';
437  when ET_HDR =>
438  case wc(1 downto 0) is
439  when "00" =>
440  if(EMAC_RxD_q /= MY_ETH(47 downto 16))then
441  is_MY_ETH <= '0';
442  end if;
443  if(and_reduce(EMAC_RxD_q) = '0')then
444  is_broadcast_ETH <= '0';
445  end if;
446  when "01" =>
447  if(EMAC_RxD_q(31 downto 16) /= MY_ETH(15 downto 0))then
448  is_MY_ETH <= '0';
449  end if;
450  if(and_reduce(EMAC_RxD_q(31 downto 16)) = '0')then
451  is_broadcast_ETH <= '0';
452  end if;
453  when "11" =>
454  if(EMAC_RxD_q = ETHTYPE_ARP)then
455  in_state <= ARP;
456  elsif(EMAC_RxD_q(31 downto 12) = ETHTYPE_IP4(31 downto 12) and EMAC_RxD_q(7 downto 0) = ETHTYPE_IP4(7 downto 0))then
457  in_state <= IP_HDR;
458  end if;
459  is_ARP <= '0';
460  is_TCP <= '0';
461  is_ICMP <= '0';
462  IS_Request <= '0';
463  IHDL <= EMAC_RxD_q(11 downto 8);
464  when others => null;
465  end case;
466 -- if(wc(2) = '1')then it is neither ARP nor IP4
467  if(wc(2) = '1' or (is_MY_ETH = '0' and is_broadcast_ETH = '0'))then
468  goto_DROP(1) <= '1';
469  in_state <= DROP;
470  end if;
471  if(EMAC_RxD(17 downto 16) = "11")then
472  IP_Length_offset(3 downto 0) <= EMAC_RxD_q(11 downto 8);
473  else
474  IP_Length_offset(3 downto 0) <= EMAC_RxD_q(11 downto 8) + 1;
475  end if;
476  when IP_HDR =>
477  if(wc(4 downto 0) = "00100")then
478  IP_Length(11 downto 2) <= EMAC_RxD_q(27 downto 18) - IP_Length_offset;
479  IP_Length(1 downto 0) <= EMAC_RxD_q(17 downto 16);
480  end if;
481  if(wc(4 downto 0) = "00101")then
482  if(or_reduce(EMAC_RxD_q(29 downto 16)) = '1')then -- no framented data accepted
483  goto_DROP(2) <= '1';
484  in_state <= DROP;
485  end if;
486  if(EMAC_RxD_q(7 downto 0) = PROTOCAL_ICMP and IHDL = x"4")then -- ICMP has no option
487  is_ICMP <= '1';
488  elsif(EMAC_RxD_q(7 downto 0) = PROTOCAL_TCP)then
489  is_TCP <= '1';
490  end if;
491  end if;
492  if(wc(4 downto 0) = "00111" and EMAC_RxD_q(15 downto 0) /= MY_IP(31 downto 16))then
493  goto_DROP(3) <= '1';
494  in_state <= DROP;
495  end if;
496  if(wc(4 downto 0) = "01000" and EMAC_RxD_q(31 downto 16) /= MY_IP(15 downto 0))then
497  goto_DROP(4) <= '1';
498  in_state <= DROP;
499  end if;
500  IHDL <= IHDL - 1;
501  if(IHDL(3 downto 1) = "000")then
502  in_state <= IP_DATA;
503  end if;
504  when IP_DATA =>
505  IP_Length(11 downto 2) <= IP_Length(11 downto 2) - 1;
506  if(ICMP_check = '1' and EMAC_RxD_q(15 downto 0) /= x"0800")then
507  goto_DROP(5) <= '1';
508  in_state <= DROP;
509  end if;
510  if((chk_IPHDR_chksum = '1' and bad_IPHDR_chksum = '1') or (is_ICMP = '0' and is_TCP = '0'))then
511  goto_DROP(6) <= '1';
512  in_state <= DROP;
513  end if;
514  if(EMAC_RxDVLD(3) = '0' and EMAC_RxDVLD_q = '1' and (or_reduce(IP_Length(11 downto 2)) = '1' or bad_Length = '1'))then
515  goto_DROP(7) <= '1';
516  in_state <= DROP;
517  end if;
518  if(wea = '1' and or_reduce(buf_space(8 downto 5)) = '0')then
519  goto_DROP(0) <= '1';
520  in_state <= DROP;
521  end if;
522  when ARP =>
523  is_ARP <= '1';
524  if(en_Rx = '1' and wc(3 downto 0) = x"4" and EMAC_RxD_q(31 downto 16) /= x"0800")then -- IP protocal?
525  goto_DROP(8) <= '1';
526  in_state <= DROP;
527  end if;
528  if(en_Rx = '1' and wc(3 downto 0) = x"5")then
529  if(EMAC_RxD_q(31 downto 16) = x"0001")then -- ARP request?
530  IS_Request <= '1';
531  else
532  IS_Request <= '0';
533  end if;
534  end if;
535  if(en_Rx = '1' and wc(3 downto 0) = x"9" and EMAC_RxD_q(15 downto 0) /= MY_IP(31 downto 16))then -- my IP address?
536  goto_DROP(10) <= '1';
537  in_state <= DROP;
538  end if;
539  if(en_Rx = '1' and wc(3 downto 0) = x"a" and EMAC_RxD_q(31 downto 16) /= MY_IP(15 downto 0))then -- my IP address?
540  goto_DROP(11) <= '1';
541  in_state <= DROP;
542  end if;
543  when others => null;
544  end case;
545  end if;
546  case IP_Length(1 downto 0) is
547  when "00" => bad_Length <= not EMAC_RxDVLD(3) or not EMAC_RxDVLD(2) or or_reduce(EMAC_RxDVLD(1 downto 0));
548  when "01" => bad_Length <= not EMAC_RxDVLD(3) or not EMAC_RxDVLD(2) or not EMAC_RxDVLD(1) or EMAC_RxDVLD(0);
549  when "10" => bad_Length <= not and_reduce(EMAC_RxDVLD);
550  when others => bad_Length <= not EMAC_RxDVLD(3) or or_reduce(EMAC_RxDVLD(2 downto 0));
551  end case;
552  if(reset_ext = '1')then
553  waddr <= (others => '0');
554  elsif(in_state = DROP or (chk_IP_chksum = '1' and bad_IP_chksum = '1'))then
555  waddr <= start_waddr;
556  elsif(wea = '1')then
557  waddr <= waddr + 1;
558  end if;
559  if(reset_ext = '1')then
560  start_waddr <= (others => '0');
561  elsif(Frame_end_dl(3) = '1' and waddr /= start_waddr)then
562  start_waddr <= waddr;
563  end if;
564  if(wea = '1')then
565  last_waddr <= waddr;
566  end if;
567  Frame_end_dl <= Frame_end_dl(2 downto 0) & (EMAC_RxGoodFrame or EMAC_RxbadFrame);
568  if(in_state = IP_HDR)then
569  rst_IPHDR_chksum <= '0';
570  else
571  rst_IPHDR_chksum <= '1';
572  end if;
573  if((in_state = ET_HDR and wc(1 downto 0) = "11") or (is_ICMP = '1' and in_state = IP_HDR))then
574  rst_IP_chksum <= '1';
575  else
576  rst_IP_chksum <= '0';
577  end if;
578 -- check IP header checksum: from first word till IHDL
579  IPHDR_data_dl <= IPHDR_data_dl(0) & IPHDR_data;
580  chk_IPHDR_chksum <= IPHDR_data_dl(1) and not IPHDR_data_dl(0);
581  if(reset_ext = '0' and Frame_end_dl(3) = '1' and waddr /= start_waddr)then
582  we_queue <= '1';
583  else
584  we_queue <= '0';
585  end if;
586  IPHDR_chksum_in <= ('0' & EMAC_RxD_q(31 downto 16)) + ('0' & EMAC_RxD_q2(15 downto 0));
587  TCP_length <= EMAC_RxD_q(31 downto 16) - ("0000000000" & EMAC_RxD_q2(11 downto 8) & "00");
588  if(in_state = ET_HDR and wc(1 downto 0) = "11")then
589  IPHDR_data <= '1';
590  elsif(IHDL = x"1")then
591  IPHDR_data <= '0';
592  end if;
593  if(IPHDR_data = '1')then
594  case wc(3 downto 0) is
595  when x"5" => IP_chksum_in <= '0' & TCP_length;
596  when x"6" => IP_chksum_in <= "000000000" & EMAC_RxD_q2(7 downto 0); -- protocol
597  when x"7" | x"8" => IP_chksum_in <= ('0' & EMAC_RxD_q(31 downto 16)) + ('0' & EMAC_RxD_q2(15 downto 0)); -- source and destination IP address
598  when others => IP_chksum_in <= (others => '0');
599  end case;
600  else
601  IP_chksum_in <= ('0' & EMAC_RxD_q(31 downto 16)) + ('0' & EMAC_RxD_q2(15 downto 0));
602  end if;
603  end if;
604 end process;
605 i_IPHDR_checksum: checksum PORT MAP(
606  c => clk,
607  r => rst_IPHDR_chksum,
608  r_value => x"ffff",
609  ce => '1',
610  d => IPHDR_chksum_in,
611  bad_chksum => bad_IPHDR_chksum,
612  s => open
613  );
614 i_IP_checksum: checksum PORT MAP(
615  c => clk,
616  r => rst_IP_chksum,
617  r_value => x"ffff",
618  ce => '1',
619  d => IP_chksum_in,
620  bad_chksum => bad_IP_chksum,
621  s => open
622  );
623 process(clk)
624 begin
625  if(clk'event and clk = '1')then
626  if(reset_ext = '1')then
627  Dout_avl_i <= '0';
628  rd_buf <= '0';
629  ec_raddr <= '0';
630  raddr <= (others => '0');
631  buf_dout_vld <= '0';
632  Dout_valid_i <= '0';
633  queue_a <= (others => '1');
634  else
635  if(en_Dout = '1' or rd_buf = '1')then
636  Dout_avl_i <= '0';
637  elsif(queue_empty = '0')then
638  Dout_avl_i <= '1';
639  end if;
640  if(en_Dout = '1' and Dout_avl_i = '1')then
641  rd_buf <= '1';
642  elsif(re_queue = '1')then
643  rd_buf <= '0';
644  end if;
645  if(re_queue = '1')then
646  buf_dout_vld <= '0';
647  elsif(queue_empty = '0')then
648  buf_dout_vld <= '1';
649  end if;
650  if(en_Dout = '1' and Dout_avl_i = '1')then
651  ec_raddr <= '1';
652  elsif(buf_dout(34) = '1')then
653  ec_raddr <= '0';
654  end if;
655  if((en_Dout = '1' and Dout_avl_i = '1') or (queue_empty = '0' and buf_dout_vld = '0') or (ec_raddr = '1' and buf_dout(34) = '0'))then
656  raddr <= raddr + 1;
657  end if;
658  Dout_valid_i <= ec_raddr or (en_Dout and Dout_avl_i);
659  if(we_queue = '1' and re_queue = '0' and (queue_empty = '0' or and_reduce(queue_a) = '1'))then
660  queue_a <= queue_a + 1;
661  elsif(we_queue = '0' and and_reduce(queue_a) = '0' and (re_queue = '1' or queue_empty = '1'))then
662  queue_a <= queue_a - 1;
663  end if;
664  end if;
665  if(buf_rden = '1')then
666  buf_dout(33 downto 0) <= buf_do(33 downto 0);
667  end if;
668  if(queue_out(8 downto 0) = raddr and ec_raddr = '1')then
669  buf_dout(34) <= '1';
670  else
671  buf_dout(34) <= '0';
672  end if;
673  if(buf_dout_vld = '0' or (en_Dout = '1' and Dout_avl_i = '1') or ec_raddr = '1')then
674  buf_rden <= '1';
675  else
676  buf_rden <= '0';
677  end if;
678  queue_in(10) <= IS_ARP;
679  queue_in(9) <= IS_Request or IS_ICMP;
680  queue_in(8 downto 0) <= last_waddr;
681  if(reset_ext = '1')then
682  queue_empty <= '1';
683  elsif(and_reduce(queue_a) = '0')then
684  queue_empty <= '0';
685  elsif(re_queue = '1')then
686  queue_empty <= '1';
687  end if;
688  if(queue_empty = '1' or re_queue = '1')then
689  queue_out <= queue_o;
690  end if;
691  if(reset_ext = '1' or queue_a = "11100")then
692  queue_full <= '0';
693  elsif(queue_a = "11101")then
694  queue_full <= '1';
695  end if;
696  last_word <= re_queue;
697  end if;
698 end process;
699 re_queue <= buf_dout(34) and Dout_valid_i;
700 g_queue: for i in 0 to 10 generate
701  i_queue : SRLC32E
702  port map (
703  Q => queue_o(i), -- SRL data output
704  Q31 => open, -- SRL cascade output pin
705  A => queue_a, -- 5-bit shift depth select input
706  CE => we_queue, -- Clock enable input
707  CLK => clk, -- Clock input
708  D => queue_in(i) -- SRL data input
709  );
710 end generate;
711 process(clk)
712 begin
713  if(clk'event and clk = '1')then
714  if(in_state = DROP)then
715  was_DROP <= '1';
716  else
717  was_DROP <= '0';
718  end if;
719  if(rstCntr = '1')then
720  GoodCntr <= (others => '0');
721  BadCntr <= (others => '0');
722  DropCntr <= (others => (others => '0'));
723  else
724  if(EMAC_RxGoodFrame = '1')then
725  GoodCntr <= GoodCntr + 1;
726  end if;
727  if(EMAC_RxBadFrame = '1')then
728  BadCntr <= BadCntr + 1;
729  end if;
730  for i in 0 to 11 loop
731  if(was_DROP = '0' and goto_DROP(i) = '1')then
732  if(i = 1)then
733  DROPCntr(i) <= DROPCntr(i) + 1;
734  else
735  DROPCntr(i)(15 downto 0) <= DROPCntr(i)(15 downto 0) + 1;
736  end if;
737  end if;
738  end loop;
739  end if;
740  end if;
741 end process;
742 process(in_state)
743 begin
744  case in_state is
745  when ET_HDR => in_states <= "001";
746  when ARP => in_states <= "010";
747  when IP_HDR => in_states <= "011";
748  when IP_DATA => in_states <= "100";
749  when DROP => in_states <= "101";
750  when others => in_states <= "000";
751  end case;
752 end process;
753 process(ipb_addr)
754 begin
755  case ipb_addr(3 downto 0) is
756  when x"0" => ipb_rdata <= "0000000" & waddr & "0000000" & raddr;
757  when x"1" => ipb_rdata <= x"0000" & "0000000" & start_waddr;
758  when x"2" => ipb_rdata <= "000" & chk_IP_chksum & bad_IP_chksum & bad_length & is_ICMP & is_TCP & is_ARP & in_states & goto_DROP & '0' & queue_full & queue_empty & queue_a;
759  when x"3" => ipb_rdata <= reset_ext & wea & wc & rst_IP_chksum & IP_chksum_in & is_MY_ETH & bad_IPHDR_chksum & chk_IPHDR_chksum;
760  when x"4" => ipb_rdata <= DROPCntr(0);
761  when x"5" => ipb_rdata <= DROPCntr(3)(15 downto 0) & DROPCntr(2)(15 downto 0);
762  when x"6" => ipb_rdata <= DROPCntr(5)(15 downto 0) & DROPCntr(4)(15 downto 0);
763  when x"7" => ipb_rdata <= DROPCntr(7)(15 downto 0) & DROPCntr(6)(15 downto 0);
764  when x"8" => ipb_rdata <= DROPCntr(9)(15 downto 0) & DROPCntr(8)(15 downto 0);
765  when x"9" => ipb_rdata <= DROPCntr(11)(15 downto 0) & DROPCntr(10)(15 downto 0);
766  when x"a" => ipb_rdata <= GoodCntr;
767  when x"b" => ipb_rdata <= BadCntr;
768  when x"c" => ipb_rdata <= DROPCntr(1);
769  when others => ipb_rdata <= (others => '0');
770  end case;
771 end process;
772 end Behavioral;
773