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),