~ruther/jesd204b-vhdl

1caca1862aa56d5164238d68a1d9f1d0002751a6 — František Boháček 2 years ago 3e9599e
feat: split synced combination and lmfc generation to separate entities
M src/jesd204b_link_rx.vhd => src/jesd204b_link_rx.vhd +12 -27
@@ 128,33 128,18 @@ architecture a1 of jesd204b_link_rx is
  end function ConfigsMatch;
begin  -- architecture a1
  -- nsynced is active LOW, set '0' if all ready
  nsynced_subclass_0: if SUBCLASSV = 0 generate
    set_nsynced: process (ci_frame_clk, ci_reset) is
    begin  -- process set_nsynced
      if ci_reset = '0' then              -- asynchronous reset (active low)
        co_nsynced <= '1';
      elsif ci_frame_clk'event and ci_frame_clk = '1' then  -- rising clock edge
        co_nsynced <= '1';
        if data_link_synced_vector = all_ones then
          co_nsynced <= '0';
        end if;
      end if;
    end process set_nsynced;
  end generate nsynced_subclass_0;

  nsynced_subclass_1: if SUBCLASSV = 1 generate
    set_nsynced: process (ci_multiframe_clk, ci_reset) is
    begin  -- process set_nsynced
      if ci_reset = '0' then              -- asynchronous reset (active low)
        co_nsynced <= '1';
      elsif ci_multiframe_clk'event and ci_multiframe_clk = '1' then  -- rising clock edge
        co_nsynced <= '1';
        if data_link_synced_vector = all_ones then
          co_nsynced <= '0';
        end if;
      end if;
    end process set_nsynced;
  end generate nsynced_subclass_1;
  sync_combination: entity work.synced_combination
    generic map (
      SUBCLASSV => SUBCLASSV,
      N         => L,
      INVERSE   => '0')
    port map (
      ci_frame_clk      => ci_frame_clk,
      ci_multiframe_clk => ci_multiframe_clk,
      ci_reset          => ci_reset,
      ci_lmfc_aligned   => '1',
      ci_synced_array   => data_link_synced_vector,
      co_nsynced        => co_nsynced);

  request_sync_gen: process (ci_char_clk, ci_reset) is
  begin  -- process request_sync

M src/jesd204b_multipoint_link_rx.vhd => src/jesd204b_multipoint_link_rx.vhd +18 -49
@@ 53,12 53,9 @@ 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 lmfc_aligned : 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)


@@ 89,59 86,31 @@ architecture a1 of jesd204b_multipoint_link_rx is
    return converters_count;
  end function sumCummulativeConverters;
begin  -- architecture a1
  nsynced <= '0' when links_nsynced = all_zeros else '1';

  co_error <= '0' when links_error = all_zeros else '1';
  co_correct_data <= '1' when links_correct_data = all_ones else '0';
  co_nsynced <= nsynced;

  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
  sync_combination : entity work.synced_combination
    generic map (
      DATA_RATE_MULT  => DATA_RATE_MULT,
      PHASE_ADJUST    => 0,
      MULTIFRAME_RATE => MULTIFRAME_RATE)
      SUBCLASSV => CONFIG(0).SUBCLASSV,
      N         => LINKS,
      INVERSE   => '1')
    port map (
      ci_frame_clk      => ci_frame_clk,
      ci_multiframe_clk => multiframe_clk,
      ci_reset          => ci_reset,
      ci_lmfc_aligned   => lmfc_aligned,
      ci_synced_array   => links_nsynced,
      co_nsynced        => nsynced);

  lmfc_generation: entity work.lmfc_generation
    port map (
      ci_device_clk     => ci_device_clk,
      ci_reset          => ci_reset,
      ci_sysref         => ci_sysref,
      ci_enable_sync    => multiframe_enable_sync,
      co_aligned        => multiframe_aligned,
      co_multiframe_clk => multiframe_clk);
      ci_nsynced        => nsynced,
      co_multiframe_clk => multiframe_clk,
      co_lmfc_aligned   => lmfc_aligned);

  links_rx : for i in 0 to LINKS - 1 generate
    link : entity work.jesd204b_link_rx

A src/lmfc_generation.vhd => src/lmfc_generation.vhd +61 -0
@@ 0,0 1,61 @@
library ieee;
use ieee.std_logic_1164.all;

