Compare commits
5 Commits
fix/gatewa
...
master
Author | SHA1 | Date | |
---|---|---|---|
7379df7b74 | |||
21a0d0e69a | |||
943febcb99 | |||
da7e329939 | |||
4bce111d69 |
@ -28,6 +28,14 @@ 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.
|
||||||
|
@ -55,12 +55,13 @@ architecture rtl of trashernet_arp is
|
|||||||
signal arp_tx_reply_ack : std_logic; -- ARP reply has been latched and is being sent
|
signal arp_tx_reply_ack : std_logic; -- ARP reply has been latched and is being sent
|
||||||
|
|
||||||
signal arp_tx_request_rq : std_logic; -- Request to transmit an ARP request
|
signal arp_tx_request_rq : std_logic; -- Request to transmit an ARP request
|
||||||
signal arp_tx_request_tpa : ip_addr_t; -- IP address that we want to know the MAC address of, either real target or gateway
|
signal arp_tx_request_tpa : ip_addr_t; -- IP address that we want to know the MAC address of
|
||||||
signal arp_tx_request_ack : std_logic; -- ARP request has been latched and is being sent
|
signal arp_tx_request_ack : std_logic; -- ARP request has been latched and is being sent
|
||||||
|
|
||||||
signal arp_rx_reply_stb : std_logic; -- An ARP reply was received (strobe)
|
signal arp_rx_reply_stb : std_logic; -- An ARP reply was received (strobe)
|
||||||
signal arp_rx_sha : mac_addr_t; -- The MAC address of the reply sender, valid with arp_rx_reply
|
signal arp_rx_sha : mac_addr_t; -- The MAC address of the reply sender, valid with arp_rx_reply
|
||||||
signal arp_rx_spa : ip_addr_t; -- The IP address of the reply sender, valid with arp_rx_reply
|
signal arp_rx_spa : ip_addr_t; -- The IP address of the reply sender, valid with arp_rx_reply
|
||||||
|
|
||||||
begin
|
begin
|
||||||
resolver : block
|
resolver : block
|
||||||
type resolver_state_t is (IDLE, QUERY_MAC);
|
type resolver_state_t is (IDLE, QUERY_MAC);
|
||||||
@ -71,10 +72,8 @@ begin
|
|||||||
|
|
||||||
signal replied_ip : ip_addr_t;
|
signal replied_ip : ip_addr_t;
|
||||||
signal replied_mac : mac_addr_t;
|
signal replied_mac : mac_addr_t;
|
||||||
|
|
||||||
signal arp_query_stb : std_logic; -- Pipelined version of arp_in.arp_query_stb
|
|
||||||
signal target_is_in_subnet : std_logic; -- Indicates whether the target IP is the subnet or whether to send this to the gateway
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
arp_resolver_main : process(rst, clk) is
|
arp_resolver_main : process(rst, clk) is
|
||||||
begin
|
begin
|
||||||
if rst then
|
if rst then
|
||||||
@ -97,7 +96,7 @@ begin
|
|||||||
|
|
||||||
case state is
|
case state is
|
||||||
when IDLE =>
|
when IDLE =>
|
||||||
if arp_query_stb then
|
if arp_in.arp_query_stb then
|
||||||
if query_mac_found then
|
if query_mac_found then
|
||||||
arp_out.arp_ok_stb <= '1';
|
arp_out.arp_ok_stb <= '1';
|
||||||
else
|
else
|
||||||
@ -119,21 +118,9 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
end process arp_resolver_main;
|
end process arp_resolver_main;
|
||||||
query_mac_found <= '1' when (arp_tx_request_tpa = replied_ip) else '0';
|
query_mac_found <= '1' when (arp_tx_request_tpa = replied_ip) else '0';
|
||||||
target_is_in_subnet <= or((arp_in.arp_ip xor ip_config.gateway) and ip_config.subnet_mask);
|
|
||||||
|
|
||||||
arp_out.arp_mac <= replied_mac;
|
arp_out.arp_mac <= replied_mac;
|
||||||
|
arp_tx_request_tpa <= arp_in.arp_ip;
|
||||||
-- Pipelines the start of query so that we get some additional time to evaluate the target+netmask.
|
|
||||||
pipeline : process (clk, rst) is
|
|
||||||
begin
|
|
||||||
if rst then
|
|
||||||
arp_tx_request_tpa <= (others => x"00");
|
|
||||||
arp_query_stb <= '0';
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
arp_tx_request_tpa <= arp_in.arp_ip when target_is_in_subnet else ip_config.gateway;
|
|
||||||
arp_query_stb <= arp_in.arp_query_stb;
|
|
||||||
end if;
|
|
||||||
end process pipeline;
|
|
||||||
|
|
||||||
timeout_timer_inst : entity work.timer
|
timeout_timer_inst : entity work.timer
|
||||||
generic map(
|
generic map(
|
||||||
|
@ -253,6 +253,7 @@ 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';
|
||||||
@ -296,7 +297,10 @@ begin
|
|||||||
-- -------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------
|
||||||
|
|
||||||
transmitter : block
|
transmitter : block
|
||||||
constant TX_STB_CNT_MAX : integer := integer(round(real(F_CLK) / real((F_ETH * 2)))) - 1;
|
constant TX_STB_CNT_IDEAL : real := real(F_CLK) / real((F_ETH * 2));
|
||||||
|
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);
|
||||||
@ -367,6 +371,9 @@ 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_valid_i : std_logic;
|
signal rx_data_i : byte;
|
||||||
|
|
||||||
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,6 +61,7 @@ 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
|
||||||
@ -75,6 +76,22 @@ 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
|
||||||
@ -98,18 +115,10 @@ 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 => rx_data_valid_i
|
b_out => phy_out.rx_data_valid
|
||||||
);
|
);
|
||||||
|
|
||||||
rxdvff : process(clk, rst) is
|
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
|
||||||
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(
|
||||||
|
Loading…
Reference in New Issue
Block a user