trashernet/trashernet/trashernet_phy_cdc.vhd

159 lines
4.4 KiB
VHDL
Raw Permalink Normal View History

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;
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
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
-- 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
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;
architecture rtl of trashernet_phy_cdc is
2021-08-28 19:09:14 +02:00
-- PHY signals
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(
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,
data_in => phy_in.tx_data_en,
data_out => phy_phy_in.tx_data_en
2021-08-28 19:09:14 +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,
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
phy_out.rx_data_valid <= '0';
2021-08-28 19:09:14 +02:00
elsif rising_edge(clk) then
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,
a_in => phy_phy_out.rx_error,
2021-08-28 19:09:14 +02:00
b_clk => clk,
b_rst => rst,
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,
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,
a_in => phy_phy_out.tx_data_ack,
2021-08-28 19:09:14 +02:00
b_clk => clk,
b_rst => rst,
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,
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,
data_in => phy_phy_out.tx_active,
data_out => phy_out.tx_active
2021-09-04 19:06:43 +02:00
);
end architecture rtl;