---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 16:09:48 08/05/2010 -- Design Name: -- Module Name: GE_in - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- Dout(17 downto 16) = "01" for header or ARP data -- Dout(17 downto 16) = "11" for IP data -- Dout(17 downto 16) = "10" for IP data last word which has odd number of bytes ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use IEEE.std_logic_misc.all; use work.amc13_pack.all; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. library UNISIM; use UNISIM.VComponents.all; Library UNIMACRO; use UNIMACRO.vcomponents.all; entity EMAC_Rx_if is Port ( clk : in STD_LOGIC; reset : in STD_LOGIC; rstCntr : IN std_logic; no_TCP_DATA : in STD_LOGIC; -- if set, TCP data are not output EMAC_RxD : in STD_LOGIC_VECTOR (31 downto 0); EMAC_RxDVLD : in STD_LOGIC_VECTOR (3 downto 0); EMAC_RxGoodFrame : in STD_LOGIC; EMAC_RxBadFrame : in STD_LOGIC; MY_IP : in STD_LOGIC_VECTOR (31 downto 0); -- my IP address MY_ETH : in STD_LOGIC_VECTOR (47 downto 0); -- my Ethernet address en_Dout : in STD_LOGIC; Dout_avl : out STD_LOGIC := '0'; Dout_type : out STD_LOGIC_VECTOR (1 downto 0):= "00"; -- 00 TCP, 01 ICMP, 10 ARP reply, 11 ARP request Dout : out STD_LOGIC_VECTOR (35 downto 0) := (others => '0'); last_word : out STD_LOGIC := '0'; Dout_valid : out STD_LOGIC := '0'; ipb_addr : in STD_LOGIC_VECTOR(31 downto 0); ipb_rdata : out STD_LOGIC_VECTOR(31 downto 0); csa : out STD_LOGIC_VECTOR (135 downto 0); csb : out STD_LOGIC_VECTOR (135 downto 0) ); end EMAC_Rx_if; architecture Behavioral of EMAC_Rx_if is COMPONENT checksum PORT( c : IN std_logic; r : IN std_logic; r_value : IN std_logic_vector(15 downto 0); ce : IN std_logic; d : IN std_logic_vector(16 downto 0); bad_chksum : OUT std_logic; s : OUT std_logic_vector(15 downto 0) ); END COMPONENT; constant ETHTYPE_IP4 : std_logic_vector(31 downto 0) := x"08004500"; constant ETHTYPE_ARP : std_logic_vector(31 downto 0) := x"08060001"; constant PROTOCAL_TCP : std_logic_vector(7 downto 0) := x"06"; constant PROTOCAL_ICMP : std_logic_vector(7 downto 0) := x"01"; type state is (IDLE, ET_HDR, ARP, IP_HDR, IP_DATA, DROP); signal in_state : state; signal goto_DROP : std_logic_vector(11 downto 0) := (others => '0'); signal buf_di : std_logic_vector(35 downto 0) := (others => '0'); signal buf_do : std_logic_vector(35 downto 0) := (others => '0'); signal buf_dout : std_logic_vector(35 downto 0) := (others => '0'); signal EMAC_RxD_q : std_logic_vector(31 downto 0) := (others => '0'); signal EMAC_RxD_q2 : std_logic_vector(31 downto 0) := (others => '0'); signal EMAC_RxD_q3 : std_logic_vector(31 downto 0) := (others => '0'); signal EMAC_RxD_q4 : std_logic_vector(31 downto 0) := (others => '0'); signal EMAC_RxDVLD_q : std_logic := '0'; signal reset_ext : std_logic := '0'; signal en_Rx : std_logic := '0'; signal wea : std_logic := '0'; signal buf_space : std_logic_vector(8 downto 0) := (others => '0'); signal waddr : std_logic_vector(8 downto 0) := (others => '0'); signal start_waddr : std_logic_vector(8 downto 0) := (others => '0'); signal last_waddr : std_logic_vector(8 downto 0) := (others => '0'); signal raddr : std_logic_vector(8 downto 0) := (others => '0'); signal wc : std_logic_vector(8 downto 0) := (others => '0'); signal byte_cnt : std_logic_vector(1 downto 0) := (others => '0'); signal ec_raddr : std_logic := '0'; signal is_ARP : std_logic := '0'; signal IS_Request : std_logic := '0'; signal is_TCP : std_logic := '0'; signal is_ICMP : std_logic := '0'; signal cut_TCP_DATA : std_logic := '0'; signal cut_TCP_DATA_r : std_logic := '0'; signal IPHDR_data : std_logic := '0'; signal IPHDR_data_dl : std_logic_vector(1 downto 0) := (others => '0'); signal IHDL : std_logic_vector(3 downto 0) := (others => '0'); signal IP_Length : std_logic_vector(11 downto 0) := (others => '0'); signal TCP_Length : std_logic_vector(15 downto 0) := (others => '0'); signal IP_Length_offset : std_logic_vector(9 downto 0) := (others => '0'); signal bad_Length : std_logic := '0'; signal rst_IP_chksum : std_logic := '0'; signal rst_IPHDR_chksum : std_logic := '0'; signal bad_IPHDR_chksum : std_logic := '0'; signal IPHDR_chksum_in : std_logic_vector(16 downto 0) := (others => '0'); signal IP_chksum_in : std_logic_vector(16 downto 0) := (others => '0'); signal bad_IP_chksum : std_logic := '0'; signal ipdata_end: std_logic := '0'; signal chk_IP_chksum : std_logic := '0'; signal chk_IPHDR_chksum : std_logic := '0'; signal ICMP_check : std_logic := '0'; signal ICMP_ECHO : std_logic := '0'; signal ICMP_chksum : std_logic := '0'; signal ICMP_newchksum : std_logic_vector(16 downto 0) := (others => '0'); signal swap_ETH_ADDR: std_logic := '0'; signal swap_IP_ADDR: std_logic := '0'; signal swap_TCP_PORT: std_logic := '0'; --signal swap_TCP_PORT_dl: std_logic_vector(1 downto 0) := (others => '0'); signal cut_TCP_DATA_dl : std_logic_vector(4 downto 0) := (others => '0'); signal SOURCE_IP : std_logic_vector(31 downto 0) := (others => '0'); signal SOURCE_ADDR : std_logic_vector(31 downto 0) := (others => '0'); signal Frame_end_dl : std_logic_vector(3 downto 0) := (others => '0'); signal EMAC_RxGoodFrame_dl : std_logic := '0'; signal Dout_valid_i: std_logic := '0'; signal Dout_avl_i: std_logic := '0'; signal we_queue: std_logic := '0'; signal re_queue: std_logic := '0'; signal queue_empty: std_logic := '0'; signal queue_full: std_logic := '0'; signal queue_a : std_logic_vector(4 downto 0) := (others => '0'); signal queue_in : std_logic_vector(10 downto 0) := (others => '0'); signal queue_out : std_logic_vector(10 downto 0) := (others => '0'); signal queue_o : std_logic_vector(10 downto 0) := (others => '0'); signal buf_rden : std_logic := '0'; signal buf_dout_vld : std_logic := '0'; signal rd_buf : std_logic := '0'; signal is_MY_ETH: std_logic := '0'; signal is_broadcast_ETH: std_logic := '0'; signal in_states : std_logic_vector(2 downto 0) := (others => '0'); signal was_DROP : std_logic := '0'; signal GoodCntr : std_logic_vector(31 downto 0) := (others => '0'); signal BadCntr : std_logic_vector(31 downto 0) := (others => '0'); signal DROPCntr : array12x32 := (others => (others => '0')); begin csa(129) <= emac_rxbadframe; csa(128) <= emac_rxdvld(3); csa(127 downto 117) <= queue_out; csa(116 downto 112) <= queue_a; csa(111 downto 106) <= raddr(5 downto 0); csa(105) <= ec_raddr; csa(104) <= buf_dout_vld; csa(103) <= buf_rden; csa(102) <= rd_buf; csa(101) <= is_broadcast_ETH; csa(100) <= is_MY_ETH; csa(99) <= queue_full; csa(98) <= queue_empty; csa(97) <= cut_tcp_data; csa(96) <= '1' when in_state = drop else '0'; csa(95) <= '1' when in_state = ip_data else '0'; csa(94) <= '1' when in_state = ip_hdr else '0'; csa(93) <= '1' when in_state = arp else '0'; csa(92) <= '1' when in_state = et_hdr else '0'; csa(91) <= '1' when in_state = idle else '0'; csa(90) <= en_dout; csa(89) <= emac_rxbadframe; csa(88) <= emac_rxgoodframe; csa(87) <= bad_iphdr_chksum; csa(86) <= chk_iphdr_chksum; csa(85) <= bad_ip_chksum; csa(84) <= chk_ip_chksum; csa(83) <= is_ICMP; csa(82) <= is_TCP; csa(81) <= is_ARP; csa(80) <= en_Rx; csa(79) <= wea; csa(78) <= re_queue; csa(77) <= we_queue; csa(76 downto 65) <= goto_drop; csa(64 downto 56) <= start_waddr; csa(55 downto 47) <= waddr; csa(46 downto 36) <= queue_in; csa(35 downto 32) <= emac_rxdvld; csa(31 downto 0) <= emac_rxd; Dout_type <= queue_out(10 downto 9); --Dout_length <= queue_out(8 downto 0); Dout <= buf_dout; Dout_valid <= Dout_valid_i; Dout_avl <= Dout_avl_i; -- bit 35 marks start of frame, bit 34 marks next to last word of the frame -- bit 33-32 are number of valid bytes of buf_dout: -- when "00" buf_dout(31 downto 0) are valid -- when "01" buf_dout(31 downto 24) are valid -- when "10" buf_dout(31 downto 16) are valid -- when "11" buf_dout(31 downto 8) are valid i_buf : BRAM_SDP_MACRO generic map ( BRAM_SIZE => "18Kb", -- Target BRAM, "18Kb" or "36Kb" DEVICE => "7SERIES", -- Target device: "VIRTEX5", "VIRTEX6", "7SERIES", "SPARTAN6" WRITE_WIDTH => 36, -- Valid values are 1-72 (37-72 only valid when BRAM_SIZE="36Kb") READ_WIDTH => 36, -- Valid values are 1-72 (37-72 only valid when BRAM_SIZE="36Kb") DO_REG => 0, -- Optional output register (0 or 1) INIT_FILE => "NONE", SIM_COLLISION_CHECK => "NONE") -- Collision check enable "ALL", "WARNING_ONLY", -- "GENERATE_X_ONLY" or "NONE" port map ( DO => buf_do, -- Output read data port, width defined by READ_WIDTH parameter DI => buf_di, -- Input write data port, width defined by WRITE_WIDTH parameter RDADDR => raddr, -- Input read address, width defined by read port depth RDCLK => clk, -- 1-bit input read clock RDEN => buf_rden, -- 1-bit input read port enable REGCE => '1', -- 1-bit input read output register enable RST => '0', -- 1-bit input reset WE => x"f", -- Input write enable, width defined by write port depth WRADDR => waddr, -- Input write address, width defined by write port depth WRCLK => clk, -- 1-bit input write clock WREN => wea -- 1-bit input write port enable ); g_SOURCE_ADDR: for i in 0 to 15 generate i_SOURCE_ADDR_h : SRL16E port map ( Q => SOURCE_ADDR(i+16), -- SRL data output A0 => '0', -- Select[0] input A1 => '1', -- Select[1] input A2 => '0', -- Select[2] input A3 => '0', -- Select[3] input CE => '1', -- Clock enable input CLK => clk, -- Clock input D => EMAC_RxD_q(i) -- SRL data input ); i_SOURCE_ADDR_l : SRL16E port map ( Q => SOURCE_ADDR(i), -- SRL data output A0 => '1', -- Select[0] input A1 => '0', -- Select[1] input A2 => '0', -- Select[2] input A3 => '0', -- Select[3] input CE => '1', -- Clock enable input CLK => clk, -- Clock input D => EMAC_RxD_q(i+16) -- SRL data input ); end generate; g_buf_di: for i in 0 to 1 generate i_buf_di : SRL16E port map ( Q => buf_di(32+i), -- SRL data output A0 => '1', -- Select[0] input A1 => '1', -- Select[1] input A2 => '0', -- Select[2] input A3 => '0', -- Select[3] input CE => '1', -- Clock enable input CLK => clk, -- Clock input D => byte_cnt(i) -- SRL data input ); end generate; i_wea : SRL16E port map ( Q => wea, -- SRL data output A0 => '0', -- Select[0] input A1 => '1', -- Select[1] input A2 => '0', -- Select[2] input A3 => '0', -- Select[3] input CE => '1', -- Clock enable input CLK => clk, -- Clock input D => en_Rx -- SRL data input ); i_chk_IP_chksum : SRL16E port map ( Q => chk_IP_chksum, -- SRL data output A0 => '0', -- Select[0] input A1 => '1', -- Select[1] input A2 => '0', -- Select[2] input A3 => '0', -- Select[3] input CE => '1', -- Clock enable input CLK => clk, -- Clock input D => ipdata_end -- SRL data input ); process(clk) begin if(clk'event and clk = '1')then if(reset = '1')then reset_ext <= '1'; elsif(EMAC_RxDVLD(3) = '0')then reset_ext <= '0'; end if; case EMAC_RxDVLD is when x"f" => EMAC_RxD_q <= EMAC_RxD; when x"e" => EMAC_RxD_q <= EMAC_RxD(31 downto 8) & x"00"; when x"c" => EMAC_RxD_q <= EMAC_RxD(31 downto 16) & x"0000"; when x"8" => EMAC_RxD_q <= EMAC_RxD(31 downto 24) & x"000000"; when others => EMAC_RxD_q <= x"00000000"; end case; if(IS_ARP = '1' and wc(3 downto 0) = x"9")then byte_cnt <= "10"; else case EMAC_RxDVLD is when x"f" => byte_cnt <= "00"; when x"e" => byte_cnt <= "11"; when x"c" => byte_cnt <= "10"; when x"8" => byte_cnt <= "01"; when others => byte_cnt <= "00"; end case; end if; -- swap_TCP_port_dl <= swap_TCP_port_dl(0) & swap_TCP_port; if(reset = '1')then cut_TCP_DATA_dl <= (others => '0'); elsif(chk_iphdr_chksum = '1' and is_TCP = '1')then cut_TCP_DATA_dl(4) <= '1'; cut_TCP_DATA_dl(3) <= EMAC_RxD_q(15) xnor EMAC_RxD_q(14); cut_TCP_DATA_dl(2) <= not EMAC_RxD_q(14); cut_TCP_DATA_dl(1 downto 0) <= EMAC_RxD_q(13 downto 12); elsif(cut_TCP_DATA_dl(4) = '1')then cut_TCP_DATA_dl <= cut_TCP_DATA_dl - 1; end if; if(cut_TCP_DATA_dl = "10000")then cut_TCP_DATA <= '1'; else cut_TCP_DATA <= '0'; end if; cut_TCP_DATA_r <= cut_TCP_DATA; if(reset_ext = '1' or Frame_end_dl(0) = '1')then wc <= (others => '0'); elsif(EMAC_RxDVLD_q = '1')then wc <= wc + 1; end if; 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 en_Rx <= '0'; elsif(in_state = ET_HDR)then en_Rx <= '1'; end if; if(IS_ARP = '0' and EMAC_RxDVLD(3) = '0' and EMAC_RxDVLD_q = '1' and ipdata_end = '0')then ipdata_end <= '1'; else ipdata_end <= '0'; end if; buf_di(35) <= cut_TCP_DATA_r; if(IS_ARP = '1')then case wc(3 downto 0) is when x"5" => EMAC_RxD_q2 <= x"0002" & MY_ETH(47 downto 32); when x"6" => EMAC_RxD_q2 <= MY_ETH(31 downto 0); when x"7" => EMAC_RxD_q2 <= MY_IP; when x"8" | x"9" | x"a" | x"b" => EMAC_RxD_q2 <= SOURCE_ADDR; when others => EMAC_RxD_q2 <= EMAC_RxD_q; end case; elsif(swap_TCP_port = '1')then 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 else EMAC_RxD_q2 <= EMAC_RxD_q; end if; if(in_state = IP_HDR and wc(3 downto 0) = X"7" and is_ICMP = '1')then ICMP_check <= '1'; else ICMP_check <= '0'; end if; ICMP_ECHO <= ICMP_check; ICMP_chksum <= ICMP_ECHO; if(ICMP_check = '1')then ICMP_newchksum(16 downto 11) <= ('0' & EMAC_RxD(31 downto 27)) + 1; ICMP_newchksum(10 downto 0) <= EMAC_RxD(26 downto 16); elsif(ICMP_newchksum(16) = '1')then ICMP_newchksum <= '0' & (ICMP_newchksum(15 downto 0) + 1); end if; if(ICMP_ECHO = '1')then EMAC_RxD_q3 <= EMAC_RxD_q2(31 downto 16) & x"0000"; -- change to ECHO reply elsif(ICMP_chksum = '1')then EMAC_RxD_q3 <= ICMP_newchksum(15 downto 0) & EMAC_RxD_q2(15 downto 0); -- change to ECHO reply elsif(swap_TCP_port = '1')then EMAC_RxD_q3 <= EMAC_RxD_q2(31 downto 16) & EMAC_RxD_q(31 downto 16); else EMAC_RxD_q3 <= EMAC_RxD_q2; end if; buf_di(31 downto 0) <= EMAC_RxD_q4; if(in_state /= ET_HDR)then swap_ETH_ADDR <= '0'; elsif(wc(0) = '1')then swap_ETH_ADDR <= '1'; end if; if(is_TCP = '1' and in_state = IP_HDR and IHDL = x"1")then swap_TCP_port <= '1'; else swap_TCP_port <= '0'; end if; -- swap_TCP_port(1) <= swap_TCP_port(0); if(in_state = IP_HDR and wc(3 downto 0) = x"7")then SOURCE_IP <= EMAC_RxD_q2(15 downto 0) & EMAC_RxD_q(31 downto 16); swap_IP_ADDR <= '1'; elsif(wc(1) = '1')then swap_IP_ADDR <= '0'; end if; if(swap_ETH_ADDR = '1')then case wc(1 downto 0) is when "10" => EMAC_RxD_q4 <= EMAC_RxD_q2(15 downto 0) & EMAC_RxD_q(31 downto 16); when "11" => EMAC_RxD_q4 <= EMAC_RxD_q2(15 downto 0) & MY_ETH(47 downto 32); when others => EMAC_RxD_q4 <= MY_ETH(31 downto 0); end case; elsif(swap_IP_ADDR = '1')then case wc(1 downto 0) is when "00" => EMAC_RxD_q4 <= EMAC_RxD_q3(31 downto 16) & EMAC_RxD_q2(15 downto 0); when "01" => EMAC_RxD_q4 <= EMAC_RxD_q2(31 downto 16) & SOURCE_IP(31 downto 16); when others => EMAC_RxD_q4 <= SOURCE_IP(15 downto 0) & EMAC_RxD_q3(15 downto 0); end case; else EMAC_RxD_q4 <= EMAC_RxD_q3; end if; EMAC_RxDVLD_q <= EMAC_RxDVLD(3); buf_space <= raddr - waddr - 1; if(reset_ext = '1' or EMAC_RxBadFrame = '1' or EMAC_RxGoodFrame = '1')then in_state <= IDLE; goto_DROP <= (others => '0'); else case in_state is when IDLE => if(EMAC_RxDVLD(3) = '1')then if(queue_full = '1' or or_reduce(buf_space(8 downto 5)) = '0')then goto_DROP(0) <= '1'; in_state <= DROP; else in_state <= ET_HDR; end if; end if; IHDL <= x"f"; is_MY_ETH <= '1'; is_broadcast_ETH <= '1'; when ET_HDR => case wc(1 downto 0) is when "00" => if(EMAC_RxD_q /= MY_ETH(47 downto 16))then is_MY_ETH <= '0'; end if; if(and_reduce(EMAC_RxD_q) = '0')then is_broadcast_ETH <= '0'; end if; when "01" => if(EMAC_RxD_q(31 downto 16) /= MY_ETH(15 downto 0))then is_MY_ETH <= '0'; end if; if(and_reduce(EMAC_RxD_q(31 downto 16)) = '0')then is_broadcast_ETH <= '0'; end if; when "11" => if(EMAC_RxD_q = ETHTYPE_ARP)then in_state <= ARP; 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 in_state <= IP_HDR; end if; is_ARP <= '0'; is_TCP <= '0'; is_ICMP <= '0'; IS_Request <= '0'; IHDL <= EMAC_RxD_q(11 downto 8); when others => null; end case; -- if(wc(2) = '1')then it is neither ARP nor IP4 if(wc(2) = '1' or (is_MY_ETH = '0' and is_broadcast_ETH = '0'))then goto_DROP(1) <= '1'; in_state <= DROP; end if; if(EMAC_RxD(17 downto 16) = "11")then IP_Length_offset(3 downto 0) <= EMAC_RxD_q(11 downto 8); else IP_Length_offset(3 downto 0) <= EMAC_RxD_q(11 downto 8) + 1; end if; when IP_HDR => if(wc(4 downto 0) = "00100")then IP_Length(11 downto 2) <= EMAC_RxD_q(27 downto 18) - IP_Length_offset; IP_Length(1 downto 0) <= EMAC_RxD_q(17 downto 16); end if; if(wc(4 downto 0) = "00101")then if(or_reduce(EMAC_RxD_q(29 downto 16)) = '1')then -- no framented data accepted goto_DROP(2) <= '1'; in_state <= DROP; end if; if(EMAC_RxD_q(7 downto 0) = PROTOCAL_ICMP and IHDL = x"4")then -- ICMP has no option is_ICMP <= '1'; elsif(EMAC_RxD_q(7 downto 0) = PROTOCAL_TCP)then is_TCP <= '1'; end if; end if; if(wc(4 downto 0) = "00111" and EMAC_RxD_q(15 downto 0) /= MY_IP(31 downto 16))then goto_DROP(3) <= '1'; in_state <= DROP; end if; if(wc(4 downto 0) = "01000" and EMAC_RxD_q(31 downto 16) /= MY_IP(15 downto 0))then goto_DROP(4) <= '1'; in_state <= DROP; end if; IHDL <= IHDL - 1; if(IHDL(3 downto 1) = "000")then in_state <= IP_DATA; end if; when IP_DATA => IP_Length(11 downto 2) <= IP_Length(11 downto 2) - 1; if(ICMP_check = '1' and EMAC_RxD_q(15 downto 0) /= x"0800")then goto_DROP(5) <= '1'; in_state <= DROP; end if; if((chk_IPHDR_chksum = '1' and bad_IPHDR_chksum = '1') or (is_ICMP = '0' and is_TCP = '0'))then goto_DROP(6) <= '1'; in_state <= DROP; end if; if(EMAC_RxDVLD(3) = '0' and EMAC_RxDVLD_q = '1' and (or_reduce(IP_Length(11 downto 2)) = '1' or bad_Length = '1'))then goto_DROP(7) <= '1'; in_state <= DROP; end if; if(wea = '1' and or_reduce(buf_space(8 downto 5)) = '0')then goto_DROP(0) <= '1'; in_state <= DROP; end if; when ARP => is_ARP <= '1'; if(en_Rx = '1' and wc(3 downto 0) = x"4" and EMAC_RxD_q(31 downto 16) /= x"0800")then -- IP protocal? goto_DROP(8) <= '1'; in_state <= DROP; end if; if(en_Rx = '1' and wc(3 downto 0) = x"5")then if(EMAC_RxD_q(31 downto 16) = x"0001")then -- ARP request? IS_Request <= '1'; else IS_Request <= '0'; end if; end if; 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? goto_DROP(10) <= '1'; in_state <= DROP; end if; 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? goto_DROP(11) <= '1'; in_state <= DROP; end if; when others => null; end case; end if; case IP_Length(1 downto 0) is when "00" => bad_Length <= not EMAC_RxDVLD(3) or not EMAC_RxDVLD(2) or or_reduce(EMAC_RxDVLD(1 downto 0)); when "01" => bad_Length <= not EMAC_RxDVLD(3) or not EMAC_RxDVLD(2) or not EMAC_RxDVLD(1) or EMAC_RxDVLD(0); when "10" => bad_Length <= not and_reduce(EMAC_RxDVLD); when others => bad_Length <= not EMAC_RxDVLD(3) or or_reduce(EMAC_RxDVLD(2 downto 0)); end case; if(reset_ext = '1')then waddr <= (others => '0'); elsif(in_state = DROP or (chk_IP_chksum = '1' and bad_IP_chksum = '1'))then waddr <= start_waddr; elsif(wea = '1')then waddr <= waddr + 1; end if; if(reset_ext = '1')then start_waddr <= (others => '0'); elsif(Frame_end_dl(3) = '1' and waddr /= start_waddr)then start_waddr <= waddr; end if; if(wea = '1')then last_waddr <= waddr; end if; Frame_end_dl <= Frame_end_dl(2 downto 0) & (EMAC_RxGoodFrame or EMAC_RxbadFrame); if(in_state = IP_HDR)then rst_IPHDR_chksum <= '0'; else rst_IPHDR_chksum <= '1'; end if; if((in_state = ET_HDR and wc(1 downto 0) = "11") or (is_ICMP = '1' and in_state = IP_HDR))then rst_IP_chksum <= '1'; else rst_IP_chksum <= '0'; end if; -- check IP header checksum: from first word till IHDL IPHDR_data_dl <= IPHDR_data_dl(0) & IPHDR_data; chk_IPHDR_chksum <= IPHDR_data_dl(1) and not IPHDR_data_dl(0); if(reset_ext = '0' and Frame_end_dl(3) = '1' and waddr /= start_waddr)then we_queue <= '1'; else we_queue <= '0'; end if; IPHDR_chksum_in <= ('0' & EMAC_RxD_q(31 downto 16)) + ('0' & EMAC_RxD_q2(15 downto 0)); TCP_length <= EMAC_RxD_q(31 downto 16) - ("0000000000" & EMAC_RxD_q2(11 downto 8) & "00"); if(in_state = ET_HDR and wc(1 downto 0) = "11")then IPHDR_data <= '1'; elsif(IHDL = x"1")then IPHDR_data <= '0'; end if; if(IPHDR_data = '1')then case wc(3 downto 0) is when x"5" => IP_chksum_in <= '0' & TCP_length; when x"6" => IP_chksum_in <= "000000000" & EMAC_RxD_q2(7 downto 0); -- protocol 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 when others => IP_chksum_in <= (others => '0'); end case; else IP_chksum_in <= ('0' & EMAC_RxD_q(31 downto 16)) + ('0' & EMAC_RxD_q2(15 downto 0)); end if; end if; end process; i_IPHDR_checksum: checksum PORT MAP( c => clk, r => rst_IPHDR_chksum, r_value => x"ffff", ce => '1', d => IPHDR_chksum_in, bad_chksum => bad_IPHDR_chksum, s => open ); i_IP_checksum: checksum PORT MAP( c => clk, r => rst_IP_chksum, r_value => x"ffff", ce => '1', d => IP_chksum_in, bad_chksum => bad_IP_chksum, s => open ); process(clk) begin if(clk'event and clk = '1')then if(reset_ext = '1')then Dout_avl_i <= '0'; rd_buf <= '0'; ec_raddr <= '0'; raddr <= (others => '0'); buf_dout_vld <= '0'; Dout_valid_i <= '0'; queue_a <= (others => '1'); else if(en_Dout = '1' or rd_buf = '1')then Dout_avl_i <= '0'; elsif(queue_empty = '0')then Dout_avl_i <= '1'; end if; if(en_Dout = '1' and Dout_avl_i = '1')then rd_buf <= '1'; elsif(re_queue = '1')then rd_buf <= '0'; end if; if(re_queue = '1')then buf_dout_vld <= '0'; elsif(queue_empty = '0')then buf_dout_vld <= '1'; end if; if(en_Dout = '1' and Dout_avl_i = '1')then ec_raddr <= '1'; elsif(buf_dout(34) = '1')then ec_raddr <= '0'; end if; 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 raddr <= raddr + 1; end if; Dout_valid_i <= ec_raddr or (en_Dout and Dout_avl_i); if(we_queue = '1' and re_queue = '0' and (queue_empty = '0' or and_reduce(queue_a) = '1'))then queue_a <= queue_a + 1; elsif(we_queue = '0' and and_reduce(queue_a) = '0' and (re_queue = '1' or queue_empty = '1'))then queue_a <= queue_a - 1; end if; end if; if(buf_rden = '1')then buf_dout(33 downto 0) <= buf_do(33 downto 0); end if; if(queue_out(8 downto 0) = raddr and ec_raddr = '1')then buf_dout(34) <= '1'; else buf_dout(34) <= '0'; end if; if(buf_dout_vld = '0' or (en_Dout = '1' and Dout_avl_i = '1') or ec_raddr = '1')then buf_rden <= '1'; else buf_rden <= '0'; end if; queue_in(10) <= IS_ARP; queue_in(9) <= IS_Request or IS_ICMP; queue_in(8 downto 0) <= last_waddr; if(reset_ext = '1')then queue_empty <= '1'; elsif(and_reduce(queue_a) = '0')then queue_empty <= '0'; elsif(re_queue = '1')then queue_empty <= '1'; end if; if(queue_empty = '1' or re_queue = '1')then queue_out <= queue_o; end if; if(reset_ext = '1' or queue_a = "11100")then queue_full <= '0'; elsif(queue_a = "11101")then queue_full <= '1'; end if; last_word <= re_queue; end if; end process; re_queue <= buf_dout(34) and Dout_valid_i; g_queue: for i in 0 to 10 generate i_queue : SRLC32E port map ( Q => queue_o(i), -- SRL data output Q31 => open, -- SRL cascade output pin A => queue_a, -- 5-bit shift depth select input CE => we_queue, -- Clock enable input CLK => clk, -- Clock input D => queue_in(i) -- SRL data input ); end generate; process(clk) begin if(clk'event and clk = '1')then if(in_state = DROP)then was_DROP <= '1'; else was_DROP <= '0'; end if; if(rstCntr = '1')then GoodCntr <= (others => '0'); BadCntr <= (others => '0'); DropCntr <= (others => (others => '0')); else if(EMAC_RxGoodFrame = '1')then GoodCntr <= GoodCntr + 1; end if; if(EMAC_RxBadFrame = '1')then BadCntr <= BadCntr + 1; end if; for i in 0 to 11 loop if(was_DROP = '0' and goto_DROP(i) = '1')then if(i = 1)then DROPCntr(i) <= DROPCntr(i) + 1; else DROPCntr(i)(15 downto 0) <= DROPCntr(i)(15 downto 0) + 1; end if; end if; end loop; end if; end if; end process; process(in_state) begin case in_state is when ET_HDR => in_states <= "001"; when ARP => in_states <= "010"; when IP_HDR => in_states <= "011"; when IP_DATA => in_states <= "100"; when DROP => in_states <= "101"; when others => in_states <= "000"; end case; end process; process(ipb_addr) begin case ipb_addr(3 downto 0) is when x"0" => ipb_rdata <= "0000000" & waddr & "0000000" & raddr; when x"1" => ipb_rdata <= x"0000" & "0000000" & start_waddr; 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; when x"3" => ipb_rdata <= reset_ext & wea & wc & rst_IP_chksum & IP_chksum_in & is_MY_ETH & bad_IPHDR_chksum & chk_IPHDR_chksum; when x"4" => ipb_rdata <= DROPCntr(0); when x"5" => ipb_rdata <= DROPCntr(3)(15 downto 0) & DROPCntr(2)(15 downto 0); when x"6" => ipb_rdata <= DROPCntr(5)(15 downto 0) & DROPCntr(4)(15 downto 0); when x"7" => ipb_rdata <= DROPCntr(7)(15 downto 0) & DROPCntr(6)(15 downto 0); when x"8" => ipb_rdata <= DROPCntr(9)(15 downto 0) & DROPCntr(8)(15 downto 0); when x"9" => ipb_rdata <= DROPCntr(11)(15 downto 0) & DROPCntr(10)(15 downto 0); when x"a" => ipb_rdata <= GoodCntr; when x"b" => ipb_rdata <= BadCntr; when x"c" => ipb_rdata <= DROPCntr(1); when others => ipb_rdata <= (others => '0'); end case; end process; end Behavioral;