Commit f38234c0 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

platform/xilinx: wrapper for Zynq Ulrascale+ GTHE4 transceiver

parent caf65744
......@@ -34,3 +34,10 @@ elif (syn_device[0:4].upper()=="XCKU"): # Kintex Ultrascale GTH
"family7-gthe3/wr_gthe3_tx_buffer_bypass.vhd",
"family7-gthe3/wr_gthe3_wrapper.vhd",
"family7-gthe3/gc_reset_synchronizer.vhd" ]);
elif (syn_device[0:4].upper()=="XCZU"): # Zynq Ultrascale GTH
files.extend(["family7-gthe4/wr_gthe4_phy_family7.vhd",
"family7-gthe4/wr_gthe4_reset.vhd",
"family7-gthe4/wr_gthe4_rx_buffer_bypass.vhd",
"family7-gthe4/wr_gthe4_tx_buffer_bypass.vhd",
"family7-gthe4/wr_gthe4_wrapper.vhd",
"family7-gthe4/gc_reset_synchronizer.vhd" ]);
library ieee;
use ieee.std_logic_1164.all;
entity gc_reset_synchronizer is
generic (
g_reset_active_out : std_logic := '0');
port (
clk_i : in std_logic;
rst_n_a_i : in std_logic;
rst_synced_o : out std_logic);
end gc_reset_synchronizer;
architecture rtl of gc_reset_synchronizer is
signal gc_sync_ffs_sync0, gc_sync_ffs_sync1, gc_sync_ffs_sync2 : std_logic;
attribute shreg_extract : string;
attribute shreg_extract of gc_sync_ffs_sync0 : signal is "no";
attribute shreg_extract of gc_sync_ffs_sync1 : signal is "no";
attribute keep : string;
attribute keep of gc_sync_ffs_sync0 : signal is "true";
attribute keep of gc_sync_ffs_sync1 : signal is "true";
-- synchronizer attribute for Vivado
attribute ASYNC_REG : string;
attribute ASYNC_REG of gc_sync_ffs_sync0 : signal is "true";
attribute ASYNC_REG of gc_sync_ffs_sync1 : signal is "true";
begin
process(clk_i, rst_n_a_i)
begin
if(rst_n_a_i = '0') then
gc_sync_ffs_sync0 <= '0';
gc_sync_ffs_sync1 <= '0';
gc_sync_ffs_sync2 <= '0';
rst_synced_o <= g_reset_active_out;
elsif rising_edge(clk_i) then
gc_sync_ffs_sync0 <= not rst_n_a_i;
gc_sync_ffs_sync1 <= gc_sync_ffs_sync0;
rst_synced_o <= gc_sync_ffs_sync1;
end if;
end process;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
entity wr_gthe4_reset is
port (
rst_i : in std_logic;
clk_free_i : in std_logic;
-- CPLL reset I/O
CPLLPD_o : out std_logic;
CPLLLOCK_i : in std_logic;
-- RX path resets
RXCDRLOCK_i : in std_logic;
RXRESETDONE_i : in std_logic;
GTRXRESET_o : out std_logic;
RXPROGDIVRESET_o : out std_logic;
RXUSERRDY_o : out std_logic;
-- TX path resets
GTTXRESET_o : out std_logic;
TXRESETDONE_i : in std_logic;
TXPROGDIVRESET_o : out std_logic;
TXUSERRDY_o : out std_logic;
rx_active_i : in std_logic;
tx_active_i : in std_logic;
done_o : out std_logic
);
end wr_gthe4_reset;
architecture rtl of wr_gthe4_reset is
constant c_RESET_TIMEOUT : integer := 1000;
type t_state is (RESTART, DONE, CPLL_WAIT_LOCK, CPLL_RESET_TIMEOUT, CDR_WAIT_LOCK, TX_ACTIVE_WAIT, RX_ACTIVE_WAIT, TX_RESET_DONE_WAIT, RX_RESET_DONE_WAIT, TX_RESET_TIMER_WAIT);
signal state : t_state;
signal rst_master_clk_free : std_logic;
signal CPLLLOCK_clk_free, tx_active_clk_free : std_logic;
signal rx_active_clk_free : std_logic;
signal TXRESETDONE_clk_free : std_logic;
signal RXRESETDONE_clk_free : std_logic;
signal RXCDRLOCK_clk_free : std_logic;
signal timeout_cnt : unsigned(15 downto 0);
begin
U_SyncResetAll : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_free_i,
rst_n_i => '1',
data_i => rst_i,
synced_o => rst_master_clk_free);
U_SyncCPLLLOCK : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_free_i,
rst_n_i => '1',
data_i => CPLLLOCK_i,
synced_o => CPLLLOCK_clk_free);
U_SyncTxActive : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_free_i,
rst_n_i => '1',
data_i => tx_active_i,
synced_o => tx_active_clk_free);
U_SyncRxActive : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_free_i,
rst_n_i => '1',
data_i => rx_active_i,
synced_o => rx_active_clk_free);
U_SyncRxResetDone : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_free_i,
rst_n_i => '1',
data_i => RXRESETDONE_i,
synced_o => RXRESETDONE_clk_free);
U_SyncTxResetDone : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_free_i,
rst_n_i => '1',
data_i => TXRESETDONE_i,
synced_o => TXRESETDONE_clk_free);
U_SyncRxCdrLock : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_free_i,
rst_n_i => '1',
data_i => RXCDRLOCK_i,
synced_o => RXCDRLOCK_clk_free);
TXPROGDIVRESET_o <= not CPLLLOCK_clk_free;
-- TX side:
-- - assert pllreset_tx, gttxreset
-- - wait for lock (plllock_tx, pllreset_tx -> 0)
-- - gttxreset -> 0
-- - wait for tx_active
-- - wait for txresetdone
-- - we're done
-- RX side:
-- - assert pllreset_rx, rxprogdivreset, gtrxreset
-- - wait for plllock_rx, pllreset_rx->0
-- - deassert gtrxreset
-- - wait for cdr lock
-- - deassert progdiv reset
-- - wait for rx_active
-- - wait for rxresetdone
-- - we're done
process(clk_free_i)
begin
if rising_edge(clk_free_i)then
if rst_master_clk_free = '1' then
state <= RESTART;
done_o <= '0';
GTTXRESET_o <= '1';
GTRXRESET_o <= '1';
RXPROGDIVRESET_o <= '1';
TXUSERRDY_o <= '0';
RXUSERRDY_o <= '0';
else
done_o <= '0';
case state is
when RESTART =>
CPLLPD_o <= '1'; -- assert both TX and RX PLL reset (we're using the
-- CPLL that serves both)
GTTXRESET_o <= '1';
GTRXRESET_o <= '1';
RXPROGDIVRESET_o <= '1';
TXUSERRDY_o <= '0';
RXUSERRDY_o <= '0';
state <= CPLL_WAIT_LOCK;
timeout_cnt <= to_unsigned(c_RESET_TIMEOUT, 16);
when CPLL_RESET_TIMEOUT =>
timeout_cnt <= timeout_cnt - 1;
if timeout_cnt = 0 then
CPLLPD_o <= '0';
state <= CPLL_WAIT_LOCK;
end if;
when CPLL_WAIT_LOCK =>
CPLLPD_o <= '0';
if CPLLLOCK_clk_free = '1' then
GTTXRESET_o <= '1';
GTRXRESET_o <= '1';
timeout_cnt <= to_unsigned(c_RESET_TIMEOUT, 16);
state <= TX_RESET_TIMER_WAIT;
end if;
when TX_RESET_TIMER_WAIT =>
timeout_cnt <= timeout_cnt - 1;
if timeout_cnt = 0 then
GTTXRESET_o <= '0';
GTRXRESET_o <= '0';
state <= TX_ACTIVE_WAIT;
end if;
when TX_ACTIVE_WAIT =>
if tx_active_clk_free = '1' then
state <= TX_RESET_DONE_WAIT;
TXUSERRDY_o <= '1';
end if;
when TX_RESET_DONE_WAIT =>
if TXRESETDONE_clk_free = '1' then
state <= CDR_WAIT_LOCK;
end if;
when CDR_WAIT_LOCK =>
if RXCDRLOCK_clk_free = '1' then
RXPROGDIVRESET_o <= '0';
state <= RX_ACTIVE_WAIT;
end if;
when RX_ACTIVE_WAIT =>
if rx_active_clk_free = '1' then
state <= RX_RESET_DONE_WAIT;
RXUSERRDY_o <= '1';
end if;
when RX_RESET_DONE_WAIT =>
if RXRESETDONE_clk_free = '1' then
state <= DONE;
end if;
when DONE =>
done_o <= '1';
end case;
end if;
end if;
end process;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use work.gencores_pkg.all;
entity wr_gthe4_rx_buffer_bypass is
port
(
clk_free_i : in std_logic;
rst_i : in std_logic;
RXUSRCLK2_i : in std_logic;
RXRESETDONE_i : in std_logic;
RXDLYSRESET_o : out std_logic;
RXSYNCDONE_i : in std_logic;
done_o : out std_logic
);
end wr_gthe4_rx_buffer_bypass;
architecture rtl of wr_gthe4_rx_buffer_bypass is
type t_state is (WAIT_RESTART, ASSERT_DLY_RESET, WAIT_SYNC_DONE, DONE);
signal state : t_state;
signal rst_rxusrclk2 : std_logic;
signal RXRESETDONE_clk_free : std_logic;
signal RXSYNCDONE_clk_free_p1 : std_logic;
signal done_int : std_logic;
begin
U_Sync_Reset : gc_sync_ffs
port map (
clk_i => RXUSRCLK2_i,
rst_n_i => '1',
data_i => rst_i,
synced_o => rst_rxusrclk2);
U_Sync_Done : gc_sync_ffs
port map (
clk_i => clk_free_i,
rst_n_i => '1',
data_i => done_int,
synced_o => done_o);
-- RX dly align procedure:
--
-- start on RXRESETDONE
-- rxdlysreset_out = 1
-- rxdlysreset_out = 0
-- wait for RE of rxsyncdone
p_rx_buffer_bypass : process(RXUSRCLK2_i)
begin
if rising_edge(RXUSRCLK2_i) then
if rst_rxusrclk2 = '1' then
state <= WAIT_RESTART;
RXDLYSRESET_o <= '0';
done_int <= '0';
else
RXDLYSRESET_o <= '0';
done_int <= '0';
case state is
when WAIT_RESTART =>
if RXRESETDONE_i = '1' then
state <= ASSERT_DLY_RESET;
end if;
when ASSERT_DLY_RESET =>
RXDLYSRESET_o <= '1';
state <= WAIT_SYNC_DONE;
when WAIT_SYNC_DONE =>
RXDLYSRESET_o <= '0';
if RXSYNCDONE_i = '1' then
state <= DONE;
end if;
when DONE =>
done_int <= '1';
end case;
end if;
end if;
end process;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use work.gencores_pkg.all;
entity wr_gthe4_tx_buffer_bypass is
port
(
clk_free_i : in std_logic;
rst_i : in std_logic;
TXUSRCLK2_i : in std_logic;
TXRESETDONE_i : in std_logic;
TXDLYSRESET_o : out std_logic;
TXSYNCDONE_i : in std_logic;
done_o : out std_logic
);
end wr_gthe4_tx_buffer_bypass;
architecture rtl of wr_gthe4_tx_buffer_bypass is
type t_state is (WAIT_RESTART, ASSERT_DLY_RESET, WAIT_SYNC_DONE, DONE);
signal rst_txusrclk2 : std_logic;
signal TXRESETDONE_clk_txusr : std_logic;
signal TXSYNCDONE_clk_txusr_p1 : std_logic;
signal TXDLYSRESET_int : std_logic;
signal done_int : std_logic;
signal state : t_state;
signal rst_n : std_logic;
begin
rst_n <= not rst_i;
U_Sync_Reset : entity work.gc_reset_synchronizer
generic map (
g_reset_active_out => '1')
port map (
clk_i => TXUSRCLK2_i,
rst_n_a_i => rst_n,
rst_synced_o => rst_txusrclk2);
U_Sync_Done : gc_sync_ffs
port map (
clk_i => clk_free_i,
rst_n_i => rst_n,
data_i => done_int,
synced_o => done_o);
U_Sync_TXRESETDONE : gc_sync_ffs
port map (
clk_i => TXUSRCLK2_i,
rst_n_i => rst_n,
data_i => TXRESETDONE_i,
synced_o => TXRESETDONE_clk_txusr);
U_Sync_TXSYNCDONE : gc_sync_ffs
port map (
clk_i => TXUSRCLK2_i,
rst_n_i => rst_n,
data_i => TXSYNCDONE_i,
ppulse_o => TXSYNCDONE_clk_txusr_p1);
-- TX dly align procedure:
--
-- start on TXRESETDONE
-- txdlysreset_out = 1
-- txdlysreset_out = 0
-- wait for RE of txsyncdone
p_tx_buffer_bypass : process(TXUSRCLK2_i, rst_txusrclk2)
begin
if rst_txusrclk2 = '1' then
state <= WAIT_RESTART;
TXDLYSRESET_int <= '0';
done_int <= '0';
elsif rising_edge(TXUSRCLK2_i) then
if rst_txusrclk2 = '1' then
state <= WAIT_RESTART;
TXDLYSRESET_int <= '0';
done_int <= '0';
else
TXDLYSRESET_int <= '0';
done_int <= '0';
case state is
when WAIT_RESTART =>
if TXRESETDONE_i = '1' then
state <= ASSERT_DLY_RESET;
end if;
when ASSERT_DLY_RESET =>
TXDLYSRESET_int <= '1';
state <= WAIT_SYNC_DONE;
when WAIT_SYNC_DONE =>
TXDLYSRESET_int <= '0';
if TXSYNCDONE_clk_txusr_p1 = '1' then
state <= DONE;
end if;
when DONE =>
done_int <= '1';
end case;
end if;
end if;
end process;
txdlysreset_o <= TXDLYSRESET_int;
end rtl;
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment