~ruther/jesd204b-vhdl

6b1d2bdefbe0998fecb242e34febeb19f1368715 — František Boháček 2 years ago f833802
feat: add basic subclass 1 support
M src/data_link/data_link_layer.vhd => src/data_link/data_link_layer.vhd +7 -3
@@ 31,12 31,14 @@ entity data_link_layer is
    ERROR_CONFIG : error_handling_config        := (2, 0, 5, 5, 5);  -- Configuration
                                        -- for the error
    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
    ci_reset     : in std_logic;        -- Reset (asynchronous, active low)
    ci_char_clk       : in std_logic;   -- Character clock
    ci_frame_clk      : in std_logic;   -- Frame clock
    ci_multiframe_clk : in std_logic;
    ci_reset          : in std_logic;   -- Reset (asynchronous, active low)

    -- link configuration
    do_lane_config : out link_config;  -- Configuration of the link


@@ 118,9 120,11 @@ 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 (
      ci_multiframe_clk          => ci_multiframe_clk,
      ci_frame_clk               => ci_frame_clk,
      ci_char_clk                => ci_char_clk,
      ci_reset                   => ci_reset,

M src/data_link/link_controller.vhd => src/data_link/link_controller.vhd +38 -23
@@ 20,41 20,43 @@ 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_multiframe_clk : in std_logic;   -- Multiframe clock
    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,14 133,27 @@ 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_subclass_0: if SUBCLASSV = 0 generate
    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;
  end generate synced_subclass_0;

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

  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';

M src/jesd204b_link_rx.vhd => src/jesd204b_link_rx.vhd +62 -29
@@ 15,38 15,40 @@ 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
    RX_BUFFER_DELAY : integer range 1 to 32        := 0;
    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;


@@ 68,6 70,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);



@@ 117,7 122,34 @@ begin  -- architecture a1
  co_nsynced <= '0' when data_link_synced_vector = all_ones else '1';

  -- 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 = 0 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;

    -- 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;

  -- 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;


@@ 138,6 170,7 @@ begin  -- architecture a1
        Q_character  => Q_character,
        ERROR_CONFIG => ERROR_CONFIG,
        SCRAMBLING   => SCRAMBLING,
        SUBCLASSV    => SUBCLASSV,
        F            => F,
        K            => K)
      port map (

M src/jesd204b_multipoint_link_rx.vhd => src/jesd204b_multipoint_link_rx.vhd +36 -12
@@ 7,22 7,28 @@ 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
    Q_character          : std_logic_vector(7 downto 0) := "10011100";  -- ILAS 2nd
    DEVICE_CLK_FREQUENCY : integer;
    DATA_RATE_MULT       : integer;     -- DEVICE_CLK_FREQ*this is lane bit rate
                                        -- 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));
    MULTIFRAME_RATE      : integer;     -- F * K, should be the same for every
                                        -- device
    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 48,9 @@ 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 nsynced : std_logic;

  -- purpose: Count lanes before link with index link_index
  function sumCummulativeLanes (
    link_index : integer range 0 to LINKS-1)


@@ 72,10 81,24 @@ 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_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_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    => nsynced,
      co_multiframe_clk => multiframe_clk);

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


@@ 104,6 127,7 @@ begin  -- architecture a1
    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),

Do not follow this link