phy: tx: Implement transmitter
This commit is contained in:
parent
6322f5a317
commit
16026849e8
@ -26,7 +26,8 @@ entity trashernet_phy is
|
|||||||
|
|
||||||
-- Ethernet physical signals
|
-- Ethernet physical signals
|
||||||
rx_p : in std_logic;
|
rx_p : in std_logic;
|
||||||
tx_p : out std_logic
|
tx_p : out std_logic;
|
||||||
|
tx_n : out std_logic
|
||||||
);
|
);
|
||||||
end entity trashernet_phy;
|
end entity trashernet_phy;
|
||||||
|
|
||||||
@ -254,19 +255,143 @@ begin
|
|||||||
-- -------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------
|
||||||
|
|
||||||
transmitter : block
|
transmitter : block
|
||||||
constant TRIG_CNT_MAX : integer := integer(round(real(F_CLK) * 16.0 * 10.0**(-3))); -- Every 16 ms
|
constant TX_STB_CNT_MAX : integer := F_CLK / (F_ETH * 2) - 1;
|
||||||
constant TRIG_CNT_MIN : integer := -integer(round(real(F_CLK) * 100.0 * 10.0**(-9))); -- For 100 ns
|
signal tx_stb_cnt : integer range 0 to TX_STB_CNT_MAX;
|
||||||
signal cnt : integer range TRIG_CNT_MIN to TRIG_CNT_MAX;
|
|
||||||
|
type tx_state_t is (IDLE, NLP, TX, IPG);
|
||||||
|
signal tx_state : tx_state_t;
|
||||||
|
signal sr : std_logic_vector(tx_data'range);
|
||||||
|
signal bit_stage : std_logic;
|
||||||
|
|
||||||
|
constant BIT_CNT_MAX_NLP : integer := 16000 / 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);
|
||||||
|
|
||||||
|
type tx_mode_t is (OFF, NLP, ACTIVE);
|
||||||
|
signal tx_mode : tx_mode_t;
|
||||||
begin
|
begin
|
||||||
-- Generates NLP to keep the link up
|
tx_main : process(clk, rst) is
|
||||||
nlp : process(clk, rst) is
|
procedure transmit_byte is
|
||||||
|
begin
|
||||||
|
tx_state <= TX;
|
||||||
|
tx_mode <= ACTIVE;
|
||||||
|
|
||||||
|
sr <= tx_data;
|
||||||
|
bit_stage <= '0';
|
||||||
|
bit_cnt <= BIT_CNT_MAX_DATA;
|
||||||
|
tx_data_ack <= '0';
|
||||||
|
end procedure transmit_byte;
|
||||||
|
|
||||||
|
procedure transmit_ipg is
|
||||||
|
begin
|
||||||
|
tx_state <= IPG;
|
||||||
|
tx_mode <= OFF;
|
||||||
|
|
||||||
|
bit_cnt <= BIT_CNT_MAX_IPG;
|
||||||
|
bit_stage <= '0';
|
||||||
|
end procedure transmit_ipg;
|
||||||
|
|
||||||
|
procedure transmit_nlp is
|
||||||
|
begin
|
||||||
|
tx_state <= NLP;
|
||||||
|
tx_mode <= NLP;
|
||||||
|
end procedure transmit_nlp;
|
||||||
|
|
||||||
|
procedure go_idle is
|
||||||
|
begin
|
||||||
|
tx_state <= IDLE;
|
||||||
|
tx_mode <= OFF;
|
||||||
|
|
||||||
|
bit_cnt <= BIT_CNT_MAX_NLP;
|
||||||
|
bit_stage <= '0';
|
||||||
|
end procedure go_idle;
|
||||||
|
|
||||||
|
variable tx_stb : std_logic; -- Strobe every 50 ns (20 MHz)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if rst then
|
if rst then
|
||||||
cnt <= TRIG_CNT_MIN;
|
tx_data_ack <= '0';
|
||||||
|
tx_stb_cnt <= TX_STB_CNT_MAX;
|
||||||
|
tx_mode <= OFF;
|
||||||
|
go_idle;
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
elsif rising_edge(clk) then
|
||||||
cnt <= TRIG_CNT_MAX when (cnt = TRIG_CNT_MIN) else cnt - 1;
|
tx_data_ack <= '0';
|
||||||
|
|
||||||
|
if tx_stb_cnt = 0 then
|
||||||
|
tx_stb_cnt <= TX_STB_CNT_MAX;
|
||||||
|
else
|
||||||
|
tx_stb_cnt <= tx_stb_cnt - 1;
|
||||||
end if;
|
end if;
|
||||||
end process nlp;
|
tx_stb := '1' when tx_stb_cnt = 0 else '0';
|
||||||
tx_p <= '1' when cnt < 0 else '0';
|
|
||||||
|
if tx_stb then
|
||||||
|
bit_stage <= not bit_stage;
|
||||||
|
end if;
|
||||||
|
if tx_stb and bit_stage then -- 100 ns (1 bit)
|
||||||
|
if (bit_cnt /= 0) then
|
||||||
|
bit_cnt <= bit_cnt - 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
case tx_state is
|
||||||
|
when IDLE =>
|
||||||
|
if tx_data_en then -- New packet to TX
|
||||||
|
transmit_byte;
|
||||||
|
tx_stb_cnt <= TX_STB_CNT_MAX; -- resync
|
||||||
|
|
||||||
|
elsif bit_cnt = 0 then -- NLP timeout
|
||||||
|
transmit_nlp;
|
||||||
|
|
||||||
|
--bit_cnt <= 1; Let's save some resources here...
|
||||||
|
bit_stage <= '0';
|
||||||
|
tx_stb_cnt <= TX_STB_CNT_MAX; -- resync
|
||||||
|
end if;
|
||||||
|
when NLP =>
|
||||||
|
if tx_stb and bit_stage then -- 100 ns duration
|
||||||
|
go_idle;
|
||||||
|
end if;
|
||||||
|
when TX =>
|
||||||
|
if tx_stb then
|
||||||
|
if (bit_stage = '1') then
|
||||||
|
sr <= '0' & sr(sr'high downto sr'low + 1);
|
||||||
|
if bit_cnt = 0 then
|
||||||
|
if tx_data_en then
|
||||||
|
transmit_byte;
|
||||||
|
else
|
||||||
|
transmit_ipg;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
when IPG =>
|
||||||
|
if bit_cnt = 0 then
|
||||||
|
go_idle;
|
||||||
|
end if;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process tx_main;
|
||||||
|
|
||||||
|
driver : process(clk, rst) is
|
||||||
|
begin
|
||||||
|
if rst then
|
||||||
|
tx_p <= '0';
|
||||||
|
tx_n <= '0';
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
case tx_mode is
|
||||||
|
when OFF =>
|
||||||
|
tx_p <= '0';
|
||||||
|
tx_n <= '0';
|
||||||
|
when NLP =>
|
||||||
|
tx_p <= '1';
|
||||||
|
tx_n <= '0';
|
||||||
|
when ACTIVE =>
|
||||||
|
tx_p <= sr(sr'low) xor bit_stage;
|
||||||
|
tx_n <= not (sr(sr'low) xor bit_stage);
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process driver;
|
||||||
|
|
||||||
end block transmitter;
|
end block transmitter;
|
||||||
end architecture rtl;
|
end architecture rtl;
|
||||||
|
Loading…
Reference in New Issue
Block a user