From 6b1d2bdefbe0998fecb242e34febeb19f1368715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Sun, 2 Apr 2023 16:32:12 +0200 Subject: [PATCH] feat: add basic subclass 1 support --- src/data_link/data_link_layer.vhd | 10 +++- src/data_link/link_controller.vhd | 61 +++++++++++-------- src/jesd204b_link_rx.vhd | 91 ++++++++++++++++++++--------- src/jesd204b_multipoint_link_rx.vhd | 48 +++++++++++---- 4 files changed, 143 insertions(+), 67 deletions(-) diff --git a/src/data_link/data_link_layer.vhd b/src/data_link/data_link_layer.vhd index 18da1b6..02d5531 100644 --- a/src/data_link/data_link_layer.vhd +++ b/src/data_link/data_link_layer.vhd @@ -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, diff --git a/src/data_link/link_controller.vhd b/src/data_link/link_controller.vhd index c8bc7f7..bf9b492 100644 --- a/src/data_link/link_controller.vhd +++ b/src/data_link/link_controller.vhd @@ -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'; diff --git a/src/jesd204b_link_rx.vhd b/src/jesd204b_link_rx.vhd index 8d90c88..075a106 100644 --- a/src/jesd204b_link_rx.vhd +++ b/src/jesd204b_link_rx.vhd @@ -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 ( diff --git a/src/jesd204b_multipoint_link_rx.vhd b/src/jesd204b_multipoint_link_rx.vhd index 4a453e5..f0f0d82 100644 --- a/src/jesd204b_multipoint_link_rx.vhd +++ b/src/jesd204b_multipoint_link_rx.vhd @@ -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), -- 2.48.1