diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd index 523a0b955f37161dd6a2424b990487cb245f0b60..0a66af3bc3b589b791cdd0e3b246c29854f393cb 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd @@ -267,7 +267,7 @@ BEGIN in_sosi => bf_out_sosi, out_sosi => mon_bf_udp_sosi, - src_in => bf_udp_siso, + out_siso => bf_udp_siso, beamlet_scale => beamlet_scale, sdp_info => sdp_info, diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd index 610fc3db5b45c859d261ee019103f79d7b85c28e..f3f0b5b2b634da7e65917eec9d798850089c5787 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd @@ -58,7 +58,7 @@ ENTITY sdp_beamformer_output IS in_sosi : IN t_dp_sosi; out_sosi : OUT t_dp_sosi; - src_in : IN t_dp_siso; + out_siso : IN t_dp_siso; sdp_info : IN t_sdp_info; beamlet_scale : IN STD_LOGIC_VECTOR(c_sdp_W_beamlet_scale-1 DOWNTO 0); @@ -164,7 +164,8 @@ BEGIN -- . Also, we need a fill FIFO here because 16b->64b will introduce gaps in our -- TX stream (not allowed by 10G TX MAC). -- . The fill fifo waits until c_fifo_fill words are received before enabling the - -- output. The total number of words in the fifo is determained by the backpressure. + -- output. The total number of words in the fifo is determined by the + -- backpressure. ------------------------------------------------------------------------------- u_dp_fifo_fill_sc : ENTITY dp_lib.dp_fifo_fill_sc GENERIC MAP ( @@ -373,7 +374,7 @@ BEGIN snk_out_arr(0) => dp_pipeline_ready_src_in, snk_in_arr(0) => dp_pipeline_ready_src_out, -- ST source - src_in_arr(0) => src_in, + src_in_arr(0) => out_siso, src_out_arr(0) => out_sosi ); diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd index af106cdfccf8f2f92daaab665100dc543cc4f0f9..deb8fb8b7938855d96c6bbc1bf81dd3d4fe9baa3 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd @@ -369,7 +369,7 @@ ENTITY sdp_station IS reg_nw_10GbE_eth10g_cipo : OUT t_mem_cipo := c_mem_cipo_rst; ---------------------------------------------- - -- QSFP for beamlet output and for ring cable + -- QSFP[1] quad for beamlet output and QSFP[0] quad for ring cable ---------------------------------------------- -- QSFP serial (6 QSFP ports per FPGA) @@ -444,12 +444,16 @@ ARCHITECTURE str OF sdp_station IS CONSTANT c_fifo_tx_size_ring : NATURAL := true_log_pow2(c_lane_packet_nof_longwords_max + c_fifo_tx_fill_margin); -- = 552 + 6 --> 1024 CONSTANT c_fifo_tx_fill_ring : NATURAL := c_fifo_tx_size_ring - c_fifo_tx_fill_margin; -- = maximum fill level, so rely on eop - CONSTANT c_nof_lane : NATURAL := 3; -- 0 = XST, 1 = BF_0, 2 = BF_1. - CONSTANT c_nof_if : NATURAL := 3; -- 3 different interfaces, QSFP, RING_0 and RING_1 - CONSTANT c_qsfp_if_offset : NATURAL := 0; -- QSFP signals are indexed at c_nof_if * I. - CONSTANT c_ring_0_if_offset : NATURAL := 1; -- RING_0 signals are indexed at c_nof_if * I + 1. - CONSTANT c_ring_1_if_offset : NATURAL := 2; -- RING_1 signals are indexed at c_nof_if * I + 2. - CONSTANT c_ring_nof_mac : NATURAL := 12; -- Using 9 out of 12 (this is NOT optimized away during synthesis), must match one of the MAC IP variations, e.g. 1, 3, 4, 12, 24, 48 + CONSTANT c_nof_even_lanes : NATURAL := 3; -- 0 = XST, 1 = BF_0, 2 = BF_1. + CONSTANT c_lane_nof_if : NATURAL := 3; -- 3 different 10GbE interfaces per pair of lanes: QSFP cable, RING_0 pcb and RING_1 pcb + CONSTANT c_ring_qsfp_if_offset : NATURAL := 0; -- QSFP cable signals are indexed at c_lane_nof_if * I. + CONSTANT c_ring_0_if_offset : NATURAL := 1; -- RING_0 pcb signals are indexed at c_lane_nof_if * I + 1. + CONSTANT c_ring_1_if_offset : NATURAL := 2; -- RING_1 pcb signals are indexed at c_lane_nof_if * I + 2. + CONSTANT c_ring_nof_mac : NATURAL := c_nof_even_lanes * c_lane_nof_if; + + -- Using c_ring_nof_mac out of 12 (this is NOT optimized away during synthesis), must + -- match one of the MAC IP variations, e.g. 1, 3, 4, 12, 24, 48 + CONSTANT c_ring_nof_mac_ip : NATURAL := 12; -- >= c_ring_nof_mac TYPE t_dp_sosi_2arr_pfb IS ARRAY (INTEGER RANGE <>) OF t_dp_sosi_arr(c_sdp_P_pfb - 1 DOWNTO 0); @@ -549,10 +553,10 @@ ARCHITECTURE str OF sdp_station IS SIGNAL xst_to_ri_sosi : t_dp_sosi := c_dp_sosi_rst; SIGNAL bf_from_ri_sosi_arr : t_dp_sosi_arr(c_sdp_N_beamsets-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL bf_to_ri_sosi_arr : t_dp_sosi_arr(c_sdp_N_beamsets-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL lane_rx_cable_sosi_arr : t_dp_sosi_arr(c_nof_lane-1 DOWNTO 0); - SIGNAL lane_tx_cable_sosi_arr : t_dp_sosi_arr(c_nof_lane-1 DOWNTO 0); - SIGNAL lane_rx_board_sosi_arr : t_dp_sosi_arr(c_nof_lane-1 DOWNTO 0); - SIGNAL lane_tx_board_sosi_arr : t_dp_sosi_arr(c_nof_lane-1 DOWNTO 0); + SIGNAL lane_rx_cable_sosi_arr : t_dp_sosi_arr(c_nof_even_lanes-1 DOWNTO 0); + SIGNAL lane_tx_cable_sosi_arr : t_dp_sosi_arr(c_nof_even_lanes-1 DOWNTO 0); + SIGNAL lane_rx_board_sosi_arr : t_dp_sosi_arr(c_nof_even_lanes-1 DOWNTO 0); + SIGNAL lane_tx_board_sosi_arr : t_dp_sosi_arr(c_nof_even_lanes-1 DOWNTO 0); SIGNAL dp_bsn_source_restart : STD_LOGIC; -- used to restart WPFB sync interval timing SIGNAL dp_bsn_source_new_interval : STD_LOGIC; -- used to mask out first sync interval for SST and BST offload @@ -567,13 +571,13 @@ ARCHITECTURE str OF sdp_station IS SIGNAL tr_ref_rst_156 : STD_LOGIC; -- 10GbE ring - SIGNAL tr_10gbe_ring_serial_tx_arr : STD_LOGIC_VECTOR(c_ring_nof_mac-1 DOWNTO 0) := (OTHERS => '0'); - SIGNAL tr_10gbe_ring_serial_rx_arr : STD_LOGIC_VECTOR(c_ring_nof_mac-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL tr_10gbe_ring_serial_tx_arr : STD_LOGIC_VECTOR(c_ring_nof_mac_ip-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL tr_10gbe_ring_serial_rx_arr : STD_LOGIC_VECTOR(c_ring_nof_mac_ip-1 DOWNTO 0) := (OTHERS => '0'); - SIGNAL tr_10gbe_ring_snk_in_arr : t_dp_sosi_arr(c_ring_nof_mac-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL tr_10gbe_ring_snk_out_arr : t_dp_siso_arr(c_ring_nof_mac-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); - SIGNAL tr_10gbe_ring_src_out_arr : t_dp_sosi_arr(c_ring_nof_mac-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL tr_10gbe_ring_src_in_arr : t_dp_siso_arr(c_ring_nof_mac-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); + SIGNAL tr_10gbe_ring_snk_in_arr : t_dp_sosi_arr(c_ring_nof_mac_ip-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL tr_10gbe_ring_snk_out_arr : t_dp_siso_arr(c_ring_nof_mac_ip-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); + SIGNAL tr_10gbe_ring_src_out_arr : t_dp_sosi_arr(c_ring_nof_mac_ip-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL tr_10gbe_ring_src_in_arr : t_dp_siso_arr(c_ring_nof_mac_ip-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); -- 10GbE beamlet output SIGNAL nw_10gbe_beamlet_output_snk_in_arr : t_dp_sosi_arr(c_nof_10GbE_beamlet_output-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); @@ -1160,7 +1164,7 @@ BEGIN ); --------------- - -- nw_10GbE beamlet output + -- nw_10GbE beamlet output via front_io QSFP[1] --------------- u_nw_10GbE_beamlet_output: ENTITY nw_10GbE_lib.nw_10GbE GENERIC MAP ( @@ -1373,31 +1377,32 @@ BEGIN miso_arr => reg_dp_block_validate_bsn_at_sync_bf_cipo_arr ); END GENERATE; + ----------------------------------------------------------------------------- -- Combine seperate signals into array for tr_10GbE ----------------------------------------------------------------------------- - gen_lane_wires : FOR I IN 0 TO c_nof_lane-1 GENERATE + gen_lane_wires : FOR I IN 0 TO c_nof_even_lanes-1 GENERATE -- QSFP_RX, use_cable_to_previous_rn=1 -> even lanes receive from cable - lane_rx_cable_sosi_arr(I) <= tr_10gbe_ring_src_out_arr(c_nof_if * I + c_qsfp_if_offset) WHEN ring_info.use_cable_to_previous_rn = '1' ELSE c_dp_sosi_rst; + lane_rx_cable_sosi_arr(I) <= tr_10gbe_ring_src_out_arr(c_lane_nof_if * I + c_ring_qsfp_if_offset) WHEN ring_info.use_cable_to_previous_rn = '1' ELSE c_dp_sosi_rst; -- QSFP_TX, use_cable_to_next_rn=1 -> even lanes transmit to cable - tr_10gbe_ring_snk_in_arr(c_nof_if * I + c_qsfp_if_offset) <= lane_tx_cable_sosi_arr(I) WHEN ring_info.use_cable_to_next_rn = '1' ELSE c_dp_sosi_rst; + tr_10gbe_ring_snk_in_arr(c_lane_nof_if * I + c_ring_qsfp_if_offset) <= lane_tx_cable_sosi_arr(I) WHEN ring_info.use_cable_to_next_rn = '1' ELSE c_dp_sosi_rst; -- RING_0_RX even lanes receive from RING_0 (from the left) - lane_rx_board_sosi_arr(I) <= tr_10gbe_ring_src_out_arr(c_nof_if * I + c_ring_0_if_offset); + lane_rx_board_sosi_arr(I) <= tr_10gbe_ring_src_out_arr(c_lane_nof_if * I + c_ring_0_if_offset); -- RING_1_TX even lanes transmit to RING_1 (to the right) - tr_10gbe_ring_snk_in_arr(c_nof_if * I + c_ring_1_if_offset) <= lane_tx_board_sosi_arr(I); + tr_10gbe_ring_snk_in_arr(c_lane_nof_if * I + c_ring_1_if_offset) <= lane_tx_board_sosi_arr(I); END GENERATE; ----------------------------------------------------------------------------- - -- tr_10GbE ring + -- tr_10GbE ring via front_io QSFP[0] ----------------------------------------------------------------------------- u_tr_10GbE_ring: ENTITY tr_10GbE_lib.tr_10GbE GENERIC MAP ( g_sim => g_sim, g_sim_level => 1, - g_nof_macs => c_ring_nof_mac, + g_nof_macs => c_ring_nof_mac_ip, g_direction => "TX_RX", g_tx_fifo_fill => c_fifo_tx_fill_ring, g_tx_fifo_size => c_fifo_tx_size_ring @@ -1437,23 +1442,23 @@ BEGIN ----------------------------------------------------------------------------- -- Seperate serial tx/rx array ----------------------------------------------------------------------------- - -- Seperating the one large serial tx/rx array from tr_10GbE to the 3 port arrays: - -- QSFP port, RING_0 port and RING_1 port. - gen_serial_wires : FOR I IN 0 TO c_nof_lane-1 GENERATE + -- Seperating the one large serial tx/rx array from tr_10GbE to the c_lane_nof_if = 3 + -- port arrays: QSFP cable port, RING_0 pcb port and RING_1 pcb port. + gen_ring_serial_wires : FOR I IN 0 TO c_nof_even_lanes-1 GENERATE -- QSFP_TX - unb2_board_front_io_serial_tx_arr(I) <= tr_10gbe_ring_serial_tx_arr(c_nof_if * I + c_qsfp_if_offset); + unb2_board_front_io_serial_tx_arr(I) <= tr_10gbe_ring_serial_tx_arr(c_lane_nof_if * I + c_ring_qsfp_if_offset); -- QSFP_RX - tr_10gbe_ring_serial_rx_arr(c_nof_if * I + c_qsfp_if_offset) <= unb2_board_front_io_serial_rx_arr(I); + tr_10gbe_ring_serial_rx_arr(c_lane_nof_if * I + c_ring_qsfp_if_offset) <= unb2_board_front_io_serial_rx_arr(I); -- RING_0_TX - RING_0_TX(I) <= tr_10gbe_ring_serial_tx_arr(c_nof_if * I + c_ring_0_if_offset); + RING_0_TX(I) <= tr_10gbe_ring_serial_tx_arr(c_lane_nof_if * I + c_ring_0_if_offset); -- RING_0_RX - tr_10gbe_ring_serial_rx_arr(c_nof_if * I + c_ring_0_if_offset) <= RING_0_RX(I); + tr_10gbe_ring_serial_rx_arr(c_lane_nof_if * I + c_ring_0_if_offset) <= RING_0_RX(I); -- RING_1_TX - RING_1_TX(I) <= tr_10gbe_ring_serial_tx_arr(c_nof_if * I + c_ring_1_if_offset); + RING_1_TX(I) <= tr_10gbe_ring_serial_tx_arr(c_lane_nof_if * I + c_ring_1_if_offset); -- RING_1_RX - tr_10gbe_ring_serial_rx_arr(c_nof_if * I + c_ring_1_if_offset) <= RING_1_RX(I); + tr_10gbe_ring_serial_rx_arr(c_lane_nof_if * I + c_ring_1_if_offset) <= RING_1_RX(I); END GENERATE; END GENERATE; diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg index 12f9c56edd7f921d5751fab385dcaca33cfa8365..8d500138501b9273d8bad9a735033150efd979c9 100644 --- a/libraries/base/dp/hdllib.cfg +++ b/libraries/base/dp/hdllib.cfg @@ -59,6 +59,7 @@ synth_files = src/vhdl/dp_fifo_fill.vhd src/vhdl/dp_fifo_fill_reg.vhd src/vhdl/dp_fifo_fill_eop.vhd + src/vhdl/dp_fifo_fill_eop_sc.vhd src/vhdl/dp_fifo_to_mm.vhd src/vhdl/dp_fifo_to_mm_reg.vhd src/vhdl/dp_fifo_from_mm.vhd @@ -251,6 +252,7 @@ test_bench_files = tb/vhdl/tb_dp_fifo_dc_mixed_widths.vhd tb/vhdl/tb_dp_fifo_sc.vhd tb/vhdl/tb_dp_fifo_to_mm.vhd + tb/vhdl/tb_dp_fifo_xonoff.vhd tb/vhdl/tb_dp_flush.vhd tb/vhdl/tb_dp_gap.vhd tb/vhdl/tb_dp_hdr_insert_remove.vhd @@ -368,6 +370,7 @@ test_bench_files = regression_test_vhdl = tb/vhdl/tb_dp_fifo_to_mm.vhd + tb/vhdl/tb_dp_fifo_xonoff.vhd tb/vhdl/tb_dp_latency_adapter.vhd tb/vhdl/tb_dp_shiftreg.vhd tb/vhdl/tb_dp_bsn_source.vhd diff --git a/libraries/base/dp/src/vhdl/dp_fifo_core.vhd b/libraries/base/dp/src/vhdl/dp_fifo_core.vhd index c8f9cb39db358df72a7a0fbd4ab161343a341e54..63085ac767e85f9dc04689ea1038483e9d5e58e1 100644 --- a/libraries/base/dp/src/vhdl/dp_fifo_core.vhd +++ b/libraries/base/dp/src/vhdl/dp_fifo_core.vhd @@ -66,7 +66,8 @@ ENTITY dp_fifo_core IS g_use_ctrl : BOOLEAN := TRUE; -- sop & eop g_use_complex : BOOLEAN := FALSE; -- TRUE feeds the concatenated complex fields (im & re) through the FIFO instead of the data field. g_fifo_size : NATURAL := 512; -- (16+2) * 512 = 1 M9K, g_data_w+2 for sop and eop - g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full + g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full for snk_out.ready + g_fifo_af_xon : NATURAL := 0; -- >=0, Nof words below max (full) at which fifo is considered almost full for snk_out.xon g_fifo_rl : NATURAL := 1 ); PORT ( @@ -96,7 +97,8 @@ ARCHITECTURE str OF dp_fifo_core IS CONSTANT c_complex_w : NATURAL := smallest(c_dp_stream_dsp_data_w, g_data_w/2); -- needed to cope with g_data_w > 2*c_dp_stream_dsp_data_w - CONSTANT c_fifo_almost_full : NATURAL := g_fifo_size-g_fifo_af_margin; -- FIFO almost full level for snk_out.ready + CONSTANT c_fifo_almost_full : NATURAL := g_fifo_size - g_fifo_af_margin; -- FIFO almost full level for snk_out.ready + CONSTANT c_fifo_almost_xon : NATURAL := g_fifo_size - g_fifo_af_xon; -- FIFO almost full level for snk_out.xon CONSTANT c_fifo_dat_w : NATURAL := func_slv_concat_w(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w); -- concat via FIFO @@ -163,11 +165,12 @@ BEGIN wr_sync, wr_ctrl); - -- pass on frame level flow control - nxt_snk_out.xon <= src_in.xon; + -- pass on frame level flow control from src_in.xon to upstream snk_out.xon, and + -- add flow contol dependent on whether the fifo can fit another block + nxt_snk_out.xon <= src_in.xon WHEN UNSIGNED(fifo_wr_usedw) <= c_fifo_almost_xon ELSE '0'; -- up stream use fifo almost full to control snk_out.ready - nxt_snk_out.ready <= NOT wr_init WHEN UNSIGNED(fifo_wr_usedw)<c_fifo_almost_full ELSE '0'; + nxt_snk_out.ready <= NOT wr_init WHEN UNSIGNED(fifo_wr_usedw) < c_fifo_almost_full ELSE '0'; gen_common_fifo_sc : IF g_use_dual_clock=FALSE GENERATE u_common_fifo_sc : ENTITY common_lib.common_fifo_sc diff --git a/libraries/base/dp/src/vhdl/dp_fifo_core_arr.vhd b/libraries/base/dp/src/vhdl/dp_fifo_core_arr.vhd index 83964e22b64cf0a3cdc95ad955082f8752e7d713..d74579e00f221eeaf386a55abde1a43f0ae4629d 100644 --- a/libraries/base/dp/src/vhdl/dp_fifo_core_arr.vhd +++ b/libraries/base/dp/src/vhdl/dp_fifo_core_arr.vhd @@ -73,7 +73,8 @@ ENTITY dp_fifo_core_arr IS g_use_ctrl : BOOLEAN := TRUE; -- sop & eop g_use_complex : BOOLEAN := FALSE; -- TRUE feeds the concatenated complex fields (im & re) through the FIFO instead of the data field. g_fifo_size : NATURAL := 512; -- (16+2) * 512 = 1 M9K, g_data_w+2 for sop and eop - g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full + g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full for snk_out.ready + g_fifo_af_xon : NATURAL := 0; -- >=0, Nof words below max (full) at which fifo is considered almost full for snk_out.xon g_fifo_rl : NATURAL := 1 ); PORT ( @@ -106,7 +107,8 @@ ARCHITECTURE str OF dp_fifo_core_arr IS CONSTANT c_complex_w : NATURAL := smallest(c_dp_stream_dsp_data_w, g_data_w/2); -- needed to cope with g_data_w > 2*c_dp_stream_dsp_data_w - CONSTANT c_fifo_almost_full : NATURAL := g_fifo_size-g_fifo_af_margin; -- FIFO almost full level for snk_out.ready + CONSTANT c_fifo_almost_full : NATURAL := g_fifo_size - g_fifo_af_margin; -- FIFO almost full level for snk_out.ready + CONSTANT c_fifo_almost_xon : NATURAL := g_fifo_size - g_fifo_af_xon; -- FIFO almost full level for snk_out.xon CONSTANT c_fifo_dat_w : NATURAL := func_slv_concat_w(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_use_aux, c_total_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, g_aux_w); -- concat via FIFO @@ -185,11 +187,12 @@ BEGIN wr_ctrl, wr_aux); - -- pass on frame level flow control - nxt_snk_out.xon <= src_in_arr(0).xon; + -- pass on frame level flow control from src_in.xon to upstream snk_out.xon, and + -- add flow contol dependent on whether the fifo can fit another block + nxt_snk_out.xon <= src_in_arr(0).xon WHEN UNSIGNED(fifo_wr_usedw) <= c_fifo_almost_xon ELSE '0'; - -- up stream use fifo almost full to control snk_out.ready - nxt_snk_out.ready <= '1' WHEN UNSIGNED(fifo_wr_usedw)<c_fifo_almost_full ELSE '0'; + -- use fifo almost full to control up stream snk_out.ready + nxt_snk_out.ready <= '1' WHEN UNSIGNED(fifo_wr_usedw) < c_fifo_almost_full ELSE '0'; gen_common_fifo_sc : IF g_use_dual_clock=FALSE GENERATE u_common_fifo_sc : ENTITY common_lib.common_fifo_sc diff --git a/libraries/base/dp/src/vhdl/dp_fifo_dc.vhd b/libraries/base/dp/src/vhdl/dp_fifo_dc.vhd index f5638052d7af7f99ebf06a4c0482791d13ac3639..211b97800f7e6bea6b800c3bbef87afe6374e13f 100644 --- a/libraries/base/dp/src/vhdl/dp_fifo_dc.vhd +++ b/libraries/base/dp/src/vhdl/dp_fifo_dc.vhd @@ -46,7 +46,8 @@ ENTITY dp_fifo_dc IS g_use_ctrl : BOOLEAN := TRUE; -- sop & eop g_use_complex : BOOLEAN := FALSE; -- TRUE feeds the concatenated complex fields (im & re) through the FIFO instead of the data field. g_fifo_size : NATURAL := 512; -- (16+2) * 512 = 1 M9K, g_data_w+2 for sop and eop - g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full + g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full for snk_out.ready + g_fifo_af_xon : NATURAL := 0; -- >=0, Nof words below max (full) at which fifo is considered almost full for snk_out.xon g_fifo_rl : NATURAL := 1 ); PORT ( @@ -91,6 +92,7 @@ BEGIN g_use_complex => g_use_complex, g_fifo_size => g_fifo_size, g_fifo_af_margin => g_fifo_af_margin, + g_fifo_af_xon => g_fifo_af_xon, g_fifo_rl => g_fifo_rl ) PORT MAP ( diff --git a/libraries/base/dp/src/vhdl/dp_fifo_dc_arr.vhd b/libraries/base/dp/src/vhdl/dp_fifo_dc_arr.vhd index 45d65e14cda439a068b419d049d6bc5db4ae507e..dcfd02e39c891d8211aadc39a74297d9410ac21c 100644 --- a/libraries/base/dp/src/vhdl/dp_fifo_dc_arr.vhd +++ b/libraries/base/dp/src/vhdl/dp_fifo_dc_arr.vhd @@ -51,7 +51,8 @@ ENTITY dp_fifo_dc_arr IS g_use_ctrl : BOOLEAN := TRUE; -- sop & eop g_use_complex : BOOLEAN := FALSE; -- TRUE feeds the concatenated complex fields (im & re) through the FIFO instead of the data field. g_fifo_size : NATURAL := 512; -- (16+2) * 512 = 1 M9K, g_data_w+2 for sop and eop - g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full + g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full for snk_out.ready + g_fifo_af_xon : NATURAL := 0; -- >=0, Nof words below max (full) at which fifo is considered almost full for snk_out.xon g_fifo_rl : NATURAL := 1 ); PORT ( @@ -101,6 +102,7 @@ BEGIN g_use_complex => g_use_complex, g_fifo_size => g_fifo_size, g_fifo_af_margin => g_fifo_af_margin, + g_fifo_af_xon => g_fifo_af_xon, g_fifo_rl => g_fifo_rl ) PORT MAP ( diff --git a/libraries/base/dp/src/vhdl/dp_fifo_dc_mixed_widths.vhd b/libraries/base/dp/src/vhdl/dp_fifo_dc_mixed_widths.vhd index 5b809003534f71183cafea90a0795368cd517104..996f267d282d660faa82c1291f34a371b47edf2a 100644 --- a/libraries/base/dp/src/vhdl/dp_fifo_dc_mixed_widths.vhd +++ b/libraries/base/dp/src/vhdl/dp_fifo_dc_mixed_widths.vhd @@ -114,7 +114,8 @@ ENTITY dp_fifo_dc_mixed_widths IS g_rd_data_w : NATURAL := 9; g_use_ctrl : BOOLEAN := TRUE; g_wr_fifo_size : NATURAL := 512; -- FIFO size in nof wr_data words - g_wr_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full + g_wr_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full for snk_out.ready + g_wr_fifo_af_xon : NATURAL := 0; -- >=0, Nof words below max (full) at which fifo is considered almost full for snk_out.xon g_rd_fifo_rl : NATURAL := 1 ); PORT ( @@ -150,8 +151,9 @@ ARCHITECTURE str OF dp_fifo_dc_mixed_widths IS CONSTANT c_ctrl_w : NATURAL := sel_a_b(g_use_ctrl, 2, 0); -- sop and eop, or no ctrl CONSTANT c_empty_w : NATURAL := ceil_log2(c_nof_narrow); - CONSTANT c_fifo_wr_almost_full : NATURAL := g_wr_fifo_size-g_wr_fifo_af_margin; -- FIFO almost full level for snk_out.ready - + CONSTANT c_fifo_wr_almost_full : NATURAL := g_wr_fifo_size - g_wr_fifo_af_margin; -- FIFO almost full level for snk_out.ready + CONSTANT c_fifo_wr_almost_xon : NATURAL := g_wr_fifo_size - g_wr_fifo_af_xon; -- FIFO almost full level for snk_out.xon + CONSTANT c_fifo_narrow_data_w : NATURAL := c_narrow_data_w + c_ctrl_w; -- if used concat control via FIFO CONSTANT c_fifo_wide_data_w : NATURAL := c_nof_narrow * c_fifo_narrow_data_w; -- all through one FIFO @@ -185,7 +187,8 @@ ARCHITECTURE str OF dp_fifo_dc_mixed_widths IS SIGNAL rd_sosi : t_dp_sosi := c_dp_sosi_rst; -- initialize default values for unused sosi fields SIGNAL i_snk_out : t_dp_siso := c_dp_siso_rst; - + SIGNAL nxt_snk_out : t_dp_siso := c_dp_siso_rst; + BEGIN -- Use i_snk_out with defaults to force unused snk_out bits and fields to '0' @@ -239,21 +242,24 @@ BEGIN wr_ful <= fifo_wr_ful; wr_usedw <= i_wr_usedw; - nxt_fifo_aful <= '0' WHEN (UNSIGNED(i_wr_usedw)<c_fifo_wr_almost_full) ELSE '1'; - + nxt_fifo_aful <= '0' WHEN (UNSIGNED(i_wr_usedw) < c_fifo_wr_almost_full) ELSE '1'; + p_wr_clk: PROCESS(wr_clk, wr_rst) BEGIN IF wr_rst='1' THEN - fifo_aful <= '0'; + fifo_aful <= '0'; + i_snk_out.xon <= '0'; ELSIF rising_edge(wr_clk) THEN - fifo_aful <= nxt_fifo_aful; + fifo_aful <= nxt_fifo_aful; + i_snk_out.xon <= nxt_snk_out.xon; END IF; END PROCESS; -- Padding is only needed for the narrow write with frame control, in all other cases the padding control defaults to the redundant initialisation values - -- pass on frame level flow control - i_snk_out.xon <= src_in.xon; + -- pass on frame level flow control from src_in.xon to upstream snk_out.xon, and + -- add flow contol dependent on whether the fifo can fit another block + nxt_snk_out.xon <= src_in.xon WHEN UNSIGNED(i_wr_usedw) <= c_fifo_wr_almost_xon ELSE '0'; -- use FIFO almost full and no padding going on to control output ready to up stream i_snk_out.ready <= (NOT fifo_aful) AND wr_pad_ready; diff --git a/libraries/base/dp/src/vhdl/dp_fifo_fill.vhd b/libraries/base/dp/src/vhdl/dp_fifo_fill.vhd index c77ea4adc285984c028092bb8ce1c843d3350eba..f3e379027b34679f52b21af52e81db2a1b9334dc 100644 --- a/libraries/base/dp/src/vhdl/dp_fifo_fill.vhd +++ b/libraries/base/dp/src/vhdl/dp_fifo_fill.vhd @@ -48,7 +48,8 @@ ENTITY dp_fifo_fill IS g_use_complex : BOOLEAN := FALSE; -- TRUE feeds the concatenated complex fields (im & re) through the FIFO instead of the data field. g_fifo_fill : NATURAL := 0; g_fifo_size : NATURAL := 256; -- (32+2) * 256 = 1 M9K, g_data_w+2 for sop and eop - g_fifo_af_margin : NATURAL := 4; -- Nof words below max (full) at which fifo is considered almost full + g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full for snk_out.ready + g_fifo_af_xon : NATURAL := 0; -- >=0, Nof words below max (full) at which fifo is considered almost full for snk_out.xon g_fifo_rl : NATURAL := 1 -- use RL=0 for internal show ahead FIFO, default use RL=1 for internal normal FIFO ); PORT ( @@ -95,6 +96,7 @@ BEGIN g_fifo_fill => g_fifo_fill, g_fifo_size => g_fifo_size, g_fifo_af_margin => g_fifo_af_margin, + g_fifo_af_xon => g_fifo_af_xon, g_fifo_rl => g_fifo_rl ) PORT MAP ( diff --git a/libraries/base/dp/src/vhdl/dp_fifo_fill_core.vhd b/libraries/base/dp/src/vhdl/dp_fifo_fill_core.vhd index ef89bbe4222771651c94497ecb019d0dd2280efb..cf1157ef538a3629b752ae022ae492e0c710bf72 100644 --- a/libraries/base/dp/src/vhdl/dp_fifo_fill_core.vhd +++ b/libraries/base/dp/src/vhdl/dp_fifo_fill_core.vhd @@ -81,7 +81,8 @@ ENTITY dp_fifo_fill_core IS g_use_complex : BOOLEAN := FALSE; -- TRUE feeds the concatenated complex fields (im & re) through the FIFO instead of the data field. g_fifo_fill : NATURAL := 0; g_fifo_size : NATURAL := 256; -- (32+2) * 256 = 1 M9K, g_data_w+2 for sop and eop - g_fifo_af_margin : NATURAL := 4; -- Nof words below max (full) at which fifo is considered almost full + g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full for snk_out.ready + g_fifo_af_xon : NATURAL := 0; -- >=0, Nof words below max (full) at which fifo is considered almost full for snk_out.xon g_fifo_rl : NATURAL := 1 -- use RL=0 for internal show ahead FIFO, default use RL=1 for internal normal FIFO ); PORT ( @@ -176,6 +177,7 @@ BEGIN g_use_complex => g_use_complex, g_fifo_size => c_fifo_size, g_fifo_af_margin => g_fifo_af_margin, + g_fifo_af_xon => g_fifo_af_xon, g_fifo_rl => c_fifo_rl ) PORT MAP ( @@ -215,6 +217,7 @@ BEGIN --g_use_complex => g_use_complex, g_fifo_size => c_fifo_size, g_fifo_af_margin => g_fifo_af_margin, + g_fifo_af_xon => g_fifo_af_xon, g_fifo_rl => c_fifo_rl ) PORT MAP ( diff --git a/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd b/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd index 9d904f89e2cf577428a406bc5ee0fb2b1530b9f6..709af7d621a57d40fea76c96079df3820cb80717 100644 --- a/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd +++ b/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd @@ -76,7 +76,8 @@ ENTITY dp_fifo_fill_eop IS g_use_complex : BOOLEAN := FALSE; -- TRUE feeds the concatenated complex fields (im & re) through the FIFO instead of the data field. g_fifo_fill : NATURAL := 0; g_fifo_size : NATURAL := 256; -- (32+2) * 256 = 1 M9K, g_data_w+2 for sop and eop - g_fifo_af_margin : NATURAL := 4; -- Nof words below max (full) at which fifo is considered almost full + g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full for snk_out.ready + g_fifo_af_xon : NATURAL := 0; -- >=0, Nof words below max (full) at which fifo is considered almost full for snk_out.xon g_fifo_rl : NATURAL := 1 -- use RL=0 for internal show ahead FIFO, default use RL=1 for internal normal FIFO ); PORT ( @@ -185,6 +186,7 @@ BEGIN g_use_complex => g_use_complex, g_fifo_size => c_fifo_size, g_fifo_af_margin => g_fifo_af_margin, + g_fifo_af_xon => g_fifo_af_xon, g_fifo_rl => c_fifo_rl ) PORT MAP ( diff --git a/libraries/base/dp/src/vhdl/dp_fifo_fill_eop_sc.vhd b/libraries/base/dp/src/vhdl/dp_fifo_fill_eop_sc.vhd new file mode 100644 index 0000000000000000000000000000000000000000..90d16481a7bfa060cc27912b8a6628f4f1e115f3 --- /dev/null +++ b/libraries/base/dp/src/vhdl/dp_fifo_fill_eop_sc.vhd @@ -0,0 +1,124 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2020 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Author: R. van der Walle, E. Kooistra +-- Purpose: Single clk wrapper for dp_fifo_fill_eop. +-- +------------------------------------------------------------------------------- + +LIBRARY IEEE, common_lib, technology_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE work.dp_stream_pkg.ALL; +USE technology_lib.technology_select_pkg.ALL; + +ENTITY dp_fifo_fill_eop_sc IS + GENERIC ( + g_technology : NATURAL := c_tech_select_default; + g_note_is_ful : BOOLEAN := TRUE; + g_data_w : NATURAL := 16; -- Should be 2 times the c_complex_w if g_use_complex = TRUE + g_data_signed : BOOLEAN := FALSE; -- TRUE extends g_data_w bits with the sign bit, FALSE pads g_data_w bits with zeros. + g_bsn_w : NATURAL := 1; + g_empty_w : NATURAL := 1; + g_channel_w : NATURAL := 1; + g_error_w : NATURAL := 1; + g_use_bsn : BOOLEAN := FALSE; + g_use_empty : BOOLEAN := FALSE; + g_use_channel : BOOLEAN := FALSE; + g_use_error : BOOLEAN := FALSE; + g_use_sync : BOOLEAN := FALSE; + g_use_complex : BOOLEAN := FALSE; -- TRUE feeds the concatenated complex fields (im & re) through the FIFO instead of the data field. + g_fifo_fill : NATURAL := 0; + g_fifo_size : NATURAL := 256; -- (32+2) * 256 = 1 M9K, g_data_w+2 for sop and eop + g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full for snk_out.ready + g_fifo_af_xon : NATURAL := 0; -- >=0, Nof words below max (full) at which fifo is considered almost full for snk_out.xon + g_fifo_rl : NATURAL := 1 -- use RL=0 for internal show ahead FIFO, default use RL=1 for internal normal FIFO + ); + PORT ( + rst : IN STD_LOGIC; + clk : IN STD_LOGIC; + -- Monitor FIFO filling + wr_ful : OUT STD_LOGIC; -- corresponds to the carry bit of wr_usedw when FIFO is full + usedw : OUT STD_LOGIC_VECTOR(ceil_log2(largest(g_fifo_size, g_fifo_fill + g_fifo_af_margin + 2))-1 DOWNTO 0); -- = ceil_log2(c_fifo_size)-1 DOWNTO 0 + rd_emp : OUT STD_LOGIC; + -- MM control FIFO filling (assume 32 bit MM interface) + wr_usedw_32b : OUT STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); -- = wr_usedw + rd_usedw_32b : OUT STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); -- = rd_usedw + rd_fill_32b : IN STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0) := TO_UVEC(g_fifo_fill, c_word_w); + -- ST sink + snk_out : OUT t_dp_siso; + snk_in : IN t_dp_sosi; + -- ST source + src_in : IN t_dp_siso := c_dp_siso_rdy; + src_out : OUT t_dp_sosi + ); +END dp_fifo_fill_eop_sc; + +ARCHITECTURE wrap OF dp_fifo_fill_eop_sc IS +BEGIN + + u_dp_fifo_fill_eop : ENTITY work.dp_fifo_fill_eop + GENERIC MAP ( + g_technology => g_technology, + g_note_is_ful => g_note_is_ful, + g_use_dual_clock => FALSE, -- single clock + g_data_w => g_data_w, + g_data_signed => g_data_signed, + g_bsn_w => g_bsn_w, + g_empty_w => g_empty_w, + g_channel_w => g_channel_w, + g_error_w => g_error_w, + g_use_bsn => g_use_bsn, + g_use_empty => g_use_empty, + g_use_channel => g_use_channel, + g_use_error => g_use_error, + g_use_sync => g_use_sync, + g_use_complex => g_use_complex, + g_fifo_fill => g_fifo_fill, + g_fifo_size => g_fifo_size, + g_fifo_af_margin => g_fifo_af_margin, + g_fifo_af_xon => g_fifo_af_xon, + g_fifo_rl => g_fifo_rl + ) + PORT MAP ( + wr_rst => rst, + wr_clk => clk, + rd_rst => rst, + rd_clk => clk, + -- Monitor FIFO filling + wr_ful => wr_ful, + wr_usedw => OPEN, + rd_usedw => usedw, -- use rd_usedw, similar as in dp_fifo_sc, dp_fifo_fill_sc + rd_emp => rd_emp, + -- MM control FIFO filling (assume 32 bit MM interface) + wr_usedw_32b => wr_usedw_32b, + rd_usedw_32b => rd_usedw_32b, + rd_fill_32b => rd_fill_32b, + -- ST sink + snk_out => snk_out, + snk_in => snk_in, + -- ST source + src_in => src_in, + src_out => src_out + ); + +END wrap; diff --git a/libraries/base/dp/src/vhdl/dp_fifo_fill_sc.vhd b/libraries/base/dp/src/vhdl/dp_fifo_fill_sc.vhd index db85d766fdeb1160ec49358fa622ac9e23bb66c8..dd7fa79f5910ad055dfbc994559513489ccda944 100644 --- a/libraries/base/dp/src/vhdl/dp_fifo_fill_sc.vhd +++ b/libraries/base/dp/src/vhdl/dp_fifo_fill_sc.vhd @@ -47,7 +47,8 @@ ENTITY dp_fifo_fill_sc IS g_use_complex : BOOLEAN := FALSE; -- TRUE feeds the concatenated complex fields (im & re) through the FIFO instead of the data field. g_fifo_fill : NATURAL := 0; g_fifo_size : NATURAL := 256; -- (32+2) * 256 = 1 M9K, g_data_w+2 for sop and eop - g_fifo_af_margin : NATURAL := 4; -- Nof words below max (full) at which fifo is considered almost full + g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full for snk_out.ready + g_fifo_af_xon : NATURAL := 0; -- >=0, Nof words below max (full) at which fifo is considered almost full for snk_out.xon g_fifo_rl : NATURAL := 1 -- use RL=0 for internal show ahead FIFO, default use RL=1 for internal normal FIFO ); PORT ( @@ -96,6 +97,7 @@ BEGIN g_fifo_fill => g_fifo_fill, g_fifo_size => g_fifo_size, g_fifo_af_margin => g_fifo_af_margin, + g_fifo_af_xon => g_fifo_af_xon, g_fifo_rl => g_fifo_rl ) PORT MAP ( diff --git a/libraries/base/dp/src/vhdl/dp_fifo_sc.vhd b/libraries/base/dp/src/vhdl/dp_fifo_sc.vhd index fb9570775d09d98e39f905748c21ad9ea61c5feb..3f261029443d6ad6de693bd149033c1fcf749052 100644 --- a/libraries/base/dp/src/vhdl/dp_fifo_sc.vhd +++ b/libraries/base/dp/src/vhdl/dp_fifo_sc.vhd @@ -48,7 +48,8 @@ ENTITY dp_fifo_sc IS g_use_ctrl : BOOLEAN := TRUE; -- sop & eop g_use_complex : BOOLEAN := FALSE; -- TRUE feeds the concatenated complex fields (im & re) through the FIFO instead of the data field. g_fifo_size : NATURAL := 512; -- (16+2) * 512 = 1 M9K, g_data_w+2 for sop and eop - g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full + g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full for snk_out.ready + g_fifo_af_xon : NATURAL := 0; -- >=0, Nof words below max (full) at which fifo is considered almost full for snk_out.xon g_fifo_rl : NATURAL := 1 ); PORT ( @@ -92,6 +93,7 @@ BEGIN g_use_complex => g_use_complex, g_fifo_size => g_fifo_size, g_fifo_af_margin => g_fifo_af_margin, + g_fifo_af_xon => g_fifo_af_xon, g_fifo_rl => g_fifo_rl ) PORT MAP ( diff --git a/libraries/base/dp/src/vhdl/dp_mux.vhd b/libraries/base/dp/src/vhdl/dp_mux.vhd index 56e06ffb4f682760bedad923f5d4bbb8c5ba2490..4326157fa81910389a417ff5fea880ad9f1f43d5 100644 --- a/libraries/base/dp/src/vhdl/dp_mux.vhd +++ b/libraries/base/dp/src/vhdl/dp_mux.vhd @@ -105,7 +105,8 @@ ENTITY dp_mux IS g_use_in_channel : BOOLEAN := FALSE; g_use_error : BOOLEAN := FALSE; g_use_sync : BOOLEAN := FALSE; - g_fifo_af_margin : NATURAL := 4; -- Nof words below max (full) at which fifo is considered almost full + g_fifo_af_margin : NATURAL := 4; -- >=4, Nof words below max (full) at which fifo is considered almost full for snk_out.ready + g_fifo_af_xon : NATURAL := 0; -- >=0, Nof words below max (full) at which fifo is considered almost full for snk_out.xon g_fifo_size : t_natural_arr := array_init(1024, 2); -- must match g_nof_input, even when g_use_fifo=FALSE g_fifo_fill : t_natural_arr := array_init( 0, 2) -- must match g_nof_input, even when g_use_fifo=FALSE ); @@ -229,6 +230,7 @@ BEGIN g_fifo_fill => c_fifo_fill(I), g_fifo_size => c_fifo_size(I), g_fifo_af_margin => g_fifo_af_margin, + g_fifo_af_xon => g_fifo_af_xon, g_fifo_rl => 1 ) PORT MAP ( diff --git a/libraries/base/dp/src/vhdl/dp_xonoff.vhd b/libraries/base/dp/src/vhdl/dp_xonoff.vhd index 9f7f9eccfdc6897f89b926d84bb6730526042d41..cfdcf122f6c0eabb05a8242cc765a47bfa046645 100644 --- a/libraries/base/dp/src/vhdl/dp_xonoff.vhd +++ b/libraries/base/dp/src/vhdl/dp_xonoff.vhd @@ -21,11 +21,58 @@ -- Purpose: Add flow XON-XOFF control by flushing frames -- Description: --- . The in_siso.ready = out_siso.ready so passed on unchanged, to support +-- The siso.xon signal provides flow control per block of data, so at +-- sop/eop boundaries. A source that listens to siso.xon can stop streaming +-- blocks when siso.xon = '0' and resume streaming blocks when siso.xon = +-- '1'. The siso.ready signal provides flow control per clock cycle. Hence +-- the siso.ready can also cause a source to stop streaming. +-- +-- If a source keeps on streaming blocks of data, becaue it does not listen +-- to siso.xon and also not to siso.ready, then the dp_xonoff can be applied +-- to drop the blocks when siso.xon = '0'. The purpose of dp_xonoff.vhd is +-- then to avoid downstream overflow, when the downstream signals +-- out_siso.xon = '0' to indicate that it cannot accept more blocks. +-- Therefore the dp_xonoff listens to the out_siso.xon and flushes +-- (discards) blocks when out_siso.xon = '0' and resumes letting blocks +-- through when siso.xon = '1' again. +-- +-- The dp_xonoff operates per block, so it takes care that complete blocks +-- are flushed when out_siso.xon = '0', or passed on when out_siso.xon = +-- '1'. Discarding blocks is acceptable to avoid overflow. Discarding data +-- in a block is not acceptable, because that would corrupt the block +-- format (e.g. its length, or cause missing sop or eop). Therefore the +-- dp_xonoff uses siso.xon and does not listen to siso.ready. +-- +-- The dp_xonoff in_siso.xon = '1' always, because the dp_xonoff will +-- discard incoming blocks if they cannot be passed on. When out_siso.xon +-- = '1', then in_siso.ready <= in_sosi.ready, so passed on. When +-- out_siso.xon = '0', then in_siso.xon = '1' and in_siso.ready <= '1' +-- (so in_siso = c_dp_sosi.rdy), because dp_xonoff can flush incoming +-- blocks at maximum rate, until out_siso.xon = '1' again. +-- +-- A dp_fifo will keep on outputing blocks when its out_siso.xon = '0', +-- because it only passes in_siso.xon <= out_siso.xon, so it relies on its +-- upsteam input to listen to the out_siso.xon. If there are still multiple +-- blocks in the FIFO then these will be output. Typicaaly it is not +-- necessary to have a dp_xonoff at the output of the dp_fifo to discard +-- these blocks, because the dp_fifo does listen to out_siso.ready = '0', +-- so the flow control per sample will then stop the dp_fifo from causing +-- downstream overflow. +-- +-- When a dp_fifo runs almost full within g_fifo_af_margin, then the +-- in_siso.ready is made '0'. New addition is g_fifo_af_xon that defines a +-- dp_fifo fill margin for making in_sosi.xon = '0'. If the upstream does +-- not listen to ready flow control and xon flow control (e.g. like input +-- from an ADC or a WG), then there may be need for an dp_xonoff at the +-- input of the FIFO to discard input blocks. +-- +-- The in_siso.ready = out_siso.ready so passed on unchanged, to support -- detailed output to input flow control per cycle. The in_siso.xon is -- always '1', because the out_siso.xon is taken care of in this -- dp_xonoff.vhd by flushing any in_sosi data when out_siso.xon = '0'. -- +-- . Use tb_dp_fifo_xonoff.vhd to verify dp_xonoff to avoid dp_fifo overflow. +-- -- . When g_bypass=TRUE then the in and out are wired and the component is void. -- . When g_bypass=FALSE then: -- The output is ON when flush='0'. @@ -61,6 +108,7 @@ ENTITY dp_xonoff IS -- Frame out out_siso : IN t_dp_siso; -- flush control via out_siso.xon out_sosi : OUT t_dp_sosi; + out_en : OUT STD_LOGIC; -- for monitoring purposes in tb -- Optional override to force XOFF ('1' = enable override) force_xoff : IN STD_LOGIC := '0' ); @@ -75,18 +123,20 @@ ARCHITECTURE rtl OF dp_xonoff IS SIGNAL flush : STD_LOGIC; SIGNAL nxt_flush : STD_LOGIC; - SIGNAL out_en : STD_LOGIC; + SIGNAL i_out_en : STD_LOGIC; SIGNAL nxt_out_en : STD_LOGIC; BEGIN + out_en <= i_out_en; + gen_bypass : IF g_bypass=TRUE GENERATE in_siso <= out_siso; out_sosi <= in_sosi; END GENERATE; no_bypass : IF g_bypass=FALSE GENERATE - in_siso.ready <= out_siso.ready OR (NOT out_en); -- pass on ready for detailed flow control per cycle only when output is enabled, otherwise ready = 1 + in_siso.ready <= out_siso.ready OR (NOT i_out_en); -- pass on ready for detailed flow control per cycle only when output is enabled, otherwise ready = 1 in_siso.xon <= '1'; -- upstream can remain on, because flush will handle out_siso.xon nxt_flush <= NOT out_siso.xon OR force_xoff; -- use xon for flow control at frame level @@ -95,11 +145,11 @@ BEGIN IF rst='1' THEN frm_busy_reg <= '0'; flush <= '0'; - out_en <= '1'; + i_out_en <= '1'; ELSIF rising_edge(clk) THEN frm_busy_reg <= frm_busy; flush <= nxt_flush; -- pipeline register flush to ease timing closure - out_en <= nxt_out_en; -- state register out_en because it can only change between frames + i_out_en <= nxt_out_en; -- state register out_en because it can only change between frames END IF; END PROCESS; @@ -114,9 +164,9 @@ BEGIN END IF; END PROCESS; - p_out_en : PROCESS(flush, out_en, frm_busy) + p_out_en : PROCESS(flush, i_out_en, frm_busy) BEGIN - nxt_out_en <= out_en; + nxt_out_en <= i_out_en; IF frm_busy='0' THEN IF flush='1' THEN nxt_out_en <= '0'; @@ -126,16 +176,16 @@ BEGIN END IF; END PROCESS; - p_out_sosi : PROCESS(in_sosi, out_en) + p_out_sosi : PROCESS(in_sosi, i_out_en) BEGIN -- Pass on sosi data via wires out_sosi <= in_sosi; -- XON/XOFF flow control via sosi control - out_sosi.sync <= in_sosi.sync AND out_en; - out_sosi.valid <= in_sosi.valid AND out_en; - out_sosi.sop <= in_sosi.sop AND out_en; - out_sosi.eop <= in_sosi.eop AND out_en; + out_sosi.sync <= in_sosi.sync AND i_out_en; + out_sosi.valid <= in_sosi.valid AND i_out_en; + out_sosi.sop <= in_sosi.sop AND i_out_en; + out_sosi.eop <= in_sosi.eop AND i_out_en; END PROCESS; END GENERATE; diff --git a/libraries/base/dp/tb/vhdl/tb_dp_fifo_xonoff.vhd b/libraries/base/dp/tb/vhdl/tb_dp_fifo_xonoff.vhd new file mode 100644 index 0000000000000000000000000000000000000000..7188c3417fcb214de2b283319bbcc4f23c8c2f84 --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_dp_fifo_xonoff.vhd @@ -0,0 +1,319 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2023 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- + +-- Author: Eric Kooistra +-- Date: 26 Apr 2023 +-- Purpose: +-- . Test bench for dp_fifos to verify xon flow control when FIFO runs full. +-- The dp_xonoff will discard blocks when its out_siso.xon = '0', to avoid +-- downstream overflow. The dp_xonoff needs to be applied when the updstream +-- source does not listen to flow control by siso.ready or by sisi.xon. +-- Description: +-- Verify that the dp_mux will not cause input FIFO overflow when the input +-- load is too large for the output capacity. +-- +-- g_use_in_xonoff g_use_out_xonoff +-- proc | | +-- dp_gen --> xonoff --> fifo_sc --> mux --> xonoff --> fifo <-- out_siso +-- frame | | arr | | | fill +-- | | | | | sc +-- | | | | | +-- bg_sosi_arr | | | | +-- fifo_in_sosi_arr | mux_out_sosi | +-- fifo_in_siso_arr | mux_in_siso | +-- mux_in_sosi_arr fifo_fill_in_sosi +-- mux_in_siso_arr fifo_fill_in_siso +-- +-- Tb stimuli: +-- . Enable input in_en after reset for 4*c_tb_nof_clk_cycles and disable it +-- before tb_end, to read FIFOs empty in c_tb_nof_clk_cycles until tb_end. +-- . Make external siso.xon = '0' for c_tb_nof_clk_cycles, to check xon flow +-- control. +-- ______________________________________ +-- in_en ___| |_________ +-- _____________________ ___________________ +-- out_siso.xon |__________| +-- +-- tb_end ___________________________________________________| +-- +-- Remark: +-- . If g_gap_size is too small to fit g_nof_inputs on a multiplexed output, +-- then g_use_in_xonoff needs to be TRUE to avoid u_in_fifo overflow. +-- . It appears that the dp_xonoff at the mux output is not needed +-- (g_use_out_xonoff = FALSE), because siso.ready or siso.xon at dp_xonoff +-- of BG outputs can provide sufficient flow control to avoid u_out_fifo +-- overflow. +-- Usage: +-- . as 12 +-- . run -all +-- Observe in Wave Window: +-- . near BG inputs: +-- - fifo_in_siso_arr +-- - dp_out_en_arr, to view dp_xonoff flushing +-- - in_fifo_usedw_arr in analogue format +-- . at MUX output: +-- - fifo_fill_in_siso +-- - dp_out_en, to view dp_xonoff flushing +-- - out_fifo_usedw in analogue format +-- Self test result is OK when there is no FAILURE due to FIFO overflow. + +LIBRARY IEEE, common_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_str_pkg.ALL; +USE common_lib.common_lfsr_sequences_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; +USE work.dp_stream_pkg.ALL; +USE work.tb_dp_pkg.ALL; + +ENTITY tb_dp_fifo_xonoff IS + GENERIC ( + g_nof_inputs : NATURAL := 2; + g_nof_blocks : NATURAL := 500; + g_block_size : NATURAL := 10; + g_gap_size : NATURAL := 0; + g_use_in_xonoff : BOOLEAN := TRUE; + g_use_out_xonoff : BOOLEAN := FALSE + ); +END tb_dp_fifo_xonoff; + + +ARCHITECTURE tb OF tb_dp_fifo_xonoff IS + + CONSTANT c_clk_period : TIME := 5 ns; + + CONSTANT c_tb_nof_clk_cycles : NATURAL := g_nof_blocks * g_block_size; + + -- Use extrnal FIFO for per input of dp_mux + -- c_fifo_af_ready >= 4, nof words below max (full) at which fifo is considered almost full for snk_out.ready + -- c_fifo_af_xon >= 0, nof words below max (full) at which fifo is considered almost full for snk_out.xon + CONSTANT c_fifo_af_ready : NATURAL := 4; + CONSTANT c_fifo_af_xon : NATURAL := g_block_size + 50; + + CONSTANT c_in_fifo_size : NATURAL := g_block_size * 20; + + CONSTANT c_out_fifo_size : NATURAL := g_block_size * 20; + CONSTANT c_out_fifo_fill : NATURAL := g_block_size; + + CONSTANT c_ready_latency : NATURAL := 1; + CONSTANT c_data_w : NATURAL := 16; + CONSTANT c_symbol_w : NATURAL := c_data_w; + CONSTANT c_symbol_init : NATURAL := 0; + CONSTANT c_nof_symbols : NATURAL := g_block_size; + CONSTANT c_bsn : NATURAL := 0; + CONSTANT c_sync : STD_LOGIC := '0'; + + CONSTANT c_nof_input_w : NATURAL := ceil_log2(g_nof_inputs); + + SIGNAL clk : STD_LOGIC := '1'; + SIGNAL rst : STD_LOGIC := '1'; + SIGNAL in_en : STD_LOGIC := '0'; + SIGNAL tb_end : STD_LOGIC := '0'; + + SIGNAL bg_siso : t_dp_siso := c_dp_siso_rdy; + SIGNAL bg_sosi_arr : t_dp_sosi_arr(0 TO g_nof_inputs-1); + SIGNAL dp_out_en_arr : STD_LOGIC_VECTOR(0 TO g_nof_inputs-1); + SIGNAL fifo_in_siso_arr : t_dp_siso_arr(0 TO g_nof_inputs-1); + SIGNAL fifo_in_sosi_arr : t_dp_sosi_arr(0 TO g_nof_inputs-1); + SIGNAL mux_in_siso_arr : t_dp_siso_arr(0 TO g_nof_inputs-1); + SIGNAL mux_in_sosi_arr : t_dp_sosi_arr(0 TO g_nof_inputs-1); + + SIGNAL mux_out_siso : t_dp_siso := c_dp_siso_rdy; + SIGNAL mux_out_sosi : t_dp_sosi; + SIGNAL dp_out_en : STD_LOGIC; + SIGNAL fifo_fill_in_siso : t_dp_siso := c_dp_siso_rdy; + SIGNAL fifo_fill_in_sosi : t_dp_sosi; + SIGNAL out_siso : t_dp_siso := c_dp_siso_rdy; + SIGNAL out_sosi : t_dp_sosi; + + -- Monitor FIFO filling + TYPE t_in_fifo_usedw_slv_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(ceil_log2(c_out_fifo_size)-1 DOWNTO 0); + + SIGNAL in_fifo_wr_ful_arr : STD_LOGIC_VECTOR(0 TO g_nof_inputs-1); + SIGNAL in_fifo_usedw_arr : t_in_fifo_usedw_slv_arr(0 TO g_nof_inputs-1); + SIGNAL in_fifo_rd_emp_arr : STD_LOGIC_VECTOR(0 TO g_nof_inputs-1); + SIGNAL out_fifo_wr_ful : STD_LOGIC; + SIGNAL out_fifo_usedw : STD_LOGIC_VECTOR(ceil_log2(c_out_fifo_size)-1 DOWNTO 0); + SIGNAL out_fifo_rd_emp : STD_LOGIC; + +BEGIN + + ------------------------------------------------------------------------------ + -- Clock & reset + ------------------------------------------------------------------------------ + clk <= (NOT clk) OR tb_end AFTER c_clk_period/2; + rst <= '1', '0' AFTER c_clk_period*7; + + ------------------------------------------------------------------------------ + -- Stimuli: + ------------------------------------------------------------------------------ + gen_bg_arr : FOR I IN 0 TO g_nof_inputs-1 GENERATE + p_bg_arr : PROCESS + BEGIN + WHILE TRUE LOOP + proc_dp_gen_frame(c_ready_latency, + c_data_w, + c_symbol_w, + c_symbol_init, + c_nof_symbols, + c_bsn + I, -- use bsn to identify the inputs + c_sync, + clk, + in_en, + bg_siso, + bg_sosi_arr(I)); + WAIT FOR g_gap_size * c_clk_period; + END LOOP; + -- Use WHILE LOOP and WAIT to avoid warning (vcom-1090) Possible infinite loop: + -- Process contains no WAIT statement. + WAIT; + END PROCESS; + + gen_dp_xonoff : IF g_use_in_xonoff GENERATE + u_dp_xonoff : ENTITY work.dp_xonoff + PORT MAP ( + rst => rst, + clk => clk, + -- Frame in + in_siso => OPEN, + in_sosi => bg_sosi_arr(I), + -- Frame out + out_siso => fifo_in_siso_arr(I), + out_sosi => fifo_in_sosi_arr(I), + out_en => dp_out_en_arr(I) + ); + END GENERATE; + no_dp_xonoff : IF NOT g_use_in_xonoff GENERATE + fifo_in_sosi_arr <= bg_sosi_arr; + dp_out_en_arr <= (OTHERS => '1'); + END GENERATE; + + u_in_fifo : ENTITY work.dp_fifo_sc + GENERIC MAP ( + g_data_w => c_data_w, + g_bsn_w => c_nof_input_w, + g_use_bsn => TRUE, -- use bsn to identify the inputs + g_use_ctrl => TRUE, -- sop & eop + g_fifo_size => c_in_fifo_size, + g_fifo_af_margin => c_fifo_af_ready, + g_fifo_af_xon => c_fifo_af_xon, + g_fifo_rl => c_ready_latency + ) + PORT MAP ( + rst => rst, + clk => clk, + -- Monitor FIFO filling + wr_ful => in_fifo_wr_ful_arr(I), + usedw => in_fifo_usedw_arr(I), + rd_emp => in_fifo_rd_emp_arr(I), + -- ST sink + snk_out => fifo_in_siso_arr(I), -- flush control via out_siso.xon + snk_in => fifo_in_sosi_arr(I), + -- ST source + src_in => mux_in_siso_arr(I), + src_out => mux_in_sosi_arr(I) + ); + END GENERATE; + + -- Enable input after reset and disable it before tb_end, to read FIFOs empty + in_en <= '0', '1' AFTER c_clk_period*17, + '0' AFTER 4 * c_tb_nof_clk_cycles * c_clk_period; + + -- Also verify toggling external siso.xon flow control + out_siso.xon <= '1', + '0' AFTER 2 * c_tb_nof_clk_cycles * c_clk_period, + '1' AFTER 3 * c_tb_nof_clk_cycles * c_clk_period; + + -- End test + tb_end <= '0', '1' AFTER 5 * c_tb_nof_clk_cycles * c_clk_period; + + ------------------------------------------------------------------------------ + -- Multiplexer + ------------------------------------------------------------------------------ + u_dp_mux : ENTITY work.dp_mux + GENERIC MAP ( + g_nof_input => g_nof_inputs, + g_fifo_size => array_init(1024, g_nof_inputs), -- must match g_nof_input, even when g_use_fifo=FALSE + g_fifo_fill => array_init( 0, g_nof_inputs) -- must match g_nof_input, even when g_use_fifo=FALSE + ) + PORT MAP ( + rst => rst, + clk => clk, + -- ST sinks + snk_out_arr => mux_in_siso_arr, + snk_in_arr => mux_in_sosi_arr, + -- ST source + src_in => mux_out_siso, + src_out => mux_out_sosi + ); + + ------------------------------------------------------------------------------ + -- Output + ------------------------------------------------------------------------------ + + gen_dp_xonoff : IF g_use_out_xonoff GENERATE + u_dp_xonoff : ENTITY work.dp_xonoff + PORT MAP ( + rst => rst, + clk => clk, + -- Frame in + in_siso => mux_out_siso, + in_sosi => mux_out_sosi, + -- Frame out + out_siso => fifo_fill_in_siso, + out_sosi => fifo_fill_in_sosi, + out_en => dp_out_en + ); + END GENERATE; + no_dp_xonoff : IF NOT g_use_out_xonoff GENERATE + fifo_fill_in_sosi <= mux_out_sosi; + mux_out_siso <= fifo_fill_in_siso; + dp_out_en <= '1'; + END GENERATE; + + u_out_fifo : ENTITY work.dp_fifo_fill_sc + --u_out_fifo : ENTITY work.dp_fifo_fill_eop_sc + GENERIC MAP ( + g_data_w => c_data_w, + g_bsn_w => c_nof_input_w, + g_use_bsn => TRUE, -- use bsn to identify the inputs + g_fifo_fill => c_out_fifo_fill, + g_fifo_size => c_out_fifo_size, + g_fifo_af_margin => c_fifo_af_ready, + g_fifo_af_xon => c_fifo_af_xon, + g_fifo_rl => c_ready_latency + ) + PORT MAP ( + rst => rst, + clk => clk, + -- Monitor FIFO filling + wr_ful => out_fifo_wr_ful, + usedw => out_fifo_usedw, + rd_emp => out_fifo_rd_emp, + -- ST sink + snk_out => fifo_fill_in_siso, + snk_in => fifo_fill_in_sosi, + -- ST source + src_in => out_siso, + src_out => out_sosi + ); + +END tb; diff --git a/libraries/base/ring/src/vhdl/ring_mux.vhd b/libraries/base/ring/src/vhdl/ring_mux.vhd index 0c6977776aefb653d5dcd4e726acd8ab3f515316..b907a921bbb4d8b808f620680f5b5476a282417a 100644 --- a/libraries/base/ring/src/vhdl/ring_mux.vhd +++ b/libraries/base/ring/src/vhdl/ring_mux.vhd @@ -46,6 +46,7 @@ ENTITY ring_mux IS g_use_empty : BOOLEAN := TRUE; g_use_error : BOOLEAN := TRUE; g_use_sync : BOOLEAN := TRUE; + g_fifo_af_xon : NATURAL := 0; -- >=0, Nof words below max (full) at which fifo is considered almost full for snk_out.xon g_fifo_size : t_natural_arr := array_init(1024, 2) -- must match c_nof_input ); PORT ( @@ -94,8 +95,8 @@ BEGIN g_use_in_channel => TRUE, g_use_error => g_use_error, g_use_sync => g_use_sync, + g_fifo_af_xon => g_fifo_af_xon, g_fifo_size => g_fifo_size - ) PORT MAP ( rst => dp_rst, diff --git a/libraries/io/ddr/src/vhdl/io_ddr.vhd b/libraries/io/ddr/src/vhdl/io_ddr.vhd index 78c7bd3c0780d789b4f968750c8ebb0f09cbcecd..9157289e2e4fab3607d1972a8d9173296a4b759e 100644 --- a/libraries/io/ddr/src/vhdl/io_ddr.vhd +++ b/libraries/io/ddr/src/vhdl/io_ddr.vhd @@ -234,7 +234,8 @@ ARCHITECTURE str OF io_ddr IS CONSTANT c_wr_use_ctrl : BOOLEAN := sel_a_b(g_wr_flush_mode="SOP", TRUE, FALSE); CONSTANT c_wr_fifo_use_ctrl : BOOLEAN := c_wr_use_sync OR c_wr_use_ctrl; - CONSTANT c_ddr_gigabytes : NATURAL := func_tech_ddr_module_size(g_tech_ddr); -- units GiByte + CONSTANT c_ddr_nofbytes_w : NATURAL := func_tech_ddr_module_nofbytes_w(g_tech_ddr); -- log2(number of bytes) + CONSTANT c_ddr_gigabytes : INTEGER := func_tech_ddr_module_gigabytes(g_tech_ddr); -- units value GiByte when value > 1 or 2**value GiByte when value < 0 CONSTANT c_ctlr_nof_bytes_per_word : NATURAL := func_tech_ddr_ctlr_ip_data_w(g_tech_ddr) / c_byte_w; -- unit byte CONSTANT c_ctlr_address_w : NATURAL := func_tech_ddr_ctlr_address_w(g_tech_ddr); @@ -523,7 +524,7 @@ BEGIN mm_reg_io_ddr <= RESIZE_UVEC(rd_fifo_full_reg & wr_fifo_full_reg, c_mem_reg_dat_w) & RESIZE_UVEC(ctlr_wr_fifo_usedw, c_mem_reg_dat_w) & RESIZE_UVEC(ctlr_rd_fifo_usedw, c_mem_reg_dat_w) & - RESIZE_UVEC(TO_UVEC(c_ddr_gigabytes, 8) & + RESIZE_UVEC(TO_SVEC(c_ddr_gigabytes, 8) & TO_UVEC(c_ctlr_nof_bytes_per_word, 8) & ctlr_tech_mosi.wr & ctlr_tech_miso.rdval & ctlr_tech_miso.cal_fail & ctlr_tech_miso.cal_ok & ctlr_rst_out_i & ctlr_wr_flush_en & ctlr_tech_miso.waitrequest_n & ctlr_tech_miso.done, c_mem_reg_dat_w); diff --git a/libraries/io/ddr/tb/vhdl/tb_io_ddr.vhd b/libraries/io/ddr/tb/vhdl/tb_io_ddr.vhd index eac49482da7a7b38127631a97b3feea871207b58..1576dda24fcb93998266da1e458863f3d1c9d031 100644 --- a/libraries/io/ddr/tb/vhdl/tb_io_ddr.vhd +++ b/libraries/io/ddr/tb/vhdl/tb_io_ddr.vhd @@ -69,10 +69,13 @@ ARCHITECTURE str of tb_io_ddr IS -- Select DDR3 or DDR4 dependent on the technology and sim model CONSTANT c_mem_ddr : t_c_tech_ddr := func_tech_sel_ddr(g_technology, g_tech_ddr3, g_tech_ddr4); + + -- Need to use >= c_tech_ddr4_sim_16k for g_block_len = 2500 in tb_tb_io_ddr CONSTANT c_sim_ddr : t_c_tech_ddr := func_tech_sel_ddr(g_technology, c_tech_ddr3_sim_16k, c_tech_ddr4_sim_16k); CONSTANT c_tech_ddr : t_c_tech_ddr := func_tech_sel_ddr(g_sim_model, c_sim_ddr, c_mem_ddr); - CONSTANT c_exp_gigabytes : NATURAL := func_tech_ddr_module_size(c_tech_ddr); + CONSTANT c_exp_gigabytes : INTEGER := func_tech_ddr_module_gigabytes(c_tech_ddr); + CONSTANT c_exp_nofbytes_w : NATURAL := func_tech_ddr_module_nofbytes_w(c_tech_ddr); CONSTANT c_exp_nof_bytes_per_word : NATURAL := func_tech_ddr_ctlr_ip_data_w(c_tech_ddr) / c_byte_w; CONSTANT c_dp_clk_period : TIME := 5 ns; -- 200 MHz @@ -166,8 +169,9 @@ ARCHITECTURE str of tb_io_ddr IS SIGNAL dbg_c_ctlr_wr_not_rd_arr : STD_LOGIC_VECTOR(0 TO c_nof_access-1) := c_ctlr_wr_not_rd_arr; SIGNAL dbg_c_tech_ddr : t_c_tech_ddr := c_tech_ddr; - SIGNAL dbg_c_exp_gigabytes : NATURAL := c_exp_gigabytes; -- = 0 for sim model, else nof GB - SIGNAL ddr_gigabytes : NATURAL; + SIGNAL dbg_c_exp_gigabytes : INTEGER := c_exp_gigabytes; -- = 0 for sim model, else nof GB + SIGNAL dbg_c_exp_nofbytes_w : NATURAL := c_exp_nofbytes_w; + SIGNAL ddr_gigabytes : INTEGER; SIGNAL dbg_c_exp_nof_bytes_per_word : NATURAL := c_exp_nof_bytes_per_word; SIGNAL ctlr_nof_bytes_per_word : NATURAL; SIGNAL dbg_c_dp_data_w : NATURAL := c_dp_data_w; @@ -274,7 +278,7 @@ BEGIN proc_mem_mm_bus_rd(0, mm_clk, reg_io_ddr_miso, reg_io_ddr_mosi); proc_mem_mm_bus_rd_latency(1, mm_clk); -- . verify ddr_gigabytes - ddr_gigabytes <= TO_UINT(reg_io_ddr_miso.rddata(23 DOWNTO 16)); + ddr_gigabytes <= TO_SINT(reg_io_ddr_miso.rddata(23 DOWNTO 16)); proc_common_wait_some_cycles(mm_clk, 1); ASSERT ddr_gigabytes = c_exp_gigabytes REPORT "Wrong read ddr_gigabytes" SEVERITY ERROR; -- . verify ctlr_nof_bytes_per_word diff --git a/libraries/technology/ddr/tech_ddr_arria10.vhd b/libraries/technology/ddr/tech_ddr_arria10.vhd index d706440e088df27496efa16f606d261b71ac2141..012b57882e8c25c26255a886863df1931ff395f0 100644 --- a/libraries/technology/ddr/tech_ddr_arria10.vhd +++ b/libraries/technology/ddr/tech_ddr_arria10.vhd @@ -71,7 +71,7 @@ END tech_ddr_arria10; ARCHITECTURE str OF tech_ddr_arria10 IS - CONSTANT c_gigabytes : NATURAL := func_tech_ddr_module_size(g_tech_ddr); + CONSTANT c_gigabytes : INTEGER := func_tech_ddr_module_gigabytes(g_tech_ddr); CONSTANT c_ctlr_address_w : NATURAL := 26; --func_tech_ddr_ctlr_address_w(g_tech_ddr); CONSTANT c_ctlr_data_w : NATURAL := 576;--func_tech_ddr_ctlr_data_w( g_tech_ddr); diff --git a/libraries/technology/ddr/tech_ddr_arria10_e1sg.vhd b/libraries/technology/ddr/tech_ddr_arria10_e1sg.vhd index c59f216e78c90925321dee6602f3f561add69899..ff65a1506508cea6098fc36c1e9242997d438b12 100644 --- a/libraries/technology/ddr/tech_ddr_arria10_e1sg.vhd +++ b/libraries/technology/ddr/tech_ddr_arria10_e1sg.vhd @@ -74,7 +74,7 @@ END tech_ddr_arria10_e1sg; ARCHITECTURE str OF tech_ddr_arria10_e1sg IS - CONSTANT c_gigabytes : NATURAL := func_tech_ddr_module_size(g_tech_ddr); + CONSTANT c_gigabytes : INTEGER := func_tech_ddr_module_gigabytes(g_tech_ddr); CONSTANT c_ctlr_address_w : NATURAL := func_tech_ddr_ctlr_address_w(g_tech_ddr); CONSTANT c_ctlr_data_w : NATURAL := 576;--func_tech_ddr_ctlr_data_w( g_tech_ddr); diff --git a/libraries/technology/ddr/tech_ddr_arria10_e2sg.vhd b/libraries/technology/ddr/tech_ddr_arria10_e2sg.vhd index 5b6f28915746718af3d4a3c20121f74b7c86d320..33876ba09e857050232506109614ffee6ef299d5 100644 --- a/libraries/technology/ddr/tech_ddr_arria10_e2sg.vhd +++ b/libraries/technology/ddr/tech_ddr_arria10_e2sg.vhd @@ -73,7 +73,7 @@ END tech_ddr_arria10_e2sg; ARCHITECTURE str OF tech_ddr_arria10_e2sg IS - CONSTANT c_gigabytes : NATURAL := func_tech_ddr_module_size(g_tech_ddr); + CONSTANT c_gigabytes : INTEGER := func_tech_ddr_module_gigabytes(g_tech_ddr); CONSTANT c_ctlr_address_w : NATURAL := func_tech_ddr_ctlr_address_w(g_tech_ddr); CONSTANT c_ctlr_ip_data_w : NATURAL := func_tech_ddr_ctlr_ip_data_w(g_tech_ddr); diff --git a/libraries/technology/ddr/tech_ddr_arria10_e3sge3.vhd b/libraries/technology/ddr/tech_ddr_arria10_e3sge3.vhd index 2a95f000aad9136b9345c1898c400622c569568a..075c74830130f3c61842093ed5831a2ad9eb706c 100644 --- a/libraries/technology/ddr/tech_ddr_arria10_e3sge3.vhd +++ b/libraries/technology/ddr/tech_ddr_arria10_e3sge3.vhd @@ -73,7 +73,7 @@ END tech_ddr_arria10_e3sge3; ARCHITECTURE str OF tech_ddr_arria10_e3sge3 IS - CONSTANT c_gigabytes : NATURAL := func_tech_ddr_module_size(g_tech_ddr); + CONSTANT c_gigabytes : INTEGER := func_tech_ddr_module_gigabytes(g_tech_ddr); CONSTANT c_ctlr_address_w : NATURAL := func_tech_ddr_ctlr_address_w(g_tech_ddr); CONSTANT c_ctlr_data_w : NATURAL := 576;--func_tech_ddr_ctlr_data_w( g_tech_ddr); diff --git a/libraries/technology/ddr/tech_ddr_mem_model.vhd b/libraries/technology/ddr/tech_ddr_mem_model.vhd index c814d05884e16fafa9b6d371d21fb0b606015102..a301052eb7f072407ba160948bbb845e939ed961 100644 --- a/libraries/technology/ddr/tech_ddr_mem_model.vhd +++ b/libraries/technology/ddr/tech_ddr_mem_model.vhd @@ -59,10 +59,10 @@ END tech_ddr_memory_model; ARCHITECTURE str OF tech_ddr_memory_model IS - CONSTANT c_gigabytes : NATURAL := func_tech_ddr_module_size(g_tech_ddr); + CONSTANT c_gigabytes : INTEGER := func_tech_ddr_module_gigabytes(g_tech_ddr); SIGNAL dbg_g_tech_ddr : t_c_tech_ddr := g_tech_ddr; - SIGNAL dbg_c_gigabytes : NATURAL := c_gigabytes; + SIGNAL dbg_c_gigabytes : INTEGER := c_gigabytes; BEGIN diff --git a/libraries/technology/ddr/tech_ddr_pkg.vhd b/libraries/technology/ddr/tech_ddr_pkg.vhd index 894e988782ebaf62ed5d9017343291b3f72a6366..fb3400258c6ba7e8620ebc0b21273abb67e44c5c 100644 --- a/libraries/technology/ddr/tech_ddr_pkg.vhd +++ b/libraries/technology/ddr/tech_ddr_pkg.vhd @@ -67,7 +67,12 @@ PACKAGE tech_ddr_pkg IS FUNCTION func_tech_ddr_ctlr_address_w(c_ddr : t_c_tech_ddr) RETURN NATURAL; -- return DDR address width for the controller data at the by rsl=4 reduced rate FUNCTION func_tech_ddr_ctlr_data_w( c_ddr : t_c_tech_ddr) RETURN NATURAL; -- return DDR data width for the controller data at the by rsl=4 reduced rate FUNCTION func_tech_ddr_ctlr_ip_data_w(c_ddr : t_c_tech_ddr) RETURN NATURAL; -- return DDR data width for the controller data at the by rsl=4 reduced rate - FUNCTION func_tech_ddr_module_size( c_ddr : t_c_tech_ddr) RETURN NATURAL; -- return DDR module size in GByte + + -- return DDR module size in log2(number of bytes), because 2**nofbytes_w may not fit in 31 bit NATURAL + FUNCTION func_tech_ddr_module_nofbytes_w(c_ddr : t_c_tech_ddr) RETURN NATURAL; + -- return DDR module size in GiBytes when >= 1 GByte which is typical on HW, else + -- return size as negative value to indicate 2**value fraction of 1GByte which is typical in simulation + FUNCTION func_tech_ddr_module_gigabytes(c_ddr : t_c_tech_ddr) RETURN INTEGER; FUNCTION func_tech_ddr_sim_size(c_ddr : t_c_tech_ddr; sim_ctrl_addr_w : NATURAL) RETURN t_c_tech_ddr; -- derive sim_ddr from c_ddr (or alternatively use predefined c_tech_ddr*_sim) FUNCTION func_tech_ddr_rewire_64b_to_72b(c_ddr : t_c_tech_ddr; vec_64b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; @@ -252,20 +257,28 @@ PACKAGE BODY tech_ddr_pkg IS RETURN v_ddr; END; - FUNCTION func_tech_ddr_module_size(c_ddr : t_c_tech_ddr) RETURN NATURAL IS + FUNCTION func_tech_ddr_module_nofbytes_w(c_ddr : t_c_tech_ddr) RETURN NATURAL IS CONSTANT c_dq_address_w : NATURAL := func_tech_ddr_dq_address_w(c_ddr); CONSTANT c_dq_nof_bytes : NATURAL := 8; -- both dw_q = 64 and 72 are regarded as having 8 bytes (either with 8 or 9 bits per byte) CONSTANT c_dq_nof_bytes_w : NATURAL := ceil_log2(c_dq_nof_bytes); CONSTANT c_module_nof_bytes_w : NATURAL := c_dq_address_w + c_dq_nof_bytes_w; + BEGIN + RETURN c_module_nof_bytes_w; + END; + + FUNCTION func_tech_ddr_module_gigabytes(c_ddr : t_c_tech_ddr) RETURN INTEGER IS + CONSTANT c_module_nof_bytes_w : NATURAL := func_tech_ddr_module_nofbytes_w(c_ddr); CONSTANT c_1GB_w : NATURAL := 30; BEGIN IF c_module_nof_bytes_w < c_1GB_w THEN - RETURN 0; + -- Return <= -1 to indicate fraction of 1GByte, so e.g. -1 implies 2**-1 = 0.5 GByte + RETURN c_module_nof_bytes_w - c_1GB_w; ELSE - RETURN 2**(c_module_nof_bytes_w-c_1GB_w); + -- Return >= 1 to indicate multiple of 1GByte = number of GByte + RETURN 2**(c_module_nof_bytes_w - c_1GB_w); END IF; END; - + FUNCTION func_tech_ddr_rewire_64b_to_72b(c_ddr : t_c_tech_ddr; vec_64b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS VARIABLE vec_72b : STD_LOGIC_VECTOR(func_tech_ddr_ctlr_ip_data_w(c_ddr) - 1 DOWNTO 0) := (OTHERS => '0'); BEGIN diff --git a/libraries/technology/ddr/tech_ddr_stratixiv.vhd b/libraries/technology/ddr/tech_ddr_stratixiv.vhd index 7e9563ee5667fcd30c7d31c0a9822f999b9e5f6c..2830195512e35b15ac6b8cbb3e3ae8446e0f955e 100644 --- a/libraries/technology/ddr/tech_ddr_stratixiv.vhd +++ b/libraries/technology/ddr/tech_ddr_stratixiv.vhd @@ -75,12 +75,12 @@ END tech_ddr_stratixiv; ARCHITECTURE str OF tech_ddr_stratixiv IS - CONSTANT c_gigabytes : NATURAL := func_tech_ddr_module_size(g_tech_ddr); + CONSTANT c_gigabytes : INTEGER := func_tech_ddr_module_gigabytes(g_tech_ddr); CONSTANT c_ctlr_address_w : NATURAL := func_tech_ddr_ctlr_address_w(g_tech_ddr); CONSTANT c_ctlr_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr); - SIGNAL dbg_c_gigabytes : NATURAL := c_gigabytes; + SIGNAL dbg_c_gigabytes : INTEGER := c_gigabytes; SIGNAL ref_rst_n : STD_LOGIC; SIGNAL ctlr_gen_rst_n : STD_LOGIC;