Commit 74e929a1 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski Committed by Grzegorz Daniluk

platform: added low phase drift GTX PHY for Virtex6

parent f0f79db0
......@@ -10,7 +10,12 @@ elif (syn_device[0:4].upper()=="XC6V"): # Virtex6
files.extend(["virtex6/wr_gtx_phy_virtex6.vhd",
"virtex6/whiterabbitgtx_wrapper_gtx.vhd",
"virtex6/gtp_phase_align_virtex6.vhd",
"virtex6/gtx_reset.vhd"])
"virtex6/gtx_reset.vhd",
"virtex6-low-phase-drift/gtx_comma_detect_lp.vhd",
"virtex6-low-phase-drift/gtx_tx_reset_lp.vhd",
"virtex6-low-phase-drift/whiterabbitgtx_wrapper_gtx_lp.vhd",
"virtex6-low-phase-drift/wr_gtx_phy_virtex6_lp.vhd"])
elif (syn_device[0:4].upper()=="XC5V"): # Virtex5
files.extend(["virtex5/wr_gtp_phy_virtex5.vhd",
"virtex5/whiterabbit_gtp_wrapper_tile_virtex5.vhd",
......
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity gtx_comma_detect_lp is
generic (
g_ID : integer
);
port (
clk_rx_i : in std_logic;
rst_i : in std_logic;
rx_data_raw_i : in std_logic_vector(19 downto 0);
link_up_o : out std_logic;
aligned_o : out std_logic;
rx_data_i : in std_logic_vector(15 downto 0);
rx_k_i : in std_logic_vector(1 downto 0);
rx_error_i : in std_logic
);
end gtx_comma_detect_lp;
architecture rtl of gtx_comma_detect_lp is
type t_state is (SYNC_LOST, SYNC_CHECK, SYNC_ACQUIRED);
constant c_IDLE_LENGTH_UP : integer := 40;
constant c_IDLE_LENGTH_LOSS : integer := 1000;
constant c_COMMA_SHIFT_WE_WANT : std_logic_vector(6 downto 0) := "0110000";
-- fixme
signal rx_data_d0 : std_logic_vector(19 downto 0);
signal rx_data_merged : std_logic_vector(49 downto 0);
signal first_comma : std_logic_vector(4 downto 0);
signal cnt : unsigned(15 downto 0);
signal state : t_state;
signal comma_found : std_logic_vector(19 downto 0);
component chipscope_icon
port (
CONTROL0 : inout std_logic_vector(35 downto 0));
end component;
component chipscope_ila
port (
CONTROL : inout std_logic_vector(35 downto 0);
CLK : in std_logic;
TRIG0 : in std_logic_vector(31 downto 0);
TRIG1 : in std_logic_vector(31 downto 0);
TRIG2 : in std_logic_vector(31 downto 0);
TRIG3 : in std_logic_vector(31 downto 0));
end component;
signal CONTROL : std_logic_vector(35 downto 0);
signal TRIG0 : std_logic_vector(31 downto 0);
signal TRIG1 : std_logic_vector(31 downto 0);
signal TRIG2 : std_logic_vector(31 downto 0);
signal TRIG3 : std_logic_vector(31 downto 0);
function f_onehot_encode (x : std_logic_vector; output_bits : integer)return std_logic_vector is
variable rv : std_logic_vector(output_bits-1 downto 0);
begin
for i in 0 to x'length-1 loop
if x(i) = '1' then
rv := std_logic_vector(to_unsigned(i, output_bits));
return rv;
end if;
end loop;
return std_logic_vector(to_unsigned(0, output_bits));
end f_onehot_encode;
constant c_K28_5_PLUS : std_logic_vector(9 downto 0) := "1010000011";
signal comma_pos : std_logic_vector(4 downto 0);
signal prev_comma_pos : std_logic_vector(4 downto 0);
signal prev_comma_pos_valid : std_logic;
signal comma_pos_valid : std_logic;
signal link_up : std_logic;
signal link_aligned : std_logic;
begin
gen1 : if g_id = 0 generate
--chipscope_icon_1 : chipscope_icon
-- port map (
-- CONTROL0 => CONTROL);
--chipscope_ila_1 : chipscope_ila
-- port map (
-- CONTROL => CONTROL,
-- CLK => clk_rx_i,
-- TRIG0 => TRIG0,
-- TRIG1 => TRIG1,
-- TRIG2 => TRIG2,
-- TRIG3 => TRIG3);
--trig0 (19 downto 0) <= rx_data_raw_i;
--trig1 (19 downto 0) <= comma_found;
--trig0(20) <= comma_pos_valid;
--trig0(21) <= link_up;
--trig0(22) <= link_aligned;
--trig2(15 downto 0) <= rx_data_i;
--trig2(17 downto 16) <= rx_k_i;
--trig2(18) <= rx_error_i;
end generate gen1;
process(clk_rx_i)
begin
if rising_edge(clk_rx_i) then
if rst_i = '1' then
comma_found <= (others => '0');
else
rx_data_d0 <= rx_data_raw_i;
rx_data_merged(39 downto 0) <= rx_data_d0 & rx_data_raw_i;
for i in 0 to 19 loop
if rx_data_merged(i + 9 downto i) = c_K28_5_PLUS or
rx_data_merged(i + 9 downto i) = (not c_K28_5_PLUS) then
comma_found(i) <= '1';
else
comma_found(i) <= '0';
end if;
end loop;
comma_pos <= f_onehot_encode(comma_found, comma_pos'length);
if unsigned(comma_found) /= 0 then
comma_pos_valid <= '1';
else
comma_pos_valid <= '0';
end if;
end if;
end if;
end process;
process(clk_rx_i)
begin
if rising_edge(clk_rx_i) then
if rst_i = '1' then
state <= SYNC_LOST;
else
case state is
when SYNC_LOST =>
link_up <= '0';
link_aligned <= '0';
if comma_pos_valid = '1' then
first_comma <= comma_pos;
state <= SYNC_CHECK;
cnt <= (others => '0');
end if;
when SYNC_CHECK =>
if comma_pos = first_comma and comma_pos_valid = '1' then
if cnt < 2 * c_IDLE_LENGTH_UP then
cnt <= cnt + 4;
end if;
elsif cnt > 0 then
cnt <= cnt - 1;
end if;
if cnt >= c_IDLE_LENGTH_UP then
state <= SYNC_ACQUIRED;
cnt <= (others => '0');
end if;
when SYNC_ACQUIRED =>
link_up <= '1';
if(comma_pos_valid = '1' and comma_pos = first_comma) then
if(unsigned(comma_pos) = 0) then
link_aligned <= '1';
end if;
cnt <= (others => '0');
else
cnt <= cnt + 1;
if cnt = c_IDLE_LENGTH_LOSS then
state <= SYNC_LOST;
end if;
end if;
end case;
end if;
end if;
end process;
aligned_o <= link_aligned;
link_up_o <= link_up;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
entity gtx_tx_reset_lp is
port (
-- uncorrelated clock (we use DDMTD here) to ensure repeated resetting of
-- the TX path will sooner or later get to the TX divider bin we want
clk_dmtd_i : in std_logic;
-- TX clock
clk_tx_i : in std_logic;
-- Master reset (clk_tx_i domain)
rst_i : in std_logic;
-- Sw reset (treat as async)
rst_sw_i : in std_logic;
-- TX PLL lock detect
txpll_lockdet_i : in std_logic;
-- GTX TX divider reset
gtx_test_o : out std_logic_vector(12 downto 0);
-- GTX TX path reset (async)
gtx_tx_reset_o : out std_logic;
-- GTX TX reset done (also async)
gtx_tx_reset_done_i : in std_logic;
-- DOne indication
done_o : out std_logic
);
end gtx_tx_reset_lp;
architecture behavioral of gtx_tx_reset_lp is
type t_state is (IDLE, PAUSE, FIRST_RST, PAUSE2, SECOND_RST, DONE);
signal state : t_state;
signal counter : unsigned(15 downto 0);
begin -- behavioral
process(clk_tx_i)
begin
if rising_edge(clk_tx_i) then
if rst_i = '1' then
state <= IDLE;
counter <= (others => '0');
else
case state is
when IDLE =>
counter <= (others => '0');
gtx_test_o <= "1000000000000";
if(txpll_lockdet_i = '1') then
state <= PAUSE;
end if;
when PAUSE =>
counter <= counter + 1;
gtx_test_o <= "1000000000000";
if(counter = 1024) then
state <= FIRST_RST;
end if;
when FIRST_RST =>
counter <= counter + 1;
gtx_test_o <= "1000000000010";
if(counter = 1024 + 256) then
state <= PAUSE2;
end if;
when PAUSE2 =>
counter <= counter + 1;
gtx_test_o <= "1000000000000";
if(counter = 1024 + 2*256) then
state <= SECOND_RST;
end if;
when SECOND_RST =>
counter <= counter + 1;
gtx_test_o <= "1000000000010";
if(counter = 1024 + 3*256) then
state <= DONE;
end if;
when DONE =>
gtx_test_o <= "1000000000000";
end case;
end if;
end if;
end process;
U_SyncResetSW : gc_sync_ffs
port map
(
clk_i => clk_dmtd_i,
rst_n_i => '1',
data_i => rst_sw_i,
ppulse_o => gtx_tx_reset_o);
U_SyncTxResetDone : gc_sync_ffs
port map
(
clk_i => clk_tx_i,
rst_n_i => '1',
data_i => gtx_tx_reset_done_i,
synced_o => done_o);
end behavioral;
This diff is collapsed.
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