Compare commits
No commits in common. "6de8d2453781d515d0c064b0e452c8081dec43f2" and "fdcb1cb719e9435c98cd875953afcb2b5fffc29f" have entirely different histories.
6de8d24537
...
fdcb1cb719
@ -226,14 +226,6 @@ architecture eth of top_hwitl is
|
|||||||
signal ipv4_protocol_out : ipv4_protocol_out_vector(IPV4_PROTOCOLS'range);
|
signal ipv4_protocol_out : ipv4_protocol_out_vector(IPV4_PROTOCOLS'range);
|
||||||
signal ipv4_protocol_in : ipv4_protocol_in_vector(IPV4_PROTOCOLS'range);
|
signal ipv4_protocol_in : ipv4_protocol_in_vector(IPV4_PROTOCOLS'range);
|
||||||
begin
|
begin
|
||||||
trashernet_icmp_inst : entity trashernet.trashernet_icmp
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst => rst,
|
|
||||||
ipv4_protocol_out => ipv4_protocol_out(IPROT_ICMP),
|
|
||||||
ipv4_protocol_in => ipv4_protocol_in(IPROT_ICMP)
|
|
||||||
);
|
|
||||||
|
|
||||||
trashernet_ipv4prot_inst : entity trashernet.trashernet_ipv4prot
|
trashernet_ipv4prot_inst : entity trashernet.trashernet_ipv4prot
|
||||||
generic map(
|
generic map(
|
||||||
IPV4_PROTOCOLS => IPV4_PROTOCOLS
|
IPV4_PROTOCOLS => IPV4_PROTOCOLS
|
||||||
@ -352,7 +344,13 @@ begin
|
|||||||
if (ethernet_ii_out(PROT_ARP).rx_header_rcv) then
|
if (ethernet_ii_out(PROT_ARP).rx_header_rcv) then
|
||||||
report "RX ARP";
|
report "RX ARP";
|
||||||
end if;
|
end if;
|
||||||
|
if (ethernet_ii_out(PROT_IPV4).rx_header_rcv) then
|
||||||
|
report "RX IP";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if ipv4_out.rx_data_valid then
|
||||||
|
report "RX IP data: " & to_hstring(ipv4_out.rx_data);
|
||||||
|
end if;
|
||||||
if ipv4_out.rx_ok_stb then
|
if ipv4_out.rx_ok_stb then
|
||||||
report "RX IP OK";
|
report "RX IP OK";
|
||||||
end if;
|
end if;
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET - A Trashy Ethernet Stack for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- fifo.vhd : Basic single-clock FIFO
|
|
||||||
-- Implements a basic single-clock FIFO
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
entity fifo is
|
|
||||||
generic(
|
|
||||||
DEPTH : natural -- Number of elements the FIFO can hold
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
-- Global
|
|
||||||
clk : in std_logic; -- Global clock
|
|
||||||
rst : in std_logic; -- Asynchronous reset
|
|
||||||
|
|
||||||
-- FIFO
|
|
||||||
clear : in std_logic; -- Synchronous reset (clear FIFO)
|
|
||||||
data_in : in std_logic_vector; -- Data into the FIFO (automatically constrains width)
|
|
||||||
push : in std_logic; -- Push `data_in` into the FIFO
|
|
||||||
full : out std_logic; -- No further elements can be pushed into the FIFO
|
|
||||||
data_out : out std_logic_vector; -- Data out of the FIFO
|
|
||||||
pop : in std_logic; -- Get an element from the FIFO
|
|
||||||
empty : out std_logic -- FIFO is empty
|
|
||||||
);
|
|
||||||
end entity fifo;
|
|
||||||
|
|
||||||
architecture rtl of fifo is
|
|
||||||
type memory_t is array (natural range <>) of std_logic_vector(data_in'range);
|
|
||||||
signal memory : memory_t(0 to DEPTH - 1);
|
|
||||||
|
|
||||||
subtype memory_pointer_t is integer range 0 to DEPTH - 1;
|
|
||||||
subtype usage_counter_t is integer range 0 to DEPTH;
|
|
||||||
|
|
||||||
signal read_pointer : memory_pointer_t;
|
|
||||||
signal write_pointer : memory_pointer_t;
|
|
||||||
signal usage_counter : usage_counter_t;
|
|
||||||
begin
|
|
||||||
fifo_proc : process(clk, rst) is
|
|
||||||
procedure increment_pointer(signal pointer : inout memory_pointer_t) is
|
|
||||||
begin
|
|
||||||
if pointer = pointer'subtype'high then
|
|
||||||
pointer <= 0;
|
|
||||||
else
|
|
||||||
pointer <= pointer + 1;
|
|
||||||
end if;
|
|
||||||
end procedure increment_pointer;
|
|
||||||
|
|
||||||
variable pushed : boolean;
|
|
||||||
variable popped : boolean;
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
read_pointer <= 0;
|
|
||||||
write_pointer <= 0;
|
|
||||||
usage_counter <= 0;
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
pushed := false;
|
|
||||||
popped := false;
|
|
||||||
|
|
||||||
if push and not full then
|
|
||||||
memory(write_pointer) <= data_in;
|
|
||||||
increment_pointer(write_pointer);
|
|
||||||
usage_counter <= usage_counter + 1;
|
|
||||||
pushed := true;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if pop and not empty then
|
|
||||||
increment_pointer(read_pointer);
|
|
||||||
usage_counter <= usage_counter - 1;
|
|
||||||
popped := true;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if pushed and popped then
|
|
||||||
usage_counter <= usage_counter;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if clear then
|
|
||||||
read_pointer <= 0;
|
|
||||||
write_pointer <= 0;
|
|
||||||
usage_counter <= 0;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process fifo_proc;
|
|
||||||
|
|
||||||
data_out <= memory(read_pointer);
|
|
||||||
empty <= '1' when usage_counter = 0 else '0';
|
|
||||||
full <= '1' when usage_counter = DEPTH else '0';
|
|
||||||
|
|
||||||
end architecture rtl;
|
|
@ -1,172 +0,0 @@
|
|||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET - A Trashy Ethernet Stack for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- trashernet_icmp.vhd : Ethernet OSI Layer 3, Network (ICMP)
|
|
||||||
-- Implements ICMP echo replies
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- Author : Markus Koch <markus@notsyncing.net>
|
|
||||||
-- Contributors : None
|
|
||||||
-- License : Mozilla Public License (MPL) Version 2
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
use work.trashernet_pkg.all;
|
|
||||||
|
|
||||||
entity trashernet_icmp is
|
|
||||||
port(
|
|
||||||
-- Global
|
|
||||||
clk : in std_logic; -- Global clock
|
|
||||||
rst : in std_logic; -- Asynchronous reset
|
|
||||||
|
|
||||||
-- IPv4 application interface
|
|
||||||
ipv4_protocol_out : in ipv4_protocol_out_t; -- IPv4 Protocol IF (out from IP Mux)
|
|
||||||
ipv4_protocol_in : out ipv4_protocol_in_t -- IPv4 Protocol IF (into IP Mux)
|
|
||||||
);
|
|
||||||
end entity trashernet_icmp;
|
|
||||||
|
|
||||||
architecture rtl of trashernet_icmp is
|
|
||||||
signal fifo_clear : std_logic;
|
|
||||||
signal fifo_data_in : std_logic_vector(byte'range);
|
|
||||||
signal fifo_push : std_logic;
|
|
||||||
signal fifo_full : std_logic; -- TODO: FIFO full error handling
|
|
||||||
signal fifo_data_out : std_logic_vector(fifo_data_in'range);
|
|
||||||
signal fifo_pop : std_logic;
|
|
||||||
signal fifo_empty : std_logic;
|
|
||||||
|
|
||||||
signal tx_response : std_logic;
|
|
||||||
signal rx_checksum : std_logic_vector(15 downto 0);
|
|
||||||
begin
|
|
||||||
fifo_inst : entity work.fifo
|
|
||||||
generic map(
|
|
||||||
DEPTH => 64
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst => rst,
|
|
||||||
clear => fifo_clear,
|
|
||||||
data_in => fifo_data_in,
|
|
||||||
push => fifo_push,
|
|
||||||
full => fifo_full,
|
|
||||||
data_out => fifo_data_out,
|
|
||||||
pop => fifo_pop,
|
|
||||||
empty => fifo_empty
|
|
||||||
);
|
|
||||||
|
|
||||||
rx : block
|
|
||||||
signal sr : byte_vector(0 to 3);
|
|
||||||
alias sr_type is sr(0);
|
|
||||||
alias sr_code is sr(1);
|
|
||||||
alias sr_checksum is sr(2 to 3);
|
|
||||||
|
|
||||||
type state_t is (HEADER, DATA, IGNORE);
|
|
||||||
signal state : state_t;
|
|
||||||
|
|
||||||
signal byte_count : integer range 0 to sr'length;
|
|
||||||
|
|
||||||
begin
|
|
||||||
rx_fsm : process(clk, rst) is
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
state <= HEADER;
|
|
||||||
byte_count <= byte_count'subtype'high;
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
|
|
||||||
if (ipv4_protocol_out.rx_data_valid = '1') and (byte_count /= 0) then
|
|
||||||
byte_count <= byte_count - 1;
|
|
||||||
if state = HEADER then
|
|
||||||
sr <= sr(sr'low + 1 to sr'high) & ipv4_protocol_out.rx_data;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
if ipv4_protocol_out.rx_header_rcv then
|
|
||||||
byte_count <= byte_count'subtype'high;
|
|
||||||
state <= HEADER;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
case state is
|
|
||||||
when HEADER =>
|
|
||||||
if byte_count = 0 then
|
|
||||||
if sr_type = x"08" then
|
|
||||||
state <= DATA;
|
|
||||||
else
|
|
||||||
state <= IGNORE;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when DATA =>
|
|
||||||
null; -- We just wait here and collect data
|
|
||||||
|
|
||||||
when IGNORE => -- Just wait until it's over
|
|
||||||
null;
|
|
||||||
end case;
|
|
||||||
end if;
|
|
||||||
end process rx_fsm;
|
|
||||||
fifo_clear <= ipv4_protocol_out.rx_header_rcv; -- TODO: This will break things when we get another Ping too soon
|
|
||||||
fifo_push <= ipv4_protocol_out.rx_data_valid when state = DATA else '0';
|
|
||||||
fifo_data_in <= ipv4_protocol_out.rx_data;
|
|
||||||
|
|
||||||
tx_response <= ipv4_protocol_out.rx_ok_stb when state = DATA else '0';
|
|
||||||
rx_checksum <= sr_checksum(2) & sr_checksum(3);
|
|
||||||
end block rx;
|
|
||||||
|
|
||||||
tx : block
|
|
||||||
signal checksum : unsigned(16 downto 0);
|
|
||||||
signal checksum_ones : unsigned(15 downto 0);
|
|
||||||
|
|
||||||
type state_t is (IDLE, HEADER, PAYLOAD);
|
|
||||||
signal state : state_t;
|
|
||||||
|
|
||||||
signal sr : byte_vector(0 to 3);
|
|
||||||
signal byte_count : integer range 0 to sr'subtype'high;
|
|
||||||
begin
|
|
||||||
|
|
||||||
checksum <= ('0' & not (unsigned(rx_checksum))) - unsigned'('0' & x"0800"); -- The only change is Type 8 changes to Type 0
|
|
||||||
checksum_ones <= not (checksum(15 downto 0) - checksum(16));
|
|
||||||
|
|
||||||
tx_fsm : process(clk, rst) is
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
if (ipv4_protocol_out.tx_data_ack = '1') and (byte_count /= 0) then
|
|
||||||
sr <= sr(sr'low + 1 to sr'high) & x"00";
|
|
||||||
byte_count <= byte_count - 1;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
case state is
|
|
||||||
when IDLE =>
|
|
||||||
if tx_response then
|
|
||||||
ipv4_protocol_in.tx_ip_address <= ipv4_protocol_out.rx_ip_address; -- TODO: This is technically too late, but ¯\_(ツ)_/¯
|
|
||||||
ipv4_protocol_in.tx_length <= ipv4_protocol_out.rx_length;
|
|
||||||
sr <= byte_vector'(
|
|
||||||
x"00",
|
|
||||||
x"00",
|
|
||||||
std_logic_vector(checksum_ones(15 downto 8)),
|
|
||||||
std_logic_vector(checksum_ones(7 downto 0))
|
|
||||||
);
|
|
||||||
byte_count <= sr'subtype'high;
|
|
||||||
state <= HEADER;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when HEADER =>
|
|
||||||
if (byte_count = 0) and (ipv4_protocol_out.tx_data_ack = '1') then
|
|
||||||
state <= PAYLOAD;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when PAYLOAD =>
|
|
||||||
if fifo_empty then
|
|
||||||
state <= IDLE;
|
|
||||||
end if;
|
|
||||||
end case;
|
|
||||||
end if;
|
|
||||||
end process tx_fsm;
|
|
||||||
|
|
||||||
fifo_pop <= ipv4_protocol_out.tx_data_ack when state = PAYLOAD else '0';
|
|
||||||
ipv4_protocol_in.tx_en <= '1' when (state = HEADER) or (state = PAYLOAD) else '0';
|
|
||||||
ipv4_protocol_in.tx_data <= sr(sr'low) when state = HEADER else fifo_data_out;
|
|
||||||
end block tx;
|
|
||||||
end architecture rtl;
|
|
@ -133,7 +133,6 @@ begin
|
|||||||
ipv4_out.rx_data_valid <= ethernet_ii_out.rx_data_valid when state = PAYLOAD else '0';
|
ipv4_out.rx_data_valid <= ethernet_ii_out.rx_data_valid when state = PAYLOAD else '0';
|
||||||
ipv4_out.rx_ip_address <= sr_source_ip;
|
ipv4_out.rx_ip_address <= sr_source_ip;
|
||||||
ipv4_out.rx_protocol <= sr_protocol;
|
ipv4_out.rx_protocol <= sr_protocol;
|
||||||
ipv4_out.rx_length <= unsigned(std_logic_vector'(sr_total_length(2) & sr_total_length(3))) - to_integer(unsigned(sr_ihl)) * 4;
|
|
||||||
|
|
||||||
end block rx;
|
end block rx;
|
||||||
|
|
||||||
|
@ -68,7 +68,6 @@ begin
|
|||||||
mux : for i in ipv4_protocol_out'range generate
|
mux : for i in ipv4_protocol_out'range generate
|
||||||
ipv4_protocol_out(i).rx_data <= ipv4_out.rx_data;
|
ipv4_protocol_out(i).rx_data <= ipv4_out.rx_data;
|
||||||
ipv4_protocol_out(i).rx_ip_address <= ipv4_out.rx_ip_address;
|
ipv4_protocol_out(i).rx_ip_address <= ipv4_out.rx_ip_address;
|
||||||
ipv4_protocol_out(i).rx_length <= ipv4_out.rx_length;
|
|
||||||
ipv4_protocol_out(i).rx_data_valid <= ipv4_out.rx_data_valid when rx_sel = i else '0';
|
ipv4_protocol_out(i).rx_data_valid <= ipv4_out.rx_data_valid when rx_sel = i else '0';
|
||||||
ipv4_protocol_out(i).rx_error_stb <= ipv4_out.rx_error_stb when rx_sel = i else '0';
|
ipv4_protocol_out(i).rx_error_stb <= ipv4_out.rx_error_stb when rx_sel = i else '0';
|
||||||
ipv4_protocol_out(i).rx_ok_stb <= ipv4_out.rx_ok_stb when rx_sel = i else '0';
|
ipv4_protocol_out(i).rx_ok_stb <= ipv4_out.rx_ok_stb when rx_sel = i else '0';
|
||||||
|
@ -147,7 +147,6 @@ package trashernet_pkg is
|
|||||||
type ipv4_out_t is record
|
type ipv4_out_t is record
|
||||||
rx_ip_address : ip_addr_t; -- Source IP address
|
rx_ip_address : ip_addr_t; -- Source IP address
|
||||||
rx_protocol : ipv4_protocol; -- Transport Protocol
|
rx_protocol : ipv4_protocol; -- Transport Protocol
|
||||||
rx_length : ipv4_length; -- Telegram length (excluding header)
|
|
||||||
|
|
||||||
rx_data : byte; -- RX data
|
rx_data : byte; -- RX data
|
||||||
rx_data_valid : std_logic; -- RX data valid strobe
|
rx_data_valid : std_logic; -- RX data valid strobe
|
||||||
@ -169,7 +168,6 @@ package trashernet_pkg is
|
|||||||
|
|
||||||
type ipv4_protocol_out_t is record
|
type ipv4_protocol_out_t is record
|
||||||
rx_ip_address : ip_addr_t; -- Source IP address
|
rx_ip_address : ip_addr_t; -- Source IP address
|
||||||
rx_length : ipv4_length; -- Telegram length (excluding header)
|
|
||||||
|
|
||||||
rx_data : byte; -- RX data
|
rx_data : byte; -- RX data
|
||||||
rx_data_valid : std_logic; -- RX data valid strobe
|
rx_data_valid : std_logic; -- RX data valid strobe
|
||||||
|
Loading…
Reference in New Issue
Block a user