OpenCores
URL https://opencores.org/ocsvn/udp_ip_stack/udp_ip_stack/trunk

Subversion Repositories udp_ip_stack

[/] [udp_ip_stack/] [trunk/] [rtl/] [vhdl/] [arp_TX.vhd] - Rev 14

Go to most recent revision | Compare with Previous | Blame | View Log

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 		Peter Fall
-- 
-- Create Date:    12:00:04 05/31/2011 
-- Design Name: 
-- Module Name:    arp_tx - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description:
--		handle transmission of an ARP packet.
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created - refactored this arp_tx module from the complete arp v0.02 module
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.arp_types.all;
 
entity arp_tx is
    Port (
			-- control signals
			send_I_have			: in std_logic;									-- pulse will be latched
			arp_entry			: in arp_entry_t;									-- arp target for I_have req (will be latched)
			send_who_has		: in std_logic;									-- pulse will be latched
			ip_entry				: in STD_LOGIC_VECTOR (31 downto 0);		-- IP target for who_has req (will be latched)
			-- MAC layer TX signals
			mac_tx_req			: out std_logic;									-- indicates that ip wants access to channel (stays up for as long as tx)
			mac_tx_granted		: in std_logic;									-- indicates that access to channel has been granted		
			data_out_ready		: in std_logic;									-- indicates system ready to consume data
			data_out_valid		: out std_logic;									-- indicates data out is valid
			data_out_first		: out std_logic;									-- with data out valid indicates the first byte of a frame
			data_out_last		: out std_logic;									-- with data out valid indicates the last byte of a frame
			data_out				: out std_logic_vector (7 downto 0);		-- ethernet frame (from dst mac addr through to last byte of frame)
			-- system signals
			our_mac_address 	: in STD_LOGIC_VECTOR (47 downto 0);
			our_ip_address 	: in STD_LOGIC_VECTOR (31 downto 0);
			tx_clk				: in std_logic;
			reset					: in std_logic
			);
end arp_tx;
 
architecture Behavioral of arp_tx is
 
	type count_mode_t is (RST,INCR,HOLD);
	type set_clr_t is (SET, CLR, HOLD);
	type tx_state_t is (IDLE,WAIT_MAC,SEND);
	type tx_mode_t is (REPLY,REQUEST);
 
	-- state variables
	signal tx_mac_chn_reqd	: std_logic;	
	signal tx_state			: tx_state_t;
	signal tx_count 			: unsigned (7 downto 0);
	signal send_I_have_reg	: std_logic;
	signal send_who_has_reg	: std_logic;
	signal I_have_target		: arp_entry_t;								-- latched target for "I have" request
	signal who_has_target	: std_logic_vector (31 downto 0);	-- latched IP for "who has" request
	signal tx_mode				: tx_mode_t;								-- what sort of tx to make
	signal target				: arp_entry_t;								-- target to send to
 
	-- busses
	signal next_tx_state 	: tx_state_t;
	signal tx_mode_val		: tx_mode_t;
	signal target_val			: arp_entry_t;
 
	-- tx control signals
	signal set_tx_state 		: std_logic;
	signal tx_count_mode		: count_mode_t;
	signal set_chn_reqd		: set_clr_t;
	signal kill_data_out_valid	: std_logic;
	signal set_send_I_have	: set_clr_t;
	signal set_send_who_has	: set_clr_t;
	signal set_tx_mode		: std_logic;
	signal set_target			: std_logic;
 
