Skip to content
Snippets Groups Projects
Commit 634d058b authored by Pepping's avatar Pepping
Browse files

Copied source files from $UNB

parent 39d783d0
No related branches found
No related tags found
No related merge requests found
-------------------------------------------------------------------------------
--
-- Copyright (C) 2012
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
--
-------------------------------------------------------------------------------
-- Purpose: User Rx interface for the UniBoard mesh
--
-- Description:
-- . The node_fn_terminal_db can receive up to 4*4 user steams via 4*3 phy
-- lanes on the UniBoard mesh. The phy streams are DP/UTH encoded and
-- get decoded and output via dp_out_sosi_arr.
-- . If g_mesh_use_tx=TRUE then the node_fn_terminal_db can also transmit test
-- data for bidirectional transceiver diagnostic purposes. The IO phy is
-- tr_nonbonded.
-- . If g_use_bsn_align=TRUE then the dp_out_sosi_arr user streams are also
-- BSN aligned.
-- . If g_use_data_buf=TRUE then at every sync the dp_out_sosi_arr blocks get
-- captured into a diag_databuffer for monitoring via MM.
-- . If g_mesh_mon_select/=0 then also internal signals in the
-- unb_terminals_mesh can be monitored via a diag_databuffer.
--
-- Remarks:
--
-- Explanation of impact of dp_distribute on c_rx_output_fifo_size:
-- The terminals transport c_usr_nof_streams_per_bus=4 blocks onto
-- g_mesh_nof_serial=3 lanes. This has an impact on c_rx_output_fifo_size.
-- The dp_distribute from 4 --> 3 causes a transpose such that the 4 usr
-- streams for t=0 are being transmitted via lane 0. While this happens
-- one g_usr_block_per later the 4 usr blocks for t=1 will be transmitted
-- via lane 1, and again one g_usr_block_per later the 4 usr blocks for
-- t=2 will be transmitted via lane 2:
--
-- 3*g_usr_block_per 3*g_usr_block_per 3*g_usr_block_per
-- <-----------------><-----------------><----------------->
-- lane 0: Block_0_1_2_3(t0) Block_0_1_2_3(t3) Block_0_1_2_3(t6)
-- lane 1: Block_0_1_2_3(t1) Block_0_1_2_3(t4) ...
-- lane 2: Block_0_1_2_3(t2) Block_0_1_2_3(t5) ...
--
-- In fact the transport of the 4 usr streams via one lane takes 3 time
-- blocks (= 3*g_usr_block_per). The BSN aligner needs to align the 4
-- usr streams until they are all present at the inputs of the BSN aligner
-- the FIFO must be able to buffer c_burst_usr_nof_block = 3 blocks,
-- because there are g_mesh_nof_serial-1 = +2 other lanes that already
-- send blocks for t1 and t2 during t0 on lane 0 and +1 because it is a
-- fill FIFO that stores at least 1 complete frame.
--
-- Explanation of impact of dp_distribute on BSN align latency:
-- In a subrack simulation with g_unb_sys=4,1,4 it follows that the BSN
-- difference can be as much as 4 for UNB1/FN0. The time difference
-- between BSN 0 for these two streams is then 5195 ns = 4.06
-- g_usr_block_per. For a single UniBoard simulation with g_unb_sys=1,1,4
-- it follows that the BSN difference becomes 2 and almost 3. The time
-- difference between these two streams is than 2495 ns = 1.95
-- g_usr_block_per. To support c_bsn_latency for the dp_bsn_align the
-- c_burst_bsn_latency therefore needs to be increased. For both subrack
-- and single Uniboard (as set by g_multi_unb) choose the same BSN latency
-- adjustment of +c_burst_usr_nof_block. For the subrack sop timeout needs
-- to be even > 5 g_usr_block_per, because otherwise the BSN difference
-- of 4 still gets missed. Therefore use c_bsn_latency = 2, so then
-- c_burst_bsn_latency = 2 + 3 = 5. Note that for the BSN comparison logic
-- the preferred values for g_bsn_latency are 3, 7, 15 because these
-- require the least logic. Similar for the c_rx_output_fifo_size
-- g_bsn_latency = 3 and 7 would result in using 1 RAMB or 2 RAMB in
-- case that g_usr_block_len=96. Therefore choose c_bsn_latency = 3 to
-- have some extra margin without logic or RAMB cost. The rules from
-- dp_bsn_align.vhd for how to choose the timeouts and the FIFO size
-- should therefore now be applied with c_burst_bsn_latency.
--
-- Explanation of impact of dp_distribute on c_phy_rx_fifo_size:
-- The dp_distribute uses one of the dual clock FIFO in tr_nonbonded to
-- fill with less than 1 block, the dual clock FIFOs on the oFirmware/designs/fn_terminal_db/src/vhdl/node_fn_terminal_db.vhdther
-- g_mesh_nof_serial-1 lanes only fill with 1 word. This less than one
-- block was observed in simulation. Assume that indeed c_phy_rx_fifo_len
-- = 1 block is sufficient to avoid using more RAM than needed.
--
-- Explanation of impact of c_rx_timeout_w on c_phy_rx_fifo_size:
-- The uth_rx timeout ensures that the rx FIFO in tr_nonbonded does not
-- overflow if the reception should suddenly stop during a frame.
-- If the c_rx_timeout_w is set +1 larger then the rx FIFO will overflow
-- as was seen in simulation. Temporarily setting the severity in
-- proc_common_fifo_asserts() to ERROR instead of FAILURE shows that the
-- terminals will recover from this overflow. The reason is that the
-- overflow will not corrupt the FIFO control, the uth_rx will ensure
-- that only complete packets get passed on and the BSN aligner will
-- after some flushing then recover the Rx alignment.
-- The uth_rx timeout restarts on every valid. In simulation one of the
-- 4 uth_rx reaches a timeout_cnt of 71 so close to 1 g_usr_block_per.
-- The other three reach at most 2 words. Typically the gap should be
-- < g_usr_block_len, because that is the maximum time that the BSN
-- aligner holds the sop. Hence using ceil_log2(g_usr_block_per)
-- yields a sufficient upper value. It is not necessary to add +1. It
-- is also not good to use less, because there could occur quite some
-- data not valid gap time between the sop and the next valid, due to
-- the BSN aligner.
--
-- Some more remarks:
-- . Use ceil_value to get the maximum FIFO size for the requested size.
-- . In fact c_burst_usr_nof_block depends on whether the terminals use
-- dp_distribute, because dp_distribute causes a transpose that results
-- in a burst.
-- . The c_bsn_latency also depends on whether there is a backplane or
-- not so on g_multi_unb. Therefore alternatively c_bsn_latency =
-- sel_a_b(g_multi_unb, 3, 0) could be used.
-- . Alternatively c_bsn_latency could be made available as generic and
-- set directly by the user. The c_burst_usr_nof_block can then be
-- removed to let all settings directly depend on g_bsn_latency. The
-- advantage is that it
LIBRARY IEEE, common_lib, dp_lib, unb_common_lib, diag_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE unb_common_lib.unb_common_pkg.ALL;
ENTITY node_fn_terminal_db IS
GENERIC(
g_sim : BOOLEAN := FALSE;
g_sim_level : NATURAL := 0; -- 0 = simulate GX IP, 1 = use fast serial behavioural model
g_use_bsn_align : BOOLEAN := TRUE; -- default TRUE, support FALSE for packet flow debugging purposes (faster synthesis)
g_use_data_buf : BOOLEAN := TRUE;
-- Application Interface
g_usr_nof_streams : NATURAL := 16;
g_usr_data_w : NATURAL := 32;
g_usr_block_len : NATURAL := 96;
g_usr_block_per : NATURAL := 256; -- block period = block length + gap length
-- Terminals Interface
g_multi_unb : BOOLEAN := FALSE;
g_use_mesh : BOOLEAN := TRUE;
g_mesh_nof_serial : NATURAL := 3; -- default only use the 3 full featured transceivers in the mesh (out of maximal 4), using only 2 is not enough
g_mesh_gx_mbps : NATURAL := 5000;
g_mesh_ena_reorder : BOOLEAN := TRUE;
g_mesh_use_tx : BOOLEAN := TRUE; -- can be FALSE for BF, use TRUE to support for bidirectional TR diagnostics
g_mesh_mon_select : NATURAL := 0; -- 0 = no data monitor buffers via MM, else see unb_terminals_mesh.vhd
g_mesh_mon_nof_words : NATURAL := 1024;
g_mesh_mon_use_sync : BOOLEAN := TRUE;
-- Auxiliary Interface
g_aux : t_c_unb_aux := c_unb_aux
);
PORT(
-- System
chip_id : IN STD_LOGIC_VECTOR(g_aux.chip_id_w-1 DOWNTO 0); -- [2:0]
mm_rst : IN STD_LOGIC;
mm_clk : IN STD_LOGIC; -- 50 MHz from xo_clk PLL in SOPC system
dp_rst : IN STD_LOGIC;
dp_clk : IN STD_LOGIC; -- 200 MHz from CLK system clock
dp_pps : IN STD_LOGIC := '0';
tr_mesh_clk : IN STD_LOGIC; -- 156.25 MHz from SB_CLK transceiver clock
cal_clk : IN STD_LOGIC; -- 40 MHz from xo_clk PLL in SOPC system
-- MM interface
-- . diag_data_buffer
ram_diag_data_buf_mosi : IN t_mem_mosi := c_mem_mosi_rst;
ram_diag_data_buf_miso : OUT t_mem_miso;
reg_diag_data_buf_mosi : IN t_mem_mosi := c_mem_mosi_rst;
reg_diag_data_buf_miso : OUT t_mem_miso;
-- . tr_nonbonded
reg_tr_nonbonded_mosi : IN t_mem_mosi := c_mem_mosi_rst;
reg_tr_nonbonded_miso : OUT t_mem_miso;
reg_diagnostics_mosi : IN t_mem_mosi := c_mem_mosi_rst;
reg_diagnostics_miso : OUT t_mem_miso;
-- . diag_data_buffer_mesh
ram_mesh_diag_data_buf_mosi : IN t_mem_mosi := c_mem_mosi_rst;
ram_mesh_diag_data_buf_miso : OUT t_mem_miso;
-- . bsn_monitor
reg_bsn_monitor_mosi : IN t_mem_mosi := c_mem_mosi_rst;
reg_bsn_monitor_miso : OUT t_mem_miso;
-- Node stream out
dp_out_sosi_arr : OUT t_dp_sosi_arr(g_usr_nof_streams-1 DOWNTO 0);
dp_out_siso_arr : IN t_dp_siso_arr(g_usr_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
-- Mesh serial interface (tr_nonbonded)
tx_serial_2arr : OUT t_unb_mesh_sl_2arr; -- Tx
rx_serial_2arr : IN t_unb_mesh_sl_2arr:= (OTHERS=>(OTHERS=>'0')) -- Rx support for diagnostics
);
END node_fn_terminal_db;
ARCHITECTURE str OF node_fn_terminal_db IS
-----------------------------------------------------------------------------
-- BSN align
-----------------------------------------------------------------------------
CONSTANT c_bsn_request_pipeline : NATURAL := 2; -- need to use 2 to ease timing closure at 200 MHz
CONSTANT c_bsn_latency : NATURAL := 3;
CONSTANT c_burst_usr_nof_block : NATURAL := g_mesh_nof_serial; -- 3 phy lane blocks t012 per user stream
CONSTANT c_burst_bsn_latency : NATURAL := c_bsn_latency + c_burst_usr_nof_block;
-----------------------------------------------------------------------------
-- Terminals
-----------------------------------------------------------------------------
CONSTANT c_usr_nof_streams_per_bus : NATURAL := g_usr_nof_streams/c_unb_nof_bn; -- 16 / 4 = 4
-- . tr_nonbonded rx fifo
CONSTANT c_burst_phy_nof_block : NATURAL := c_usr_nof_streams_per_bus; -- burst of 4 usr blocks per t0 per phy lane
CONSTANT c_phy_block_len : NATURAL := g_usr_block_len; -- no data packing so phy frame is about as long as the user frame (expect for few overhead words)
CONSTANT c_phy_rx_fifo_len : NATURAL := c_phy_block_len * 1; -- assume only need to store less than one block in practise
CONSTANT c_phy_rx_fifo_size : NATURAL := ceil_value(c_phy_rx_fifo_len, c_bram_m9k_fifo_depth); -- use tr_nonbonded Rx dual clock FIFO to buffer for dp_distribute
-- . uth_rx timeout_cnt
CONSTANT c_rx_timeout_w : NATURAL := 0;--ceil_log2(g_usr_block_per);
-- . uth_terminal_rx output fifo
CONSTANT c_rx_output_fifo_len : NATURAL := (c_burst_bsn_latency + 2) * g_usr_block_len;
CONSTANT c_rx_output_fifo_size : NATURAL := ceil_value(c_rx_output_fifo_len, c_bram_m9k_fifo_depth);
CONSTANT c_rx_output_fifo_fill : NATURAL := g_usr_block_len; -- keep a full block in the FIFO to ensure that dp_bsn_align gets input without data not valid gaps when the lane rate is slower (as with tr_nonbonded)
-- . BSN aligner timeouts
CONSTANT c_sop_timeout : NATURAL := (c_burst_bsn_latency + 1) * g_usr_block_per; -- wait for sop for some block periods
CONSTANT c_xoff_timeout : NATURAL := c_burst_bsn_latency * 2 * g_usr_block_per;
SIGNAL rx_usr_siso_2arr : t_unb_mesh_siso_2arr;
SIGNAL rx_usr_sosi_2arr : t_unb_mesh_sosi_2arr;
SIGNAL rx_rew_siso_2arr : t_unb_mesh_siso_2arr;
SIGNAL rx_rew_sosi_2arr : t_unb_mesh_sosi_2arr;
SIGNAL rx_usr_siso_arr : t_dp_siso_arr(g_usr_nof_streams-1 DOWNTO 0);
SIGNAL rx_usr_sosi_arr : t_dp_sosi_arr(g_usr_nof_streams-1 DOWNTO 0);
-----------------------------------------------------------------------------
-- Data buffer
-----------------------------------------------------------------------------
SIGNAL db_in_sosi_arr : t_dp_sosi_arr(g_usr_nof_streams-1 DOWNTO 0);
BEGIN
gen_mesh: IF g_use_mesh = TRUE GENERATE
-----------------------------------------------------------------------------
-- Terminals
-----------------------------------------------------------------------------
u_terminals_mesh : ENTITY unb_common_lib.unb_terminals_mesh
GENERIC MAP (
g_sim => g_sim,
g_sim_level => g_sim_level,
-- System
g_node_type => e_fn,
g_nof_bus => c_unb_nof_bn, -- 4 to 4 nodes in mesh
-- User
g_usr_use_complex => TRUE,
g_usr_data_w => g_usr_data_w,
g_usr_frame_len => g_usr_block_len,
g_usr_nof_streams => c_usr_nof_streams_per_bus,
-- Phy
g_phy_nof_serial => g_mesh_nof_serial,
g_phy_gx_mbps => g_mesh_gx_mbps,
g_phy_rx_fifo_size => c_phy_rx_fifo_size,
g_phy_ena_reorder => g_mesh_ena_reorder,
-- Tx
g_use_tx => g_mesh_use_tx, -- optionally do support diag Tx
g_tx_input_use_fifo => FALSE, -- no user Tx
-- Rx
g_use_rx => TRUE, -- user Rx must be TRUE for DB in FN,
g_rx_output_use_fifo => TRUE, -- Rx output provides FIFOs to ensure that dp_distribute does not get blocked due to substantial backpressure on another output
g_rx_output_fifo_size => c_rx_output_fifo_size,
g_rx_output_fifo_fill => c_rx_output_fifo_fill,
g_rx_timeout_w => c_rx_timeout_w,
-- Monitoring
g_mon_select => g_mesh_mon_select,
g_mon_nof_words => g_mesh_mon_nof_words,
g_mon_use_sync => g_mesh_mon_use_sync
)
PORT MAP (
chip_id => chip_id,
mm_rst => mm_rst,
mm_clk => mm_clk,
dp_rst => dp_rst,
dp_clk => dp_clk,
dp_sync => dp_pps,
tr_clk => tr_mesh_clk,
cal_clk => cal_clk,
-- User interface (4 nodes)(4 input streams)
rx_usr_siso_2arr => rx_usr_siso_2arr,
rx_usr_sosi_2arr => rx_usr_sosi_2arr, -- Rx (user Tx from FN to BN is unused)
-- Mesh interface level (4 nodes)(4 lanes)
-- . Serial (tr_nonbonded)
tx_serial_2arr => tx_serial_2arr, -- Tx
rx_serial_2arr => rx_serial_2arr, -- Rx
-- MM Control
-- . tr_nonbonded
reg_tr_nonbonded_mosi => reg_tr_nonbonded_mosi,
reg_tr_nonbonded_miso => reg_tr_nonbonded_miso,
reg_diagnostics_mosi => reg_diagnostics_mosi,
reg_diagnostics_miso => reg_diagnostics_miso,
-- . diag_data_buffer
ram_diag_data_buf_mosi => ram_mesh_diag_data_buf_mosi,
ram_diag_data_buf_miso => ram_mesh_diag_data_buf_miso
);
---------------------------------------------------------------------------------------
-- Forward the received streams, rewire for single or multi UniBoard use
---------------------------------------------------------------------------------------
gen_single_unb: IF g_multi_unb = FALSE GENERATE
rx_usr_siso_2arr <= rx_rew_siso_2arr;
rx_rew_sosi_2arr <= rx_usr_sosi_2arr;
END GENERATE;
gen_multi_unb: IF g_multi_unb = TRUE GENERATE
rx_rew_sosi_2arr <= func_unb_transpose_2arr(rx_usr_sosi_2arr);
rx_usr_siso_2arr <= func_unb_transpose_2arr(rx_rew_siso_2arr);
END GENERATE;
---------------------------------------------------------------------------------------
-- From 2d to 1d array
---------------------------------------------------------------------------------------
gen_i : FOR I IN 0 TO c_unb_nof_bn-1 GENERATE
gen_j : FOR J IN 0 TO c_usr_nof_streams_per_bus-1 GENERATE
rx_rew_siso_2arr(I)(J) <= rx_usr_siso_arr(I*c_usr_nof_streams_per_bus + J);
rx_usr_sosi_arr(I*c_usr_nof_streams_per_bus + J) <= rx_rew_sosi_2arr(I)(J);
END GENERATE;
END GENERATE;
-----------------------------------------------------------------------------
-- BSN align
-----------------------------------------------------------------------------
no_align : IF g_use_bsn_align=FALSE GENERATE
rx_usr_siso_arr <= (OTHERS=>c_dp_siso_rdy);
reg_bsn_monitor_miso <= c_mem_miso_rst;
END GENERATE;
gen_align : IF g_use_bsn_align=TRUE GENERATE
u_bsn_align : ENTITY dp_lib.dp_bsn_align
GENERIC MAP (
g_block_size => g_usr_block_len,
g_nof_input => g_usr_nof_streams,
g_xoff_timeout => c_xoff_timeout,
g_sop_timeout => c_sop_timeout,
g_bsn_latency => c_burst_bsn_latency,
g_bsn_request_pipeline => c_bsn_request_pipeline
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
-- ST sinks
snk_out_arr => rx_usr_siso_arr,
snk_in_arr => rx_usr_sosi_arr,
-- ST source
src_in_arr => dp_out_siso_arr,
src_out_arr => db_in_sosi_arr,
-- MM
in_en_evt => '0', -- pulse '1' indicates that the in_en_arr user input enables have been updated
in_en_arr => (OTHERS=>'1') -- default all user inputs are enabled
);
u_bsn_monitor_align : ENTITY dp_lib.mms_dp_bsn_monitor
GENERIC MAP (
g_nof_streams => 1, -- All streams are synchronous. Only monitor stream(0).
g_cross_clock_domain => TRUE,
g_bsn_w => c_dp_stream_bsn_w,
g_cnt_sop_w => c_word_w,
g_cnt_valid_w => c_word_w,
g_log_first_bsn => TRUE
)
PORT MAP (
-- Memory-mapped clock domain
mm_rst => mm_rst,
mm_clk => mm_clk,
reg_mosi => reg_bsn_monitor_mosi,
reg_miso => reg_bsn_monitor_miso,
-- Streaming clock domain
dp_rst => dp_rst,
dp_clk => dp_clk,
in_siso_arr => (OTHERS=>c_dp_siso_rdy),
in_sosi_arr => db_in_sosi_arr(0 DOWNTO 0)
);
END GENERATE;
-----------------------------------------------------------------------------
-- Data buffer
-----------------------------------------------------------------------------
no_data_buf : IF g_use_data_buf=FALSE GENERATE
ram_diag_data_buf_miso <= c_mem_miso_rst;
reg_diag_data_buf_miso <= c_mem_miso_rst;
END GENERATE;
gen_data_buf : IF g_use_data_buf=TRUE GENERATE
u_data_buf : ENTITY diag_lib.mms_diag_data_buffer
GENERIC MAP (
g_nof_streams => g_usr_nof_streams,
g_data_w => g_usr_data_w,
g_buf_nof_data => 1024,
g_buf_use_sync => TRUE
)
PORT MAP (
-- System
mm_rst => mm_rst,
mm_clk => mm_clk,
dp_rst => dp_rst,
dp_clk => dp_clk,
-- MM interface
ram_data_buf_mosi => ram_diag_data_buf_mosi,
ram_data_buf_miso => ram_diag_data_buf_miso,
reg_data_buf_mosi => reg_diag_data_buf_mosi,
reg_data_buf_miso => reg_diag_data_buf_miso,
-- ST interface
in_sync => db_in_sosi_arr(0).sync,
in_sosi_arr => db_in_sosi_arr
);
END GENERATE;
-----------------------------------------------------------------------------
-- Entity DP out
-----------------------------------------------------------------------------
dp_out_sosi_arr <= db_in_sosi_arr;
END GENERATE;
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