From f0f9a1953bc00eff6498fa4e95f90a4a8cc62537 Mon Sep 17 00:00:00 2001 From: Markus Koch Date: Tue, 23 Jul 2024 19:10:46 +0200 Subject: [PATCH] fpga: Implement functional Ethernet controller --- fpga/hdl/design/top.vhd | 45 ++++++----- fpga/hdl/design/trashernet_phy_wb.vhd | 111 +++++++++++++++++++++++--- fpga/hdl/trashernet | 2 +- 3 files changed, 126 insertions(+), 32 deletions(-) diff --git a/fpga/hdl/design/top.vhd b/fpga/hdl/design/top.vhd index 31ebdd6..dab827f 100644 --- a/fpga/hdl/design/top.vhd +++ b/fpga/hdl/design/top.vhd @@ -25,35 +25,35 @@ entity top is UART_BAUD : integer := 19200 ); port( - clk_50m : in std_logic; -- System clock + clk_50m : in std_logic; -- System clock -- UART - uart_tx : out std_logic; -- UART TX - uart_rx : in std_logic; -- UART RX + uart_tx : out std_logic; -- UART TX + uart_rx : in std_logic; -- UART RX -- Trashernet - eth_rx_p : in std_logic; -- Ethernet RX+ + eth_rx_p : in std_logic; -- Ethernet RX+ --eth_rx_n : in std_logic; -- Ethernet RX- - eth_tx_p : out std_logic_vector(3 downto 0); -- Ethernet TX+ - eth_tx_n : out std_logic_vector(3 downto 0); -- Ethernet TX- + eth_tx_p : out std_logic_vector(3 downto 0); -- Ethernet TX+ + eth_tx_n : out std_logic_vector(3 downto 0); -- Ethernet TX- -- LEDs - eth_led_green : out std_logic; - eth_led_orange : out std_logic; - led_user : out std_logic; -- + eth_led_green_n : out std_logic; + eth_led_orange_n : out std_logic; + led_user : out std_logic; -- -- PSRAM IF - psram_ce_n : out std_logic; - psram_sclk : out std_logic; - psram_sio : inout std_logic_vector(3 downto 0); -- + psram_ce_n : out std_logic; + psram_sclk : out std_logic; + psram_sio : inout std_logic_vector(3 downto 0); -- -- Config Flash - flash_ce_n : out std_logic; - flash_sclk : out std_logic; - flash_sio : inout std_logic_vector(3 downto 0); -- + flash_ce_n : out std_logic; + flash_sclk : out std_logic; + flash_sio : inout std_logic_vector(3 downto 0); -- -- PMOD - pmod : inout std_logic_vector(7 downto 0) + pmod : inout std_logic_vector(7 downto 0) ); end entity top; @@ -69,6 +69,9 @@ architecture rtl of top is signal eth_tx_n_i : std_logic; signal eth_rx_p_i : std_logic; + signal eth_led_green : std_logic; + signal eth_led_orange : std_logic; + -- System Timer signal irq_timer : std_logic; @@ -247,7 +250,9 @@ begin wb_i => wb_eth_i, rx_p => eth_rx_p_i, tx_p => eth_tx_p_i, - tx_n => eth_tx_n_i + tx_n => eth_tx_n_i, + led_rx => eth_led_green, + led_tx => eth_led_orange ); eth_tx_p <= (others => eth_tx_p_i); eth_tx_n <= (others => eth_tx_n_i); @@ -264,9 +269,9 @@ begin mask => wishbone_masks ); - eth_led_green <= uart_tx; - eth_led_orange <= uart_rx; - led_user <= not psram_ce_n; + eth_led_green_n <= not eth_led_green; + eth_led_orange_n <= not eth_led_orange; + led_user <= not uart_tx or not uart_rx; flash_ce_n <= 'Z'; flash_sclk <= 'Z'; diff --git a/fpga/hdl/design/trashernet_phy_wb.vhd b/fpga/hdl/design/trashernet_phy_wb.vhd index 4172561..5f3e20a 100644 --- a/fpga/hdl/design/trashernet_phy_wb.vhd +++ b/fpga/hdl/design/trashernet_phy_wb.vhd @@ -37,7 +37,10 @@ entity trashernet_phy_wb is -- Ethernet physical signals rx_p : in std_logic; tx_p : out std_logic; - tx_n : out std_logic + tx_n : out std_logic; + -- LEDs + led_tx : out std_logic; + led_rx : out std_logic ); end entity trashernet_phy_wb; @@ -46,6 +49,9 @@ architecture RTL of trashernet_phy_wb is signal phy_out : phy_out_t; -- PHY application IF (out) signal phy_in : phy_in_t; -- PHY application IF (in) + signal mac_out : raw_mac_out_t; -- MAC application IF (out) + signal mac_in : raw_mac_in_t; -- MAC application IF (in) + signal wb_adr : unsigned(2 downto 2); signal status_register : std_logic_vector(31 downto 0); @@ -57,6 +63,11 @@ architecture RTL of trashernet_phy_wb is signal tx_fifo_commit : std_logic; signal tx_fifo_empty : std_logic; signal tx_fifo_data : std_logic_vector(7 downto 0); + + signal rx_fifo_empty : std_logic; + signal rx_bitcount : std_logic_vector(10 downto 0); + signal rx_fifo_block_count : std_logic_vector(rx_bitcount'range); + signal rx_block_next : std_logic; begin trashernet_phy_inst : entity trashernet.trashernet_phy_cdc generic map( @@ -74,6 +85,16 @@ begin tx_n => tx_n ); + trashernet_raw_mac_inst : entity trashernet.trashernet_raw_mac + port map( + clk => clk, + rst => rst, + phy_out => phy_out, + phy_in => phy_in, + mac_out => mac_out, + mac_in => mac_in + ); + rx_fifo_inst : entity generics.fifo_block generic map( SIZE => 2047 @@ -82,18 +103,48 @@ begin clk => clk, rst_a => '0', clr => rst, - data_in => phy_out.rx_data, - write => phy_out.rx_data_valid, - commit => not phy_out.rx_active, - abort => '0', + data_in => mac_out.rx_mac_data, + write => mac_out.rx_mac_valid, + commit => mac_out.rx_mac_crc_ok, + abort => mac_out.rx_mac_crc_error, full => open, data_out => rx_fifo_data, data_first => open, - empty => open, + empty => rx_fifo_empty, read => rx_fifo_read, usage => open ); + fifo_inst : entity generics.fifo + generic map( + SIZE => 31 + ) + port map( + clk => clk, + rst_a => '0', + clr => rst, + data_in => rx_bitcount, + write => mac_out.rx_mac_crc_ok, + full => open, + data_out => rx_fifo_block_count, + empty => open, + read => rx_block_next, + usage => open + ); + + rxcount : process(rst, clk) is + begin + if rst then + rx_bitcount <= (others => '0'); + + elsif rising_edge(clk) then + if mac_out.rx_mac_crc_error or mac_out.rx_mac_crc_ok then + rx_bitcount <= (others => '0'); + elsif mac_out.rx_mac_valid then + rx_bitcount <= std_logic_vector(unsigned(rx_bitcount) + 1); + end if; + end if; + end process rxcount; tx_fifo_inst : entity generics.fifo_block generic map( SIZE => 2047 @@ -110,7 +161,7 @@ begin data_out => tx_fifo_data, data_first => open, empty => tx_fifo_empty, - read => phy_out.tx_data_ack, + read => mac_out.tx_mac_data_ack, usage => open ); @@ -122,12 +173,14 @@ begin rx_fifo_read <= '0'; tx_fifo_write <= '0'; tx_fifo_commit <= '0'; + rx_block_next <= '0'; elsif rising_edge(clk) then wb_o.ack <= '0'; rx_fifo_read <= '0'; tx_fifo_write <= '0'; tx_fifo_commit <= '0'; + rx_block_next <= '0'; if (wb_i.cyc and wb_i.stb) then wb_o.ack <= '1'; @@ -136,7 +189,8 @@ begin wb_o.dat <= status_register; if wb_o.ack = '0' then if wb_i.we = '1' then - tx_fifo_commit <= '1'; + tx_fifo_commit <= wb_i.dat(2); + rx_block_next <= wb_i.dat(1); end if; end if; else @@ -159,8 +213,43 @@ begin wb_o.rty <= '1'; wb_o.stall <= '0'; - phy_in.tx_data_en <= not tx_fifo_empty; -- FIXME: this does not care about inter-packet gaps indicated by `data_first` - phy_in.tx_data <= tx_fifo_data; + mac_in.tx_mac_data_en <= not tx_fifo_empty; -- FIXME: this does not care about inter-packet gaps indicated by `data_first` + mac_in.tx_mac_data <= tx_fifo_data; - status_register <= (x"0000" & x"000" & "000" & phy_out.carrier_detect); + status_register <= ("0" & x"0" & rx_fifo_block_count & -- 31..16 + x"000" & "0" & (not tx_fifo_empty) & (not rx_fifo_empty) & phy_out.carrier_detect); + + ledstretch : process(clk) is + constant CMAX : integer := integer(0.2 / (1.0 / real(F_CLK))); + variable cnt : integer range 0 to CMAX; + begin + if rising_edge(clk) then + if cnt = 0 then + led_rx <= phy_out.carrier_detect; + if phy_out.rx_active then + cnt := CMAX; + end if; + else + led_rx <= '0'; + cnt := cnt - 1; + end if; + end if; + end process ledstretch; + + ledstretch2 : process(clk) is + constant CMAX : integer := integer(0.2 / (1.0 / real(F_CLK))); + variable cnt : integer range 0 to CMAX; + begin + if rising_edge(clk) then + if cnt = 0 then + led_tx <= '0'; + if phy_out.tx_active then + cnt := CMAX; + end if; + else + led_tx <= '1'; + cnt := cnt - 1; + end if; + end if; + end process ledstretch2; end architecture RTL; diff --git a/fpga/hdl/trashernet b/fpga/hdl/trashernet index 21a0d0e..206332f 160000 --- a/fpga/hdl/trashernet +++ b/fpga/hdl/trashernet @@ -1 +1 @@ -Subproject commit 21a0d0e69aeacf9747bfac0262e0d7ca30a691d9 +Subproject commit 206332f3d1c1f5b704bad09b1380a8aed8b736aa