Commit a224e333 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski Committed by Tristan Gingold

reverse oversampled DDMTD mode

wr_core: add generic for reverse DDMTD operation
wr_gtx_phy_kintex7_lp: make 'reversed' DDMTD operation a generic
parent 1b0ac87a
Pipeline #4839 canceled with stage
......@@ -6,7 +6,6 @@
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-02-25
-- Last update: 2019-06-18
-- Platform : FPGA-generic
-- Standard : VHDL '93
-------------------------------------------------------------------------------
......@@ -48,14 +47,12 @@ entity dmtd_sampler is
-- (at the cost of detector bandwidth)
g_divide_input_by_2 : boolean := false;
-- reversed mode: samples clk_dmtd with clk_in.
-- reversed mode: samples clk_dmtd_i with clk_in_i.
g_reverse : boolean := false;
g_oversample : boolean := false;
g_oversample_factor : integer := 1;
g_is_ref : boolean := false
-- enables oversampling: in this case, clk_dmtd_over_i is used and the
-- divider for picking the DDMTD tags must be supplied through r_oversample_div_i.
g_with_oversampling : boolean := false
);
port (
-- input clock
......@@ -67,8 +64,12 @@ entity dmtd_sampler is
clk_dmtd_i : in std_logic;
clk_dmtd_over_i : in std_logic := '0';
-- Sync signal. if g_with_oversampling == TRUE, must be provided in the
-- lk_dmtd_over_i clock domain
sync_p1_i : in std_logic := '0';
r_oversample_div_i : in std_logic_vector(5 downto 0) := (others => '0');
clk_sampled_o : out std_logic
);
......@@ -87,51 +88,42 @@ architecture rtl of dmtd_sampler is
attribute keep of clk_i_d2 : signal is "true";
attribute keep of clk_i_d3 : signal is "true";
signal div_sreg : std_logic_vector(g_oversample_factor-1 downto 0) :=
std_logic_vector(to_unsigned(1, g_oversample_factor));
signal sync_p1_over_p : std_logic;
signal over_div_cnt : unsigned(5 downto 0);
signal sync_p1_d : std_logic;
signal over_div_p : std_logic;
signal en_i_d0 : std_logic;
begin -- rtl
gen_oversampled : if(g_oversample) generate
gen_input_div2 : if(g_divide_input_by_2 = true) generate
p_divide_input_clock : process(clk_in_i)
begin
if rising_edge(clk_in_i) then
clk_in <= not clk_in;
end if;
end process;
end generate gen_input_div2;
gen_straight_oversampled : if( g_with_oversampling = true and g_reverse = false ) generate
gen_input_straight : if(g_divide_input_by_2 = false) generate
clk_in <= clk_in_i;
end generate gen_input_straight;
gc_sync_ffs_1: entity work.gc_sync_ffs
port map (
clk_i => clk_dmtd_over_i,
rst_n_i => '1',
data_i => sync_p1_i,
synced_o => open,
npulse_o => open,
ppulse_o => sync_p1_over_p);
clk_in <= clk_in_i;
process(clk_dmtd_over_i)
begin
if rising_edge(clk_dmtd_over_i) then
if (sync_p1_over_p = '1') then
div_sreg(0) <= '1';
div_sreg(g_oversample_factor-1 downto 1) <= (others => '0');
sync_p1_d <= sync_p1_i;
if sync_p1_d = '1' then
over_div_cnt <= (others => '0');
over_div_p <= '1';
elsif over_div_cnt = unsigned(r_oversample_div_i) then
over_div_cnt <= (others => '0');
over_div_p <= '1';
else
div_sreg <= div_sreg(0) & div_sreg(div_sreg'length-1 downto 1);
over_div_cnt <= over_div_cnt + 1;
over_div_p <= '0';
end if;
clk_i_d0 <= clk_in;
clk_i_d0 <= clk_in;
if div_sreg(0) = '1' then
-- the actual DDMTD is right below
if over_div_p = '1' then
clk_i_d1 <= clk_i_d0;
end if;
end if;
end process;
......@@ -143,10 +135,10 @@ begin -- rtl
end if;
end process;
end generate gen_oversampled;
end generate gen_straight_oversampled;
gen_straight : if(g_reverse = false and g_oversample = false ) generate
gen_straight_nonoversampled : if(g_reverse = false and g_with_oversampling = false ) generate
gen_input_div2 : if(g_divide_input_by_2 = true) generate
p_divide_input_clock : process(clk_in_i)
......@@ -164,16 +156,17 @@ begin -- rtl
p_the_dmtd_itself : process(clk_dmtd_i)
begin
if rising_edge(clk_dmtd_i) then
clk_i_d0 <= clk_in and en_i;
clk_i_d1 <= clk_i_d0;
clk_i_d0 <= clk_in;
en_i_d0 <= en_i;
clk_i_d1 <= not( clk_i_d0 and en_i_d0 );
clk_i_d2 <= clk_i_d1;
clk_i_d3 <= clk_i_d2;
end if;
end process;
end generate gen_straight;
end generate gen_straight_nonoversampled;
gen_reverse : if(g_reverse = true and g_oversample = false) generate
gen_reverse_nonoversampled : if(g_reverse = true and g_with_oversampling = false) generate
assert (not g_divide_input_by_2) report "dmtd_with_deglitcher: g_reverse implies g_divide_input_by_2 == false" severity failure;
......@@ -182,7 +175,9 @@ begin -- rtl
p_the_dmtd_itself : process(clk_in)
begin
if rising_edge(clk_in) then
clk_i_d0 <= clk_dmtd_i;
if en_i = '1' then
clk_i_d0 <= clk_dmtd_i;
end if;
clk_i_d1 <= clk_i_d0;
end if;
end process;
......@@ -196,8 +191,8 @@ begin -- rtl
end if;
end process;
end generate gen_reverse;
end generate gen_reverse_nonoversampled;
clk_sampled_o <= clk_i_d3;
end rtl;
......@@ -6,7 +6,6 @@
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-02-25
-- Last update: 2023-06-02
-- Platform : FPGA-generic
-- Standard : VHDL '93
-------------------------------------------------------------------------------
......@@ -18,20 +17,20 @@
--
-- Copyright (c) 2009 - 2011 CERN
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details.
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
......@@ -56,18 +55,21 @@ entity dmtd_with_deglitcher is
-- the following formula:
-- g_counter_bits = log2(f_in / abs(f_in - f_dmtd)) + 1
g_counter_bits : natural := 17;
g_chipscope : boolean := false;
-- Divides the inputs by 2 (effectively passing the clock through a flip flop)
-- before it gets to the DMTD, effectively removing Place&Route warnings
-- (at the cost of detector bandwidth)
g_divide_input_by_2 : boolean := false;
-- enables oversampling mode. In this case, the oversampling divider must
-- be provided through r_oversample_div_i port.
g_with_oversampling : boolean := false;
g_oversample : boolean := false;
g_oversample_factor : integer := 1;
-- enables jitter measurement statistic registers (r_low_o, r_high_o,
-- r_samples_o, r_minmax_sel_i, r_reset_i ). They take some resources, so use with care.
g_with_jitter_stats_regs : boolean := false;
-- reversed mode: samples clk_dmtd with clk_in.
-- reversed mode: samples clk_dmtd_i with clk_in_i.
g_reverse : boolean := false;
-- uses an external DDMTD sampler and just deglitches and generates tags
......@@ -99,21 +101,28 @@ entity dmtd_with_deglitcher is
-- [clk_dmtd_i] counter resync output, pulses when free_cntr == 0
resync_p_o : out std_logic;
-- DMTD clock enable, active high. Can be used to reduce the DMTD sampling
-- frequency - for example, two 10 MHz signals cannot be sampled directly
-- with a 125 MHz clock, but it's possible with a 5 MHz reference, obtained
-- by asserting clk_dmtd_en_i every 25 clk_dmtd_i cycles.
-- [clk_dmtd_over_i] counter resync input (oversampled mode)
resync_p_over_i : in std_logic := '0';
clk_dmtd_en_i : in std_logic := '1';
-- CONTROL REGISTERS (wired from SoftPLL)
-- [clk_dmtd_i] deglitcher threshold
deglitch_threshold_i : in std_logic_vector(15 downto 0);
r_deglitch_threshold_i : in std_logic_vector(15 downto 0);
-- fractional mode input clock divider
r_oversample_in_div_i : in std_logic_vector(5 downto 0) := (others => '0');
-- fractional mode PPS alignment clock divider
r_oversample_pps_div_i : in std_logic_vector(5 downto 0) := (others => '0');
-- [clk_dmtd_i] raw DDMTD output (for debugging purposes)
dbg_dmtdout_o : out std_logic;
-- [clk_in_i] 1 PPS input for fractional clock-to-PPS alignment.
pps_p1_i : in std_logic := '0';
-- [clk_sys_i] deglitched edge tag value
tag_o : out std_logic_vector(g_counter_bits-1 downto 0);
tag_pps_mark_o : out std_logic;
-- [clk_sys_i] pulse indicates new phase tag on tag_o
tag_stb_p1_o : out std_logic;
......@@ -123,7 +132,7 @@ end dmtd_with_deglitcher;
architecture rtl of dmtd_with_deglitcher is
type t_state is (WAIT_STABLE_0, WAIT_EDGE, GOT_EDGE);
signal state : t_state;
......@@ -131,8 +140,6 @@ architecture rtl of dmtd_with_deglitcher is
signal stab_cntr : unsigned(15 downto 0);
signal free_cntr : unsigned(g_counter_bits-1 downto 0);
signal s_one : std_logic;
signal clk_sampled : std_logic;
signal new_edge_sreg : std_logic_vector(5 downto 0);
......@@ -141,7 +148,7 @@ architecture rtl of dmtd_with_deglitcher is
signal tag_int : unsigned(g_counter_bits-1 downto 0);
signal resync_p_dmtd : std_logic;
begin -- rtl
U_Sync_Resync_Pulse : gc_sync_ffs
......@@ -159,15 +166,16 @@ begin -- rtl
generic map (
g_divide_input_by_2 => g_divide_input_by_2,
g_reverse => g_reverse,
g_oversample_factor => g_oversample_factor,
g_oversample => g_oversample)
g_with_oversampling => g_with_oversampling)
port map (
clk_in_i => clk_in_i,
sync_p1_i => '0',
en_i => '1',
sync_p1_i => resync_p_over_i,
clk_dmtd_over_i => clk_dmtd_over_i,
clk_dmtd_i => clk_dmtd_i,
clk_sampled_o => clk_sampled);
clk_sampled_o => clk_sampled,
r_oversample_div_i => r_oversample_in_div_i );
end generate gen_builtin;
gen_externally_sampled : if g_use_sampled_clock generate
......@@ -185,8 +193,9 @@ begin -- rtl
state <= WAIT_STABLE_0;
free_cntr <= (others => '0');
new_edge_sreg <= (others => '0');
elsif(clk_dmtd_en_i = '1') then
else
free_cntr <= free_cntr + 1;
case state is
when WAIT_STABLE_0 => -- out-of-sync
new_edge_sreg <= '0' & new_edge_sreg(new_edge_sreg'length-1 downto 1);
......@@ -198,7 +207,7 @@ begin -- rtl
end if;
-- DMTD output stable counter hit the LOW level threshold?
if stab_cntr = unsigned(deglitch_threshold_i) then
if stab_cntr = unsigned(r_deglitch_threshold_i) then
state <= WAIT_EDGE;
end if;
......@@ -214,7 +223,7 @@ begin -- rtl
tag_int <= tag_int + 1;
end if;
if stab_cntr = unsigned(deglitch_threshold_i) then
if stab_cntr = unsigned(r_deglitch_threshold_i) then
state <= WAIT_STABLE_0;
tag_o <= std_logic_vector(tag_int);
new_edge_sreg <= (others => '1');
......@@ -225,7 +234,7 @@ begin -- rtl
stab_cntr <= stab_cntr + 1;
end if;
end case;
end if;
end if;
......
......@@ -214,6 +214,17 @@ architecture behavioral of ep_rx_pcs_16bit is
signal pcs_valid_int : std_logic;
signal timestamp_pending : std_logic_vector(2 downto 0) := "000";
attribute mark_debug : string;
attribute mark_debug of pcs_fab_out : signal is "true";
attribute mark_debug of d_err : signal is "true";
attribute mark_debug of d_data : signal is "true";
attribute mark_debug of d_is_idle : signal is "true";
attribute mark_debug of d_is_k : signal is "true";
attribute mark_debug of odd_reception : signal is "true";
attribute mark_debug of d_is_k_shrunk : signal is "true";
attribute mark_debug of rx_synced : signal is "true";
attribute mark_debug of rx_state : signal is "true";
signal mdio_wr_spec_rx_cal_stat_rx_clk : std_logic;
signal mdio_wr_spec_cal_crst_rx_clk : std_logic;
......
......@@ -480,6 +480,9 @@ architecture syn of wr_endpoint is
TRIG3 : in std_logic_vector(31 downto 0));
end component;
attribute mark_debug : string;
attribute mark_debug of rmon_events_o : signal is "true";
begin
U_Sync_phy_rdy_sysclk : gc_sync_ffs
......
......@@ -354,7 +354,6 @@ begin -- rtl
rst_n_sysclk_i => rst_n_i,
clk_dmtd_i => clk_dmtd_i,
clk_dmtd_en_i => '1',
clk_sys_i => clk_sys_i,
clk_in_i => clk_ref_i(i),
......@@ -364,39 +363,40 @@ begin -- rtl
tag_o => tags(i),
tag_stb_p1_o => tags_p(i),
deglitch_threshold_i => deglitch_thr_slv);
r_deglitch_threshold_i => deglitch_thr_slv);
end generate gen_ref_dmtds;
gen_feedback_dmtds : for i in 0 to g_num_outputs-1 generate
signal resync_p : std_logic;
begin
resync_p <= f_pick(i = 0, '0', fb_resync_out(0));
DMTD_FB : entity work.dmtd_with_deglitcher
generic map (
g_counter_bits => g_tag_bits,
g_divide_input_by_2 => g_divide_input_by_2,
g_reverse => g_reverse_dmtds,
g_use_sampled_clock => false,
g_oversample => g_aux_config(i).oversample,
g_oversample_factor => g_aux_config(i).divider)
g_with_oversampling => g_aux_config(i).oversample)
port map (
rst_n_dmtdclk_i => rst_dmtd_n_i,
rst_n_sysclk_i => rst_n_i,
clk_dmtd_i => clk_dmtd_i,
clk_dmtd_en_i => '1',
clk_dmtd_over_i => clk_dmtd_over_i,
clk_sys_i => clk_sys_i,
clk_in_i => clk_fb_i(i),
resync_p_a_i => fb_resync_out(0),
resync_p_a_i => resync_p,
resync_p_o => fb_resync_out(i),
tag_o => tags(i+g_num_ref_inputs),
tag_stb_p1_o => tags_p(i+g_num_ref_inputs),
deglitch_threshold_i => deglitch_thr_slv,
r_deglitch_threshold_i => deglitch_thr_slv,
dbg_dmtdout_o => open,
dbg_clk_d3_o => debug_o(i)); --debug_o(4));
......@@ -418,7 +418,6 @@ begin -- rtl
rst_n_dmtdclk_i => rst_dmtd_n_i,
rst_n_sysclk_i => rst_n_i,
clk_dmtd_i => clk_dmtd_i,
clk_dmtd_en_i => '1',
clk_sys_i => clk_sys_i,
clk_in_i => clk_ext_mul_i(I),
......@@ -428,7 +427,7 @@ begin -- rtl
tag_o => tags(g_num_ref_inputs + g_num_outputs + I),
tag_stb_p1_o => tags_p(g_num_ref_inputs + g_num_outputs + I),
deglitch_threshold_i => deglitch_thr_slv);
r_deglitch_threshold_i => deglitch_thr_slv);
end generate gen_ext_dmtds;
......
......@@ -99,6 +99,7 @@ entity wr_core is
g_aux_sdb : t_sdb_device := c_wrc_periph3_sdb;
g_softpll_enable_debugger : boolean := false;
g_softpll_use_sampled_ref_clocks : boolean := false;
g_softpll_reverse_dmtds : boolean := false;
g_vuart_fifo_size : integer := 1024;
g_pcs_16bit : boolean := false;
g_records_for_phy : boolean := false;
......@@ -639,8 +640,8 @@ begin
-----------------------------------------------------------------------------
U_SOFTPLL : entity work.xwr_softpll_ng
generic map(
g_reverse_dmtds => false,
g_divide_input_by_2 => not g_pcs_16bit,
g_reverse_dmtds => g_softpll_reverse_dmtds,
g_divide_input_by_2 => not g_pcs_16bit and not g_softpll_reverse_dmtds,
g_with_debug_fifo => g_softpll_enable_debugger,
g_tag_bits => 22,
g_dac_bits => g_dac_bits,
......
......@@ -421,6 +421,7 @@ package wrcore_pkg is
g_aux_sdb : t_sdb_device := c_wrc_periph3_sdb;
g_softpll_enable_debugger : boolean := false;
g_softpll_use_sampled_ref_clocks : boolean := false;
g_softpll_reverse_dmtds : boolean := false;
g_vuart_fifo_size : integer := 1024;
g_pcs_16bit : boolean := false;
g_records_for_phy : boolean := false;
......@@ -577,6 +578,7 @@ package wrcore_pkg is
g_aux_sdb : t_sdb_device := c_wrc_periph3_sdb;
g_softpll_enable_debugger : boolean := false;
g_softpll_use_sampled_ref_clocks : boolean := false;
g_softpll_reverse_dmtds : boolean := false;
g_vuart_fifo_size : integer := 1024;
g_pcs_16bit : boolean := false;
g_records_for_phy : boolean := false;
......
......@@ -97,6 +97,7 @@ entity xwr_core is
g_aux_sdb : t_sdb_device := c_wrc_periph3_sdb;
g_softpll_enable_debugger : boolean := false;
g_softpll_use_sampled_ref_clocks : boolean := false;
g_softpll_reverse_dmtds : boolean := false;
g_vuart_fifo_size : integer := 1024;
g_pcs_16bit : boolean := false;
g_records_for_phy : boolean := false;
......@@ -314,6 +315,7 @@ begin
g_aux_sdb => g_aux_sdb,
g_softpll_enable_debugger => g_softpll_enable_debugger,
g_softpll_use_sampled_ref_clocks => g_softpll_use_sampled_ref_clocks,
g_softpll_reverse_dmtds => g_softpll_reverse_dmtds,
g_vuart_fifo_size => g_vuart_fifo_size,
g_pcs_16bit => g_pcs_16bit,
g_records_for_phy => g_records_for_phy,
......
......@@ -51,7 +51,9 @@ entity wr_gtx_phy_kintex7_lp is
generic (
-- set to non-zero value to speed up the simulation by reducing some delays
g_simulation : integer := 0;
g_id : integer := 0
g_id : integer := 0;
g_reverse_ddmtds : boolean := false
);
port (
......@@ -277,7 +279,7 @@ architecture rtl of wr_gtx_phy_kintex7_lp is
signal ddmtd_mask_cnt_sreg_fedge : std_logic_vector(3 downto 0);
signal ddmtd_mask_sync_62m5 : std_logic;
signal ddmtd_mask_sync_250m, ddmtd_mask_sync_250m_d, ddmtd_mask_sync_250m_p : std_logic;
signal ddmtd_mask_sync_250m, ddmtd_mask_sync_250m_d, ddmtd_mask_sync_250m_p, ddmtd_mask_sync_250m_p_fedge : std_logic;
signal cpll_reset, cpll_locked : std_logic;
......@@ -349,17 +351,17 @@ begin -- rtl
U_Sampler_RX : entity work.dmtd_sampler
generic map (
g_divide_input_by_2 => false,
g_reverse => false)
g_reverse => g_reverse_ddmtds)
port map (
clk_in_i => clk_rx_250m,
en_i => ddmtd_mask_cnt_sreg_fedge(3),
en_i => f_pick(g_reverse_ddmtds, ddmtd_mask_sync_250m_p, ddmtd_mask_sync_250m_p_fedge),
clk_dmtd_i => clk_dmtd_i,
clk_sampled_o => rx_rec_clk_sampled);
U_Sampler_TX : entity work.dmtd_sampler
generic map (
g_divide_input_by_2 => false,
g_reverse => false)
g_reverse => g_reverse_ddmtds)
port map (
clk_in_i => tx_out_clk_div2,
clk_dmtd_i => clk_dmtd_i,
......@@ -368,7 +370,7 @@ begin -- rtl
U_Sampler_REFCLK : entity work.dmtd_sampler
generic map (
g_divide_input_by_2 => false,
g_reverse => false)
g_reverse => g_reverse_ddmtds)
port map (
clk_in_i => clk_ref_i,
clk_dmtd_i => clk_dmtd_i,
......@@ -392,18 +394,14 @@ begin -- rtl
elsif rising_edge(clk_rx_250m) then
ddmtd_mask_sync_250m <= ddmtd_mask_sync_62m5; -- need stringent setup constraint for this one
ddmtd_mask_sync_250m_d <= ddmtd_mask_sync_250m;
ddmtd_mask_sync_250m_p <= ddmtd_mask_sync_250m and not ddmtd_mask_sync_250m_d;
ddmtd_mask_sync_250m_p <= ddmtd_mask_sync_250m xor ddmtd_mask_sync_250m_d;
end if;
end process;
process(clk_rx_250m)
begin
if falling_edge(clk_rx_250m) then
if ddmtd_mask_sync_250m_p = '1' then
ddmtd_mask_cnt_sreg_fedge <= "1000";
else
ddmtd_mask_cnt_sreg_fedge <= ddmtd_mask_cnt_sreg_fedge(0) & ddmtd_mask_cnt_sreg_fedge(3 downto 1);
end if;
ddmtd_mask_sync_250m_p_fedge <= ddmtd_mask_sync_250m_p;
end if;
end process;
......
......@@ -13,8 +13,6 @@ module wr_1000basex_phy_tx_path_model
input [15:0] tx_data_i,
input [1:0] tx_k_i,
input [19:0] tx_raw_i,
input [15:0] tx_data_i,
input [1:0] tx_k_i,
input tx_is_raw_i,
output tx_disparity_o,
......@@ -33,9 +31,6 @@ module wr_1000basex_phy_tx_path_model
reg clk_tx = 0;
<<<<<<< HEAD
=======
function bit[31:0] f_reverse(bit[31:0] x, int n);
bit [31:0] rv;
......@@ -46,10 +41,6 @@ module wr_1000basex_phy_tx_path_model
return rv;
endfunction // f_reverse
>>>>>>> origin/Virtex5_PHY_fix
always@(posedge clk_ref_i)
if(pll_en)
begin
......
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