M src/jesd204b_link_rx.vhd => src/jesd204b_link_rx.vhd +21 -14
@@ 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),
M src/jesd204b_multipoint_link_rx.vhd => src/jesd204b_multipoint_link_rx.vhd +42 -2
@@ 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
M src/lmfc_counter.vhd => src/lmfc_counter.vhd +5 -1
@@ 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;