From d1fbb4316290470cb778bdffef4595bf6f445c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Mon, 3 Apr 2023 19:59:07 +0200 Subject: [PATCH] feat: pass synced only if lmfc is aligned after losing synchronization (subclass 1) --- src/jesd204b_link_rx.vhd | 35 ++++++++++++++--------- src/jesd204b_multipoint_link_rx.vhd | 44 +++++++++++++++++++++++++++-- src/lmfc_counter.vhd | 6 +++- 3 files changed, 68 insertions(+), 17 deletions(-) diff --git a/src/jesd204b_link_rx.vhd b/src/jesd204b_link_rx.vhd index a1b91ff..f47b05e 100644 --- a/src/jesd204b_link_rx.vhd +++ b/src/jesd204b_link_rx.vhd @@ -61,6 +61,8 @@ entity jesd204b_link_rx is end entity jesd204b_link_rx; architecture a1 of jesd204b_link_rx is + signal request_sync : std_logic; + signal request_sync_event : std_logic; signal reg_synced : std_logic; signal next_synced : std_logic; @@ -150,6 +152,24 @@ begin -- architecture a1 end process set_nsynced; end generate nsynced_subclass_1; + request_sync_gen: process (ci_char_clk, ci_reset) is + begin -- process request_sync + if ci_reset = '0' then -- asynchronous reset (active low) + request_sync_event <= '0'; + reg_synced <= '0'; + elsif ci_char_clk'event and ci_char_clk = '1' then -- rising clock edge + reg_synced <= next_synced; + + if request_sync_event = '1' then + request_sync_event <= '0'; + elsif next_synced = '0' and reg_synced = '1' then + -- if any of the data links becomes desynchronized, + -- request sync on every one of them. + request_sync_event <= '1'; + end if; + end if; + end process request_sync_gen; + -- start lanes data after all are ready start_lanes_subclass_0: if SUBCLASSV = 0 generate data_link_start <= '1' when data_link_ready_vector = all_ones else '0'; @@ -166,17 +186,6 @@ begin -- architecture a1 frame_index <= frame_index + 1; end if; end process set_frame_index; - - -- let all lanes start at RX_BUFFER_DELAY frames after multiframe clock - -- only if all data links are ready. - -- Note that this is not 100% standard respecting implementation. - -- The lanes should be freed after defined LMFC after synced is asserted, - -- but this is much easier. And provided that the presupposition that - -- delay of all lanes is lower than multiframe period, - -- it will work correctly according to the standard. - -- In all other cases, it's not correct according to the standard, - -- but the data will flow and the only difference will be the total - -- delay. data_link_start <= '1' when frame_index = RX_BUFFER_DELAY and data_link_ready_vector = all_ones else '0'; end generate start_lanes_subclass_1; @@ -185,7 +194,6 @@ begin -- architecture a1 transport_frame_state_array <= data_link_frame_state_array; -- TODO: buffer -- frame_state if -- scrambling - -- error '1' if configs do not match co_error <= not ConfigsMatch(lane_configuration_array); co_correct_data <= co_frame_state.user_data; @@ -208,12 +216,11 @@ begin -- architecture a1 port map ( ci_char_clk => ci_char_clk, ci_frame_clk => ci_frame_clk, - ci_multiframe_clk => ci_multiframe_clk, ci_reset => ci_reset, do_lane_config => lane_configuration_array(i), co_lane_ready => data_link_ready_vector(i), ci_lane_start => data_link_start, - ci_request_sync => ci_request_sync, + ci_request_sync => request_sync, co_synced => data_link_synced_vector(i), di_10b => di_transceiver_data(i), do_aligned_chars => data_link_aligned_chars_array(i), diff --git a/src/jesd204b_multipoint_link_rx.vhd b/src/jesd204b_multipoint_link_rx.vhd index 0584ec5..2759562 100644 --- a/src/jesd204b_multipoint_link_rx.vhd +++ b/src/jesd204b_multipoint_link_rx.vhd @@ -49,8 +49,12 @@ architecture a1 of jesd204b_multipoint_link_rx is signal links_nsynced : std_logic_vector(LINKS - 1 downto 0); signal multiframe_clk : std_logic; + signal multiframe_aligned : std_logic; + signal multiframe_enable_sync : std_logic; signal nsynced : std_logic; + signal reg_lmfc_aligned : std_logic; + -- purpose: Count lanes before link with index link_index function sumCummulativeLanes ( link_index : integer range 0 to LINKS-1) @@ -83,10 +87,45 @@ architecture a1 of jesd204b_multipoint_link_rx is begin -- architecture a1 nsynced <= '0' when links_nsynced = all_zeros else '1'; - co_nsynced <= nsynced; co_error <= '0' when links_error = all_zeros else '1'; co_correct_data <= '1' when links_correct_data = all_ones else '0'; + multiframe_subclass_0: if CONFIG(0).SUBCLASSV = 0 generate + co_nsynced <= nsynced; + end generate multiframe_subclass_0; + + multiframe_subclass_1: if CONFIG(0).SUBCLASSV = 1 generate + sysref_alignment: process (ci_device_clk, ci_reset) is + begin -- process sysref_alignment + if ci_reset = '0' then -- asynchronous reset (active low) + reg_lmfc_aligned <= '0'; + multiframe_enable_sync <= '0'; + elsif ci_device_clk'event and ci_device_clk = '1' then -- rising clock edge + if multiframe_enable_sync = '0' and reg_lmfc_aligned = '0' then + multiframe_enable_sync <= '1'; + elsif reg_lmfc_aligned = '0' and multiframe_aligned = '1' then + reg_lmfc_aligned <= '1'; + multiframe_enable_sync <= '0'; + elsif co_nsynced = '0' and nsynced = '1' then + reg_lmfc_aligned <= '0'; + multiframe_enable_sync <= '1'; + end if; + end if; + end process sysref_alignment; + + set_multiframe_sync: process (multiframe_clk, ci_reset) is + begin -- process set_multiframe_sync + if ci_reset = '0' then -- asynchronous reset (active low) + co_nsynced <= '1'; + elsif multiframe_clk'event and multiframe_clk = '1' then -- rising clock edge + co_nsynced <= '1'; + if nsynced = '0' and reg_lmfc_aligned = '1' then + co_nsynced <= '0'; + end if; + end if; + end process set_multiframe_sync; + end generate multiframe_subclass_1; + multiframe_gen: entity work.lmfc_counter generic map ( DATA_RATE_MULT => DATA_RATE_MULT, @@ -96,7 +135,8 @@ begin -- architecture a1 ci_device_clk => ci_device_clk, ci_reset => ci_reset, ci_sysref => ci_sysref, - ci_enable_sync => nsynced, + ci_enable_sync => multiframe_enable_sync, + co_aligned => multiframe_aligned, co_multiframe_clk => multiframe_clk); links_rx: for i in 0 to LINKS - 1 generate diff --git a/src/lmfc_counter.vhd b/src/lmfc_counter.vhd index e624aea..3e6189c 100644 --- a/src/lmfc_counter.vhd +++ b/src/lmfc_counter.vhd @@ -15,6 +15,7 @@ entity lmfc_counter is ci_reset : in std_logic; ci_sysref : in std_logic; ci_enable_sync : in std_logic; -- Whether to adjust to SYSREF + co_aligned : out std_logic; co_multiframe_clk : out std_logic); end entity lmfc_counter; @@ -28,12 +29,15 @@ begin -- architecture a1 count_phase_adjust: process (ci_device_clk, ci_reset) is begin -- process increase if ci_reset = '0' then -- asynchronous reset (active low) - count <= 0; + count <= (-1) mod COUNT_TO; prev_sysref <= '0'; + co_aligned <= '0'; elsif ci_device_clk'event and ci_device_clk = '1' then -- rising clock edge count <= (count + 1) mod COUNT_TO; + co_aligned <= '0'; if prev_sysref = '0' and ci_sysref = '1' and ci_enable_sync = '1' then count <= (-PHASE_ADJUST + 1) mod COUNT_TO; + co_aligned <= '1'; end if; prev_sysref <= ci_sysref; end if; -- 2.48.1