begin
 
	tx_combinatorial : process (
		-- input signals
		send_I_have, send_who_has, arp_entry, ip_entry, data_out_ready, mac_tx_granted, 
		our_mac_address, our_ip_address, reset, 
		-- state variables
		tx_state, tx_count, tx_mac_chn_reqd, I_have_target, who_has_target, 
		send_I_have_reg, send_who_has_reg, tx_mode, target, 
		-- busses
		next_tx_state, tx_mode_val, target_val, 
		-- control signals
		tx_count_mode, kill_data_out_valid, set_send_I_have, set_send_who_has, 
		set_chn_reqd, set_tx_mode, set_target
		)
	begin
		-- set output followers
		mac_tx_req <= tx_mac_chn_reqd;	
 
		-- set combinatorial output defaults
		data_out_first <= '0';
 
		case tx_state is
			when SEND   =>
				if data_out_ready = '1' and kill_data_out_valid = '0' then
					data_out_valid <= '1';
				else
					data_out_valid <= '0';
				end if;
			when OTHERS =>	data_out_valid <= '0';				
		end case;
 
		-- set bus defaults
		next_tx_state <= IDLE;
		tx_mode_val <= REPLY;
		target_val.ip <= (others => '0');
		target_val.mac <= (others => '0');
 
		-- set signal defaults
		set_tx_state <= '0';
		tx_count_mode <= HOLD;
		data_out <= x"00";
		data_out_last <= '0';
		set_chn_reqd <= HOLD;
		kill_data_out_valid <= '0';
		set_send_I_have <= HOLD;
		set_send_who_has <= HOLD;
		set_tx_mode <= '0';
		set_target <= '0';
 
		-- process requests in regardless of FSM state
		if send_I_have = '1' then
			set_send_I_have <= SET;
		end if;
		if send_who_has = '1' then
			set_send_who_has <= SET;
		end if;		
 
		-- TX FSM
		case tx_state is
			when IDLE =>
				tx_count_mode <= RST;
				if send_I_have_reg = '1' then
					set_chn_reqd <= SET;
					tx_mode_val <= REPLY;
					set_tx_mode <= '1';
					target_val <= I_have_target;
					set_target <= '1';
					set_send_I_have <= CLR;
					next_tx_state <= WAIT_MAC;
					set_tx_state <= '1';
				elsif send_who_has_reg = '1' then
					set_chn_reqd <= SET;
					tx_mode_val <= REQUEST;
					set_tx_mode <= '1';
					target_val.ip <= who_has_target;
					target_val.mac <= (others => '0');
					set_target <= '1';
					set_send_who_has <= CLR;
					next_tx_state <= WAIT_MAC;
					set_tx_state <= '1';
				else
					set_chn_reqd <= CLR;
				end if;
 
			when WAIT_MAC =>
				tx_count_mode <= RST;
				if mac_tx_granted = '1' then
					next_tx_state <= SEND;
					set_tx_state <= '1';
				end if;
				-- TODO - should handle timeout here
 
			when SEND =>
				if data_out_ready = '1' then
						tx_count_mode <= INCR;
				end if;
				case tx_count is
					when x"00"  =>
						data_out_first <= data_out_ready;
						data_out <= x"ff";													-- dst = broadcast
 
					when x"01"  => data_out <= x"ff";
					when x"02"  => data_out <= x"ff";
					when x"03"  => data_out <= x"ff";
					when x"04"  => data_out <= x"ff"; 
					when x"05"  => data_out <= x"ff"; 
					when x"06"  => data_out <= our_mac_address (47 downto 40); 	-- src = our mac
					when x"07"  => data_out <= our_mac_address (39 downto 32); 
					when x"08"  => data_out <= our_mac_address (31 downto 24); 
					when x"09"  => data_out <= our_mac_address (23 downto 16); 
					when x"0a"  => data_out <= our_mac_address (15 downto 8); 
					when x"0b"  => data_out <= our_mac_address (7 downto 0); 
					when x"0c"  => data_out <= x"08"; 									-- pkt type = 0806 : ARP
					when x"0d"  => data_out <= x"06"; 
					when x"0e"  => data_out <= x"00"; 									-- HW type = 0001 : eth
					when x"0f"  => data_out <= x"01"; 
					when x"10"  => data_out <= x"08"; 									-- protocol = 0800 : ip
					when x"11"  => data_out <= x"00"; 
					when x"12"  => data_out <= x"06"; 									-- HW size = 06
					when x"13"  => data_out <= x"04"; 									-- prot size = 04
 
					when x"14"  =>	data_out <= x"00"; 									-- opcode =		
					when x"15"  =>
						if tx_mode = REPLY then
							data_out <= x"02";																			-- 02 : REPLY
						else
							data_out <= x"01";																			-- 01 : REQ
						end if;
 
					when x"16" => data_out <= our_mac_address (47 downto 40); 	-- sender mac
					when x"17" => data_out <= our_mac_address (39 downto 32); 
					when x"18" => data_out <= our_mac_address (31 downto 24); 
					when x"19" => data_out <= our_mac_address (23 downto 16); 
					when x"1a" => data_out <= our_mac_address (15 downto 8); 
					when x"1b" => data_out <= our_mac_address (7 downto 0); 
					when x"1c" => data_out <= our_ip_address (31 downto 24); 	-- sender ip
					when x"1d" => data_out <= our_ip_address (23 downto 16); 
					when x"1e" => data_out <= our_ip_address (15 downto 8); 
					when x"1f" => data_out <= our_ip_address (7 downto 0); 
					when x"20" => data_out <= target.mac (47 downto 40); 	-- target mac
					when x"21" => data_out <= target.mac (39 downto 32); 
					when x"22" => data_out <= target.mac (31 downto 24); 
					when x"23" => data_out <= target.mac (23 downto 16); 
					when x"24" => data_out <= target.mac (15 downto 8); 
					when x"25" => data_out <= target.mac (7 downto 0); 
					when x"26" => data_out <= target.ip  (31 downto 24); 	-- target ip
					when x"27" => data_out <= target.ip   (23 downto 16); 
					when x"28" => data_out <= target.ip   (15 downto 8);
 
					when x"29" =>
						data_out <= target.ip(7 downto 0); 
						data_out_last <= '1';
 
					when x"2a" =>
						kill_data_out_valid <= '1';	-- data is no longer valid
						next_tx_state <= IDLE;
						set_tx_state <= '1';	
 
					when others =>
						next_tx_state <= IDLE;
						set_tx_state <= '1';	
				end case;
		end case;
	end process;
 
	tx_sequential : process (tx_clk)
	begin
		if rising_edge(tx_clk) then
			if reset = '1' then
				-- reset state variables
				tx_state <= IDLE;
				tx_count <= (others => '0');
				tx_mac_chn_reqd <= '0';
				send_I_have_reg <= '0';
				send_who_has_reg <= '0';
				who_has_target <= (others => '0');
				I_have_target.ip <= (others => '0');
				I_have_target.mac <= (others => '0');	
				target.ip <= (others => '0');
				target.mac <= (others => '0');					
 
			else
				-- normal (non reset) processing
 
				-- Next tx_state processing
				if set_tx_state = '1' then
					tx_state <= next_tx_state;
				else
					tx_state <= tx_state;
				end if;
 
				-- input request latching
				case set_send_I_have is
					when SET  =>
						send_I_have_reg <= '1';
						I_have_target <= arp_entry;
					when CLR =>
						send_I_have_reg <= '0';
						I_have_target <= I_have_target;
					when HOLD =>
						send_I_have_reg <= send_I_have_reg;
						I_have_target <= I_have_target;
				end case;
 
				case set_send_who_has is
					when SET  =>
						send_who_has_reg <= '1';
						who_has_target <= ip_entry;
					when CLR =>
						send_who_has_reg <= '0';
						who_has_target <= who_has_target;
					when HOLD =>
						send_who_has_reg <= send_who_has_reg;
						who_has_target <= who_has_target;
				end case;
 
				-- tx mode
				if set_tx_mode = '1' then
					tx_mode <= tx_mode_val;
				else
					tx_mode <= tx_mode;
				end if;
 
				-- target latching
				if set_target = '1' then
					target <= target_val;
				else
					target <= target;
				end if;
 
				-- tx_count processing
				case tx_count_mode is
					when RST =>
						tx_count <= x"00";
					when INCR =>
						tx_count <= tx_count + 1;
					when HOLD =>
						tx_count <= tx_count;
				end case;
 
				-- control access request to mac tx chn
				case set_chn_reqd is
					when SET => tx_mac_chn_reqd <= '1';
					when CLR => tx_mac_chn_reqd <= '0';
					when HOLD => tx_mac_chn_reqd <= tx_mac_chn_reqd;
				end case;
 
			end if;
		end if;
	end process;
 
 
end Behavioral;
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.