Compare commits
1 Commits
9258edd0d9
...
3d530f6625
Author | SHA1 | Date | |
---|---|---|---|
3d530f6625 |
@ -1,10 +1,35 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<com.sigasi.hdt.shared.librarymapping.model:LibraryMappings xmlns:com.sigasi.hdt.shared.librarymapping.model="com.sigasi.hdt.vhdl.scoping.librarymapping" Version="2">
|
<com.sigasi.hdt.shared.librarymapping.model:LibraryMappings xmlns:com.sigasi.hdt.shared.librarymapping.model="com.sigasi.hdt.vhdl.scoping.librarymapping" Version="2">
|
||||||
<Mappings Location="bench" Library="bench"/>
|
<Mappings Location="bench" Library="bench"/>
|
||||||
|
<Mappings Location="cocotb" Library="cocotb"/>
|
||||||
<Mappings Location="design" Library="design"/>
|
<Mappings Location="design" Library="design"/>
|
||||||
<Mappings Location="Common Libraries/IEEE" Library="ieee"/>
|
<Mappings Location="Common Libraries/IEEE" Library="ieee"/>
|
||||||
<Mappings Location="Common Libraries/IEEE Synopsys" Library="ieee"/>
|
<Mappings Location="Common Libraries/IEEE Synopsys" Library="ieee"/>
|
||||||
|
<Mappings Location="" Library="not mapped"/>
|
||||||
<Mappings Location="Common Libraries" Library="not mapped"/>
|
<Mappings Location="Common Libraries" Library="not mapped"/>
|
||||||
|
<Mappings Location="Common Libraries/vunit" Library="not mapped"/>
|
||||||
|
<Mappings Location="cocotb/__pycache__" Library="not mapped"/>
|
||||||
|
<Mappings Location="cocotb/sim_build" Library="not mapped"/>
|
||||||
<Mappings Location="Common Libraries/STD" Library="std"/>
|
<Mappings Location="Common Libraries/STD" Library="std"/>
|
||||||
<Mappings Location="trashernet" Library="trashernet"/>
|
<Mappings Location="trashernet" Library="trashernet"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/IP_complete_nomac.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/IPv4.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/IPv4_RX.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/IPv4_TX.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/UDP_Complete_nomac.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/UDP_RX.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/UDP_TX.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/arp.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/arp_REQ.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/arp_RX.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/arp_STORE_br.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/arp_SYNC.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/arp_TX.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/arp_types.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/arpv2.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/axi.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/ipv4_types.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="udp_ip_stack/rtl/vhdl/tx_arbitrator.vhd" Library="udpip"/>
|
||||||
|
<Mappings Location="Common Libraries/vunit/vunit/vhdl" Library="vunit_lib"/>
|
||||||
|
<Mappings Location="Common Libraries/src" Library="xp2"/>
|
||||||
</com.sigasi.hdt.shared.librarymapping.model:LibraryMappings>
|
</com.sigasi.hdt.shared.librarymapping.model:LibraryMappings>
|
||||||
|
27
.project
27
.project
@ -5,6 +5,16 @@
|
|||||||
<projects>
|
<projects>
|
||||||
</projects>
|
</projects>
|
||||||
<buildSpec>
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||||
|
<triggers>full,incremental,</triggers>
|
||||||
|
<arguments>
|
||||||
|
<dictionary>
|
||||||
|
<key>LaunchConfigHandle</key>
|
||||||
|
<value><project>/.externalToolBuilders/com.sigasi.hdt.toolchains.vunit.builder.launch</value>
|
||||||
|
</dictionary>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
<buildCommand>
|
<buildCommand>
|
||||||
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
|
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
|
||||||
<arguments>
|
<arguments>
|
||||||
@ -12,9 +22,9 @@
|
|||||||
</buildCommand>
|
</buildCommand>
|
||||||
</buildSpec>
|
</buildSpec>
|
||||||
<natures>
|
<natures>
|
||||||
<nature>com.sigasi.hdt.verilog.ui.verilogNature</nature>
|
|
||||||
<nature>com.sigasi.hdt.vhdl.ui.vhdlNature</nature>
|
<nature>com.sigasi.hdt.vhdl.ui.vhdlNature</nature>
|
||||||
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
|
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
|
||||||
|
<nature>com.sigasi.hdt.toolchains.vunit.nature</nature>
|
||||||
</natures>
|
</natures>
|
||||||
<linkedResources>
|
<linkedResources>
|
||||||
<link>
|
<link>
|
||||||
@ -22,6 +32,11 @@
|
|||||||
<type>2</type>
|
<type>2</type>
|
||||||
<locationURI>virtual:/virtual</locationURI>
|
<locationURI>virtual:/virtual</locationURI>
|
||||||
</link>
|
</link>
|
||||||
|
<link>
|
||||||
|
<name>Common Libraries/DRAG_REUSABLE_LIBRARIES_HERE.txt</name>
|
||||||
|
<type>1</type>
|
||||||
|
<locationURI>sigasiresource:/vhdl/readme.txt</locationURI>
|
||||||
|
</link>
|
||||||
<link>
|
<link>
|
||||||
<name>Common Libraries/IEEE</name>
|
<name>Common Libraries/IEEE</name>
|
||||||
<type>2</type>
|
<type>2</type>
|
||||||
@ -37,5 +52,15 @@
|
|||||||
<type>2</type>
|
<type>2</type>
|
||||||
<locationURI>sigasiresource:/vhdl/2008/STD</locationURI>
|
<locationURI>sigasiresource:/vhdl/2008/STD</locationURI>
|
||||||
</link>
|
</link>
|
||||||
|
<link>
|
||||||
|
<name>Common Libraries/src</name>
|
||||||
|
<type>2</type>
|
||||||
|
<location>/usr/local/diamond/3.12/cae_library/simulation/vhdl/xp2/src</location>
|
||||||
|
</link>
|
||||||
|
<link>
|
||||||
|
<name>Common Libraries/vunit</name>
|
||||||
|
<type>2</type>
|
||||||
|
<locationURI>PARENT-1-PROJECT_LOC/vunit</locationURI>
|
||||||
|
</link>
|
||||||
</linkedResources>
|
</linkedResources>
|
||||||
</projectDescription>
|
</projectDescription>
|
||||||
|
2
.settings/com.sigasi.hdt.toolchains.vunit.prefs
Normal file
2
.settings/com.sigasi.hdt.toolchains.vunit.prefs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
VUnitScriptLocation=vunit/run.py
|
||||||
|
eclipse.preferences.version=1
|
@ -1,2 +0,0 @@
|
|||||||
eclipse.preferences.version=1
|
|
||||||
isEnabled=true
|
|
@ -1 +0,0 @@
|
|||||||
<project>=sv2012
|
|
@ -1,2 +0,0 @@
|
|||||||
eclipse.preferences.version=1
|
|
||||||
isEnabled=true
|
|
@ -1,5 +1,5 @@
|
|||||||
eclipse.preferences.version=1
|
eclipse.preferences.version=1
|
||||||
encoding//Common\ Libraries/IEEE=UTF-8
|
encoding//Common\ Libraries/IEEE=utf-8
|
||||||
encoding//Common\ Libraries/IEEE\ Synopsys=UTF-8
|
encoding//Common\ Libraries/IEEE\ Synopsys=utf-8
|
||||||
encoding//Common\ Libraries/STD=UTF-8
|
encoding//Common\ Libraries/STD=utf-8
|
||||||
encoding//Common\ Libraries=UTF-8
|
encoding/Common\ Libraries=utf-8
|
||||||
|
@ -28,14 +28,6 @@ Notes:
|
|||||||
* The RX pull up/downs are probably not the best idea, and fixable in a better way. But for now, this shall work -- and suffice!
|
* The RX pull up/downs are probably not the best idea, and fixable in a better way. But for now, this shall work -- and suffice!
|
||||||
* On the TX side, I'm grossly overloading the drivers. A line driver would probably be a good idea. Or you can just parallel multiple outputs ;D
|
* On the TX side, I'm grossly overloading the drivers. A line driver would probably be a good idea. Or you can just parallel multiple outputs ;D
|
||||||
|
|
||||||
## Stats
|
|
||||||
|
|
||||||
Sythesized for a Lattice LFXP2-5E FPGA using LSE / Diamond v3.12:
|
|
||||||
|
|
||||||
| Configuration | Slices | LUT4 | Registers |
|
|
||||||
| ---------------- | ------ | ---- | --------- |
|
|
||||||
| `trashernet_phy` | 115 | 188 | 91 |
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||||
|
@ -31,6 +31,7 @@ architecture bench of bench_trashernet_phy is
|
|||||||
signal tx_p : std_logic;
|
signal tx_p : std_logic;
|
||||||
signal tx_n : std_logic;
|
signal tx_n : std_logic;
|
||||||
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
trashernet_phy_cdc_inst : entity trashernet.trashernet_phy_cdc
|
trashernet_phy_cdc_inst : entity trashernet.trashernet_phy_cdc
|
||||||
generic map(
|
generic map(
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
configuration cfg_cocotb_top_hwitl_mac of cocotb_top_hwitl is
|
|
||||||
for bench
|
|
||||||
for top_mac_test_inst : top_hwitl
|
|
||||||
use entity design.top_hwitl(mac);
|
|
||||||
end for;
|
|
||||||
end for;
|
|
||||||
end configuration cfg_cocotb_top_hwitl_mac;
|
|
@ -1,8 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Set up virtual device using
|
|
||||||
sudo ip link add dev veth1 type veth peer name veth2
|
|
||||||
sudo ip link set up veth1
|
|
||||||
sudo ip link set up veth2
|
|
||||||
sudo ip addr add 192.168.2.1/24 dev veth1
|
|
||||||
sudo ip link set promisc on dev veth1
|
|
||||||
|
|
@ -225,20 +225,7 @@ 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);
|
||||||
|
|
||||||
signal udp_out : udp_out_t;
|
|
||||||
signal udp_in : udp_in_t;
|
|
||||||
begin
|
begin
|
||||||
trashernet_udp_inst : entity trashernet.trashernet_udp
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rst => rst,
|
|
||||||
ipv4_protocol_in => ipv4_protocol_in(IPROT_UDP),
|
|
||||||
ipv4_protocol_out => ipv4_protocol_out(IPROT_UDP),
|
|
||||||
udp_out => udp_out,
|
|
||||||
udp_in => udp_in
|
|
||||||
);
|
|
||||||
|
|
||||||
trashernet_icmp_inst : entity trashernet.trashernet_icmp
|
trashernet_icmp_inst : entity trashernet.trashernet_icmp
|
||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
@ -392,19 +379,16 @@ begin
|
|||||||
signal state : state_t;
|
signal state : state_t;
|
||||||
|
|
||||||
constant PACKET : byte_vector := (
|
constant PACKET : byte_vector := (
|
||||||
|
x"10", x"00", -- Source port
|
||||||
|
x"04", x"00", -- Destination port
|
||||||
|
x"00", x"15", -- Length
|
||||||
|
x"00", x"00", -- Checksum (not used)
|
||||||
x"48", x"65", x"6C", x"6C", x"6F", x"20", x"57", x"6F", x"72", x"6C", x"64", x"21", x"0a" -- Payload
|
x"48", x"65", x"6C", x"6C", x"6F", x"20", x"57", x"6F", x"72", x"6C", x"64", x"21", x"0a" -- Payload
|
||||||
);
|
);
|
||||||
signal sr : byte_vector(PACKET'range);
|
signal sr : byte_vector(PACKET'range);
|
||||||
signal cnt : integer range 0 to sr'length - 1;
|
signal cnt : integer range 0 to sr'length - 1;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
udp_in.tx_en <= '1' when state = TX else '0';
|
|
||||||
udp_in.tx_ip_address <= (x"C0", x"A8", x"02", x"01");
|
|
||||||
udp_in.tx_source_port <= x"ABCD";
|
|
||||||
udp_in.tx_destination_port <= x"00FF";
|
|
||||||
udp_in.tx_length <= to_unsigned(sr'length, 16);
|
|
||||||
udp_in.tx_data <= sr(0);
|
|
||||||
|
|
||||||
tx_udp : process(clk, rst) is
|
tx_udp : process(clk, rst) is
|
||||||
begin
|
begin
|
||||||
if rst then
|
if rst then
|
||||||
@ -421,8 +405,7 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
|
|
||||||
when TX =>
|
when TX =>
|
||||||
if udp_out.tx_data_ack then
|
if ipv4_protocol_out(IPROT_UDP).tx_data_ack then
|
||||||
report "UDP: byte ack";
|
|
||||||
sr <= sr(sr'low + 1 to sr'high) & x"00";
|
sr <= sr(sr'low + 1 to sr'high) & x"00";
|
||||||
if cnt = 0 then
|
if cnt = 0 then
|
||||||
state <= DONE;
|
state <= DONE;
|
||||||
@ -430,11 +413,11 @@ begin
|
|||||||
cnt <= cnt - 1;
|
cnt <= cnt - 1;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
if udp_out.tx_err_stb then
|
if ipv4_protocol_out(IPROT_UDP).tx_err_stb then
|
||||||
report "UDP: TX ERROR";
|
report "UDP: TX ERROR";
|
||||||
state <= DONE;
|
state <= DONE;
|
||||||
end if;
|
end if;
|
||||||
if udp_out.tx_ok_stb then
|
if ipv4_protocol_out(IPROT_UDP).tx_ok_stb then
|
||||||
report "UDP: TX OK stb in TX state -- that shouldn't happen, right?";
|
report "UDP: TX OK stb in TX state -- that shouldn't happen, right?";
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
@ -444,27 +427,12 @@ begin
|
|||||||
end case;
|
end case;
|
||||||
end if;
|
end if;
|
||||||
end process tx_udp;
|
end process tx_udp;
|
||||||
|
ipv4_protocol_in(IPROT_UDP).tx_en <= '1' when state = TX else '0';
|
||||||
|
ipv4_protocol_in(IPROT_UDP).tx_ip_address <= (x"C0", x"A8", x"02", x"01");
|
||||||
|
ipv4_protocol_in(IPROT_UDP).tx_length <= to_unsigned(sr'length, 16);
|
||||||
|
ipv4_protocol_in(IPROT_UDP).tx_data <= sr(0);
|
||||||
end block tx_udp_p;
|
end block tx_udp_p;
|
||||||
|
|
||||||
rx_udp_p : block
|
|
||||||
begin
|
|
||||||
rx_udp : process(clk, rst) is
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
if udp_out.rx_header_rcv then
|
|
||||||
report "UDP: RX on port " & --
|
|
||||||
to_string(to_integer(udp_out.rx_destination_port)) & " from port " & --
|
|
||||||
to_string(to_integer(udp_out.rx_source_port));
|
|
||||||
end if;
|
|
||||||
if udp_out.rx_data_valid then
|
|
||||||
report "UDP: RX: " & to_hstring(udp_out.rx_data);
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process rx_udp;
|
|
||||||
end block rx_udp_p;
|
|
||||||
|
|
||||||
icmp : process(clk) is
|
icmp : process(clk) is
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk) then
|
if rising_edge(clk) then
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
vunit_hdl
|
|
||||||
cocotb
|
|
@ -174,13 +174,11 @@ begin
|
|||||||
ipv4_out.tx_data_ack <= '0';
|
ipv4_out.tx_data_ack <= '0';
|
||||||
arp_in.arp_query_stb <= '0';
|
arp_in.arp_query_stb <= '0';
|
||||||
ipv4_out.tx_err_stb <= '0';
|
ipv4_out.tx_err_stb <= '0';
|
||||||
ipv4_out.tx_ok_stb <= '0';
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
elsif rising_edge(clk) then
|
||||||
arp_in.arp_query_stb <= '0';
|
arp_in.arp_query_stb <= '0';
|
||||||
ipv4_out.tx_data_ack <= '0';
|
ipv4_out.tx_data_ack <= '0';
|
||||||
ipv4_out.tx_err_stb <= '0';
|
ipv4_out.tx_err_stb <= '0';
|
||||||
ipv4_out.tx_ok_stb <= '0';
|
|
||||||
|
|
||||||
if (ethernet_ii_out.tx_data_ack = '1') or (state = CALC_CKS) then
|
if (ethernet_ii_out.tx_data_ack = '1') or (state = CALC_CKS) then
|
||||||
if byte_cnt > 0 then
|
if byte_cnt > 0 then
|
||||||
@ -194,12 +192,6 @@ begin
|
|||||||
if ipv4_in.tx_en then
|
if ipv4_in.tx_en then
|
||||||
arp_in.arp_query_stb <= '1';
|
arp_in.arp_query_stb <= '1';
|
||||||
state <= ARP;
|
state <= ARP;
|
||||||
|
|
||||||
if or((to_std_logic_vector(ipv4_config.gateway) xor to_std_logic_vector(arp_in.arp_ip)) and to_std_logic_vector(ipv4_config.subnet_mask)) then
|
|
||||||
arp_in.arp_ip <= ipv4_config.gateway;
|
|
||||||
else
|
|
||||||
arp_in.arp_ip <= ipv4_in.tx_ip_address;
|
|
||||||
end if;
|
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
when ARP =>
|
when ARP =>
|
||||||
@ -241,7 +233,6 @@ begin
|
|||||||
ipv4_out.tx_data_ack <= '1';
|
ipv4_out.tx_data_ack <= '1';
|
||||||
if not ipv4_in.tx_en then
|
if not ipv4_in.tx_en then
|
||||||
state <= IDLE;
|
state <= IDLE;
|
||||||
ipv4_out.tx_ok_stb <= '1';
|
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end case;
|
end case;
|
||||||
@ -250,6 +241,9 @@ begin
|
|||||||
|
|
||||||
ethernet_ii_in.tx_data <= sr(sr'low);
|
ethernet_ii_in.tx_data <= sr(sr'low);
|
||||||
ethernet_ii_in.tx_en <= '1' when (state = HEADER) or (state = PAYLOAD) else '0';
|
ethernet_ii_in.tx_en <= '1' when (state = HEADER) or (state = PAYLOAD) else '0';
|
||||||
|
|
||||||
|
arp_in.arp_ip <= ipv4_in.tx_ip_address;
|
||||||
|
|
||||||
end block tx;
|
end block tx;
|
||||||
|
|
||||||
end architecture rtl;
|
end architecture rtl;
|
||||||
|
@ -253,7 +253,6 @@ begin
|
|||||||
begin
|
begin
|
||||||
if rst then
|
if rst then
|
||||||
phy_out.rx_data_valid <= '0';
|
phy_out.rx_data_valid <= '0';
|
||||||
phy_out.rx_data <= (others => '0'); -- Needed for yosys to compile
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
elsif rising_edge(clk) then
|
||||||
phy_out.rx_data_valid <= '0';
|
phy_out.rx_data_valid <= '0';
|
||||||
@ -297,10 +296,7 @@ begin
|
|||||||
-- -------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------
|
||||||
|
|
||||||
transmitter : block
|
transmitter : block
|
||||||
constant TX_STB_CNT_IDEAL : real := real(F_CLK) / real((F_ETH * 2));
|
constant TX_STB_CNT_MAX : integer := integer(round(real(F_CLK) / real((F_ETH * 2)))) - 1;
|
||||||
constant TX_STB_SKIP_ERROR : real := abs (round(TX_STB_CNT_IDEAL) - TX_STB_CNT_IDEAL);
|
|
||||||
constant TX_STB_CNT_MAX : integer := integer(round(TX_STB_CNT_IDEAL + 0.25)) - 1; -- Round up starting for error > 0.25
|
|
||||||
constant TX_STB_SKIP_SECOND : boolean := TX_STB_SKIP_ERROR >= 0.25; -- Skip one clock cycle every other symbol to hit clock rate in between when the divider is close to x.5
|
|
||||||
signal tx_stb_cnt : integer range 0 to TX_STB_CNT_MAX;
|
signal tx_stb_cnt : integer range 0 to TX_STB_CNT_MAX;
|
||||||
|
|
||||||
type tx_state_t is (IDLE, NLP, TX, IPG);
|
type tx_state_t is (IDLE, NLP, TX, IPG);
|
||||||
@ -371,9 +367,6 @@ begin
|
|||||||
|
|
||||||
if tx_stb_cnt = 0 then
|
if tx_stb_cnt = 0 then
|
||||||
tx_stb_cnt <= TX_STB_CNT_MAX;
|
tx_stb_cnt <= TX_STB_CNT_MAX;
|
||||||
if TX_STB_SKIP_SECOND and bit_stage = '1' then
|
|
||||||
tx_stb_cnt <= TX_STB_CNT_MAX - 1;
|
|
||||||
end if;
|
|
||||||
else
|
else
|
||||||
tx_stb_cnt <= tx_stb_cnt - 1;
|
tx_stb_cnt <= tx_stb_cnt - 1;
|
||||||
end if;
|
end if;
|
||||||
|
@ -44,14 +44,14 @@ architecture rtl of trashernet_phy_cdc is
|
|||||||
signal phy_phy_in : phy_in_t;
|
signal phy_phy_in : phy_in_t;
|
||||||
|
|
||||||
-- Helper signals
|
-- Helper signals
|
||||||
signal rx_data_i : byte;
|
signal rx_data_valid_i : std_logic;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
assert F_CLK_PHY > 2 * F_CLK report "F_CLK_PHY must be at least 2x F_CLK" severity failure;
|
||||||
|
|
||||||
-- -------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------
|
||||||
-- Drives: PHY clock domain
|
-- Drives: PHY clock domain
|
||||||
-- -------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------
|
||||||
|
|
||||||
-- Reset synchronizer for PHY
|
|
||||||
rstsync : process(phy_clk, rst) is
|
rstsync : process(phy_clk, rst) is
|
||||||
begin
|
begin
|
||||||
if rst then
|
if rst then
|
||||||
@ -61,7 +61,6 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
end process rstsync;
|
end process rstsync;
|
||||||
|
|
||||||
-- Operate Trashernet in PHY clock domain
|
|
||||||
trashernet_phy_inst : entity work.trashernet_phy
|
trashernet_phy_inst : entity work.trashernet_phy
|
||||||
generic map(
|
generic map(
|
||||||
F_CLK => F_CLK_PHY
|
F_CLK => F_CLK_PHY
|
||||||
@ -76,22 +75,6 @@ begin
|
|||||||
tx_n => tx_n
|
tx_n => tx_n
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Latch data in PHY clock domain when valid is strobed
|
|
||||||
-- If the other clock domain is slower than the time it takes for the strobe to synchronize,
|
|
||||||
-- `phy_phy_out.rx_data` will already have shifted in the next bit and no longer be valid.
|
|
||||||
-- Therefore, we need to latch it here.
|
|
||||||
rxdff : process(phy_clk, rst) is
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
rx_data_i <= (others => '0');
|
|
||||||
|
|
||||||
elsif rising_edge(phy_clk) then
|
|
||||||
if phy_phy_out.rx_data_valid then
|
|
||||||
rx_data_i <= phy_phy_out.rx_data;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process rxdff;
|
|
||||||
|
|
||||||
synchronizer_txen_inst : entity work.synchronizer
|
synchronizer_txen_inst : entity work.synchronizer
|
||||||
generic map(
|
generic map(
|
||||||
SIZE => 5
|
SIZE => 5
|
||||||
@ -115,10 +98,18 @@ begin
|
|||||||
a_in => phy_phy_out.rx_data_valid,
|
a_in => phy_phy_out.rx_data_valid,
|
||||||
b_clk => clk,
|
b_clk => clk,
|
||||||
b_rst => rst,
|
b_rst => rst,
|
||||||
b_out => phy_out.rx_data_valid
|
b_out => rx_data_valid_i
|
||||||
);
|
);
|
||||||
|
|
||||||
phy_out.rx_data <= rx_data_i; -- No need to synchronize in new clock domain as latched data has been stable for a while thanks to the delay in the _valid synchronizer
|
rxdvff : process(clk, rst) is
|
||||||
|
begin
|
||||||
|
if rst then
|
||||||
|
phy_out.rx_data_valid <= '0';
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
phy_out.rx_data_valid <= rx_data_valid_i;
|
||||||
|
phy_out.rx_data <= phy_phy_out.rx_data; -- Data should be stable after the time it takes the _valid signal to go through the synchronizer
|
||||||
|
end if;
|
||||||
|
end process rxdvff;
|
||||||
|
|
||||||
cdc_strobe_rxer_inst : entity work.cdc_strobe
|
cdc_strobe_rxer_inst : entity work.cdc_strobe
|
||||||
port map(
|
port map(
|
||||||
|
@ -32,7 +32,6 @@ package trashernet_pkg is
|
|||||||
-- IP specific types
|
-- IP specific types
|
||||||
subtype ip_addr_t is byte_vector(0 to 3);
|
subtype ip_addr_t is byte_vector(0 to 3);
|
||||||
function ip_to_string(constant ip_address : in ip_addr_t) return string;
|
function ip_to_string(constant ip_address : in ip_addr_t) return string;
|
||||||
function to_std_logic_vector(ip_address : ip_addr_t) return std_logic_vector;
|
|
||||||
|
|
||||||
-- Configuration interface
|
-- Configuration interface
|
||||||
type configuration_t is record
|
type configuration_t is record
|
||||||
@ -192,50 +191,6 @@ package trashernet_pkg is
|
|||||||
type ipv4_protocol_out_vector is array (natural range <>) of ipv4_protocol_out_t;
|
type ipv4_protocol_out_vector is array (natural range <>) of ipv4_protocol_out_t;
|
||||||
type ipv4_protocol_in_vector is array (natural range <>) of ipv4_protocol_in_t;
|
type ipv4_protocol_in_vector is array (natural range <>) of ipv4_protocol_in_t;
|
||||||
|
|
||||||
-- UDP interface
|
|
||||||
subtype udp_port_t is unsigned(15 downto 0);
|
|
||||||
subtype udp_length_t is unsigned(15 downto 0);
|
|
||||||
type udp_out_t is record
|
|
||||||
rx_data : byte; -- RX Data
|
|
||||||
rx_data_valid : std_logic; -- RX data valid strobe
|
|
||||||
|
|
||||||
rx_header_rcv : std_logic; -- Start of reception
|
|
||||||
rx_source_port : udp_port_t; -- UDP source port
|
|
||||||
rx_destination_port : udp_port_t; -- UDP destination port
|
|
||||||
rx_length : udp_length_t; -- UDP length
|
|
||||||
|
|
||||||
rx_ok_stb : std_logic; -- End of packet, checksum OK
|
|
||||||
rx_error_stb : std_logic; -- End of packet, checksum invalid
|
|
||||||
|
|
||||||
tx_data_ack : std_logic; -- Give next data byte or disable `tx_en`
|
|
||||||
tx_ok_stb : std_logic; -- Transmission successful
|
|
||||||
tx_err_stb : std_logic; -- Transmission failed
|
|
||||||
end record udp_out_t;
|
|
||||||
type udp_in_t is record
|
|
||||||
tx_ip_address : ip_addr_t; -- Destination IP address
|
|
||||||
tx_source_port : udp_port_t; -- UDP source port
|
|
||||||
tx_destination_port : udp_port_t; -- UDP destination port
|
|
||||||
tx_length : udp_length_t; -- UDP length
|
|
||||||
|
|
||||||
tx_en : std_logic; -- Start and continue transmitting
|
|
||||||
tx_data : byte;
|
|
||||||
end record udp_in_t;
|
|
||||||
|
|
||||||
type udpprot_rx_out_t is record
|
|
||||||
temp : std_logic;
|
|
||||||
end record udpprot_rx_out_t;
|
|
||||||
type udpprot_rx_in_t is record
|
|
||||||
temp : std_logic;
|
|
||||||
end record udpprot_rx_in_t;
|
|
||||||
type udpprot_tx_out_t is record
|
|
||||||
temp : std_logic;
|
|
||||||
end record udpprot_tx_out_t;
|
|
||||||
type udpprot_tx_in_t is record
|
|
||||||
temp : std_logic;
|
|
||||||
end record udpprot_tx_in_t;
|
|
||||||
subtype portnum is integer range 0 to 65535;
|
|
||||||
type udp_port_vector is array (natural range <>) of portnum;
|
|
||||||
|
|
||||||
-- General helper functions
|
-- General helper functions
|
||||||
function to_std_logic(constant bool : boolean) return std_logic;
|
function to_std_logic(constant bool : boolean) return std_logic;
|
||||||
end package trashernet_pkg;
|
end package trashernet_pkg;
|
||||||
@ -263,11 +218,6 @@ package body trashernet_pkg is
|
|||||||
;
|
;
|
||||||
end function ip_to_string;
|
end function ip_to_string;
|
||||||
|
|
||||||
function to_std_logic_vector(ip_address : ip_addr_t) return std_logic_vector is
|
|
||||||
begin
|
|
||||||
return ip_address(0) & ip_address(1) & ip_address(2) & ip_address(3);
|
|
||||||
end function to_std_logic_vector;
|
|
||||||
|
|
||||||
function to_std_logic(constant bool : boolean) return std_logic is
|
function to_std_logic(constant bool : boolean) return std_logic is
|
||||||
variable ret : std_logic;
|
variable ret : std_logic;
|
||||||
begin
|
begin
|
||||||
|
@ -1,160 +0,0 @@
|
|||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- TRASHERNET - A Trashy Ethernet Stack for FPGAs --
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- trashernet_ipv4.vhd : Ethernet OSI Layer 3, Network (IPv4)
|
|
||||||
-- Implements packet handling and IP-Layer en-/decoding.
|
|
||||||
-- -------------------------------------------------------------------------- --
|
|
||||||
-- 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_udp is
|
|
||||||
-- generic(
|
|
||||||
-- UDP_PORTS_RX : udp_port_vector; -- Ports to receive on
|
|
||||||
-- UDP_PORTS_TX : udp_port_vector -- Ports to transmit on
|
|
||||||
-- );
|
|
||||||
port(
|
|
||||||
-- Global
|
|
||||||
clk : in std_logic; -- Global clock
|
|
||||||
rst : in std_logic; -- Asynchronous reset
|
|
||||||
|
|
||||||
-- IPv4 application interface
|
|
||||||
ipv4_protocol_in : out ipv4_protocol_in_t; -- IPv4 IF (out from IP Protocol)
|
|
||||||
ipv4_protocol_out : in ipv4_protocol_out_t; -- IPv4 IF (into IP Protocol)
|
|
||||||
|
|
||||||
-- UDP application interface
|
|
||||||
udp_out : out udp_out_t;
|
|
||||||
udp_in : in udp_in_t
|
|
||||||
-- udpprot_rx_out : out udpprot_rx_out_t; -- UDP Application IF for receiving data (out from UDP)
|
|
||||||
-- udpprot_rx_in : in udpprot_rx_in_t; -- UDP Application IF for receiving data (into UDP)
|
|
||||||
-- udpprot_tx_out : out udpprot_tx_out_t; -- UDP Application IF for transmitting data (out from UDP)
|
|
||||||
-- udpprot_tx_in : in udpprot_tx_in_t -- UDP Application IF for transmitting data (in from UDP)
|
|
||||||
);
|
|
||||||
end entity trashernet_udp;
|
|
||||||
|
|
||||||
architecture rtl of trashernet_udp is
|
|
||||||
begin
|
|
||||||
receiver : block
|
|
||||||
constant BYTECOUNT_HEADER : integer := 8; -- Mandatory header fields
|
|
||||||
signal sr : byte_vector(0 to BYTECOUNT_HEADER - 1) := (others => x"00"); -- Init to zero to squelch metavalue warnings
|
|
||||||
alias sr_source_port is sr(0 to 1);
|
|
||||||
alias sr_destination_port is sr(2 to 3);
|
|
||||||
alias sr_length is sr(4 to 5);
|
|
||||||
alias sr_source_checksum is sr(6 to 7);
|
|
||||||
signal bytecount : integer range 0 to BYTECOUNT_HEADER - 1;
|
|
||||||
|
|
||||||
type state_t is (HEADER, PAYLOAD);
|
|
||||||
signal state : state_t;
|
|
||||||
begin
|
|
||||||
rxp : process(rst, clk) is
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
state <= HEADER;
|
|
||||||
udp_out.rx_header_rcv <= '0';
|
|
||||||
udp_out.rx_error_stb <= '0';
|
|
||||||
udp_out.rx_ok_stb <= '0';
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
udp_out.rx_header_rcv <= '0';
|
|
||||||
udp_out.rx_error_stb <= ipv4_protocol_out.rx_error_stb;
|
|
||||||
udp_out.rx_ok_stb <= ipv4_protocol_out.rx_ok_stb;
|
|
||||||
|
|
||||||
case state is
|
|
||||||
when HEADER =>
|
|
||||||
if ipv4_protocol_out.rx_data_valid then
|
|
||||||
sr <= sr(sr'low + 1 to sr'high) & ipv4_protocol_out.rx_data;
|
|
||||||
if bytecount = BYTECOUNT_HEADER - 1 then
|
|
||||||
state <= PAYLOAD;
|
|
||||||
udp_out.rx_header_rcv <= '1';
|
|
||||||
else
|
|
||||||
bytecount <= bytecount + 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when PAYLOAD =>
|
|
||||||
udp_out.rx_data <= ipv4_protocol_out.rx_data;
|
|
||||||
udp_out.rx_data_valid <= ipv4_protocol_out.rx_data_valid;
|
|
||||||
end case;
|
|
||||||
|
|
||||||
if ipv4_protocol_out.rx_header_rcv or ipv4_protocol_out.rx_error_stb or ipv4_protocol_out.rx_ok_stb then
|
|
||||||
state <= HEADER;
|
|
||||||
bytecount <= 0;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process rxp;
|
|
||||||
|
|
||||||
udp_out.rx_source_port <= unsigned(std_logic_vector'(sr_source_port(0) & sr_source_port(1)));
|
|
||||||
udp_out.rx_destination_port <= unsigned(std_logic_vector'(sr_destination_port(2) & sr_destination_port(3)));
|
|
||||||
udp_out.rx_length <= unsigned(std_logic_vector'(sr_length(4) & sr_length(5)));
|
|
||||||
end block receiver;
|
|
||||||
|
|
||||||
transmitter : block
|
|
||||||
constant BYTECOUNT_HEADER : integer := 8; -- Mandatory header fields
|
|
||||||
signal sr : byte_vector(0 to BYTECOUNT_HEADER - 1) := (others => x"00"); -- Init to zero to squelch metavalue warnings
|
|
||||||
signal byte_cnt : integer range 0 to sr'length - 1;
|
|
||||||
|
|
||||||
type state_t is (IDLE, HEADER, PAYLOAD);
|
|
||||||
signal state : state_t;
|
|
||||||
begin
|
|
||||||
txp : process(rst, clk) is
|
|
||||||
variable full_length : udp_length_t;
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
udp_out.tx_data_ack <= '0';
|
|
||||||
udp_out.tx_err_stb <= '0';
|
|
||||||
udp_out.tx_ok_stb <= '0';
|
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
udp_out.tx_data_ack <= '0';
|
|
||||||
udp_out.tx_err_stb <= ipv4_protocol_out.tx_err_stb;
|
|
||||||
udp_out.tx_ok_stb <= ipv4_protocol_out.tx_ok_stb;
|
|
||||||
|
|
||||||
if ipv4_protocol_out.tx_data_ack = '1' then
|
|
||||||
if byte_cnt > 0 then
|
|
||||||
byte_cnt <= byte_cnt - 1;
|
|
||||||
end if;
|
|
||||||
sr <= sr(sr'low + 1 to sr'high) & x"00";
|
|
||||||
end if;
|
|
||||||
case state is
|
|
||||||
when IDLE =>
|
|
||||||
if udp_in.tx_en then
|
|
||||||
full_length := udp_in.tx_length + BYTECOUNT_HEADER;
|
|
||||||
sr <= byte_vector'(byte(udp_in.tx_source_port(15 downto 8)), byte(udp_in.tx_source_port(7 downto 0)), --
|
|
||||||
byte(udp_in.tx_destination_port(15 downto 8)), byte(udp_in.tx_destination_port(7 downto 0)), --
|
|
||||||
byte(full_length(15 downto 8)), byte(full_length(7 downto 0)), --
|
|
||||||
x"00", x"00");
|
|
||||||
byte_cnt <= sr'length - 1;
|
|
||||||
ipv4_protocol_in.tx_length <= full_length;
|
|
||||||
ipv4_protocol_in.tx_ip_address <= udp_in.tx_ip_address;
|
|
||||||
state <= HEADER;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when HEADER =>
|
|
||||||
if byte_cnt = 0 then
|
|
||||||
state <= PAYLOAD;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when PAYLOAD =>
|
|
||||||
if ipv4_protocol_out.tx_data_ack then
|
|
||||||
sr(sr'low) <= udp_in.tx_data;
|
|
||||||
udp_out.tx_data_ack <= '1';
|
|
||||||
if not udp_in.tx_en then
|
|
||||||
state <= IDLE;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end case;
|
|
||||||
end if;
|
|
||||||
end process txp;
|
|
||||||
|
|
||||||
ipv4_protocol_in.tx_data <= sr(sr'low);
|
|
||||||
ipv4_protocol_in.tx_en <= '1' when (state /= IDLE) else '0';
|
|
||||||
end block transmitter;
|
|
||||||
|
|
||||||
end architecture rtl;
|
|
Loading…
x
Reference in New Issue
Block a user