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-25 11:07:12 +02:00
use work.trashernet_pkg. all ;
2021-09-04 19:05:49 +02:00
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
2021-09-25 12:28:04 +02:00
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
2021-08-28 19:09:14 +02:00
2021-09-25 12:28:04 +02:00
-- PHY application interface
phy_out : out phy_out_t ; -- PHY application IF (out)
phy_in : in phy_in_t ; -- PHY application IF (in)
2021-08-28 19:09:14 +02:00
-- Ethernet physical signals
2021-09-25 12:28:04 +02:00
rx_p : in std_logic ;
tx_p : out std_logic ;
tx_n : out std_logic
2021-08-28 19:09:14 +02:00
) ;
end entity trashernet_phy_cdc ;
2021-09-25 12:28:04 +02:00
architecture rtl of trashernet_phy_cdc is
2021-08-28 19:09:14 +02:00
-- PHY signals
2021-09-25 12:28:04 +02:00
signal phy_rst : std_logic ;
signal phy_phy_out : phy_out_t ;
signal phy_phy_in : phy_in_t ;
2021-08-28 19:09:14 +02:00
-- Helper signals
signal rx_data_valid_i : std_logic ;
begin
2022-10-30 17:29:14 +01:00
assert F_CLK_PHY > 2 * F_CLK report "F_CLK_PHY must be at least 2x F_CLK" severity failure ;
2021-08-28 19:09:14 +02:00
-- -------------------------------------------------------------------------
-- 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 (
2021-09-25 12:28:04 +02:00
clk = > phy_clk ,
rst = > phy_rst ,
phy_out = > phy_phy_out ,
phy_in = > phy_phy_in ,
rx_p = > rx_p ,
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 ,
2021-09-25 12:28:04 +02:00
data_in = > phy_in . tx_data_en ,
data_out = > phy_phy_in . tx_data_en
2021-08-28 19:09:14 +02:00
) ;
2021-09-25 12:28:04 +02:00
phy_phy_in . tx_data < = phy_in . 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)
2021-08-28 19:09:14 +02:00
-- -------------------------------------------------------------------------
-- Drives: System clock domain
-- -------------------------------------------------------------------------
cdc_strobe_rxdv_inst : entity work . cdc_strobe
port map (
a_clk = > phy_clk ,
a_rst = > phy_rst ,
2021-09-25 12:28:04 +02:00
a_in = > phy_phy_out . rx_data_valid ,
2021-08-28 19:09:14 +02:00
b_clk = > clk ,
b_rst = > rst ,
b_out = > rx_data_valid_i
) ;
rxdvff : process ( clk , rst ) is
begin
if rst then
2021-09-25 12:28:04 +02:00
phy_out . rx_data_valid < = '0' ;
2021-08-28 19:09:14 +02:00
elsif rising_edge ( clk ) then
2021-09-25 12:28:04 +02:00
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
2021-08-28 19:09:14 +02:00
end if ;
end process rxdvff ;
cdc_strobe_rxer_inst : entity work . cdc_strobe
port map (
a_clk = > phy_clk ,
a_rst = > phy_rst ,
2021-09-25 12:28:04 +02:00
a_in = > phy_phy_out . rx_error ,
2021-08-28 19:09:14 +02:00
b_clk = > clk ,
b_rst = > rst ,
2021-09-25 12:28:04 +02:00
b_out = > phy_out . rx_error
2021-08-28 19:09:14 +02:00
) ;
synchronizer_rxa_inst : entity work . synchronizer
port map (
clk = > clk ,
rst = > rst ,
2021-09-25 12:28:04 +02:00
data_in = > phy_phy_out . rx_active ,
data_out = > phy_out . rx_active
2021-08-28 19:09:14 +02:00
) ;
cdc_strobe_txack_inst : entity work . cdc_strobe
port map (
a_clk = > phy_clk ,
a_rst = > phy_rst ,
2021-09-25 12:28:04 +02:00
a_in = > phy_phy_out . tx_data_ack ,
2021-08-28 19:09:14 +02:00
b_clk = > clk ,
b_rst = > rst ,
2021-09-25 12:28:04 +02:00
b_out = > phy_out . tx_data_ack
2021-08-28 19:09:14 +02:00
) ;
synchronizer_crs_inst : entity work . synchronizer
port map (
clk = > clk ,
rst = > rst ,
2021-09-25 12:28:04 +02:00
data_in = > phy_phy_out . carrier_detect ,
data_out = > phy_out . carrier_detect
2021-08-28 19:09:14 +02:00
) ;
2021-09-04 19:06:43 +02:00
synchronizer_txa_inst : entity work . synchronizer
port map (
clk = > clk ,
rst = > rst ,
2021-09-25 12:28:04 +02:00
data_in = > phy_phy_out . tx_active ,
data_out = > phy_out . tx_active
2021-09-04 19:06:43 +02:00
) ;
2021-09-25 12:28:04 +02:00
end architecture rtl ;