Compare commits

...

3 Commits

Author SHA1 Message Date
dddfdbabc1 phy: Add CDC wrapper 2021-08-28 19:09:14 +02:00
d16f1afd9a phy: Rename rx/tx signals 2021-08-28 19:08:37 +02:00
3900d454f9 misc: Allow dynamic length for synchronizer 2021-08-28 19:08:07 +02:00
4 changed files with 221 additions and 14 deletions

51
trashernet/cdc_strobe.vhd Normal file
View File

@ -0,0 +1,51 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity cdc_strobe is
generic(
SYNCHRONIZERS : integer := 3
);
port(
a_clk : in std_logic;
a_rst : in std_logic;
a_in : in std_logic;
b_clk : in std_logic;
b_rst : in std_logic;
b_out : out std_logic
);
end entity cdc_strobe;
architecture rtl of cdc_strobe is
signal a_toggle : std_logic;
signal b_toggle : std_logic;
signal b_toggle_last : std_logic;
begin
togglify : process(a_clk, a_rst) is
begin
if a_rst then
a_toggle <= '0';
elsif rising_edge(a_clk) then
if (a_in) then
a_toggle <= not a_toggle;
end if;
end if;
end process togglify;
synchronizer_inst : entity work.synchronizer
generic map(
SIZE => SYNCHRONIZERS
)
port map(
clk => b_clk,
rst => b_rst,
data_in => a_toggle,
data_out => b_toggle
);
-- strobify
b_toggle_last <= '0' when b_rst
else b_toggle when rising_edge(b_clk)
;
b_out <= (b_toggle ?/= b_toggle_last);
end architecture rtl;

View File

@ -3,6 +3,9 @@ use ieee.std_logic_1164.all;
use ieee.numeric_std.all; use ieee.numeric_std.all;
entity synchronizer is entity synchronizer is
generic(
SIZE : integer := 3
);
port( port(
clk : in std_logic; clk : in std_logic;
rst : in std_logic; rst : in std_logic;
@ -12,7 +15,7 @@ entity synchronizer is
end entity synchronizer; end entity synchronizer;
architecture RTL of synchronizer is architecture RTL of synchronizer is
signal sr : std_logic_vector(2 downto 0); signal sr : std_logic_vector(SIZE - 1 downto 0);
begin begin
sync : process(clk, rst) is sync : process(clk, rst) is
begin begin

View File

@ -5,7 +5,7 @@ use ieee.math_real.all;
entity trashernet_phy is entity trashernet_phy is
generic( generic(
F_CLK : in integer F_CLK : in integer -- Clock frequency
); );
port( port(
-- Global -- Global
@ -13,16 +13,16 @@ entity trashernet_phy is
rst : in std_logic; -- Asynchronous reset rst : in std_logic; -- Asynchronous reset
-- Eth -- Eth
data_rx : out std_logic_vector(7 downto 0); -- RX Data rx_data : out std_logic_vector(7 downto 0); -- RX Data
data_rx_valid : out std_logic; -- RX Data valid rx_data_valid : out std_logic; -- RX Data valid
rx_active : out std_logic; -- RX of packet in progress rx_active : out std_logic; -- RX of packet in progress
data_tx : in std_logic_vector(7 downto 0); -- TX Data tx_data : in std_logic_vector(7 downto 0); -- TX Data
data_tx_en : in std_logic; tx_data_en : in std_logic; -- Transmitter enable
data_tx_ack : out std_logic; -- tx_data_ack : out std_logic; -- Latched data_tx
carrier_detect : out std_logic; -- carrier_detect : out std_logic; -- Carrier detected
rx_error : out std_logic; -- rx_error : out std_logic; -- Receive error
-- Ethernet physical signals -- Ethernet physical signals
rx_p : in std_logic; rx_p : in std_logic;
@ -212,17 +212,17 @@ begin
bytizer : process(clk, rst) is bytizer : process(clk, rst) is
begin begin
if rst then if rst then
data_rx_valid <= '0'; rx_data_valid <= '0';
data_rx <= (others => '0'); rx_data <= (others => '0');
elsif rising_edge(clk) then elsif rising_edge(clk) then
data_rx_valid <= '0'; rx_data_valid <= '0';
if rx_active then if rx_active then
if (bit_stb) then if (bit_stb) then
data_rx <= bit_value & data_rx(data_rx'high downto data_rx'low + 1); rx_data <= bit_value & rx_data(rx_data'high downto rx_data'low + 1);
if (bit_cnt = 7) then if (bit_cnt = 7) then
data_rx_valid <= '1'; rx_data_valid <= '1';
bit_cnt <= 0; bit_cnt <= 0;
else else
bit_cnt <= bit_cnt + 1; bit_cnt <= bit_cnt + 1;

View File

@ -0,0 +1,153 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
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
rx_data : out std_logic_vector(7 downto 0); -- RX Data
rx_data_valid : out std_logic; -- RX Data valid
rx_active : out std_logic; -- RX of packet in progress
tx_data : in std_logic_vector(7 downto 0); -- TX Data
tx_data_en : in std_logic; -- Transmitter enable
tx_data_ack : out std_logic; -- Latched data_tx
carrier_detect : out std_logic; -- Carrier detected
rx_error : out std_logic; -- Receive error
-- Ethernet physical signals
rx_p : in std_logic;
tx_p : out std_logic
);
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;
-- 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,
carrier_detect => phy_carrier_detect,
rx_error => phy_rx_error,
rx_p => rx_p,
tx_p => tx_p
);
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
);
end architecture RTL;