Line 22... |
Line 22... |
-- Revision 0.04 - Added handling of broadcast address
|
-- Revision 0.04 - Added handling of broadcast address
|
-- Additional Comments:
|
-- Additional Comments:
|
--
|
--
|
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
library IEEE;
|
library IEEE;
|
use IEEE.STD_LOGIC_1164.ALL;
|
use IEEE.STD_LOGIC_1164.all;
|
use IEEE.NUMERIC_STD.ALL;
|
use IEEE.NUMERIC_STD.all;
|
use work.axi.all;
|
use work.axi.all;
|
use work.ipv4_types.all;
|
use work.ipv4_types.all;
|
use work.arp_types.all;
|
use work.arp_types.all;
|
|
|
entity IPv4_TX is
|
entity IPv4_TX is
|
Port (
|
port (
|
-- IP Layer signals
|
-- IP Layer signals
|
ip_tx_start : in std_logic;
|
ip_tx_start : in std_logic;
|
ip_tx : in ipv4_tx_type; -- IP tx cxns
|
ip_tx : in ipv4_tx_type; -- IP tx cxns
|
ip_tx_result : out std_logic_vector (1 downto 0); -- tx status (changes during transmission)
|
ip_tx_result : out std_logic_vector (1 downto 0); -- tx status (changes during transmission)
|
ip_tx_data_out_ready : out std_logic; -- indicates IP TX is ready to take data
|
ip_tx_data_out_ready : out std_logic; -- indicates IP TX is ready to take data
|
|
|
-- system signals
|
-- system signals
|
clk : in STD_LOGIC; -- same clock used to clock mac data and ip data
|
clk : in std_logic; -- same clock used to clock mac data and ip data
|
reset : in STD_LOGIC;
|
reset : in std_logic;
|
our_ip_address : in STD_LOGIC_VECTOR (31 downto 0);
|
our_ip_address : in std_logic_vector (31 downto 0);
|
our_mac_address : in std_logic_vector (47 downto 0);
|
our_mac_address : in std_logic_vector (47 downto 0);
|
-- ARP lookup signals
|
-- ARP lookup signals
|
arp_req_req : out arp_req_req_type;
|
arp_req_req : out arp_req_req_type;
|
arp_req_rslt : in arp_req_rslt_type;
|
arp_req_rslt : in arp_req_rslt_type;
|
-- MAC layer TX signals
|
-- MAC layer TX signals
|
Line 107... |
Line 107... |
|
|
-- tx temp signals
|
-- tx temp signals
|
signal total_length : std_logic_vector (15 downto 0); -- computed combinatorially from header size
|
signal total_length : std_logic_vector (15 downto 0); -- computed combinatorially from header size
|
|
|
|
|
FUNCTION inv_if_one(s1:std_logic_vector;en:std_logic) return std_logic_vector is
|
function inv_if_one(s1 : std_logic_vector; en : std_logic) return std_logic_vector is
|
--this function inverts all the bits of a vector if
|
--this function inverts all the bits of a vector if
|
--'en' is '1'.
|
--'en' is '1'.
|
VARIABLE Z : std_logic_vector(s1'high downto s1'low);
|
variable Z : std_logic_vector(s1'high downto s1'low);
|
BEGIN
|
begin
|
FOR i IN (s1'low) to s1'high LOOP
|
for i in (s1'low) to s1'high loop
|
Z(i) := en XOR s1(i);
|
Z(i) := en xor s1(i);
|
END LOOP;
|
end loop;
|
RETURN Z;
|
return Z;
|
END inv_if_one; -- end function
|
end inv_if_one; -- end function
|
|
|
|
|
-- IP datagram header format
|
-- IP datagram header format
|
--
|
--
|
-- 0 4 8 16 19 24 31
|
-- 0 4 8 16 19 24 31
|
Line 157... |
Line 157... |
-- combinatorial process to implement FSM and determine control signals
|
-- combinatorial process to implement FSM and determine control signals
|
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
|
|
tx_combinatorial : process(
|
tx_combinatorial : process(
|
-- input signals
|
-- input signals
|
ip_tx_start, ip_tx, clk, our_ip_address, our_mac_address, arp_req_rslt,
|
ip_tx_start, ip_tx, our_ip_address, our_mac_address, arp_req_rslt, --clk,
|
mac_tx_granted, mac_data_out_ready,
|
mac_tx_granted, mac_data_out_ready,
|
-- state variables
|
-- state variables
|
tx_state, tx_count, tx_result_reg, tx_mac, tx_mac_chn_reqd,
|
tx_state, tx_count, tx_result_reg, tx_mac, tx_mac_chn_reqd,
|
mac_lookup_req, tx_hdr_cks, arp_req_ip_reg, mac_data_out_ready_reg,
|
mac_lookup_req, tx_hdr_cks, arp_req_ip_reg, mac_data_out_ready_reg,
|
-- control signals
|
-- control signals
|
Line 360... |
Line 360... |
set_tx_state <= '1';
|
set_tx_state <= '1';
|
end case;
|
end case;
|
end if;
|
end if;
|
|
|
when SEND_USER_DATA =>
|
when SEND_USER_DATA =>
|
ip_tx_data_out_ready <= mac_data_out_ready and mac_data_out_ready_reg; -- in this state, we are always ready to accept user data for tx
|
ip_tx_data_out_ready <= mac_data_out_ready;-- and mac_data_out_ready_reg; -- in this state, we are always ready to accept user data for tx
|
if mac_data_out_ready = '1' then
|
if mac_data_out_ready = '1' then
|
if ip_tx.data.data_out_valid = '1' or tx_count = x"000" then
|
if ip_tx.data.data_out_valid = '1' or tx_count = x"000" then
|
-- only increment if ready and valid has been subsequently established, otherwise data count moves on too fast
|
-- only increment if ready and valid has been subsequently established, otherwise data count moves on too fast
|
if unsigned(tx_count) = unsigned(ip_tx.hdr.data_length) then
|
if unsigned(tx_count) = unsigned(ip_tx.hdr.data_length) then
|
-- TX terminated due to count - end normally
|
-- TX terminated due to count - end normally
|
Line 373... |
Line 373... |
tx_data <= ip_tx.data.data_out;
|
tx_data <= ip_tx.data.data_out;
|
next_tx_result <= IPTX_RESULT_SENT;
|
next_tx_result <= IPTX_RESULT_SENT;
|
set_tx_result <= '1';
|
set_tx_result <= '1';
|
next_tx_state <= IDLE;
|
next_tx_state <= IDLE;
|
set_tx_state <= '1';
|
set_tx_state <= '1';
|
|
if ip_tx.data.data_out_last = '0' then
|
|
next_tx_result <= IPTX_RESULT_ERR;
|
|
end if;
|
elsif ip_tx.data.data_out_last = '1' then
|
elsif ip_tx.data.data_out_last = '1' then
|
-- TX terminated due to receiving last indication from upstream - end with error
|
-- TX terminated due to receiving last indication from upstream - end with error
|
set_last <= '1';
|
set_last <= '1';
|
set_chn_reqd <= CLR;
|
set_chn_reqd <= CLR;
|
tx_data <= ip_tx.data.data_out;
|
tx_data <= ip_tx.data.data_out;
|
Line 397... |
Line 400... |
|
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- sequential process to action control signals and change states and outputs
|
-- sequential process to action control signals and change states and outputs
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
|
|
tx_sequential : process (clk,reset,mac_data_out_ready_reg)
|
tx_sequential : process (clk)--, reset, mac_data_out_ready_reg)
|
begin
|
begin
|
if rising_edge(clk) then
|
-- if rising_edge(clk) then
|
mac_data_out_ready_reg <= mac_data_out_ready;
|
-- mac_data_out_ready_reg <= mac_data_out_ready;
|
else
|
-- else
|
mac_data_out_ready_reg <= mac_data_out_ready_reg;
|
-- mac_data_out_ready_reg <= mac_data_out_ready_reg;
|
end if;
|
-- end if;
|
|
|
if rising_edge(clk) then
|
if rising_edge(clk) then
|
if reset = '1' then
|
if reset = '1' then
|
-- reset state variables
|
-- reset state variables
|
tx_state <= IDLE;
|
tx_state <= IDLE;
|
Line 476... |
Line 479... |
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- Process to calculate CRC in parallel with pkt out processing
|
-- Process to calculate CRC in parallel with pkt out processing
|
-- this process must yield a valid CRC before it is required to be used in the hdr
|
-- this process must yield a valid CRC before it is required to be used in the hdr
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
|
|
crc : process (clk,reset)
|
crc : process (clk)--, reset)
|
begin
|
begin
|
if rising_edge(clk) then
|
if rising_edge(clk) then
|
case crc_state is
|
case crc_state is
|
when IDLE =>
|
when IDLE =>
|
if ip_tx_start = '1' then
|
if ip_tx_start = '1' then
|