phy: Fix NLPs

We need a different NLP timeout for RX than TX.
Also use a prescaler to improve timing.
This commit is contained in:
Markus Koch 2022-01-29 20:15:02 +01:00
parent a9039a175c
commit 075f935e12

View File

@ -39,8 +39,31 @@ end entity trashernet_phy;
architecture rtl of trashernet_phy is
constant F_ETH : integer := 10000000;
signal tick_ms : std_logic; -- 1 ms tick (for NLP)
begin
common : block
constant TICK_MS_CNT_MAX : integer := (F_CLK / 1000) - 1;
signal tick_ms_count : integer range 0 to TICK_MS_CNT_MAX;
begin
mstick : process(clk, rst) is
begin
if rst then
tick_ms_count <= TICK_MS_CNT_MAX;
tick_ms <= '0';
elsif rising_edge(clk) then
tick_ms <= '0';
if tick_ms_count = 0 then
tick_ms <= '1';
tick_ms_count <= TICK_MS_CNT_MAX;
else
tick_ms_count <= tick_ms_count - 1;
end if;
end if;
end process mstick;
end block common;
receiver : block
-- Signal conditioning
signal rx : std_logic;
@ -56,7 +79,7 @@ begin
signal bit_cnt : integer range 0 to 7;
-- NLP supervision
constant NLP_TIMEOUT_CNT_MAX : integer := integer(round(real(F_CLK) * 16.0 * 10.0 ** (-3))) - 1; -- Every 16 ms
constant NLP_TIMEOUT_CNT_MAX : integer := (16 + 8) - 1; -- Every 16 ms (timebase 1 ms)
signal nlp_timeout_cnt : integer range 0 to NLP_TIMEOUT_CNT_MAX;
begin
-- Synchronize RX input
@ -248,11 +271,13 @@ begin
if rx_edge then -- Technically, we should use only the rising edge here, but a project called `trashernet` probably won't mind ;)
nlp_timeout_cnt <= NLP_TIMEOUT_CNT_MAX;
else
if (nlp_timeout_cnt /= 0) then
if tick_ms then
if nlp_timeout_cnt /= 0 then
nlp_timeout_cnt <= nlp_timeout_cnt - 1;
end if;
end if;
end if;
end if;
end process nlp_timeout_p;
phy_out.carrier_detect <= '1' when nlp_timeout_cnt /= 0 else '0';
end block receiver;
@ -268,10 +293,11 @@ begin
signal sr : std_logic_vector(phy_in.tx_data'range);
signal bit_stage : std_logic;
constant BIT_CNT_MAX_NLP : integer := 16000000 / 100; -- 16 ms (timebase 100 ns)
constant BIT_CNT_MAX_IPG : integer := 96;
constant BIT_CNT_MAX_DATA : integer := sr'length - 1;
signal bit_cnt : integer range 0 to maximum(maximum(BIT_CNT_MAX_NLP, BIT_CNT_MAX_DATA), BIT_CNT_MAX_IPG);
signal bit_cnt : integer range 0 to maximum(BIT_CNT_MAX_IPG, BIT_CNT_MAX_DATA);
constant NLP_CNT_MAX : integer := 15; -- specced 16 ms, but there's margin, so let's choose 15 to save a bit (timebase 1 ms)
signal nlp_cnt : integer range 0 to NLP_CNT_MAX;
type tx_mode_t is (OFF, NLP, ACTIVE);
signal tx_mode : tx_mode_t;
@ -308,7 +334,7 @@ begin
tx_state <= IDLE;
tx_mode <= OFF;
bit_cnt <= BIT_CNT_MAX_NLP;
nlp_cnt <= NLP_CNT_MAX;
bit_stage <= '0';
end procedure go_idle;
@ -343,7 +369,11 @@ begin
bit_cnt <= bit_cnt - 1;
end if;
end if;
if tick_ms then
if (nlp_cnt /= 0) then
nlp_cnt <= nlp_cnt - 1;
end if;
end if;
case tx_state is
when IDLE =>
if phy_in.tx_data_en then -- New packet to TX
@ -352,7 +382,7 @@ begin
bit_stage <= '1';
tx_stb_cnt <= TX_STB_CNT_MAX; -- resync
elsif bit_cnt = 0 then -- NLP timeout
elsif nlp_cnt = 0 then -- NLP timeout
transmit_nlp;
--bit_cnt <= 1; Let's save some resources here...