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,