library ieee;
use ieee.std_logic_1164.all;
use work.jesd204b_pkg.all;
use work.data_link_pkg.all;
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
-- frame character
A_character : std_logic_vector(7 downto 0) := "01111100"; -- Multiframe
-- alignment character
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_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;
co_error : out std_logic;
di_transceiver_data : in lane_input_array(0 to LANES - 1);
do_samples : out simple_samples_array(0 to LINKS - 1)(0 to CONFIG(0).M - 1, 0 to CONFIG(0).CS - 1);
co_frame_state : out frame_state_array(0 to LINKS - 1);
co_correct_data : out std_logic);
end entity jesd204b_multipoint_link_rx;
architecture a1 of jesd204b_multipoint_link_rx is
constant all_ones : std_logic_vector(LINKS - 1 downto 0) := (others => '1');
constant all_zeros : std_logic_vector(LINKS - 1 downto 0) := (others => '0');
signal links_correct_data : std_logic_vector(LINKS - 1 downto 0);
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)
return integer is
variable lanes_count : integer := 0;
begin -- function sumCummulativeLanes
if link_index /= 0 then
for i in 0 to link_index -1 loop
lanes_count := lanes_count + CONFIG(i).L;
end loop; -- i
end if;
return lanes_count;
end function sumCummulativeLanes;
-- purpose: Count converters before link with index link_index
function sumCummulativeConverters (
link_index : integer range 0 to LINKS-1)
return integer is
variable converters_count : integer := 0;
begin -- function sumCummulativeConverters
if link_index /= 0 then
for i in 0 to link_index -1 loop
converters_count := converters_count + CONFIG(i).M;
end loop; -- i
end if;
return converters_count;
end function sumCummulativeConverters;
begin -- architecture a1
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';
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,
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),
co_frame_state => co_frame_state(i),
co_correct_data => links_correct_data(i));
end generate links_rx;
end architecture a1;