diff --git a/libraries/io/aduh/src/vhdl/lvdsh_dd_phs4.vhd b/libraries/io/aduh/src/vhdl/lvdsh_dd_phs4.vhd index 385070755e568427ed87dca798f003f535908e31..ff7b5771c14b9718b1812a151b02569c1f89824a 100644 --- a/libraries/io/aduh/src/vhdl/lvdsh_dd_phs4.vhd +++ b/libraries/io/aduh/src/vhdl/lvdsh_dd_phs4.vhd @@ -24,9 +24,11 @@ USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; USE common_lib.common_pkg.ALL; +-- Author: Eric Kooistra -- Purpose: Detect the wide band factor phase 0, 1, 2 or 3 of the 200 MHz -- dp_clk using the rising and falling edge of the double data rate --- 400 MHz in_clk clock. +-- 400 MHz in_clk clock. The aim is to detect same sample phase +-- after each restart of the ADC, without the need for calibration. -- Description: -- The edges of the in_clk occur at the 800 MHz sample rate of the ADC. The -- in_clk is a double data rate (DDR) 400 MHz clock as indicated by @@ -46,12 +48,13 @@ USE common_lib.common_pkg.ALL; -- g_wb_factor-1 samples. -- The sample phase alignment within a g_wb_factor=4 sample word is done by -- lvdsh_dd_phs4_align. After that the word phase is also aligned by --- adjusting the latency between wb_sync and dp_sync which. +-- adjusting the roundtrip latency between wb_sync and dp_sync which are both +-- derived from the selected dp_phs_clk. -- Both the sample phase alignment and the word phase alignment use the -- dp_phs_clk as reference. For the sample phase alignment within a word the -- dp_phs_clk could run at the same 200 MHz rate as the dp_clk. However to --- support a word latency of about 16 dp_clk cycles the dp_phs_clk are --- divided by 32 at the PLL and only their rising edge is used to do the +-- support a roundtrip word latency of about 16 dp_clk cycles the dp_phs_clk +-- are divided by 32 at the PLL and only their rising edge is used to do the -- alignments. -- The g_nof_dp_phs_clk>= 1 and maximum 6. When g_nof_dp_phs_clk=6 then -- typically each dp_phs_clk is shifted by 11.25 or 22.5 degrees where 90 @@ -59,7 +62,7 @@ USE common_lib.common_pkg.ALL; -- period. By selecting one suitable out of a range of phase shifted -- dp_phs_clk it is possible to find a proper dp_phs_clk reference for all -- signal paths in the different nodes. --- The whole sample phase realingment scheme relies on fixed clock +-- The whole sample phase realignment scheme relies on fixed clock -- distribution delays on the boards and in the FPGA. Therefore a clock tree -- network is used for the dp_phs_clk as well, even though the dp_phs_clk -- does not clock any logic. The dp_phs_clk gets sampled by the dp_clk to @@ -91,6 +94,22 @@ USE common_lib.common_pkg.ALL; -- an entire sample period and via MM control one phase is selected per -- BN- ADU pair. The MM control is then needed to select always the same -- phase in case not always the same phase is found automatically. +-- . With multiple Apertif subracks it appears that the word alignment found +-- for all ADC paths is not always the same for all ADC paths. This cannot +-- be avoided with this lvdsh_dd_phs4, therefore any residual sample phase +-- uncertainty needs to be accounted for by calibration. However for most +-- ADC dp_dat paths this lvdsh_dd_phs4 will ensure a proper word alignment +-- that makes it feasible to perform coherent beamforming. +-- . On Apertif subracks it appears that sometimes over hours an initial word +-- alignment will get adjusted and this then causes a brief disturbance in +-- the dp_dat values or it may even cause a sample shift that remains. Such +-- a sample shift would harm the remainder of the observation. By setting +-- in_maintain_phs='1' after word alignment it can be ensured that this word +-- alignment maintained as long as the ADC in_clk remains active (so in +-- practise for as long as the observation will last or the Apertif frontend +-- and subracks remain on). The maintain lock feature is enabled when +-- g_maintain_phs = TRUE. +-- ENTITY lvdsh_dd_phs4 IS GENERIC ( @@ -98,6 +117,7 @@ ENTITY lvdsh_dd_phs4 IS g_wb_factor : NATURAL := 4; -- fixed wideband factor 4 = c_rx_factor*c_dd_factor g_dp_phs_clk_period : NATURAL := 32; -- number of dp_clk periods per dp_phs_clk period, must match g_clk*_divide_by in unb_clk200_pll g_nof_dp_phs_clk : NATURAL := 2; -- nof dp_phs_clk that can be used to detect lock + g_maintain_phs : BOOLEAN := TRUE; -- when TRUE maintain the stable lock once it is found, else keep on checking whether the stable lock is still stable g_wb_use_rising_edge : BOOLEAN := FALSE; -- when TRUE using rising edge of dp_clk domain to capture wb_sync as reference for dp_sync from in_clk domain, else use falling edge g_in_dat_w : NATURAL := 8 -- nof PHY data bits ); @@ -148,34 +168,40 @@ ARCHITECTURE str OF lvdsh_dd_phs4 IS CONSTANT c_word_req_lat : NATURAL := 4; CONSTANT c_dp_phs_align_restart_w : NATURAL := 5; - CONSTANT c_in_dd_phs_locked_w : NATURAL := sel_a_b(g_sim, 12, 25); -- used to ensure that dd_phs_locked is only declared if dd_phs is detected ok for at least 2**(g_dd_phs_locked_w-1) in_clk cycles - CONSTANT c_dp_dd_phs_timeout_w : NATURAL := c_in_dd_phs_locked_w + 0; -- dd_phs locked timeout in dp_clk domain, use c_dd_factor longer or more than c_in_dd_phs_locked_w - CONSTANT c_wb_sync_offset : INTEGER := g_dp_phs_clk_period/2; - CONSTANT c_wb_sync_delta : INTEGER := 0; -- use c_wb_sync_offset for default FIFO fill level and c_wb_sync_delta < 0 or > 0 to decrease or increase it somewhat - CONSTANT c_wb_sync_latency : NATURAL := c_wb_sync_offset + c_wb_sync_delta; -- nof dp_clk cycles from getting wb_sync back via dp_sync - CONSTANT c_wb_sync_period : NATURAL := g_dp_phs_clk_period; -- nof dp_clk cycles for wb_sync period, must be > c_wb_sync_latency + CONSTANT c_in_dd_phs_locked_w : NATURAL := sel_a_b(g_sim, 12, 30); -- used to ensure that dd_phs_locked is only declared if dd_phs is detected ok for at least 2**(g_dd_phs_locked_w-1) in_clk cycles + CONSTANT c_dp_dd_phs_timeout_w : NATURAL := c_in_dd_phs_locked_w; -- dd_phs locked timeout in dp_clk domain, so c_dd_factor=2 longer than c_in_dd_phs_locked_w, because c_in_dd_phs_locked_w runs + -- in the in_clk domain. This is enough to find stable lock if it is possible to have stable lock at the selected dp_phs_clk. + + CONSTANT c_wb_sync_period : NATURAL := g_dp_phs_clk_period; -- nof dp_clk cycles for wb_sync period, must be > c_wb_sync_roundtrip CONSTANT c_wb_cnt_w : NATURAL := ceil_log2(c_wb_sync_period); - CONSTANT c_wb_fifo_latency : NATURAL := c_wb_sync_latency-9; -- estimated FIFO fill level based on simulation and measurement on hardware (6, 7 and 8 occur) + CONSTANT c_wb_fifo_fill_offset : INTEGER := 2; -- some offset to adjust the mean fifo fill level + CONSTANT c_wb_sync_in_latency : NATURAL := 12; -- estimated nof dp_clk cycles latency of wb_sync transfer in the in_clk domain based on simulation and measurement on hardware + CONSTANT c_wb_sync_roundtrip : NATURAL := c_wb_fifo_fill_offset+g_dp_phs_clk_period/2; -- achieve this nof dp_clk cycles from getting wb_sync back via dp_sync + CONSTANT c_wb_fifo_fill_level : NATURAL := c_wb_fifo_fill_offset+c_wb_sync_roundtrip-c_wb_sync_in_latency; -- expected FIFO fill level on read side (mean level +- 1 can occur), CONSTANT c_wb_fifo_fill_margin : NATURAL := 2; -- some symmetrical FIFO filled margin >= 0, use 0 in theory, use 1 to allow some timing uncertainty in rdusedw of dual clock FIFO - CONSTANT c_wb_fifo_fill_margin_p : NATURAL := c_wb_fifo_fill_margin; -- some FIFO more filled margin >= 0, use 0 or 1 to allow 8 and 9 - CONSTANT c_wb_fifo_fill_margin_n : NATURAL := c_wb_fifo_fill_margin; -- some FIFO less filled margin >= 0, use 1 or 2 to allow 7 and 6 - CONSTANT c_wb_fifo_fill_max : NATURAL := c_wb_fifo_latency+c_wb_fifo_fill_margin_p; -- maximum FIFO fill level at any time - CONSTANT c_wb_fifo_fill_min : NATURAL := c_wb_fifo_latency-c_wb_fifo_fill_margin_n; -- minimum FIFO fill level during lock + CONSTANT c_wb_fifo_fill_margin_p : NATURAL := c_wb_fifo_fill_margin; -- some FIFO more filled margin >= 0, use 0 or 1 to allow 8 and 9 + CONSTANT c_wb_fifo_fill_margin_n : NATURAL := c_wb_fifo_fill_margin; -- some FIFO less filled margin >= 0, use 1 or 2 to allow 7 and 6 + CONSTANT c_wb_fifo_fill_max : NATURAL := c_wb_fifo_fill_level+c_wb_fifo_fill_margin_p; -- maximum FIFO fill level at any time + CONSTANT c_wb_fifo_fill_min : NATURAL := c_wb_fifo_fill_level-c_wb_fifo_fill_margin_n; -- minimum FIFO fill level during lock -- view debug signals in Wave Window SIGNAL dbg_c_dp_phs_align_en : BOOLEAN := c_dp_phs_align_en; - SIGNAL dbg_c_wb_sync_latency : NATURAL := c_wb_sync_latency; + SIGNAL dbg_c_wb_sync_period : NATURAL := c_wb_sync_period; + SIGNAL dbg_c_wb_fifo_fill_offset : INTEGER := c_wb_fifo_fill_offset; + SIGNAL dbg_c_wb_sync_in_latency : NATURAL := c_wb_sync_in_latency; + SIGNAL dbg_c_wb_sync_roundtrip : NATURAL := c_wb_sync_roundtrip; SIGNAL dbg_c_wb_fifo_fill_max : NATURAL := c_wb_fifo_fill_max; - SIGNAL dbg_c_wb_fifo_latency : NATURAL := c_wb_fifo_latency; + SIGNAL dbg_c_wb_fifo_fill_level : NATURAL := c_wb_fifo_fill_level; -- must be > c_word_req_lat to ensure that fifo_rdusedw > 0 SIGNAL dbg_c_wb_fifo_fill_min : NATURAL := c_wb_fifo_fill_min; SIGNAL dbg_status_0_out_word_locked : STD_LOGIC; SIGNAL dbg_status_1_out_word_stable : STD_LOGIC; SIGNAL dbg_status_4_dp_phs_locked : STD_LOGIC; + SIGNAL dbg_status_5_wb_roundtrip_stable : STD_LOGIC; SIGNAL dbg_status_6_dp_in_clk_detected : STD_LOGIC; SIGNAL dbg_status_7_dp_in_clk_stable : STD_LOGIC; SIGNAL dbg_status_15_8_fifo_rdusedw : STD_LOGIC_VECTOR(7 DOWNTO 0); - SIGNAL dbg_status_23_16_wb_cnt_latency : STD_LOGIC_VECTOR(7 DOWNTO 0); + SIGNAL dbg_status_23_16_wb_cnt_roundtrip : STD_LOGIC_VECTOR(7 DOWNTO 0); SIGNAL dbg_status_27_24_dp_phs_clk_select : STD_LOGIC_VECTOR(3 DOWNTO 0); SIGNAL dbg_status_31_28_dp_raw_phs : STD_LOGIC_VECTOR(3 DOWNTO 0); @@ -202,6 +228,7 @@ ARCHITECTURE str OF lvdsh_dd_phs4 IS SIGNAL in_fifo_wr_dat : STD_LOGIC_VECTOR(c_fifo_dat_w-1 DOWNTO 0); SIGNAL in_fifo_wr_req : STD_LOGIC; SIGNAL in_phs_align_en : STD_LOGIC; + SIGNAL in_maintain_phs : STD_LOGIC := '0'; SIGNAL r_in : t_in_reg; SIGNAL nxt_r_in : t_in_reg; @@ -239,12 +266,13 @@ ARCHITECTURE str OF lvdsh_dd_phs4 IS prev_dp_sync_cap : STD_LOGIC; dp_sync : STD_LOGIC; wb_cnt_clr : STD_LOGIC; - wb_cnt_latency : STD_LOGIC_VECTOR(c_wb_cnt_w-1 DOWNTO 0); - wb_cnt_latency_hold : STD_LOGIC_VECTOR(c_wb_cnt_w-1 DOWNTO 0); + wb_cnt_roundtrip : STD_LOGIC_VECTOR(c_wb_cnt_w-1 DOWNTO 0); + wb_cnt_roundtrip_hold: STD_LOGIC_VECTOR(c_wb_cnt_w-1 DOWNTO 0); dp_word_req : STD_LOGIC; dp_word_req_dly : STD_LOGIC_VECTOR(c_word_req_lat-1 DOWNTO 0); dp_word_locked : STD_LOGIC; dp_word_lock_failed : STD_LOGIC; + dp_maintain_phs : STD_LOGIC; END RECORD; SIGNAL r_dp : t_dp_reg; @@ -274,14 +302,22 @@ ARCHITECTURE str OF lvdsh_dd_phs4 IS SIGNAL wb_phs_clk : STD_LOGIC; SIGNAL wb_sync_cap : STD_LOGIC; SIGNAL wb_cnt : STD_LOGIC_VECTOR(c_wb_cnt_w-1 DOWNTO 0); + SIGNAL wb_roundtrip_lock : STD_LOGIC; + SIGNAL wb_roundtrip_stable : STD_LOGIC; BEGIN ------------------------------------------------------------------------------ -- Reset input section when lock is lost ------------------------------------------------------------------------------ - + -- Multiple triggers for dp_phs_align_restart + -- + -- . The dp_phs_align_restart is an input to the dp_in_rst_req that drives in_rst for lvdsh_dd_phs4_align + -- . When out_word_stable='1' then dp_maintain_phs='1' if g_maintain_phs=TRUE. The dp_phs_timeout and dp_phs_lock_lost can then + -- no longer occur, because the lvdsh_dd_phs4_align then continues on the current phs using common_toggle_align. + -- The dp_word_lock_failed can still occur, but only if the course check on wb_cnt_roundtrip latency and fifo_rdusedw FIFO fill + -- level fails by more than a +-1 margin. dp_phs_align_restart <= dp_phs_timeout OR dp_phs_lock_lost OR r_dp.dp_word_lock_failed; -- Extend dp_phs_align_restart to filter out any subsequent restart triggers @@ -319,6 +355,9 @@ BEGIN -- . the in_clk has stopped, or -- . the dp_phs_clk_en_vec was changed via MM, or -- . an internal dp_phs_align_restart request occured + -- When out_word_stable='1' then dp_maintain_phs='1' if g_maintain_phs=TRUE. The dp_in_clk_stopped and dp_phs_clk_en_vec_evt + -- can the then still cause a reset. When dp_maintain_phs='1' the dp_phs_align_restart will effectively not occur anymore, + -- because both dp_clk and in_clk are active and in lock and any jitter is ignored. nxt_r_dp.dp_in_rst_req <= dp_in_clk_stopped OR dp_phs_clk_en_vec_evt OR dp_phs_align_restart_extend; u_common_async_in_rst : ENTITY common_lib.common_async @@ -404,10 +443,11 @@ BEGIN u_lvdsh_dd_phs4_align : ENTITY work.lvdsh_dd_phs4_align GENERIC MAP ( - g_wb_factor => g_wb_factor, - g_nof_dp_phs_clk => g_nof_dp_phs_clk, - g_dd_phs_locked_w => c_in_dd_phs_locked_w, - g_in_dat_w => g_in_dat_w + g_wb_factor => g_wb_factor, + g_nof_dp_phs_clk => g_nof_dp_phs_clk, + g_dp_phs_clk_period => g_dp_phs_clk_period, + g_dd_phs_locked_w => c_in_dd_phs_locked_w, + g_in_dat_w => g_in_dat_w ) PORT MAP ( -- DP clock reference for word alignment @@ -419,6 +459,7 @@ BEGIN in_clk => in_clk, in_dat_hi => in_dat_hi, in_dat_lo => in_dat_lo, + in_maintain_phs => in_maintain_phs, raw_phs => raw_phs, out_phs_locked => dd_phs_locked, @@ -437,7 +478,7 @@ BEGIN -- Support raw data without realignment ------------------------------------------------------------------------------ - u_common_async_1 : ENTITY common_lib.common_async + u_common_async_in_phs_align_en : ENTITY common_lib.common_async GENERIC MAP ( g_delay_len => c_delay_len ) @@ -580,10 +621,10 @@ BEGIN dp_phs_timeout <= dp_phs_timeout_cnt(dp_phs_timeout_cnt'HIGH); -- dp_phs_timeout pulse also restarts the timer ------------------------------------------------------------------------------ - -- Determine DP word lock based on the wb_sync - dp_sync latency + -- Determine DP word lock based on the wb_sync - dp_sync roundtrip latency via in_clk domain ------------------------------------------------------------------------------ - -- Measure and align the wb_sync to dp_sync latency + -- Measure and align the wb_sync to dp_sync roundtrip latency u_common_counter_wb_cnt : ENTITY common_lib.common_counter GENERIC MAP ( g_width => c_wb_cnt_w @@ -600,11 +641,14 @@ BEGIN nxt_r_dp.dp_word_req_dly(c_word_req_lat-1 DOWNTO 0) <= r_dp.dp_word_req_dly(c_word_req_lat-2 DOWNTO 0) & r_dp.dp_word_req; - p_dp_word_lock : PROCESS (r_dp, wb_cnt, fifo_rd_emp, fifo_rdusedw) + -- Monitor wb_cnt of roundtrip latency + wb_roundtrip_lock <= '1' WHEN UNSIGNED(r_dp.wb_cnt_roundtrip)=c_wb_sync_roundtrip ELSE '0'; + + p_dp_word_lock : PROCESS (r_dp, wb_cnt, wb_roundtrip_lock, fifo_rd_emp, fifo_rdusedw) BEGIN - nxt_r_dp.wb_cnt_clr <= '1'; - nxt_r_dp.wb_cnt_latency <= (OTHERS=>'0'); - nxt_r_dp.wb_cnt_latency_hold <= (OTHERS=>'0'); + nxt_r_dp.wb_cnt_clr <= '1'; + nxt_r_dp.wb_cnt_roundtrip <= (OTHERS=>'0'); + nxt_r_dp.wb_cnt_roundtrip_hold <= (OTHERS=>'0'); nxt_r_dp.dp_word_req <= '1'; nxt_r_dp.dp_word_locked <= '0'; @@ -615,16 +659,16 @@ BEGIN -- Realignment enabled -------------------------------------------------------------------------- IF r_dp.dp_phs_locked='1' THEN - -- Measure wb_sync - dp_sync latency - nxt_r_dp.wb_cnt_clr <= r_dp.wb_cnt_clr; - nxt_r_dp.wb_cnt_latency <= r_dp.wb_cnt_latency; - nxt_r_dp.wb_cnt_latency_hold <= r_dp.wb_cnt_latency_hold; + -- Measure wb_sync - dp_sync roundtrip latency + nxt_r_dp.wb_cnt_clr <= r_dp.wb_cnt_clr; + nxt_r_dp.wb_cnt_roundtrip <= r_dp.wb_cnt_roundtrip; + nxt_r_dp.wb_cnt_roundtrip_hold <= r_dp.wb_cnt_roundtrip_hold; IF r_dp.wb_sync='1' THEN nxt_r_dp.wb_cnt_clr <= '0'; ELSIF r_dp.dp_sync='1' THEN nxt_r_dp.wb_cnt_clr <= '1'; - nxt_r_dp.wb_cnt_latency <= wb_cnt; - nxt_r_dp.wb_cnt_latency_hold <= r_dp.wb_cnt_latency; + nxt_r_dp.wb_cnt_roundtrip <= wb_cnt; + nxt_r_dp.wb_cnt_roundtrip_hold <= r_dp.wb_cnt_roundtrip; END IF; -- Word lock control @@ -633,35 +677,36 @@ BEGIN IF r_dp.dp_word_locked='0' THEN -- Word lock acquisition IF r_dp.dp_sync='1' THEN -- dp_sync implies also that the FIFO is not empty, so no need to check fifo_rd_emp to avoid false dp_phs_val via dp_word_req_dly - -- Adjust wb_sync - dp_sync latency to become c_wb_sync_latency - IF UNSIGNED(wb_cnt) < c_wb_sync_latency THEN + -- Adjust wb_sync - dp_sync roundtrip latency to become c_wb_sync_roundtrip + IF UNSIGNED(wb_cnt) < c_wb_sync_roundtrip THEN nxt_r_dp.dp_word_req <= '0'; -- too early dp_sync so slip 1 word - ELSIF UNSIGNED(wb_cnt) = c_wb_sync_latency THEN + ELSIF UNSIGNED(wb_cnt) = c_wb_sync_roundtrip THEN nxt_r_dp.dp_word_locked <= '1'; -- declare word locked -- Fine check FIFO fill level when lock is declared IF UNSIGNED(fifo_rdusedw) < c_wb_fifo_fill_min THEN - nxt_r_dp.dp_word_lock_failed <= '1'; -- unexpected FIFO latency, so recover via in_rst + nxt_r_dp.dp_word_lock_failed <= '1'; -- unexpected change in FIFO fill level, so recover via in_rst END IF; END IF; -- Fine check that latency is incrementing properly during word lock acquisition - IF UNSIGNED(r_dp.wb_cnt_latency_hold)>0 THEN - IF UNSIGNED(r_dp.wb_cnt_latency_hold)/=UNSIGNED(r_dp.wb_cnt_latency)-1 THEN - nxt_r_dp.dp_word_lock_failed <= '1'; -- wrong latency increment, so recover via in_rst + IF UNSIGNED(r_dp.wb_cnt_roundtrip_hold)>0 THEN + IF UNSIGNED(r_dp.wb_cnt_roundtrip_hold)/=UNSIGNED(r_dp.wb_cnt_roundtrip)-1 THEN + nxt_r_dp.dp_word_lock_failed <= '1'; -- wrong roundtrip latency increment, so recover via in_rst END IF; END IF; END IF; ELSE -- *** Word locked, this is the correct end state for the ALIGNED data processing *** - -- Fine check latency during stable word lock - IF UNSIGNED(r_dp.wb_cnt_latency) /= c_wb_sync_latency THEN + -- Fine check roundtrip latency during stable word lock + IF wb_roundtrip_lock='0' AND r_dp.dp_maintain_phs = '0' THEN + -- After achieving dp_word_locked, but while dp_maintain_phs is still '0' the wb_cnt_roundtrip must exactly match c_wb_sync_roundtrip. nxt_r_dp.dp_word_lock_failed <= '1'; -- word lock lost, so recover via in_rst END IF; -- Fine check FIFO fill level during stable word lock IF UNSIGNED(fifo_rdusedw) < c_wb_fifo_fill_min THEN - nxt_r_dp.dp_word_lock_failed <= '1'; -- unexpected FIFO latency, so recover via in_rst + nxt_r_dp.dp_word_lock_failed <= '1'; -- unexpected change in FIFO fill level, so recover via in_rst END IF; END IF; END IF; @@ -676,7 +721,7 @@ BEGIN IF r_dp.dp_word_locked='0' THEN -- Word lock acquisition IF fifo_rd_emp='0' THEN -- no dp_sync in raw mode, so need to use fifo_rd_emp to check that FIFO is not empty to avoid false dp_phs_val due to dp_word_req_dly - IF UNSIGNED(fifo_rdusedw) <= c_wb_fifo_latency-c_word_req_lat THEN + IF UNSIGNED(fifo_rdusedw) <= c_wb_fifo_fill_level-c_word_req_lat THEN nxt_r_dp.dp_word_req <= '0'; -- too few words in FIFO so slip 1 word ELSIF UNSIGNED(fifo_rdusedw) >= c_wb_fifo_fill_min THEN nxt_r_dp.dp_word_locked <= '1'; -- declare word locked @@ -687,19 +732,19 @@ BEGIN -- Fine check FIFO fill level during stable word lock IF UNSIGNED(fifo_rdusedw) < c_wb_fifo_fill_min THEN - nxt_r_dp.dp_word_lock_failed <= '1'; -- unexpected FIFO latency, so recover via in_rst + nxt_r_dp.dp_word_lock_failed <= '1'; -- unexpected change in FIFO fill level, so recover via in_rst END IF; END IF; END IF; END IF; - -- Course check latency and FIFO fill level at any time - IF UNSIGNED(wb_cnt) > c_wb_sync_latency+1 THEN + -- Course check roundtrip latency and FIFO fill level at any time + IF UNSIGNED(wb_cnt) > c_wb_sync_roundtrip+1 THEN nxt_r_dp.dp_word_lock_failed <= '1'; -- timeout dp_sync, so recover via in_rst END IF; IF UNSIGNED(fifo_rdusedw) > c_wb_fifo_fill_max THEN - nxt_r_dp.dp_word_lock_failed <= '1'; -- unexpected FIFO latency, so recover via in_rst + nxt_r_dp.dp_word_lock_failed <= '1'; -- unexpected change in FIFO fill level, so recover via in_rst END IF; END PROCESS; @@ -712,9 +757,10 @@ BEGIN -- Debug monitor status i_out_status <= (OTHERS=>'0'); i_out_status( 4) <= r_dp.dp_phs_locked; -- 1 bit + i_out_status( 5) <= wb_roundtrip_stable; -- 1 bit i_out_status( 7 DOWNTO 6) <= dp_in_clk_stable & dp_in_clk_detected; -- 2 bit i_out_status(15 DOWNTO 8) <= fifo_rdusedw; -- c_fifo_size_w = 8 - i_out_status(23 DOWNTO 16) <= RESIZE_UVEC(r_dp.wb_cnt_latency, 8); -- c_wb_cnt_w <= 8 + i_out_status(23 DOWNTO 16) <= RESIZE_UVEC(r_dp.wb_cnt_roundtrip, 8); -- c_wb_cnt_w <= 8 i_out_status(27 DOWNTO 24) <= TO_UVEC(r_dp.dp_phs_clk_select, 4); -- g_nof_dp_phs_clk <= 6, fits in 4 bit i_out_status(31 DOWNTO 28) <= r_dp.dp_raw_phs; -- g_wb_factor = 4 END PROCESS; @@ -725,15 +771,16 @@ BEGIN dbg_status_0_out_word_locked <= r_dp.dp_word_locked; dbg_status_1_out_word_stable <= i_out_word_stable; dbg_status_4_dp_phs_locked <= i_out_status(4); + dbg_status_5_wb_roundtrip_stable <= i_out_status(5); dbg_status_6_dp_in_clk_detected <= i_out_status(6); dbg_status_7_dp_in_clk_stable <= i_out_status(7); dbg_status_15_8_fifo_rdusedw <= i_out_status(15 DOWNTO 8); - dbg_status_23_16_wb_cnt_latency <= i_out_status(23 DOWNTO 16); + dbg_status_23_16_wb_cnt_roundtrip <= i_out_status(23 DOWNTO 16); dbg_status_27_24_dp_phs_clk_select <= i_out_status(27 DOWNTO 24); dbg_status_31_28_dp_raw_phs <= i_out_status(31 DOWNTO 28) WHEN r_dp.dp_val='1' AND r_dp.le_val='1'; -- latch to view only yhe raw_phs when in lock END GENERATE; - u_common_stable_monitor : ENTITY common_lib.common_stable_monitor + u_common_stable_monitor_word_lock : ENTITY common_lib.common_stable_monitor PORT MAP ( rst => dp_rst, clk => dp_clk, @@ -742,10 +789,38 @@ BEGIN r_stable => i_out_word_stable, r_stable_ack => out_word_stable_ack ); - + + u_common_stable_monitor_wb_cnt_roundtrip : ENTITY common_lib.common_stable_monitor + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + -- MM + r_in => wb_roundtrip_lock, + r_stable => wb_roundtrip_stable, + r_stable_ack => out_word_stable_ack + ); + out_word_locked <= r_dp.dp_word_locked; out_word_stable <= i_out_word_stable; + ------------------------------------------------------------------------------ + -- Enable alignment or maintain current alignment once out_word_stable is achieved + ------------------------------------------------------------------------------ + nxt_r_dp.dp_maintain_phs <= i_out_word_stable WHEN g_maintain_phs=TRUE ELSE '0'; + + u_common_async_in_maintain_phs : ENTITY common_lib.common_async + GENERIC MAP ( + g_rst_level => '1', + g_delay_len => c_delay_len + ) + PORT MAP ( + rst => '0', + clk => in_clk, + din => r_dp.dp_maintain_phs, + dout => in_maintain_phs + ); + + ------------------------------------------------------------------------------ -- Registers ------------------------------------------------------------------------------ @@ -766,6 +841,7 @@ BEGIN BEGIN IF dp_rst='1' THEN r_dp.wb_sync_cap <= '0'; + r_dp.wb_sync <= '0'; r_dp.dp_in_rst_req <= '1'; r_dp.fifo_rd_req <= '0'; r_dp.le_sync <= '0'; @@ -782,11 +858,12 @@ BEGIN r_dp.prev_dp_sync_cap <= '0'; r_dp.dp_sync <= '0'; r_dp.wb_cnt_clr <= '1'; - r_dp.wb_cnt_latency <= (OTHERS=>'1'); + r_dp.wb_cnt_roundtrip <= (OTHERS=>'1'); r_dp.dp_word_req <= '1'; r_dp.dp_word_req_dly <= (OTHERS=>'1'); r_dp.dp_word_locked <= '0'; r_dp.dp_word_lock_failed <= '0'; + r_dp.dp_maintain_phs <= '0'; ELSIF rising_edge(dp_clk) THEN r_dp <= nxt_r_dp; END IF;