~ruther/jesd204b-vhdl

d1fbb4316290470cb778bdffef4595bf6f445c2b — František Boháček 2 years ago 6ac19e8
feat: pass synced only if lmfc is aligned after losing synchronization (subclass 1)
3 files changed, 68 insertions(+), 17 deletions(-)

M src/jesd204b_link_rx.vhd
M src/jesd204b_multipoint_link_rx.vhd
M src/lmfc_counter.vhd
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;

Do not follow this link