entity lmfc_generation is
  generic (
    MULTIFRAME_RATE : integer;
    DATA_RATE_MULT  : integer);
  port (
    ci_device_clk     : in  std_logic;
    ci_reset          : in  std_logic;
    ci_sysref         : in  std_logic;
    ci_nsynced        : in  std_logic;
    co_multiframe_clk : out std_logic;
    co_lmfc_aligned   : out std_logic);
end entity lmfc_generation;

architecture a1 of lmfc_generation is
  signal prev_nsynced : std_logic;
  signal reg_lmfc_aligned : std_logic;

  signal multiframe_clk : std_logic;
  signal multiframe_aligned : std_logic;
  signal multiframe_enable_sync : std_logic;
begin  -- architecture a1
  co_lmfc_aligned <= reg_lmfc_aligned;
  co_multiframe_clk <= multiframe_clk;

  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';
      prev_nsynced <= '1';
    elsif ci_device_clk'event and ci_device_clk = '1' then  -- rising clock edge
        prev_nsynced <= ci_nsynced;
      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 prev_nsynced = '0' and ci_nsynced = '1' then
        reg_lmfc_aligned <= '0';
        multiframe_enable_sync <= '1';
      end if;
    end if;
  end process sysref_alignment;

  multiframe_gen: entity work.lmfc_counter
  generic map (
    DATA_RATE_MULT  => DATA_RATE_MULT,
    PHASE_ADJUST    => 0,
    MULTIFRAME_RATE => MULTIFRAME_RATE)
  port map (
    ci_device_clk     => ci_device_clk,
    ci_reset          => ci_reset,
    ci_sysref         => ci_sysref,
    ci_enable_sync    => multiframe_enable_sync,
    co_aligned        => multiframe_aligned,
    co_multiframe_clk => multiframe_clk);

end architecture a1;

A src/synced_combination.vhd => src/synced_combination.vhd +58 -0
@@ 0,0 1,58 @@
library ieee;
use ieee.std_logic_1164.all;

entity synced_combination is

  generic (
    SUBCLASSV : integer := 0;
    N : integer := 1;
    INVERSE : std_logic := '0');
  port (
    ci_frame_clk : in std_logic;
    ci_multiframe_clk : in std_logic;
    ci_reset : in std_logic;
    ci_lmfc_aligned : in std_logic;
    ci_synced_array : std_logic_vector(N-1 downto 0);
    co_nsynced : out std_logic);

end entity synced_combination;

architecture a1 of synced_combination is
  constant all_ones : std_logic_vector(N - 1 downto 0) := (others => '1');
  constant all_zeros : std_logic_vector(N - 1 downto 0) := (others => '0');

  signal nsynced : std_logic;
begin  -- architecture a1
  gen_nsynced: if INVERSE = '0' generate
    nsynced <= '0' when ci_synced_array = all_ones else '1';
  end generate gen_nsynced;
  gen_nsynced_inverse: if INVERSE = '1' generate
    nsynced <= '0' when ci_synced_array = all_zeros else '1';
  end generate gen_nsynced_inverse;

  nsynced_subclass_0: if SUBCLASSV = 0 generate
    set_nsynced: process (ci_frame_clk, ci_reset) is
    begin  -- process set_nsynced
      if ci_reset = '0' then              -- asynchronous reset (active low)
        co_nsynced <= '1';
      elsif ci_frame_clk'event and ci_frame_clk = '1' then  -- rising clock edge
        co_nsynced <= nsynced;
      end if;
    end process set_nsynced;
  end generate nsynced_subclass_0;

  nsynced_subclass_1: if SUBCLASSV = 1 generate
    set_nsynced: process (ci_multiframe_clk, ci_reset) is
    begin  -- process set_nsynced
      if ci_reset = '0' then              -- asynchronous reset (active low)
        co_nsynced <= '1';
      elsif ci_multiframe_clk'event and ci_multiframe_clk = '1' then  -- rising clock edge
        co_nsynced <= '1';
        if nsynced = '0' and ci_lmfc_aligned = '1' then
          co_nsynced <= '0';
        end if;
      end if;
    end process set_nsynced;
  end generate nsynced_subclass_1;

end architecture a1;

Do not follow this link