~ruther/jesd204b-vhdl

3e9599ef10eead139b55c2e9fd5b67d60b998ef7 — Rutherther 2 years ago ee374b1 + 3c666c1
Merge pull request #25 from Rutherther/feat/subclass-1-support

Add subclass 1 support
M src/data_link/data_link_layer.vhd => src/data_link/data_link_layer.vhd +15 -8
@@ 22,17 22,22 @@ use work.transport_pkg.all;

entity data_link_layer is
  generic (
    K_character  : std_logic_vector(7 downto 0) := "10111100";  -- K sync character
    R_character  : std_logic_vector(7 downto 0) := "00011100";  -- ILAS
    K_character       : std_logic_vector(7 downto 0) := "10111100";  -- K sync character
    R_character       : std_logic_vector(7 downto 0) := "00011100";  -- ILAS
                                        -- multiframe start
    A_character  : std_logic_vector(7 downto 0) := "01111100";  -- multiframe end
    Q_character  : std_logic_vector(7 downto 0) := "10011100";  -- 2nd ILAS frame
    A_character       : std_logic_vector(7 downto 0) := "01111100";  -- multiframe end
    Q_character       : std_logic_vector(7 downto 0) := "10011100";  -- 2nd ILAS frame
                                        -- 2nd character
    ERROR_CONFIG : error_handling_config        := (2, 0, 5, 5, 5);  -- Configuration
    ALIGN_BUFFER_SIZE : integer                      := 255;  -- Size of a
                                                              -- buffer that is
                                                              -- used for
                                                              -- aligning lanes
    ERROR_CONFIG      : error_handling_config        := (2, 0, 5, 5, 5);  -- Configuration
                                        -- for the error
    SCRAMBLING   : std_logic                    := '0';  -- Whether scrambling is enabled
    F            : integer range 1 to 256       := 2;  -- Number of octets in a frame
    K            : integer range 1 to 32        := 1);  -- Number of frames in a mutliframe
    SCRAMBLING        : std_logic                    := '0';  -- Whether scrambling is enabled
    SUBCLASSV         : integer range 0 to 1         := 0;
    F                 : integer range 1 to 256       := 2;  -- Number of octets in a frame
    K                 : integer range 1 to 32        := 1);  -- Number of frames in a mutliframe
  port (
    ci_char_clk  : in std_logic;        -- Character clock
    ci_frame_clk : in std_logic;        -- Frame clock


@@ 118,6 123,7 @@ begin  -- architecture a1
  link_controller_ci_resync <= error_handler_co_request_sync or ci_request_sync;
  link_controller : entity work.link_controller
    generic map (
      SUBCLASSV => SUBCLASSV,
      F => F,
      K => K)
    port map (


@@ 155,6 161,7 @@ begin  -- architecture a1
  -- lane alignment
  lane_alignment : entity work.lane_alignment
    generic map (
      BUFFER_SIZE => ALIGN_BUFFER_SIZE,
      F => F,
      K => K)
    port map (

M src/data_link/lane_alignment.vhd => src/data_link/lane_alignment.vhd +9 -9
@@ 17,7 17,7 @@ entity lane_alignment is
  generic (
    F               : integer range 1 to 256;  -- Number of octets in a frame
    K               : integer range 1 to 32;  -- Number of frames in a multiframe
    buffer_size     : integer                      := 256;  -- How many octets to keep
    BUFFER_SIZE     : integer                      := 256;  -- How many octets to keep
    R_character     : std_logic_vector(7 downto 0) := "00011100";  -- The /R/ character
    dummy_character : character_vector             := ('1', '0', '0', "10111100", '0'));
-- Character to send before the buffer is ready and started


@@ 42,18 42,18 @@ entity lane_alignment is
end entity lane_alignment;

architecture a1 of lane_alignment is
  type buffer_array is array (0 to buffer_size) of character_vector;
  type buffer_array is array (0 to BUFFER_SIZE) of character_vector;
  signal buff : buffer_array := (others => ('0', '0', '0', "00000000", '0'));

  signal reg_ready : std_logic := '0';
  signal reg_started : std_logic := '0';
  signal reg_error : std_logic := '0';

  signal reg_write_index : integer range 0 to buffer_size := 0;
  signal reg_read_index  : integer range 0 to buffer_size := 0;
  signal reg_write_index : integer range 0 to BUFFER_SIZE := 0;
  signal reg_read_index  : integer range 0 to BUFFER_SIZE := 0;

  signal next_write_index : integer range 0 to buffer_size-1 := 0;
  signal next_read_index  : integer range 0 to buffer_size-1 := 0;
  signal next_write_index : integer range 0 to BUFFER_SIZE-1 := 0;
  signal next_read_index  : integer range 0 to BUFFER_SIZE-1 := 0;
  signal next_ready       : std_logic                        := '0';
  signal next_started     : std_logic                        := '0';
  signal next_error       : std_logic                        := '0';


@@ 85,15 85,15 @@ begin  -- architecture a1
  co_error <= reg_error;
  -- TODO handle realignment ?

  next_write_index <= ((reg_write_index + 1) mod buffer_size) when reg_ready = '1' or next_ready = '1' else
  next_write_index <= ((reg_write_index + 1) mod BUFFER_SIZE) when reg_ready = '1' or next_ready = '1' else
                      0;
  next_read_index <= ((reg_read_index + 1) mod buffer_size) when reg_started = '1' else
  next_read_index <= ((reg_read_index + 1) mod BUFFER_SIZE) when reg_started = '1' else
                     0;

  next_ready <= '0' when ci_state = INIT else
                '1' when reg_ready = '1' or (di_char.kout = '1' and di_char.d8b = R_character and (ci_state = CGS or ci_state = ILS)) else
                '0';
  next_started <= '0' when reg_ready = '0' else
  next_started <= '0' when reg_ready = '0' or ci_state = CGS else
                  '1' when (ci_start = '1' or reg_started = '1') else
                  '0';
  co_aligned <= reg_started;            -- TODO: check for misalignment

M src/data_link/link_controller.vhd => src/data_link/link_controller.vhd +17 -24
@@ 20,41 20,42 @@ use work.data_link_pkg.all;

entity link_controller is
  generic (
    F : integer range 1 to 256; -- Number of octets in a frame
    K : integer range 1 to 32; -- Number of frames in a multiframe
    K_character  : std_logic_vector(7 downto 0) := "10111100");  -- Sync character
    SUBCLASSV   : integer range 0 to 1 := 0;
    F           : integer range 1 to 256;     -- Number of octets in a frame
    K           : integer range 1 to 32;  -- Number of frames in a multiframe
    K_character : std_logic_vector(7 downto 0) := "10111100");  -- Sync character
  port (
    ci_frame_clk : in std_logic;        -- Frame clock
    ci_char_clk : in std_logic;         -- Character clock
    ci_reset : in std_logic;            -- Reset (asynchronous, active low)
    di_char : in character_vector;      -- Output character from 8b10b decoder
    ci_frame_clk      : in std_logic;   -- Frame clock
    ci_char_clk       : in std_logic;   -- Character clock
    ci_reset          : in std_logic;   -- Reset (asynchronous, active low)
    di_char           : in character_vector;  -- Output character from 8b10b decoder

    do_config : out link_config;        -- Config found in ILAS
    do_config : out link_config;  -- Config found in ILAS

    ci_lane_alignment_error : in std_logic;  -- Signals a problem with lane
    ci_lane_alignment_error   : in std_logic;  -- Signals a problem with lane
                                             -- alignment in this data link
                                             -- (see lane alighnment component)
    ci_lane_alignment_aligned : in std_logic;  -- Signals that lane is
                                               -- correctly aligned (see
                                               -- lane_alignment component)
    ci_lane_alignment_ready : in std_logic;  -- Signals that the lane received
    ci_lane_alignment_ready   : in std_logic;  -- Signals that the lane received
                                             -- /A/ and is waiting to start
                                             -- sending data (see
                                             -- lane_alignment component)

    ci_frame_alignment_error : in std_logic;  -- Signals that the frame was misaligned.
    ci_frame_alignment_error   : in std_logic;  -- Signals that the frame was misaligned.
    ci_frame_alignment_aligned : in std_logic;  -- Signals that the frame end
                                                -- was found and did not change.

    ci_resync : in std_logic;           -- Whether to start syncing again.
    ci_resync : in std_logic;  -- Whether to start syncing again.

    co_synced : out std_logic;          -- Whether the lane is synced (received
    co_synced              : out std_logic;  -- Whether the lane is synced (received
                                        -- 4 /K/ characters and proceeds correctly)
    co_state : out link_state;          -- The state of the lane.
    co_state               : out link_state;  -- The state of the lane.
    co_uncorrectable_error : out std_logic;  -- Detected an uncorrectable
                                             -- error, has to resync (ilas
                                             -- parsing error)
    co_error : out std_logic);          -- Detected any error, processing may
    co_error               : out std_logic);          -- Detected any error, processing may
                                        -- differ
end entity link_controller;



@@ 131,18 132,10 @@ begin  -- architecture a1
    end if;
  end process set_state;

  set_synced: process(ci_frame_clk, ci_reset) is
  begin
    if ci_reset = '0' then
      co_synced <= '0';
    elsif ci_frame_clk'event and ci_frame_clk = '1' then
      co_synced <= synced;
    end if;
  end process set_synced;

  synced <= '0' when reg_state = INIT or (reg_state = CGS and reg_k_counter < SYNC_COUNT) else '1';
  full_synchronization <= '0' when synced = '0' or correct_8b10b_characters < FULL_SYNCHRONIZATION_AFTER else '1';

  co_synced <= synced;
  co_state <= reg_state;
  -- TODO: add ILAS errors, add CGS error in case sync does not happen for long
  -- time

M src/jesd204b_link_rx.vhd => src/jesd204b_link_rx.vhd +118 -40
@@ 15,38 15,44 @@ use work.jesd204b_pkg.all;

entity jesd204b_link_rx is
  generic (
    K_character  : std_logic_vector(7 downto 0) := "10111100";  -- Sync character
    R_character  : std_logic_vector(7 downto 0) := "00011100";  -- ILAS first
    K_character       : std_logic_vector(7 downto 0) := "10111100";  -- Sync character
    R_character       : std_logic_vector(7 downto 0) := "00011100";  -- ILAS first
                                        -- frame character
    A_character  : std_logic_vector(7 downto 0) := "01111100";  -- Multiframe
    A_character       : std_logic_vector(7 downto 0) := "01111100";  -- Multiframe
                                        -- alignment character
    Q_character  : std_logic_vector(7 downto 0) := "10011100";  -- ILAS 2nd
    Q_character       : std_logic_vector(7 downto 0) := "10011100";  -- ILAS 2nd
                                        -- frame 2nd character
    ADJCNT       : integer range 0 to 15        := 0;
    ADJDIR       : std_logic                    := '0';
    BID          : integer range 0 to 15        := 0;
    DID          : integer range 0 to 255       := 0;
    HD           : std_logic                    := '0';
    JESDV        : integer range 0 to 7         := 1;
    PHADJ        : std_logic                    := '0';
    SUBCLASSV    : integer range 0 to 7         := 0;
    K            : integer range 1 to 32;  -- Number of frames in a
                                           -- multiframe
    CS           : integer range 0 to 3;   -- Number of control bits per sample
    M            : integer range 1 to 256;  -- Number of converters
    S            : integer range 1 to 32;  -- Number of samples
    L            : integer range 1 to 32;  -- Number of lanes
    F            : integer range 1 to 256;  -- Number of octets in a frame
    CF           : integer range 0 to 32;  -- Number of control words
    N            : integer range 1 to 32;  -- Size of a sample
    Nn           : integer range 1 to 32;  -- Size of a word (sample + ctrl if CF
    ERROR_CONFIG : error_handling_config        := (2, 0, 5, 5, 5);
    SCRAMBLING   : std_logic                    := '0');
    ADJCNT            : integer range 0 to 15        := 0;
    ADJDIR            : std_logic                    := '0';
    BID               : integer range 0 to 15        := 0;
    DID               : integer range 0 to 255       := 0;
    HD                : std_logic                    := '0';
    JESDV             : integer range 0 to 7         := 1;
    PHADJ             : std_logic                    := '0';
    SUBCLASSV         : integer range 0 to 7         := 0;
    K                 : integer range 1 to 32;  -- Number of frames in a
                                                -- multiframe
    CS                : integer range 0 to 3;  -- Number of control bits per sample
    M                 : integer range 1 to 256;  -- Number of converters
    S                 : integer range 1 to 32;  -- Number of samples
    L                 : integer range 1 to 32;  -- Number of lanes
    F                 : integer range 1 to 256;  -- Number of octets in a frame
    CF                : integer range 0 to 32;  -- Number of control words
    N                 : integer range 1 to 32;  -- Size of a sample
    Nn                : integer range 1 to 32;  -- Size of a word (sample + ctrl if CF
    ALIGN_BUFFER_SIZE : integer                      := 255;  -- Size of a
                                                              -- buffer that is
                                                              -- used for
                                                              -- aligning lanes
    RX_BUFFER_DELAY   : integer range 1 to 32        := 1;
    ERROR_CONFIG      : error_handling_config        := (2, 0, 5, 5, 5);
    SCRAMBLING        : std_logic                    := '0');
  port (
    ci_char_clk     : in std_logic;     -- Character clock
    ci_frame_clk    : in std_logic;     -- Frame clock
    ci_reset        : in std_logic;     -- Reset (asynchronous, active low)
    ci_request_sync : in std_logic;     -- Request synchronization
    ci_char_clk       : in std_logic;   -- Character clock
    ci_frame_clk      : in std_logic;   -- Frame clock
    ci_multiframe_clk : in std_logic;  -- Mutliframe clock (subclass 1, 2 only)
    ci_reset          : in std_logic;   -- Reset (asynchronous, active low)
    ci_request_sync   : in std_logic;   -- Request synchronization

    co_nsynced : out std_logic;  -- Whether receiver is synced (active low)
    co_error   : out std_logic;


@@ 59,6 65,11 @@ 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;
  -- == DATA LINK ==
  -- outputs
  signal data_link_ready_vector : std_logic_vector(L-1 downto 0) := (others => '0');


@@ 68,6 79,9 @@ architecture a1 of jesd204b_link_rx is
  -- inputs
  signal data_link_start : std_logic := '0';

  -- subclass 1 support
  signal frame_index : integer;

  -- == DESCRAMBLER ==
  signal descrambler_aligned_chars_array : lane_character_array(0 to L-1)(F*8-1 downto 0);



@@ 114,32 128,96 @@ architecture a1 of jesd204b_link_rx is
  end function ConfigsMatch;
begin  -- architecture a1
  -- nsynced is active LOW, set '0' if all ready
  co_nsynced <= '0' when data_link_synced_vector = all_ones else '1';
  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;

  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
  data_link_start <= '1' when data_link_ready_vector = all_ones else '0';
  start_lanes_subclass_0: if SUBCLASSV = 0 generate
    data_link_start <= '1' when data_link_ready_vector = all_ones else '0';
  end generate start_lanes_subclass_0;

  start_lanes_subclass_1: if SUBCLASSV = 1 generate
    set_frame_index: process (ci_frame_clk, ci_multiframe_clk, ci_reset) is
    begin  -- process set_frame_idnex
      if ci_reset = '0' then            -- asynchronous reset (active low)
        frame_index <= 0;
      elsif ci_multiframe_clk'event and ci_multiframe_clk = '1' then  -- rising clock edge
        frame_index <= 0;
      elsif ci_frame_clk'event and ci_frame_clk = '1' then  -- rising clock edge
        frame_index <= frame_index + 1;
      end if;
    end process set_frame_index;
    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;

  -- characters either from scrambler if scrambling enabled or directly from data_link
  transport_chars_array <= descrambler_aligned_chars_array when SCRAMBLING = '1' else data_link_aligned_chars_array;
  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;

  next_synced <= '1' when data_link_synced_vector = all_ones else '0';
  request_sync <= request_sync_event or ci_request_sync;

  data_links : for i in 0 to L-1 generate
    data_link_layer : entity work.data_link_layer
      generic map (
        K_character  => K_character,
        R_character  => R_character,
        A_character  => A_character,
        Q_character  => Q_character,
        ERROR_CONFIG => ERROR_CONFIG,
        SCRAMBLING   => SCRAMBLING,
        F            => F,
        K            => K)
        ALIGN_BUFFER_SIZE => ALIGN_BUFFER_SIZE,
        K_character       => K_character,
        R_character       => R_character,
        A_character       => A_character,
        Q_character       => Q_character,
        ERROR_CONFIG      => ERROR_CONFIG,
        SCRAMBLING        => SCRAMBLING,
        SUBCLASSV         => SUBCLASSV,
        F                 => F,
        K                 => K)
      port map (
        ci_char_clk      => ci_char_clk,
        ci_frame_clk     => ci_frame_clk,


@@ 147,7 225,7 @@ begin  -- architecture a1
        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 +108 -38
@@ 7,22 7,32 @@ use work.transport_pkg.all;
entity jesd204b_multipoint_link_rx is

  generic (
    K_character  : std_logic_vector(7 downto 0) := "10111100";  -- Sync character
    R_character  : std_logic_vector(7 downto 0) := "00011100";  -- ILAS first
    K_character          : std_logic_vector(7 downto 0) := "10111100";  -- Sync character
    R_character          : std_logic_vector(7 downto 0) := "00011100";  -- ILAS first
                                        -- frame character
    A_character  : std_logic_vector(7 downto 0) := "01111100";  -- Multiframe
    A_character          : std_logic_vector(7 downto 0) := "01111100";  -- Multiframe
                                        -- alignment character
    Q_character  : std_logic_vector(7 downto 0) := "10011100";  -- ILAS 2nd
                                        -- frame 2nd character
    LINKS        : integer;             -- Count of links
    LANES        : integer;             -- Total nubmer of lanes
    CONVERTERS   : integer;             -- Total number of converters
    CONFIG       : link_config_array(0 to LINKS - 1);
    ERROR_CONFIG : error_handling_config        := (2, 0, 5, 5, 5));
    Q_character          : std_logic_vector(7 downto 0) := "10011100";  -- ILAS 2nd
    DATA_RATE_MULT       : integer;  -- DEVICE_CLK_FREQ*this is lane bit rate
                                     -- frame 2nd character
    MULTIFRAME_RATE      : integer;     -- F * K, should be the same for every
                                        -- device
    ALIGN_BUFFER_SIZE : integer                      := 255;  -- Size of a
                                                              -- buffer that is
                                                              -- used for
                                                              -- aligning lanes
    RX_BUFFER_DELAY      : integer range 1 to 32        := 1;
    LINKS                : integer;     -- Count of links
    LANES                : integer;     -- Total nubmer of lanes
    CONVERTERS           : integer;     -- Total number of converters
    CONFIG               : link_config_array(0 to LINKS - 1);
    ERROR_CONFIG         : error_handling_config        := (2, 0, 5, 5, 5));

  port (
    ci_char_clk          : in  std_logic;
    ci_frame_clk          : in  std_logic;
    ci_device_clk       : in  std_logic;
    ci_char_clk         : in  std_logic;
    ci_frame_clk        : in  std_logic;
    ci_sysref           : in  std_logic;
    ci_reset            : in  std_logic;
    ci_request_sync     : in  std_logic;
    co_nsynced          : out std_logic;


@@ 42,6 52,13 @@ architecture a1 of jesd204b_multipoint_link_rx is
  signal links_error : std_logic_vector(LINKS - 1 downto 0);
  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)


@@ 72,44 89,97 @@ architecture a1 of jesd204b_multipoint_link_rx is
    return converters_count;
  end function sumCummulativeConverters;
begin  -- architecture a1
  co_nsynced <= '0' when links_nsynced = all_zeros else '1';
  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';

  links_rx: for i in 0 to LINKS - 1 generate
    link: entity work.jesd204b_link_rx
  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,
      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);

  links_rx : for i in 0 to LINKS - 1 generate
    link : entity work.jesd204b_link_rx
      generic map (
        K_character  => K_character,
        R_character  => R_character,
        A_character  => A_character,
        Q_character  => Q_character,
        ERROR_CONFIG => ERROR_CONFIG,
        ADJCNT       => CONFIG(i).ADJCNT,
        BID          => CONFIG(i).BID,
        DID          => CONFIG(i).DID,
        HD           => CONFIG(i).HD,
        JESDV        => CONFIG(i).JESDV,
        PHADJ        => CONFIG(i).PHADJ,
        SUBCLASSV    => CONFIG(i).SUBCLASSV,
        K            => CONFIG(i).K,
        CS           => CONFIG(i).CS,
        M            => CONFIG(i).M,
        S            => CONFIG(i).S,
        L            => CONFIG(i).L,
        F            => CONFIG(i).F,
        CF           => CONFIG(i).CF,
        N            => CONFIG(i).N,
        Nn           => CONFIG(i).Nn,
        ADJDIR       => CONFIG(i).ADJDIR)
        K_character       => K_character,
        R_character       => R_character,
        A_character       => A_character,
        Q_character       => Q_character,
        ERROR_CONFIG      => ERROR_CONFIG,
        ALIGN_BUFFER_SIZE => ALIGN_BUFFER_SIZE,
        RX_BUFFER_DELAY   => RX_BUFFER_DELAY,
        ADJCNT            => CONFIG(i).ADJCNT,
        BID               => CONFIG(i).BID,
        DID               => CONFIG(i).DID,
        HD                => CONFIG(i).HD,
        JESDV             => CONFIG(i).JESDV,
        PHADJ             => CONFIG(i).PHADJ,
        SUBCLASSV         => CONFIG(i).SUBCLASSV,
        K                 => CONFIG(i).K,
        CS                => CONFIG(i).CS,
        M                 => CONFIG(i).M,
        S                 => CONFIG(i).S,
        L                 => CONFIG(i).L,
        F                 => CONFIG(i).F,
        CF                => CONFIG(i).CF,
        N                 => CONFIG(i).N,
        Nn                => CONFIG(i).Nn,
        ADJDIR            => CONFIG(i).ADJDIR)
    port map (
      ci_char_clk         => ci_char_clk,
      ci_frame_clk        => ci_frame_clk,
      ci_multiframe_clk   => multiframe_clk,
      ci_reset            => ci_reset,
      ci_request_sync     => ci_request_sync,
      co_nsynced          => links_nsynced(i),
      co_error            => links_error(i),
      di_transceiver_data => di_transceiver_data(sumCummulativeLanes(i) to sumCummulativeLanes(i) + CONFIG(i).L - 1),
      do_samples          => do_samples(i), -- do_samples(sumCummulativeConverters(i) to sumCummulativeConverters(i) + CONFIG(i).M - 1),
      do_samples          => do_samples(i),  -- do_samples(sumCummulativeConverters(i) to sumCummulativeConverters(i) + CONFIG(i).M - 1),
      co_frame_state      => co_frame_state(i),
      co_correct_data     => links_correct_data(i));
  end generate links_rx;

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

entity lmfc_counter is

  generic (
    DATA_RATE_MULT         : integer;   -- DEV_CLK_FREQ*this is the frequency
                                        -- of data rate (bit rate)
    PHASE_ADJUST           : integer;   -- How many more clock cycles to wait
                                        -- after sysref until lmfc ticks
    MULTIFRAME_RATE        : integer);

  port (
    ci_device_clk     : in  std_logic;
    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;

architecture a1 of lmfc_counter is
  constant COUNT_TO : integer := MULTIFRAME_RATE/(DATA_RATE_MULT/10);

  signal count : integer range 0 to COUNT_TO;
  signal prev_sysref : std_logic;
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 <= (-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;
  end process count_phase_adjust;

  co_multiframe_clk <= '1' when count < COUNT_TO / 2 else '0';

end architecture a1;

M testbench/jesd204b_multipoint_data_tb.vhd => testbench/jesd204b_multipoint_data_tb.vhd +34 -4
@@ 11,6 11,8 @@ end entity jesd204b_multipoint_rx_data_tb;
architecture a1 of jesd204b_multipoint_rx_data_tb is
  constant LANES : integer := 2;
  constant LINKS : integer := 2;
  constant F : integer := 2;
  constant K : integer := 9;
  constant CONFIG : link_config_array(0 to LINKS - 1) :=
  (
    (0, '0', 0, 0, 2, 0, 2, '0', 1, 9, 1, 0, 1, 14, 16, '0', 1, '0', 0, "00000000", "00000000", "000000000", 0),


@@ 45,6 47,17 @@ architecture a1 of jesd204b_multipoint_rx_data_tb is
    (data => (("10111100", '1'), ("10111100", '1'))),
    (data => (("10111100", '1'), ("10111100", '1'))),
    (data => (("10111100", '1'), ("10111100", '1'))),
    (data => (("10111100", '1'), ("10111100", '1'))),
    (data => (("10111100", '1'), ("10111100", '1'))),
    (data => (("10111100", '1'), ("10111100", '1'))),
    (data => (("10111100", '1'), ("10111100", '1'))),
    (data => (("10111100", '1'), ("10111100", '1'))),
    (data => (("10111100", '1'), ("10111100", '1'))),
    (data => (("10111100", '1'), ("10111100", '1'))),
    (data => (("10111100", '1'), ("10111100", '1'))),
    (data => (("10111100", '1'), ("10111100", '1'))),
    (data => (("10111100", '1'), ("10111100", '1'))),
    (data => (("10111100", '1'), ("10111100", '1'))),
    (data => (("00011100", '1'), ("00011100", '1'))), -- 1st ILAS multiframe start
    (data => (("00000000", '0'), ("00000000", '0'))),
    (data => (("00000000", '0'), ("00000000", '0'))),


@@ 127,13 140,15 @@ architecture a1 of jesd204b_multipoint_rx_data_tb is

  constant char_clk_period : time := 1 ns;    -- The clock period
  constant frame_clk_period : time := 1 ns * CONFIG(0).F;    -- The clock period
  constant sysref_period : time := char_clk_period * CONFIG(0).K * CONFIG(0).F;    -- The clock period

  signal di_transceiver_data : lane_input_array(0 to LANES-1);
  signal di_lane_data : lane_data_array(0 to LANES-1);

  signal char_clk : std_logic := '0';        -- The clock
  signal frame_clk : std_logic := '0';        -- The clock
  signal reset : std_logic := '0';      -- The reset
  signal sysref    : std_logic := '0';
  signal char_clk  : std_logic := '0';  -- The clock
  signal frame_clk : std_logic := '0';  -- The clock
  signal reset     : std_logic := '0';  -- The reset

  signal test_vec_index : integer := 0;



@@ 146,13 161,18 @@ architecture a1 of jesd204b_multipoint_rx_data_tb is
begin  -- architecture a1
  uut : entity work.jesd204b_multipoint_link_rx
    generic map (
      DATA_RATE_MULT => 10,
      MULTIFRAME_RATE => F*K,
      RX_BUFFER_DELAY => 6,
      LINKS      => LINKS,
      LANES      => LANES,
      CONVERTERS => 2,
      CONFIG     => CONFIG)
    port map (
      ci_device_clk       => char_clk,
      ci_char_clk         => char_clk,
      ci_frame_clk        => frame_clk,
      ci_sysref           => sysref,
      ci_reset            => reset,
      ci_request_sync     => '0',
      di_transceiver_data => di_transceiver_data,


@@ 173,9 193,19 @@ begin  -- architecture a1
  end generate encoders;

  char_clk <= not char_clk after char_clk_period/2;
  frame_clk <= not frame_clk after frame_clk_period/2;
  sysref <= not sysref after sysref_period/2;
  reset <= '1' after char_clk_period*2;

  frame_clk_gen: process is
  begin  -- process frame_clk_gen
    wait for char_clk_period/2;

    while true loop
      frame_clk <= not frame_clk;
      wait for frame_clk_period/2;
    end loop;
  end process frame_clk_gen;

  test: process is
  begin  -- process test
    wait for char_clk_period*2;

M testbench/jesd204b_rx_data_tb.vhd => testbench/jesd204b_rx_data_tb.vhd +1 -0
@@ 160,6 160,7 @@ begin  -- architecture a1
    port map (
      ci_char_clk         => char_clk,
      ci_frame_clk        => frame_clk,
      ci_multiframe_clk   => '0',
      ci_reset            => reset,
      ci_request_sync     => '0',
      di_transceiver_data => di_transceiver_data,

M testbench/jesd204b_rx_ils_tb.vhd => testbench/jesd204b_rx_ils_tb.vhd +1 -0
@@ 156,6 156,7 @@ begin  -- architecture a1
    port map (
      ci_char_clk         => char_clk,
      ci_frame_clk        => frame_clk,
      ci_multiframe_clk   => '0',
      ci_reset            => reset,
      ci_request_sync     => '0',
      di_transceiver_data => di_transceiver_data,

M testbench/jesd204b_rx_kchars_tb.vhd => testbench/jesd204b_rx_kchars_tb.vhd +1 -0
@@ 96,6 96,7 @@ begin  -- architecture a1
    port map (
      ci_char_clk         => char_clk,
      ci_frame_clk        => frame_clk,
      ci_multiframe_clk   => '0',
      ci_reset            => reset,
      ci_request_sync     => '0',
      di_transceiver_data => di_transceiver_data,

Do not follow this link