2021-09-04 19:33:32 +02:00
-- -------------------------------------------------------------------------- --
-- TRASHERNET - A Trashy Ethernet Stack for FPGAs --
-- -------------------------------------------------------------------------- --
-- trashernet_phy_cdc.vhd : Dual clock wrapper for the trashernet_phy
-- Implements CDC between the PHY and DATA clock domains.
-- -------------------------------------------------------------------------- --
-- Author : Markus Koch <markus@notsyncing.net>
-- Contributors : None
-- License : Mozilla Public License (MPL) Version 2
-- -------------------------------------------------------------------------- --
2021-08-28 19:09:14 +02:00
library ieee ;
use ieee.std_logic_1164. all ;
use ieee.numeric_std. all ;
2021-09-04 19:05:49 +02:00
use work.trashernet_types. all ;
2021-08-28 19:09:14 +02:00
entity trashernet_phy_cdc is
generic (
F_CLK : in integer ; -- Clock frequency of design IF
F_CLK_PHY : in integer -- PHY clock (expected to be faster than F_CLK)
) ;
port (
-- Global
clk : in std_logic ; -- Clock for internal interface
phy_clk : in std_logic ; -- Clock for PHY (rx_p, tx_p)
rst : in std_logic ; -- Asynchronous reset
-- System interface
2021-09-04 19:05:49 +02:00
rx_data : out byte ; -- RX Data
2021-08-28 19:09:14 +02:00
rx_data_valid : out std_logic ; -- RX Data valid
rx_active : out std_logic ; -- RX of packet in progress
2021-09-04 19:05:49 +02:00
tx_data : in byte ; -- TX Data
2021-08-28 19:09:14 +02:00
tx_data_en : in std_logic ; -- Transmitter enable
tx_data_ack : out std_logic ; -- Latched data_tx
2021-09-04 19:06:43 +02:00
tx_active : out std_logic ; -- Transmission in progress
2021-08-28 19:09:14 +02:00
carrier_detect : out std_logic ; -- Carrier detected
rx_error : out std_logic ; -- Receive error
-- Ethernet physical signals
rx_p : in std_logic ;
2021-09-04 19:08:42 +02:00
tx_p : out std_logic ;
tx_n : out std_logic
2021-08-28 19:09:14 +02:00
) ;
end entity trashernet_phy_cdc ;
architecture RTL of trashernet_phy_cdc is
-- PHY signals
signal phy_rst : std_logic ;
signal phy_rx_data : std_logic_vector ( 7 downto 0 ) ;
signal phy_rx_data_valid : std_logic ;
signal phy_rx_active : std_logic ;
signal phy_tx_data : std_logic_vector ( 7 downto 0 ) ;
signal phy_tx_data_en : std_logic ;
signal phy_tx_data_ack : std_logic ;
signal phy_carrier_detect : std_logic ;
signal phy_rx_error : std_logic ;
2021-09-04 19:06:43 +02:00
signal phy_tx_active : std_logic ;
2021-08-28 19:09:14 +02:00
-- Helper signals
signal rx_data_valid_i : std_logic ;
begin
-- -------------------------------------------------------------------------
-- Drives: PHY clock domain
-- -------------------------------------------------------------------------
rstsync : process ( phy_clk , rst ) is
begin
if rst then
phy_rst < = '1' ;
elsif rising_edge ( phy_clk ) then
phy_rst < = '0' ;
end if ;
end process rstsync ;
trashernet_phy_inst : entity work . trashernet_phy
generic map (
F_CLK = > F_CLK_PHY
)
port map (
clk = > phy_clk ,
rst = > phy_rst ,
rx_data = > phy_rx_data ,
rx_data_valid = > phy_rx_data_valid ,
rx_active = > phy_rx_active ,
tx_data = > phy_tx_data ,
tx_data_en = > phy_tx_data_en ,
tx_data_ack = > phy_tx_data_ack ,
2021-09-04 19:06:43 +02:00
tx_active = > phy_tx_active ,
2021-08-28 19:09:14 +02:00
carrier_detect = > phy_carrier_detect ,
rx_error = > phy_rx_error ,
rx_p = > rx_p ,
2021-09-04 19:08:42 +02:00
tx_p = > tx_p ,
tx_n = > tx_n
2021-08-28 19:09:14 +02:00
) ;
synchronizer_txen_inst : entity work . synchronizer
generic map (
SIZE = > 5
)
port map (
clk = > phy_clk ,
rst = > phy_rst ,
data_in = > tx_data_en ,
data_out = > phy_tx_data_en
) ;
phy_tx_data < = tx_data ; -- When tx_data_en is through the synchronizer, this should be stable (and in the other direction, it should only change when we don't read it anyways)
-- -------------------------------------------------------------------------
-- Drives: System clock domain
-- -------------------------------------------------------------------------
cdc_strobe_rxdv_inst : entity work . cdc_strobe
port map (
a_clk = > phy_clk ,
a_rst = > phy_rst ,
a_in = > phy_rx_data_valid ,
b_clk = > clk ,
b_rst = > rst ,
b_out = > rx_data_valid_i
) ;
rxdvff : process ( clk , rst ) is
begin
if rst then
rx_data_valid < = '0' ;
elsif rising_edge ( clk ) then
rx_data_valid < = rx_data_valid_i ;
rx_data < = phy_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
port map (
a_clk = > phy_clk ,
a_rst = > phy_rst ,
a_in = > phy_rx_error ,
b_clk = > clk ,
b_rst = > rst ,
b_out = > rx_error
) ;
synchronizer_rxa_inst : entity work . synchronizer
port map (
clk = > clk ,
rst = > rst ,
data_in = > phy_rx_active ,
data_out = > rx_active
) ;
cdc_strobe_txack_inst : entity work . cdc_strobe
port map (
a_clk = > phy_clk ,
a_rst = > phy_rst ,
a_in = > phy_tx_data_ack ,
b_clk = > clk ,
b_rst = > rst ,
b_out = > tx_data_ack
) ;
synchronizer_crs_inst : entity work . synchronizer
port map (
clk = > clk ,
rst = > rst ,
data_in = > phy_carrier_detect ,
data_out = > carrier_detect
) ;
2021-09-04 19:06:43 +02:00
synchronizer_txa_inst : entity work . synchronizer
port map (
clk = > clk ,
rst = > rst ,
data_in = > phy_tx_active ,
data_out = > tx_active
) ;
2021-08-28 19:09:14 +02:00
end architecture RTL ;