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

Add ip_arria10_e2sg_jesd204b_v2.vhd with clock domain crossing FIFO in IP

parent 89cfcb83
No related branches found
No related tags found
1 merge request!381rx_clk -> dp_clk FIFO in JESD204b component.
......@@ -2,11 +2,12 @@ hdl_lib_name = ip_arria10_e2sg_jesd204b
hdl_library_clause_name = ip_arria10_e2sg_jesd204b_lib
hdl_lib_uses_synth = technology tech_pll common dp
hdl_lib_uses_sim = ip_arria10_e2sg_altera_iopll_1930 ip_arria10_e2sg_altera_jesd204_1920 ip_arria10_e2sg_altera_reset_sequencer_191 ip_arria10_e2sg_altera_xcvr_reset_control_191
hdl_lib_technology = ip_arria10_e2sg
hdl_lib_technology = ip_arria10_e2sg
synth_files =
ip_arria10_e2sg_jesd204b_component_pkg.vhd
ip_arria10_e2sg_jesd204b.vhd
ip_arria10_e2sg_jesd204b_v2.vhd
test_bench_files =
......@@ -24,7 +25,7 @@ quartus_qip_files =
$HDL_BUILD_DIR/<buildset_name>/qsys-generate/ip_arria10_e2sg_jesd204b_tx/ip_arria10_e2sg_jesd204b_tx.qip
[generate_ip_libs]
qsys-generate_ip_files =
qsys-generate_ip_files =
ip_arria10_e2sg_jesd204b_rx_200MHz.ip
ip_arria10_e2sg_jesd204b_rx_core_pll_200MHz.ip
ip_arria10_e2sg_jesd204b_rx_reset_seq.ip
......
--------------------------------------------------------------------------------
--
-- Copyright (C) 2014
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
--------------------------------------------------------------------------------
-- Authors : J Hargreaves, L Hiemstra
-- Purpose: Combine IP components needed to create a JESD204B interface
-- Initially supports RX_ONLY for receiving data from an ADC
-- Description
-- Currently only 12 streams because of the 12 channel reset block
-- The sync_n signals are gated together to form g_nof_sync_n outputs
--
library IEEE, common_lib, dp_lib, technology_lib, ip_arria10_e2sg_jesd204b_lib;
use IEEE.std_logic_1164.all;
use technology_lib.technology_pkg.all;
use common_lib.common_pkg.all;
use common_lib.common_mem_pkg.all;
use dp_lib.dp_stream_pkg.all;
use ip_arria10_e2sg_jesd204b_lib.ip_arria10_e2sg_jesd204b_component_pkg.all;
entity ip_arria10_e2sg_jesd204b_v2 is
generic (
g_sim : boolean := false;
g_nof_streams : natural := 1;
g_nof_sync_n : natural := 1;
g_direction : string := "RX_ONLY"; -- "TX_RX", "TX_ONLY", "RX_ONLY"
g_jesd_freq : string := "200MHz"
);
port (
-- JESD204B external signals
jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock
-- reference pin
jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase with
-- respect to jesd204b_device_clk
jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization /
-- syncronization phase
-- Data to fabric
dp_clk : in std_logic;
dp_rst : in std_logic;
dp_sosi_arr : out t_dp_sosi_arr(g_nof_streams - 1 downto 0); -- Parallel data and sync to fabric
-- MM Control
mm_clk : in std_logic;
mm_rst : in std_logic;
jesd204b_disable_arr : in std_logic_vector(g_nof_streams - 1 downto 0);
jesd204b_mosi : in t_mem_mosi; -- mm control
jesd204b_miso : out t_mem_miso;
-- Serial connections to transceiver pins
serial_tx_arr : out std_logic_vector(g_nof_streams - 1 downto 0); -- Not used for ADC
serial_rx_arr : in std_logic_vector(g_nof_streams - 1 downto 0)
);
end ip_arria10_e2sg_jesd204b_v2;
architecture str of ip_arria10_e2sg_jesd204b_v2 is
-- JESD IP constants
-- . JESD204B MM has 256 bytes = 64 words, so mm_addr_w = 6 would be enough,
-- but using mm_addr_w = 8 and span = 256 words is fine too.
constant c_jesd204b_mm_addr_w : natural := 8;
constant c_jesd204b_rx_data_w : natural := 32;
constant c_jesd204b_rx_framer_data_w : natural := c_jesd204b_rx_data_w / 2; -- = 16, two samples in parallel
constant c_jesd204b_rx_somf_w : natural := c_jesd204b_rx_data_w / 8; -- = 4, one somf bit per octet
constant c_jesd204b_rx_framer_somf_w : natural := c_jesd204b_rx_somf_w / 2; -- = 2, two samples in parallel
constant c_nof_sync_n_per_group : natural := sel_a_b(g_nof_streams / g_nof_sync_n = 0,
1, g_nof_streams / g_nof_sync_n);
constant c_fifo_size : natural := 64;
constant c_fifo_fill_level : natural := 10;
constant c_fifo_fill_margin : natural := 4;
-- FSM for rxlink_clk to dp_clk FIFO read access
type t_fifo_state_enum is (s_fifo_low, s_fifo_filled);
-- JESD204 control status registers
signal jesd204b_mosi_arr : t_mem_mosi_arr(g_nof_streams - 1 downto 0);
signal jesd204b_miso_arr : t_mem_miso_arr(g_nof_streams - 1 downto 0) := (others => c_mem_miso_rst);
signal reset_seq_mosi_arr : t_mem_mosi_arr(g_nof_streams - 1 downto 0) := (others => c_mem_mosi_rst);
signal reset_seq_miso_arr : t_mem_miso_arr(g_nof_streams - 1 downto 0) := (others => c_mem_miso_rst);
-- Clocks
signal rxframe_clk : std_logic;
signal rxlink_clk : std_logic;
signal jesd204b_avs_clk : std_logic;
-- Reset and control signals, 1 bit per lane
signal dev_lane_aligned : std_logic_vector(g_nof_streams - 1 downto 0);
signal rx_analogreset_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal rx_cal_busy_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal rx_digitalreset_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal rx_islockedtodata_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal dev_lane_aligned_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal rx_csr_lane_powerdown_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal xcvr_rst_ctrl_rx_ready_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal rx_xcvr_ready_in_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal mm_rx_xcvr_ready_in_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal pll_reset_async_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal pll_reset_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal xcvr_rst_arr : std_logic_vector(g_nof_streams - 1 downto 0) := (others => '1');
signal rx_avs_rst_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 : 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 rxlink_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal core_pll_locked : std_logic;
signal mm_core_pll_locked : std_logic;
signal rxlink_sysref_1 : std_logic;
signal rxlink_sysref_2 : std_logic;
signal rxframe_sysref_1 : std_logic;
signal rxframe_sysref_2 : std_logic;
-- Data path
signal jesd204b_rx_link_data_arr : std_logic_vector(c_jesd204b_rx_data_w * g_nof_streams - 1 downto 0);
signal jesd204b_rx_link_valid_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal rxlink_valid : std_logic;
signal jesd204b_rx_somf_arr : std_logic_vector(c_jesd204b_rx_somf_w * g_nof_streams - 1 downto 0);
signal rxlink_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 fifo_state : t_fifo_state_enum;
signal fifo_rd_usedw : std_logic_vector(ceil_log2(c_fifo_size) - 1 downto 0);
signal dp_toggle : std_logic := '0';
signal dp_valid : std_logic := '0';
-- outputs to control ADC initialization/syncronization phase
signal jesd204b_sync_n_internal_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal jesd204b_sync_n_enabled_arr : std_logic_vector(g_nof_streams - 1 downto 0);
signal jesd204b_sync_n_combined_arr : std_logic_vector(g_nof_sync_n - 1 downto 0);
-- Component declarations for the IP blocks
component ip_arria10_e2sg_jesd204b_rx_200MHz is
port (
alldev_lane_aligned : in std_logic := 'X'; -- export
csr_cf : out std_logic_vector(4 downto 0); -- export
csr_cs : out std_logic_vector(1 downto 0); -- export
csr_f : out std_logic_vector(7 downto 0); -- export
csr_hd : out std_logic; -- export
csr_k : out std_logic_vector(4 downto 0); -- export
csr_l : out std_logic_vector(4 downto 0); -- export
csr_lane_powerdown : out std_logic_vector(0 downto 0); -- export
csr_m : out std_logic_vector(7 downto 0); -- export
csr_n : out std_logic_vector(4 downto 0); -- export
csr_np : out std_logic_vector(4 downto 0); -- export
csr_rx_testmode : out std_logic_vector(3 downto 0); -- export
csr_s : out std_logic_vector(4 downto 0); -- export
dev_lane_aligned : out std_logic; -- export
dev_sync_n : out std_logic; -- export
jesd204_rx_avs_chipselect : in std_logic := 'X';
jesd204_rx_avs_address : in std_logic_vector(c_jesd204b_mm_addr_w - 1 downto 0) := (others => 'X');
jesd204_rx_avs_read : in std_logic := 'X';
jesd204_rx_avs_readdata : out std_logic_vector(31 downto 0);
jesd204_rx_avs_waitrequest : out std_logic;
jesd204_rx_avs_write : in std_logic := 'X';
jesd204_rx_avs_writedata : in std_logic_vector(31 downto 0) := (others => 'X');
jesd204_rx_avs_clk : in std_logic := 'X';
jesd204_rx_avs_rst_n : in std_logic := 'X';
jesd204_rx_dlb_data : in std_logic_vector(31 downto 0) := (others => 'X'); -- export
jesd204_rx_dlb_data_valid : in std_logic_vector(0 downto 0) := (others => 'X'); -- export
jesd204_rx_dlb_disperr : in std_logic_vector(3 downto 0) := (others => 'X'); -- export
jesd204_rx_dlb_errdetect : in std_logic_vector(3 downto 0) := (others => 'X'); -- export
jesd204_rx_dlb_kchar_data : in std_logic_vector(3 downto 0) := (others => 'X'); -- export
jesd204_rx_frame_error : in std_logic := 'X'; -- export
jesd204_rx_int : out std_logic; -- irq
jesd204_rx_link_data : out std_logic_vector(c_jesd204b_rx_data_w - 1 downto 0); -- data
jesd204_rx_link_valid : out std_logic; -- valid
jesd204_rx_link_ready : in std_logic := 'X'; -- ready
pll_ref_clk : in std_logic := 'X'; -- clk
rx_analogreset : in std_logic_vector(0 downto 0) := (others => 'X'); -- rx_analogreset
rx_cal_busy : out std_logic_vector(0 downto 0); -- rx_cal_busy
rx_digitalreset : in std_logic_vector(0 downto 0) := (others => 'X'); -- rx_digitalreset
rx_islockedtodata : out std_logic_vector(0 downto 0); -- rx_is_lockedtodata
rx_serial_data : in std_logic_vector(0 downto 0) := (others => 'X'); -- rx_serial_data
rxlink_clk : in std_logic := 'X'; -- clk
rxlink_rst_n_reset_n : in std_logic := 'X'; -- reset_n
rxphy_clk : out std_logic_vector(0 downto 0); -- export
sof : out std_logic_vector(3 downto 0); -- export
somf : out std_logic_vector(c_jesd204b_rx_somf_w - 1 downto 0); -- export
sysref : in std_logic := 'X' -- export
);
end component ip_arria10_e2sg_jesd204b_rx_200MHz;
component ip_arria10_e2sg_jesd204b_rx_core_pll_200MHz is
port (
locked : out std_logic; -- export
outclk_0 : out std_logic; -- clk
outclk_1 : out std_logic; -- clk
refclk : in std_logic := 'X'; -- clk
rst : in std_logic := 'X' -- reset
);
end component ip_arria10_e2sg_jesd204b_rx_core_pll_200MHz;
component ip_arria10_e2sg_jesd204b_rx_reset_seq is
port (
av_address : in std_logic_vector(7 downto 0) := (others => 'X'); -- address
av_readdata : out std_logic_vector(31 downto 0); -- readdata
av_read : in std_logic := 'X'; -- read
av_writedata : in std_logic_vector(31 downto 0) := (others => 'X'); -- writedata
av_write : in std_logic := 'X'; -- write
irq : out std_logic; -- irq
clk : in std_logic := 'X'; -- clk
csr_reset : in std_logic := 'X'; -- reset
reset1_dsrt_qual : in std_logic := 'X'; -- reset1_dsrt_qual
reset2_dsrt_qual : in std_logic := 'X'; -- reset2_dsrt_qual
reset5_dsrt_qual : in std_logic := 'X'; -- reset5_dsrt_qual
reset_in0 : in std_logic := 'X'; -- reset
reset_out0 : out std_logic; -- reset
reset_out1 : out std_logic; -- reset
reset_out2 : out std_logic; -- reset
reset_out3 : out std_logic; -- reset
reset_out4 : out std_logic; -- reset
reset_out5 : out std_logic; -- reset
reset_out6 : out std_logic; -- reset
reset_out7 : out std_logic -- reset
);
end component ip_arria10_e2sg_jesd204b_rx_reset_seq;
component ip_arria10_e2sg_jesd204b_rx_xcvr_reset_control_12 is
port (
clock : in std_logic := 'X'; -- clk
reset : in std_logic := 'X'; -- reset
rx_analogreset : out std_logic_vector(11 downto 0); -- rx_analogreset
rx_cal_busy : in std_logic_vector(11 downto 0) := (others => 'X'); -- rx_cal_busy
rx_digitalreset : out std_logic_vector(11 downto 0); -- rx_digitalreset
rx_is_lockedtodata : in std_logic_vector(11 downto 0) := (others => 'X'); -- rx_is_lockedtodata
rx_ready : out std_logic_vector(11 downto 0) -- rx_ready
);
end component ip_arria10_e2sg_jesd204b_rx_xcvr_reset_control_12;
begin
-- The mm_rst resets the MM interface, but is also used to reset the JESD IP reset sequencer.
-- Therefore a reset of mm_rst effectively resets the entire ip_arria10_e2sg_jesd204b.
-- The avs clock is driven by the rxlink_clk for simulation. This is a workaround for a bug
-- in the Q18.0 IP where the jesd receiver fails to recognize the SYSREF pulse
gen_simclock : if g_sim = true generate
jesd204b_avs_clk <= rxlink_clk;
end generate;
-- For synthesis the avs clock is driven by the mm_clk as usual
gen_synthclock : if g_sim = false generate
jesd204b_avs_clk <= mm_clk;
end generate;
gen_jesd204b_rx : if g_direction = "RX_ONLY" generate
gen_jesd204b_rx_channels : for I in 0 to g_nof_streams - 1 generate
-----------------------------------------------------------------------------
-- The JESD204 IP (rx only)
-----------------------------------------------------------------------------
gen_jesd204b_rx_freqsel : if g_jesd_freq = "200MHz" generate
u_ip_arria10_e2sg_jesd204b_rx_200MHz : ip_arria10_e2sg_jesd204b_rx_200MHz
port map (
alldev_lane_aligned => dev_lane_aligned_arr(i),
csr_cf => OPEN,
csr_cs => OPEN,
csr_f => OPEN,
csr_hd => OPEN,
csr_k => OPEN,
csr_l => OPEN,
csr_lane_powerdown => rx_csr_lane_powerdown_arr(i downto i),
csr_m => OPEN,
csr_n => OPEN,
csr_np => OPEN,
csr_rx_testmode => OPEN,
csr_s => OPEN,
dev_lane_aligned => dev_lane_aligned_arr(i),
dev_sync_n => jesd204b_sync_n_internal_arr(i),
jesd204_rx_avs_chipselect => '1',
jesd204_rx_avs_address => jesd204b_mosi_arr(i).address(c_jesd204b_mm_addr_w - 1 downto 0),
jesd204_rx_avs_read => jesd204b_mosi_arr(i).rd,
jesd204_rx_avs_readdata => jesd204b_miso_arr(i).rddata(31 downto 0),
jesd204_rx_avs_waitrequest => jesd204b_miso_arr(i).waitrequest,
jesd204_rx_avs_write => jesd204b_mosi_arr(i).wr,
jesd204_rx_avs_writedata => jesd204b_mosi_arr(i).wrdata(31 downto 0),
jesd204_rx_avs_clk => jesd204b_avs_clk,
jesd204_rx_avs_rst_n => rx_avs_rst_n_arr(i),
jesd204_rx_dlb_data => (others => '0'), -- debug/loopback testing
jesd204_rx_dlb_data_valid => (others => '0'), -- debug/loopback testing
jesd204_rx_dlb_disperr => (others => '0'), -- debug/loopback testing
jesd204_rx_dlb_errdetect => (others => '0'), -- debug/loopback testing
jesd204_rx_dlb_kchar_data => (others => '0'), -- debug/loopback testing
jesd204_rx_frame_error => '0', -- jesd204_rx_frame_error.export
jesd204_rx_int => OPEN, -- Connected to status IO in example design
jesd204_rx_link_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),
jesd204_rx_link_valid => jesd204b_rx_link_valid_arr(i),
jesd204_rx_link_ready => '1',
pll_ref_clk => jesd204b_refclk, -- Aka device_clock, same as reference for the link/frame
-- clock IOPLL (Intel JESD204B-UG p63)
rx_analogreset => rx_analogreset_arr(I downto I),
rx_cal_busy => rx_cal_busy_arr(I downto I),
rx_digitalreset => rx_digitalreset_arr(I downto I),
rx_islockedtodata => rx_islockedtodata_arr(I downto I),
rx_serial_data => serial_rx_arr(i downto i),
rxlink_clk => rxlink_clk,
rxlink_rst_n_reset_n => rxlink_rst_n_arr(i), -- Assoc with rxlink_clk (Intel JESD204B-UG p69)
rxphy_clk => OPEN, -- Not used in Subclass 0 (Intel JESD204B-UG p63)
sof => OPEN,
somf => jesd204b_rx_somf_arr(c_jesd204b_rx_somf_w * i + c_jesd204b_rx_somf_w - 1
downto c_jesd204b_rx_somf_w * i),
sysref => rxlink_sysref_2
);
-- Group jesd204b_rx_link data, valid and sync (= sysref) into rxlink_sosi_arr,
-- no need to transfer jesd204b rx_somf
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));
rxlink_sosi_arr(i).sync <= rxlink_sysref_2;
rxlink_sosi_arr(i).valid <= rxlink_valid;
-- One cycle rd-rdval latency, waitrequest = '0' fixed
jesd204b_miso_arr(i).rdval <= jesd204b_mosi_arr(i).rd when rising_edge(jesd204b_avs_clk);
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
-----------------------------------------------------------------------------
u_ip_arria10_e2sg_jesd204b_rx_reset_seq : ip_arria10_e2sg_jesd204b_rx_reset_seq
port map (
av_address => reset_seq_mosi_arr(i).address(7 downto 0),
av_readdata => reset_seq_miso_arr(i).rddata(31 downto 0),
av_read => reset_seq_mosi_arr(i).rd,
av_writedata => reset_seq_mosi_arr(i).wrdata(31 downto 0),
av_write => reset_seq_mosi_arr(i).wr,
irq => open,
clk => mm_clk, -- use clk = mm_clk for av_* port
csr_reset => mm_rst,
reset1_dsrt_qual => mm_core_pll_locked, -- core pll_locked synchronised to clk = mm_clk domain
reset2_dsrt_qual => '1', -- Tied to '1' in example design. Tx xcvr is not used.
reset5_dsrt_qual => mm_rx_xcvr_ready_in_arr(i),
reset_in0 => mm_rst,
-- reset_out* signals are in mm_clk domain
reset_out0 => pll_reset_async_arr(i), -- Use channel 0 to reset the core pll
reset_out1 => xcvr_rst_arr(i), -- Use channel 1 to reset the transceiver reset controller
reset_out2 => open,
reset_out3 => open,
reset_out4 => open,
reset_out5 => rx_avs_rst_arr(i),
reset_out6 => rxlink_rst_async_arr(i),
reset_out7 => rxframe_rst_async_arr(i)
);
-- synchronize pll_reset
u_common_areset_pll : entity common_lib.common_areset
port map (
in_rst => pll_reset_async_arr(i),
clk => jesd204b_refclk,
out_rst => pll_reset_arr(i)
);
-- synchronize rxlink reset
u_common_areset_rxlink : entity common_lib.common_areset
port map (
in_rst => rxlink_rst_async_arr(i),
clk => rxlink_clk,
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
xcvr_rst_ctrl_rx_ready_arr(i) = '1' else '0';
-- synchronize rx_xcvr_ready_in_arr to mm_clk
u_common_async_rx_xcvr_ready : entity common_lib.common_async
generic map (
g_rst_level => '0' -- When in_rst is asserted, dout = '0'
)
port map (
rst => mm_rst,
clk => mm_clk,
din => rx_xcvr_ready_in_arr(i),
dout => mm_rx_xcvr_ready_in_arr(i)
);
-- Invert the active-low resets
rx_avs_rst_n_arr(i) <= not rx_avs_rst_arr(i);
rxlink_rst_n_arr(i) <= not rxlink_rst_arr(i);
-----------------------------------------------------------------------------
-- Deframers in dp_clk domain
-----------------------------------------------------------------------------
p_deframer : process (dp_clk)
begin
if rising_edge(dp_clk) then
if dp_valid = '0' then
dp_sosi_arr(i) <= c_dp_sosi_rst; -- Force all to 0 when Rx JESD204B has stopped
else
dp_sosi_arr(i).valid <= '1';
if dp_toggle = '1' then
dp_sosi_arr(i).sync <= dplink_sosi_arr(i).sync;
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));
else
dp_sosi_arr(i).sync <= '0';
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));
end if;
end if;
end if;
end process;
end generate; -- gen_jesd204b_rx_channels : for I in 0 to g_nof_streams-1 generate
-- Combine into single resets
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
-----------------------------------------------------------------------------
-- The dp_fifo_core_arr.vhd FIFO in dp_fifo_dc_arr.vhd.vhd passes on for ctrl and info
-- fields from snk_in_arr(0) and data fields from all snk_in_arr(). Similar for flow
-- control the FIFO uses src_in_arr(0).ready as read strobe. Using only input (0) is
-- possible, because all snk_in_arr() inputs will have same ctrl and info when Rx
-- JESD204B IP is synchronized.
u_dp_fifo_dc_arr : entity dp_lib.dp_fifo_dc_arr
generic map (
g_nof_streams => g_nof_streams,
g_data_w => c_jesd204b_rx_framer_data_w, -- 16b
g_data_signed => true,
g_use_sync => true,
g_use_channel => false, -- no need to pass on jesd204b_rx_somf_arr
g_fifo_size => c_fifo_size
)
port map (
wr_rst => rxlink_rst,
wr_clk => rxlink_clk,
rd_rst => dp_rst,
rd_clk => dp_clk,
rd_usedw => fifo_rd_usedw,
snk_in_arr => rxlink_sosi_arr,
src_in_arr => dplink_siso_arr,
src_out_arr => dplink_sosi_arr
);
-- 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,
-- 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
-- as the input rxlink_sosi_arr(0).valid is active. The fill margin avoids that
-- there can occur once a one dp_clk cycle disturbance in the toggling, in case
-- rxlink_clk and dp_clk almost coincide.
dplink_siso_arr <= func_dp_stream_arr_set(dplink_siso_arr, dp_toggle, "READY");
p_fsm_dp_toggle : process(dp_rst, dp_clk)
begin
if dp_rst = '1' then
dp_toggle <= '0';
dp_valid <= '0';
fifo_state <= s_fifo_low;
elsif rising_edge(dp_clk) then
case fifo_state is
when s_fifo_low =>
dp_toggle <= '0';
dp_valid <= '0';
if to_uint(fifo_rd_usedw) >= c_fifo_fill_level + c_fifo_fill_margin then
fifo_state <= s_fifo_filled;
end if;
when others => -- = s_fifo_filled
dp_toggle <= not dp_toggle;
dp_valid <= '1';
if to_uint(fifo_rd_usedw) < c_fifo_fill_level then
fifo_state <= s_fifo_low;
end if;
end case;
end if;
end process;
-----------------------------------------------------------------------------
-- Reclock sysref and the sync_n output
-- See: https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_jesd204b.pdf
-- Figure 25, page 151
-----------------------------------------------------------------------------
p_reclocksysref : process (core_pll_locked, rxlink_clk)
begin
if core_pll_locked = '0' then
rxlink_sysref_1 <= '0';
rxlink_sysref_2 <= '0';
jesd204b_sync_n_arr <= (others => '0');
elsif rising_edge(rxlink_clk) then
rxlink_sysref_1 <= jesd204b_sysref;
rxlink_sysref_2 <= rxlink_sysref_1;
jesd204b_sync_n_arr <= jesd204b_sync_n_combined_arr;
end if;
end process;
-- IOPLL in source synchronous or normal mode. (Intel JESD204B-UG p66)
gen_jesd204b_rx_corepll_freqsel : if g_jesd_freq = "200MHz" generate
u_ip_arria10_e2sg_jesd204b_rx_corepll_200MHz : ip_arria10_e2sg_jesd204b_rx_core_pll_200MHz
port map (
locked => core_pll_locked,
outclk_0 => rxlink_clk, -- out 100 MHz
outclk_1 => rxframe_clk, -- out 200 MHz
refclk => jesd204b_refclk, -- in 200 MHz
rst => pll_reset_arr(0)
);
end generate;
u_common_areset_pll_locked : entity common_lib.common_areset
generic map (
g_in_rst_level => '0', -- synchronises the rising edge of input in_rst.
g_rst_level => '0'
)
port map (
in_rst => core_pll_locked,
clk => mm_clk,
out_rst => mm_core_pll_locked
);
-- Transceiver reset controller. Use g_nof_streams out of 12 channels. Receive only
-- Clock set to 100MHz (use rxlink_clk)
u_ip_arria10_e2sg_jesd204b_rx_xcvr_reset_control : ip_arria10_e2sg_jesd204b_rx_xcvr_reset_control_12
port map (
clock => rxlink_clk,
reset => xcvr_rst_arr(0), -- From Reset Sequencer output1 as per example design,
-- the reset input is synchronised internally.
rx_analogreset => rx_analogreset_arr, -- output to reset RX PMA. Release before deasserting
-- link and avs resets (Intel JESD204B-UG p70)
rx_cal_busy => rx_cal_busy_arr, -- input from PHY
rx_digitalreset => rx_digitalreset_arr, -- output to reset RX PCS. Release before deasserting
-- link and avs resets (Intel JESD204B-UG p70)
rx_is_lockedtodata => rx_islockedtodata_arr, -- input from PHY
rx_ready => xcvr_rst_ctrl_rx_ready_arr -- From example design: gate with
-- rx_csr_lane_powerdown to reset transceiver
);
end generate; -- gen_jesd204b_rx : IF g_direction = "RX_ONLY" GENERATE
gen_enable_sync_n : for i in 0 to g_nof_streams - 1 generate
-- The sync_n_enabled output is active '0'. For disabled signal inputs the sync_n_enabled output
-- is forced to '1', so that for the disabled (= inactive = not used)
-- signal inputs the sync_n_internal from the JESD IP will not pull sync_n_enabled low.
-- The purpose of being able to disable inactive signal inputs is that this avoids that one
-- inactive signal input will cause all signal inputs in a group that share the sync_n_combined
-- to become unavailable (see gen_group_sync_n).
-- For disabled channels (in jesd204b_disable_arr), the SYNC_N output will not be used
jesd204b_sync_n_enabled_arr(i) <= jesd204b_sync_n_internal_arr(i) or jesd204b_disable_arr(i);
end generate;
-----------------------------------------------------------------------------
-- Group the SYNC_N outputs
-----------------------------------------------------------------------------
gen_group_sync_n : for i in 0 to g_nof_sync_n - 1 generate
jesd204b_sync_n_combined_arr(i) <= vector_and(jesd204b_sync_n_enabled_arr(
c_nof_sync_n_per_group * i + c_nof_sync_n_per_group - 1 downto
c_nof_sync_n_per_group * i));
end generate;
-----------------------------------------------------------------------------
-- MM bus mux
-----------------------------------------------------------------------------
u_common_mem_mux_mac : entity common_lib.common_mem_mux
generic map (
g_nof_mosi => g_nof_streams,
g_mult_addr_w => c_jesd204b_mm_addr_w
)
port map (
mosi => jesd204b_mosi,
miso => jesd204b_miso,
mosi_arr => jesd204b_mosi_arr,
miso_arr => jesd204b_miso_arr
);
end str;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment