Skip to content
Snippets Groups Projects
Commit 0dc64aad authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Verified with tb_tech_jes204b.vhd.

parent 29b8795f
No related branches found
No related tags found
1 merge request!381rx_clk -> dp_clk FIFO in JESD204b component.
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
-- --
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Authors : J Hargreaves, L Hiemstra -- Authors : J Hargreaves, L Hiemstra, E. Kooistra
-- Purpose: Combine IP components needed to create a JESD204B interface -- Purpose: Combine IP components needed to create a JESD204B interface
-- Initially supports RX_ONLY for receiving data from an ADC -- Initially supports RX_ONLY for receiving data from an ADC
-- Description -- Description
...@@ -119,9 +119,6 @@ architecture str of ip_arria10_e1sg_jesd204b_v2 is ...@@ -119,9 +119,6 @@ architecture str of ip_arria10_e1sg_jesd204b_v2 is
signal rxlink_rst_async_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rxlink_rst_async_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal rxlink_rst_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rxlink_rst_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal rxlink_rst : std_logic; signal rxlink_rst : std_logic;
signal rxframe_rst_async_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal dpframe_rst_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal dpframe_rst : std_logic;
signal rx_avs_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rx_avs_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal rxlink_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rxlink_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal core_pll_locked : std_logic; signal core_pll_locked : std_logic;
...@@ -145,14 +142,14 @@ architecture str of ip_arria10_e1sg_jesd204b_v2 is ...@@ -145,14 +142,14 @@ architecture str of ip_arria10_e1sg_jesd204b_v2 is
signal jesd204b_rx_link_somf_hi : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0); signal jesd204b_rx_link_somf_hi : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0);
signal jesd204b_rx_link_somf_lo : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0); signal jesd204b_rx_link_somf_lo : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0);
signal rxlink_valid : std_logic;
signal rxlink_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0) := (others => c_dp_sosi_rst); signal rxlink_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0) := (others => c_dp_sosi_rst);
signal dplink_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0); signal dplink_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0);
signal dplink_siso_arr : t_dp_siso_arr(g_nof_streams - 1 downto 0); signal dplink_siso_arr : t_dp_siso_arr(g_nof_streams - 1 downto 0);
signal fifo_state : t_fifo_state_enum; signal fifo_state : t_fifo_state_enum;
signal fifo_rd_usedw : std_logic_vector(ceil_log2(c_fifo_size) - 1 downto 0); signal fifo_rd_usedw : std_logic_vector(ceil_log2(c_fifo_size) - 1 downto 0);
signal dp_toggle : std_logic := '0'; signal fifo_filled : std_logic := '0';
signal dp_valid : std_logic := '0'; signal dp_index : std_logic := '0';
signal dp_ready : std_logic := '0';
-- debug signal to view input 0 in Wave Window -- debug signal to view input 0 in Wave Window
signal rxlink_sosi : t_dp_sosi; signal rxlink_sosi : t_dp_sosi;
...@@ -365,22 +362,28 @@ begin ...@@ -365,22 +362,28 @@ begin
sysref => rxlink_sysref sysref => rxlink_sysref
); );
-- Group jesd204b_rx_link data, valid and sync (= sysref) into rxlink_sosi_arr, -- Group jesd204b_rx_link data and sync (= sysref) into rxlink_sosi_arr. When an JESD204B interface
-- no need to transfer jesd204b rx_somf -- input is in lock, then its jesd204b_rx_link data and sync are synchronous, and the MSpart of the
-- data then contains the even (0) sample and the LSpart contains the odd (1) sample (= big endian).
-- In the rxframe_clk domain the sync is active in the even (0) sample, so in the dp_clk domain the
-- sync is passed on when the data MSpart is read and forced to '0' for the data LSpart,
-- All synchronization info is contained in the alignement of rxlink_clk, data and sync, the valid
-- does not provide additional synchronization info. The valid does indicate whether the link is in
-- lock or not, but for the subsequent data processing the sync is sufficient to start. The valid
-- could be used as monitor point, but it is sufficient to use the JESD204B IP monitor points. For
-- same reason it is also not necessary to pass on the jesd204b_rx_link_somf_arr status.
-- Therefore always write the FIFO when rxlink_clk is active and rxlink_rst is released, independent
-- of whether the input is in lock or not.
rxlink_sosi_arr(i).data <= RESIZE_DP_DATA(jesd204b_rx_link_data_arr rxlink_sosi_arr(i).data <= RESIZE_DP_DATA(jesd204b_rx_link_data_arr
(i * c_jesd204b_rx_data_w + c_jesd204b_rx_data_w - 1 downto (i * c_jesd204b_rx_data_w + c_jesd204b_rx_data_w - 1 downto
i * c_jesd204b_rx_data_w)); i * c_jesd204b_rx_data_w));
rxlink_sosi_arr(i).sync <= rxlink_sysref; rxlink_sosi_arr(i).sync <= rxlink_sysref;
rxlink_sosi_arr(i).valid <= rxlink_valid; rxlink_sosi_arr(i).valid <= '1';
-- One cycle rd-rdval latency, waitrequest = '0' fixed -- One cycle rd-rdval latency, waitrequest = '0' fixed
jesd204b_miso_arr(i).rdval <= jesd204b_mosi_arr(i).rd when rising_edge(jesd204b_avs_clk); jesd204b_miso_arr(i).rdval <= jesd204b_mosi_arr(i).rd when rising_edge(jesd204b_avs_clk);
end generate; end generate;
-- Combine into single valid if one or more inputs are valid, because all inputs are passed on
-- to dp_clk domain in parallel via a single FIFO
rxlink_valid <= vector_or(jesd204b_rx_link_valid_arr) when rising_edge(rxlink_clk);
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Reset sequencer for each channel -- Reset sequencer for each channel
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
...@@ -406,7 +409,7 @@ begin ...@@ -406,7 +409,7 @@ begin
reset_out4 => open, reset_out4 => open,
reset_out5 => rx_avs_rst_arr(i), reset_out5 => rx_avs_rst_arr(i),
reset_out6 => rxlink_rst_async_arr(i), reset_out6 => rxlink_rst_async_arr(i),
reset_out7 => rxframe_rst_async_arr(i) reset_out7 => open
); );
-- synchronize pll_reset -- synchronize pll_reset
...@@ -425,14 +428,6 @@ begin ...@@ -425,14 +428,6 @@ begin
out_rst => rxlink_rst_arr(i) out_rst => rxlink_rst_arr(i)
); );
-- synchronize rxframe reset
u_common_areset_rxframe : entity common_lib.common_areset
port map (
in_rst => rxframe_rst_async_arr(i),
clk => dp_clk,
out_rst => dpframe_rst_arr(i)
);
rx_xcvr_ready_in_arr(i) <= '1' when rx_csr_lane_powerdown_arr(i) = '1' or rx_xcvr_ready_in_arr(i) <= '1' when rx_csr_lane_powerdown_arr(i) = '1' or
xcvr_rst_ctrl_rx_ready_arr(i) = '1' else '0'; xcvr_rst_ctrl_rx_ready_arr(i) = '1' else '0';
...@@ -458,29 +453,30 @@ begin ...@@ -458,29 +453,30 @@ begin
p_deframer : process (dp_clk) p_deframer : process (dp_clk)
begin begin
if rising_edge(dp_clk) then if rising_edge(dp_clk) then
if dp_valid = '0' then if fifo_filled = '0' then
i_dp_sosi_arr(i) <= c_dp_sosi_rst; -- Force all to 0 when Rx JESD204B has stopped i_dp_sosi_arr(i) <= c_dp_sosi_rst; -- Force all to 0 when Rx JESD204B has stopped
else else
i_dp_sosi_arr(i).valid <= '1'; i_dp_sosi_arr(i).valid <= '1';
if dp_toggle = '1' then if dp_index = '0' then
-- MS data with sync at even dp_index = 0
i_dp_sosi_arr(i).sync <= dplink_sosi_arr(i).sync; i_dp_sosi_arr(i).sync <= dplink_sosi_arr(i).sync;
i_dp_sosi_arr(i).data <= RESIZE_DP_SDATA(dplink_sosi_arr(i).data( i_dp_sosi_arr(i).data <= RESIZE_DP_SDATA(dplink_sosi_arr(i).data(
c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w - 1 downto c_jesd204b_rx_data_w * i + c_jesd204b_rx_data_w - 1 downto
c_jesd204b_rx_data_w * i)); c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w));
else else
-- LS data at odd dp_index = 1
i_dp_sosi_arr(i).sync <= '0'; i_dp_sosi_arr(i).sync <= '0';
i_dp_sosi_arr(i).data <= RESIZE_DP_SDATA(dplink_sosi_arr(i).data( i_dp_sosi_arr(i).data <= RESIZE_DP_SDATA(dplink_sosi_arr(i).data(
c_jesd204b_rx_data_w * i + c_jesd204b_rx_data_w - 1 downto c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w - 1 downto
c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w)); c_jesd204b_rx_data_w * i));
end if; end if;
end if; end if;
end if; end if;
end process; end process;
end generate; -- gen_jesd204b_rx_channels : for I in 0 to g_nof_streams-1 generate end generate; -- gen_jesd204b_rx_channels : for I in 0 to g_nof_streams-1 generate
-- Combine into single resets -- Combine into single reset
rxlink_rst <= vector_or(rxlink_rst_arr) when rising_edge(rxlink_clk); rxlink_rst <= vector_or(rxlink_rst_arr) when rising_edge(rxlink_clk);
dpframe_rst <= vector_or(dpframe_rst_arr) when rising_edge(dp_clk);
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Cross from 100 MHz rxlink_clk domain to 200MHz dp_clk domain using a FIFO -- Cross from 100 MHz rxlink_clk domain to 200MHz dp_clk domain using a FIFO
...@@ -510,33 +506,51 @@ begin ...@@ -510,33 +506,51 @@ begin
src_out_arr => dplink_sosi_arr src_out_arr => dplink_sosi_arr
); );
dplink_siso_arr <= func_dp_stream_arr_set(dplink_siso_arr, dp_ready, "READY");
-- The dp_clk at 200 MHz and rxlink_clk at 100 MHz are locked to same reference. -- The dp_clk at 200 MHz and rxlink_clk at 100 MHz are locked to same reference.
-- Toggle dp_toggle every dp_clk cycle to have the same read rate in dp_clk domain, -- Toggle dp_index every dp_clk cycle to have the same read rate in dp_clk domain,
-- as the write rate in rxlink_clk domain. -- as the write rate in rxlink_clk domain.
-- Use finite state machine to fill the FIFO with fill margin above a nominal FIFO --
-- fill level, so that the dp_toggle keep on toggling once it has started, as long -- Use a finite state machine (FSM) to fill the FIFO with fill margin above a
-- as the input rxlink_sosi_arr(0).valid is active. The fill margin avoids that -- nominal FIFO fill level, so that the dp_index keeps on toggling once it has
-- started, as long as the FIFO remains filled. The fill margin avoids that
-- there can occur once a one dp_clk cycle disturbance in the toggling, in case -- there can occur once a one dp_clk cycle disturbance in the toggling, in case
-- rxlink_clk and dp_clk almost coincide. -- rxlink_clk and dp_clk almost coincide.
dplink_siso_arr <= func_dp_stream_arr_set(dplink_siso_arr, dp_toggle, "READY"); --
-- Simulation with tb_tech_jesd204b.vhd reveals that the double data word is always
p_fsm_dp_toggle : process(dp_rst, dp_clk) -- read high part first and low part next, independent of the phase of dp_index.
-- This is because reading ab, cd, ef, ... is equivalent to reading bc, de, fg, ...
-- However the phase of dp_ready with respect to dp_index is important for reading
-- the sync, because if dp_ready has the wrong phase, then the sync is missed at
-- the FIFO output.
-- . If dp_index = '0' or '1' initialy, then in both cases use dp_ready <= not
-- dp_index, and then in both cases the latency dp_sosi.sync and data = 1000 is
-- then 340 ns
-- . Do not use dp_ready <= dp_index, because then the dp_sosi.sync gets missed.
-- Therefore choose to use dp_index = '0' initially, because then dp_ready =
-- dp_index always.
p_fsm_dp_index : process(dp_rst, dp_clk)
begin begin
if dp_rst = '1' then if dp_rst = '1' then
dp_toggle <= '0'; dp_index <= '0';
dp_valid <= '0'; dp_ready <= '0';
fifo_filled <= '0';
fifo_state <= s_fifo_low; fifo_state <= s_fifo_low;
elsif rising_edge(dp_clk) then elsif rising_edge(dp_clk) then
case fifo_state is case fifo_state is
when s_fifo_low => when s_fifo_low =>
dp_toggle <= '0'; dp_index <= '0';
dp_valid <= '0'; dp_ready <= '0'; -- fill the FIFO, so no double data word request
fifo_filled <= '0';
if to_uint(fifo_rd_usedw) >= c_fifo_fill_level + c_fifo_fill_margin then if to_uint(fifo_rd_usedw) >= c_fifo_fill_level + c_fifo_fill_margin then
fifo_state <= s_fifo_filled; fifo_state <= s_fifo_filled;
end if; end if;
when others => -- = s_fifo_filled when others => -- = s_fifo_filled
dp_toggle <= not dp_toggle; dp_index <= not dp_index;
dp_valid <= '1'; dp_ready <= not dp_index; -- alternately request next double data word
fifo_filled <= '1';
if to_uint(fifo_rd_usedw) < c_fifo_fill_level then if to_uint(fifo_rd_usedw) < c_fifo_fill_level then
fifo_state <= s_fifo_low; fifo_state <= s_fifo_low;
end if; end if;
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
-- --
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Authors : J Hargreaves, L Hiemstra -- Authors : J Hargreaves, L Hiemstra, E. Kooistra
-- Purpose: Combine IP components needed to create a JESD204B interface -- Purpose: Combine IP components needed to create a JESD204B interface
-- Initially supports RX_ONLY for receiving data from an ADC -- Initially supports RX_ONLY for receiving data from an ADC
-- Description -- Description
...@@ -119,9 +119,6 @@ architecture str of ip_arria10_e2sg_jesd204b_v2 is ...@@ -119,9 +119,6 @@ architecture str of ip_arria10_e2sg_jesd204b_v2 is
signal rxlink_rst_async_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rxlink_rst_async_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal rxlink_rst_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rxlink_rst_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal rxlink_rst : std_logic; signal rxlink_rst : std_logic;
signal rxframe_rst_async_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal dpframe_rst_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal dpframe_rst : std_logic;
signal rx_avs_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rx_avs_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal rxlink_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rxlink_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal core_pll_locked : std_logic; signal core_pll_locked : std_logic;
...@@ -145,14 +142,14 @@ architecture str of ip_arria10_e2sg_jesd204b_v2 is ...@@ -145,14 +142,14 @@ architecture str of ip_arria10_e2sg_jesd204b_v2 is
signal jesd204b_rx_link_somf_hi : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0); signal jesd204b_rx_link_somf_hi : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0);
signal jesd204b_rx_link_somf_lo : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0); signal jesd204b_rx_link_somf_lo : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0);
signal rxlink_valid : std_logic;
signal rxlink_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0) := (others => c_dp_sosi_rst); signal rxlink_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0) := (others => c_dp_sosi_rst);
signal dplink_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0); signal dplink_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0);
signal dplink_siso_arr : t_dp_siso_arr(g_nof_streams - 1 downto 0); signal dplink_siso_arr : t_dp_siso_arr(g_nof_streams - 1 downto 0);
signal fifo_state : t_fifo_state_enum; signal fifo_state : t_fifo_state_enum;
signal fifo_rd_usedw : std_logic_vector(ceil_log2(c_fifo_size) - 1 downto 0); signal fifo_rd_usedw : std_logic_vector(ceil_log2(c_fifo_size) - 1 downto 0);
signal dp_toggle : std_logic := '0'; signal fifo_filled : std_logic := '0';
signal dp_valid : std_logic := '0'; signal dp_index : std_logic := '0';
signal dp_ready : std_logic := '0';
-- debug signal to view input 0 in Wave Window -- debug signal to view input 0 in Wave Window
signal rxlink_sosi : t_dp_sosi; signal rxlink_sosi : t_dp_sosi;
...@@ -365,22 +362,28 @@ begin ...@@ -365,22 +362,28 @@ begin
sysref => rxlink_sysref sysref => rxlink_sysref
); );
-- Group jesd204b_rx_link data, valid and sync (= sysref) into rxlink_sosi_arr, -- Group jesd204b_rx_link data and sync (= sysref) into rxlink_sosi_arr. When an JESD204B interface
-- no need to transfer jesd204b rx_somf -- input is in lock, then its jesd204b_rx_link data and sync are synchronous, and the MSpart of the
-- data then contains the even (0) sample and the LSpart contains the odd (1) sample (= big endian).
-- In the rxframe_clk domain the sync is active in the even (0) sample, so in the dp_clk domain the
-- sync is passed on when the data MSpart is read and forced to '0' for the data LSpart,
-- All synchronization info is contained in the alignement of rxlink_clk, data and sync, the valid
-- does not provide additional synchronization info. The valid does indicate whether the link is in
-- lock or not, but for the subsequent data processing the sync is sufficient to start. The valid
-- could be used as monitor point, but it is sufficient to use the JESD204B IP monitor points. For
-- same reason it is also not necessary to pass on the jesd204b_rx_link_somf_arr status.
-- Therefore always write the FIFO when rxlink_clk is active and rxlink_rst is released, independent
-- of whether the input is in lock or not.
rxlink_sosi_arr(i).data <= RESIZE_DP_DATA(jesd204b_rx_link_data_arr rxlink_sosi_arr(i).data <= RESIZE_DP_DATA(jesd204b_rx_link_data_arr
(i * c_jesd204b_rx_data_w + c_jesd204b_rx_data_w - 1 downto (i * c_jesd204b_rx_data_w + c_jesd204b_rx_data_w - 1 downto
i * c_jesd204b_rx_data_w)); i * c_jesd204b_rx_data_w));
rxlink_sosi_arr(i).sync <= rxlink_sysref; rxlink_sosi_arr(i).sync <= rxlink_sysref;
rxlink_sosi_arr(i).valid <= rxlink_valid; rxlink_sosi_arr(i).valid <= '1';
-- One cycle rd-rdval latency, waitrequest = '0' fixed -- One cycle rd-rdval latency, waitrequest = '0' fixed
jesd204b_miso_arr(i).rdval <= jesd204b_mosi_arr(i).rd when rising_edge(jesd204b_avs_clk); jesd204b_miso_arr(i).rdval <= jesd204b_mosi_arr(i).rd when rising_edge(jesd204b_avs_clk);
end generate; end generate;
-- Combine into single valid if one or more inputs are valid, because all inputs are passed on
-- to dp_clk domain in parallel via a single FIFO
rxlink_valid <= vector_or(jesd204b_rx_link_valid_arr) when rising_edge(rxlink_clk);
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Reset sequencer for each channel -- Reset sequencer for each channel
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
...@@ -406,7 +409,7 @@ begin ...@@ -406,7 +409,7 @@ begin
reset_out4 => open, reset_out4 => open,
reset_out5 => rx_avs_rst_arr(i), reset_out5 => rx_avs_rst_arr(i),
reset_out6 => rxlink_rst_async_arr(i), reset_out6 => rxlink_rst_async_arr(i),
reset_out7 => rxframe_rst_async_arr(i) reset_out7 => open
); );
-- synchronize pll_reset -- synchronize pll_reset
...@@ -425,14 +428,6 @@ begin ...@@ -425,14 +428,6 @@ begin
out_rst => rxlink_rst_arr(i) out_rst => rxlink_rst_arr(i)
); );
-- synchronize rxframe reset
u_common_areset_rxframe : entity common_lib.common_areset
port map (
in_rst => rxframe_rst_async_arr(i),
clk => dp_clk,
out_rst => dpframe_rst_arr(i)
);
rx_xcvr_ready_in_arr(i) <= '1' when rx_csr_lane_powerdown_arr(i) = '1' or rx_xcvr_ready_in_arr(i) <= '1' when rx_csr_lane_powerdown_arr(i) = '1' or
xcvr_rst_ctrl_rx_ready_arr(i) = '1' else '0'; xcvr_rst_ctrl_rx_ready_arr(i) = '1' else '0';
...@@ -458,29 +453,30 @@ begin ...@@ -458,29 +453,30 @@ begin
p_deframer : process (dp_clk) p_deframer : process (dp_clk)
begin begin
if rising_edge(dp_clk) then if rising_edge(dp_clk) then
if dp_valid = '0' then if fifo_filled = '0' then
i_dp_sosi_arr(i) <= c_dp_sosi_rst; -- Force all to 0 when Rx JESD204B has stopped i_dp_sosi_arr(i) <= c_dp_sosi_rst; -- Force all to 0 when Rx JESD204B has stopped
else else
i_dp_sosi_arr(i).valid <= '1'; i_dp_sosi_arr(i).valid <= '1';
if dp_toggle = '1' then if dp_index = '0' then
-- MS data with sync at even dp_index = 0
i_dp_sosi_arr(i).sync <= dplink_sosi_arr(i).sync; i_dp_sosi_arr(i).sync <= dplink_sosi_arr(i).sync;
i_dp_sosi_arr(i).data <= RESIZE_DP_SDATA(dplink_sosi_arr(i).data( i_dp_sosi_arr(i).data <= RESIZE_DP_SDATA(dplink_sosi_arr(i).data(
c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w - 1 downto c_jesd204b_rx_data_w * i + c_jesd204b_rx_data_w - 1 downto
c_jesd204b_rx_data_w * i)); c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w));
else else
-- LS data at odd dp_index = 1
i_dp_sosi_arr(i).sync <= '0'; i_dp_sosi_arr(i).sync <= '0';
i_dp_sosi_arr(i).data <= RESIZE_DP_SDATA(dplink_sosi_arr(i).data( i_dp_sosi_arr(i).data <= RESIZE_DP_SDATA(dplink_sosi_arr(i).data(
c_jesd204b_rx_data_w * i + c_jesd204b_rx_data_w - 1 downto c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w - 1 downto
c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w)); c_jesd204b_rx_data_w * i));
end if; end if;
end if; end if;
end if; end if;
end process; end process;
end generate; -- gen_jesd204b_rx_channels : for I in 0 to g_nof_streams-1 generate end generate; -- gen_jesd204b_rx_channels : for I in 0 to g_nof_streams-1 generate
-- Combine into single resets -- Combine into single reset
rxlink_rst <= vector_or(rxlink_rst_arr) when rising_edge(rxlink_clk); rxlink_rst <= vector_or(rxlink_rst_arr) when rising_edge(rxlink_clk);
dpframe_rst <= vector_or(dpframe_rst_arr) when rising_edge(dp_clk);
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Cross from 100 MHz rxlink_clk domain to 200MHz dp_clk domain using a FIFO -- Cross from 100 MHz rxlink_clk domain to 200MHz dp_clk domain using a FIFO
...@@ -510,33 +506,51 @@ begin ...@@ -510,33 +506,51 @@ begin
src_out_arr => dplink_sosi_arr src_out_arr => dplink_sosi_arr
); );
dplink_siso_arr <= func_dp_stream_arr_set(dplink_siso_arr, dp_ready, "READY");
-- The dp_clk at 200 MHz and rxlink_clk at 100 MHz are locked to same reference. -- The dp_clk at 200 MHz and rxlink_clk at 100 MHz are locked to same reference.
-- Toggle dp_toggle every dp_clk cycle to have the same read rate in dp_clk domain, -- Toggle dp_index every dp_clk cycle to have the same read rate in dp_clk domain,
-- as the write rate in rxlink_clk domain. -- as the write rate in rxlink_clk domain.
-- Use finite state machine to fill the FIFO with fill margin above a nominal FIFO --
-- fill level, so that the dp_toggle keep on toggling once it has started, as long -- Use a finite state machine (FSM) to fill the FIFO with fill margin above a
-- as the input rxlink_sosi_arr(0).valid is active. The fill margin avoids that -- nominal FIFO fill level, so that the dp_index keeps on toggling once it has
-- started, as long as the FIFO remains filled. The fill margin avoids that
-- there can occur once a one dp_clk cycle disturbance in the toggling, in case -- there can occur once a one dp_clk cycle disturbance in the toggling, in case
-- rxlink_clk and dp_clk almost coincide. -- rxlink_clk and dp_clk almost coincide.
dplink_siso_arr <= func_dp_stream_arr_set(dplink_siso_arr, dp_toggle, "READY"); --
-- Simulation with tb_tech_jesd204b.vhd reveals that the double data word is always
p_fsm_dp_toggle : process(dp_rst, dp_clk) -- read high part first and low part next, independent of the phase of dp_index.
-- This is because reading ab, cd, ef, ... is equivalent to reading bc, de, fg, ...
-- However the phase of dp_ready with respect to dp_index is important for reading
-- the sync, because if dp_ready has the wrong phase, then the sync is missed at
-- the FIFO output.
-- . If dp_index = '0' or '1' initialy, then in both cases use dp_ready <= not
-- dp_index, and then in both cases the latency dp_sosi.sync and data = 1000 is
-- then 340 ns
-- . Do not use dp_ready <= dp_index, because then the dp_sosi.sync gets missed.
-- Therefore choose to use dp_index = '0' initially, because then dp_ready =
-- dp_index always.
p_fsm_dp_index : process(dp_rst, dp_clk)
begin begin
if dp_rst = '1' then if dp_rst = '1' then
dp_toggle <= '0'; dp_index <= '0';
dp_valid <= '0'; dp_ready <= '0';
fifo_filled <= '0';
fifo_state <= s_fifo_low; fifo_state <= s_fifo_low;
elsif rising_edge(dp_clk) then elsif rising_edge(dp_clk) then
case fifo_state is case fifo_state is
when s_fifo_low => when s_fifo_low =>
dp_toggle <= '0'; dp_index <= '0';
dp_valid <= '0'; dp_ready <= '0'; -- fill the FIFO, so no double data word request
fifo_filled <= '0';
if to_uint(fifo_rd_usedw) >= c_fifo_fill_level + c_fifo_fill_margin then if to_uint(fifo_rd_usedw) >= c_fifo_fill_level + c_fifo_fill_margin then
fifo_state <= s_fifo_filled; fifo_state <= s_fifo_filled;
end if; end if;
when others => -- = s_fifo_filled when others => -- = s_fifo_filled
dp_toggle <= not dp_toggle; dp_index <= not dp_index;
dp_valid <= '1'; dp_ready <= not dp_index; -- alternately request next double data word
fifo_filled <= '1';
if to_uint(fifo_rd_usedw) < c_fifo_fill_level then if to_uint(fifo_rd_usedw) < c_fifo_fill_level then
fifo_state <= s_fifo_low; fifo_state <= s_fifo_low;
end if; end if;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment