diff --git a/applications/lofar2/libraries/sdp/hdllib.cfg b/applications/lofar2/libraries/sdp/hdllib.cfg index 06720dbf4fed95af61f17c22350b8afce784719d..d82f2018d6eee058d3c6c5894ff4bfdfc5d075bf 100644 --- a/applications/lofar2/libraries/sdp/hdllib.cfg +++ b/applications/lofar2/libraries/sdp/hdllib.cfg @@ -13,12 +13,14 @@ synth_files = src/vhdl/sdp_info_reg.vhd src/vhdl/sdp_info.vhd src/vhdl/sdp_beamformer_output.vhd + src/vhdl/sdp_statistics_offload.vhd src/vhdl/node_sdp_adc_input_and_timing.vhd src/vhdl/node_sdp_filterbank.vhd src/vhdl/node_sdp_beamformer.vhd test_bench_files = tb/vhdl/tb_sdp_info.vhd + tb/vhdl/tb_sdp_statistics_offload.vhd regression_test_vhdl = tb/vhdl/tb_sdp_info.vhd diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd new file mode 100644 index 0000000000000000000000000000000000000000..1e364d312a7e91a0a00f14098c023513f7769ef5 --- /dev/null +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd @@ -0,0 +1,377 @@ +------------------------------------------------------------------------------- +-- +-- 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: P. Donker + +-- Purpose: +-- . SDP statistics offload +-- Description: +-- +-- https://support.astron.nl/confluence/pages/viewpage.action?spaceKey=L2M&title=L5+SDPFW+Design+Document%3A+Subband+filterbank +-- https://plm.astron.nl/polarion/#/project/LOFAR2System/wiki/L2%20Interface%20Control%20Documents/SC%20to%20SDP%20ICD +-- +-- Remark: +-- . Offload SST, BST or XST data from the memory to a network interface +-- get data from mm bus and assemble header from from other input settings +-- +-- A processing node (PN) in the ring ia called a ring node (RN). +-- +-- g_statistics_type = "SST" +-- data_id.signal_input_index = rn_id * S_pn +-- nof_signal_inputs = 1 +-- nof_statistics_per_packet = N_sub +-- +-- g_statistics_type = "BST" +-- data_id.beamlet_index = g_beamset_index * S_sub_bf +-- nof_signal_inputs = 0 (default not used) +-- nof_statistics_per_packet = S_sub_bf +-- +-- g_statistics_type = "XST" +-- data_id.signal_input_A_index = rn_id * S_pn +-- data_id.signal_input_B_index = function of correlator cell instance and rn_id * S_pn +-- nof_signal_inputs = S_pn => 12 (fixed) +-- nof_statistics_per_packet = S_pn * S_pn => 12 * 12 = 144 +------------------------------------------------------------------------------- + +LIBRARY IEEE, common_lib, mm_lib, dp_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE common_lib.common_field_pkg.ALL; +USE common_lib.common_network_layers_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE work.sdp_pkg.ALL; + +ENTITY sdp_statistics_offload IS + GENERIC ( + g_statistics_type : STRING := "SST"; + g_offload_time : NATURAL := 0; + g_beamset_id : NATURAL := 0 + ); + PORT ( + -- Clocks and reset + mm_rst : IN STD_LOGIC; -- reset synchronous with mm_clk + mm_clk : IN STD_LOGIC; -- memory-mapped bus clock + + dp_clk : IN STD_LOGIC; + dp_rst : IN STD_LOGIC; + + -- from MM master multiplexer + master_mosi : IN t_mem_mosi := c_mem_mosi_rst; + master_miso : OUT t_mem_miso; + + reg_enable_mosi : IN t_mem_mosi := c_mem_mosi_rst; + reg_enable_miso : OUT t_mem_miso; + + reg_hdr_dat_mosi : IN t_mem_mosi := c_mem_mosi_rst; + reg_hdr_dat_miso : OUT t_mem_miso; + + in_sosi : IN t_dp_sosi; -- from selector (sst_sosi_arr[0]) + out_sosi : OUT t_dp_sosi; -- output from SST UDP offload (sst_udp_sosi) + + -- inputs from other blocks + eth_src_mac : IN STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0); + udp_src_port : IN STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0); + ip_src_addr : IN STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0); + sdp_info : IN t_sdp_info; + + gn_index : IN NATURAL + ); +END sdp_statistics_offload; + + +ARCHITECTURE str OF sdp_statistics_offload IS + + CONSTANT c_version : NATURAL := 1; + CONSTANT c_marker : NATURAL := sel_a_b((g_statistics_type="BST"), 66, sel_a_b((g_statistics_type="XST"), 88, 83)); -- based on g_statistics_type: 'S'=0x53="SST", 'B'=0x42="BST", 'X'=0x58="XST" + CONSTANT c_nof_statistics_per_packet : NATURAL := 0; + CONSTANT c_data_size : NATURAL := 2; + CONSTANT c_step_size : NATURAL := 4; + CONSTANT c_nof_data : NATURAL := 512; + CONSTANT c_block_size : NATURAL := c_nof_data * c_data_size * (c_step_size / c_data_size); + CONSTANT c_nof_streams : NATURAL := 1; + CONSTANT c_nof_signal_inputs : NATURAL := sel_a_b(g_statistics_type="BST", 0, sel_a_b(g_statistics_type="XST", c_sdp_S_pn, 1)); + CONSTANT c_nof_statistics_per_package : NATURAL := sel_a_b(g_statistics_type="BST", c_sdp_S_sub_bf, sel_a_b(g_statistics_type="XST", (c_sdp_S_pn*c_sdp_S_pn*c_nof_complex), c_sdp_N_sub)); + + CONSTANT c_beamlet_id : NATURAL := g_beamset_id * c_sdp_S_sub_bf; + + TYPE t_reg IS RECORD + block_count : NATURAL; + start_address : NATURAL; + start_pulse : STD_LOGIC; + dp_header_info : STD_LOGIC_VECTOR(1023 DOWNTO 0); + data_id : STD_LOGIC_VECTOR(31 DOWNTO 0); + END RECORD; + + CONSTANT c_reg_rst : t_reg := (0, 0, '0', (OTHERS => '0'), (OTHERS => '0')); + + SIGNAL r : t_reg; + SIGNAL d : t_reg; + + SIGNAL m_mosi : t_mem_mosi; + SIGNAL m_miso : t_mem_miso; + SIGNAL trigger : STD_LOGIC := '0'; + SIGNAL nof_cycles_dly : NATURAL := 0; + SIGNAL mm_done : STD_LOGIC := '0'; + SIGNAL start_addr : NATURAL := 0; + SIGNAL start_pulse : STD_LOGIC := '0'; + SIGNAL dp_block_from_mm_src_out : t_dp_sosi; + SIGNAL dp_block_from_mm_src_in : t_dp_siso; + + SIGNAL dp_header_info : STD_LOGIC_VECTOR(1023 DOWNTO 0):= (OTHERS => '0'); + SIGNAL payload_err : STD_LOGIC := '0'; + SIGNAL integration_interval_cnt : NATURAL := 0; + SIGNAL integration_interval : STD_LOGIC_VECTOR(24-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL bsn_at_sync : STD_LOGIC_VECTOR(64-1 DOWNTO 0) := (OTHERS => '0'); + + SIGNAL sdp_data_id : STD_LOGIC_VECTOR(32-1 DOWNTO 0); + + ------------------------------------------------------------------------------- + -- dp_offload_tx + ------------------------------------------------------------------------------- + CONSTANT c_nof_hdr_fields : NATURAL := 3+12+4+20+1; -- 592b; 9.25 64b words + -- c_hdr_field_sel for each field: 0=data path, 1=MM controlled + CONSTANT c_hdr_field_sel : STD_LOGIC_VECTOR(c_nof_hdr_fields-1 DOWNTO 0) := "101"&"111111111001"&"0111"&"00000000000000000000"&"0"; -- TODO + + CONSTANT c_hdr_field_arr : t_common_field_arr(c_nof_hdr_fields-1 DOWNTO 0) := ( ( field_name_pad("eth_dst_mac" ), "RW", 48, field_default(x"00074306C700") ), -- 00074306C700=DOP36-eth0 + ( field_name_pad("eth_src_mac" ), "RW", 48, field_default(0) ), + ( field_name_pad("eth_type" ), "RO", 16, field_default(x"0800") ), + + ( field_name_pad("ip_version" ), "RO", 4, field_default(4) ), + ( field_name_pad("ip_header_length" ), "RO", 4, field_default(5) ), + ( field_name_pad("ip_services" ), "RO", 8, field_default(0) ), + ( field_name_pad("ip_total_length" ), "RO", 16, field_default(7868) ), + ( field_name_pad("ip_identification" ), "RO", 16, field_default(0) ), + ( field_name_pad("ip_flags" ), "RO", 3, field_default(2) ), + ( field_name_pad("ip_fragment_offset" ), "RO", 13, field_default(0) ), + ( field_name_pad("ip_time_to_live" ), "RO", 8, field_default(127) ), + ( field_name_pad("ip_protocol" ), "RO", 8, field_default(17) ), + ( field_name_pad("ip_header_checksum" ), "RW", 16, field_default(0) ), + ( field_name_pad("ip_src_addr" ), "RW", 32, field_default(0) ), + ( field_name_pad("ip_dst_addr" ), "RW", 32, field_default(x"C0A80001") ), -- C0A80001=DOP36-eth0 '192.168.0.1' + + ( field_name_pad("udp_src_port" ), "RW", 16, field_default(0) ), + ( field_name_pad("udp_dst_port" ), "RW", 16, field_default(0) ), + ( field_name_pad("udp_total_length" ), "RO", 16, field_default(7848) ), + ( field_name_pad("udp_checksum" ), "RO", 16, field_default(0) ), + + ( field_name_pad("sdp_marker" ), "RO", 8, field_default(c_marker) ), + ( field_name_pad("sdp_version_id" ), "RO", 8, field_default(c_version) ), + ( field_name_pad("sdp_observation_id" ), "RW", 32, field_default(0) ), + ( field_name_pad("sdp_station_id" ), "RW", 16, field_default(0) ), + + ( field_name_pad("sdp_source_info_antenna_band_id" ), "RW", 1, field_default(0) ), + ( field_name_pad("sdp_source_info_nyquist_zone_id" ), "RW", 2, field_default(0) ), + ( field_name_pad("sdp_source_info_f_adc" ), "RW", 1, field_default(0) ), + ( field_name_pad("sdp_source_info_fsub_type" ), "RW", 1, field_default(0) ), + ( field_name_pad("sdp_source_info_payload_error" ), "RW", 1, field_default(0) ), + ( field_name_pad("sdp_source_info_beam_repositioning_flag" ), "RW", 1, field_default(0) ), + ( field_name_pad("sdp_source_info_subband_calibrated_flag" ), "RW", 1, field_default(0) ), + ( field_name_pad("sdp_source_info_reserved" ), "RO", 3, field_default(0) ), + ( field_name_pad("sdp_source_info_gn_id" ), "RW", 5, field_default(0) ), + + ( field_name_pad("sdp_reserved" ), "RO", 8, field_default(0) ), + ( field_name_pad("sdp_integration_interval" ), "RW", 24, field_default(0) ), + ( field_name_pad("sdp_data_id" ), "RW", 32, field_default(0) ), + ( field_name_pad("sdp_nof_signal_inputs" ), "RO", 8, field_default(c_nof_signal_inputs) ), + ( field_name_pad("sdp_nof_bytes_per_statistics" ), "RO", 8, field_default(8) ), + ( field_name_pad("sdp_nof_statistics_per_package" ), "RO", 16, field_default(c_nof_statistics_per_package) ), + ( field_name_pad("sdp_block_period" ), "RO", 16, field_default(5120) ), + + ( field_name_pad("dp_bsn" ), "RW", 64, field_default(0) ) ); + +BEGIN + + m_mosi <= master_mosi; + master_miso <= m_miso; + + -- count number of sop's in a sync interval + p_bsn_at_sync : PROCESS(in_sosi) + BEGIN + IF in_sosi.sync = '1' THEN + bsn_at_sync <= in_sosi.bsn(63 DOWNTO 0); + END IF; + END PROCESS; + + -- count number of sop's in a sync interval + p_integration_interval : PROCESS(in_sosi) + VARIABLE cnt : NATURAL; + BEGIN + cnt := integration_interval_cnt; + IF in_sosi.sync = '1' THEN + integration_interval <= TO_UVEC(cnt, integration_interval'LENGTH); + integration_interval_cnt <= 0; + ELSE + IF in_sosi.sop = '1' THEN + integration_interval_cnt <= cnt + 1; + END IF; + END IF; + END PROCESS; + + -- get payload errors and keep them till next sync + p_payload_error : PROCESS(in_sosi) + VARIABLE err : STD_LOGIC; + BEGIN + err := payload_err; + IF in_sosi.sync = '1' THEN + payload_err <= '0'; + ELSE + payload_err <= err OR in_sosi.err(0); + END IF; + END PROCESS; + + + ------------------------------------------------------------------------------- + -- Assemble offload info + ------------------------------------------------------------------------------- + dp_header_info(field_hi(c_hdr_field_arr, "eth_src_mac" ) DOWNTO field_lo(c_hdr_field_arr, "eth_src_mac" )) <= eth_src_mac; + dp_header_info(field_hi(c_hdr_field_arr, "udp_src_port") DOWNTO field_lo(c_hdr_field_arr, "udp_src_port")) <= udp_src_port; + dp_header_info(field_hi(c_hdr_field_arr, "ip_src_addr" ) DOWNTO field_lo(c_hdr_field_arr, "ip_src_addr" )) <= ip_src_addr; + + dp_header_info(field_hi(c_hdr_field_arr, "sdp_observation_id" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_observation_id" )) <= sdp_info.observation_id; + dp_header_info(field_hi(c_hdr_field_arr, "sdp_station_id" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_station_id" )) <= sdp_info.station_id; + dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_antenna_band_id" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_antenna_band_id" )) <= SLV(sdp_info.antenna_band_index); + dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_nyquist_zone_id" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_nyquist_zone_id" )) <= sdp_info.nyquist_zone_index; + dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_f_adc" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_f_adc" )) <= SLV(sdp_info.f_adc); + dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_fsub_type" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_fsub_type" )) <= SLV(sdp_info.fsub_type); + dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_payload_error" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_payload_error" )) <= SLV(payload_err); + dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_beam_repositioning_flag" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_beam_repositioning_flag" )) <= SLV(sdp_info.beam_repositioning_flag); + dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_subband_calibrated_flag" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_subband_calibrated_flag" )) <= SLV(sdp_info.subband_calibrated_flag); + dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_reserved" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_reserved" )) <= (OTHERS => '0'); + dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_gn_id" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_gn_id" )) <= TO_UVEC(gn_index, 5); + dp_header_info(field_hi(c_hdr_field_arr, "sdp_reserved" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_reserved" )) <= (OTHERS => '0'); + dp_header_info(field_hi(c_hdr_field_arr, "sdp_integration_interval" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_integration_interval" )) <= integration_interval; + dp_header_info(field_hi(c_hdr_field_arr, "sdp_data_id" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_data_id" )) <= sdp_data_id; + dp_header_info(field_hi(c_hdr_field_arr, "sdp_block_period" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_block_period" )) <= sdp_info.block_period; + + dp_header_info(field_hi(c_hdr_field_arr, "dp_bsn" ) DOWNTO field_lo(c_hdr_field_arr, "dp_bsn" )) <= bsn_at_sync; + + + + nof_cycles_dly <= gn_index * g_offload_time; + sdp_data_id <= r.data_id; + + p_reg : PROCESS(dp_rst, dp_clk) + BEGIN + IF dp_rst='1' THEN + r <= c_reg_rst; + ELSIF rising_edge(dp_clk) THEN + r <= d; + END IF; + END PROCESS; + + + p_control_packet_offload : PROCESS(r, trigger, mm_done) + BEGIN + d <= r; + + -- assign sdp_data_id for different statistic types + IF g_statistics_type = "SST" THEN + d.data_id <= x"000000" & TO_UVEC(r.block_count, 8); + ELSIF g_statistics_type = "BST" THEN + d.data_id <= x"0000" & TO_UVEC(c_beamlet_id, 24); + ELSIF g_statistics_type = "XST" THEN + d.data_id <= x"00" & TO_UVEC(0, 8) & TO_UVEC(0, 8) & TO_UVEC(0, 8); -- TODO fill fill in right values. + ELSE + d.data_id <= x"00000000"; + END IF; + + IF trigger = '1' OR mm_done = '1' THEN + d.block_count <= r.block_count + 1; + IF (r.block_count + 1) mod 2 = 0 THEN + d.start_address <= d.block_count / 2 * c_block_size; + ELSE + d.start_address <= r.start_address + c_data_size; + END IF; + d.start_pulse <= '1'; + END IF; + + IF mm_done = '1' THEN + d.dp_header_info <= dp_header_info; + END IF; + + IF d.block_count >= c_sdp_S_pn THEN + d.block_count <= 0; + d.start_address <= 0; + END IF; + + END PROCESS; + + + u_mms_common_variable_delay : ENTITY common_lib.mms_common_variable_delay + GENERIC MAP ( + g_max_delay => 1 + ) + PORT MAP ( + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + + -- MM interface + reg_enable_mosi => reg_enable_mosi, + reg_enable_miso => reg_enable_miso, + + delay => nof_cycles_dly, + trigger => in_sosi.sync, + trigger_dly => trigger + ); + + u_dp_block_from_mm : ENTITY dp_lib.dp_block_from_mm + GENERIC MAP ( + g_data_size => c_data_size, + g_step_size => c_step_size, + g_nof_data => c_nof_data + ) + PORT MAP( + rst => mm_rst, + clk => mm_clk, + start_pulse => r.start_pulse, + start_address => r.start_address, + mm_done => mm_done, + mm_mosi => m_mosi, + mm_miso => m_miso, + out_sosi => dp_block_from_mm_src_out, + out_siso => dp_block_from_mm_src_in + ); + + u_dp_offload_tx_v3: ENTITY dp_lib.dp_offload_tx_v3 + GENERIC MAP ( + g_nof_streams => c_nof_streams, + g_data_w => c_word_w, + g_symbol_w => c_byte_w, + g_hdr_field_arr => c_hdr_field_arr, + g_hdr_field_sel => c_hdr_field_sel + ) + PORT MAP( + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + reg_hdr_dat_mosi => reg_hdr_dat_mosi, + reg_hdr_dat_miso => reg_hdr_dat_miso, + snk_in_arr(0) => dp_block_from_mm_src_out, + snk_out_arr(0) => dp_block_from_mm_src_in, + src_out_arr(0) => out_sosi, + hdr_fields_in_arr(0) => r.dp_header_info -- hdr_fields_in_arr(i) is considered valid @ snk_in_arr(i).sop + ); +END str; diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd new file mode 100644 index 0000000000000000000000000000000000000000..0f95f9a467771a3254ac791b060cee4769931b32 --- /dev/null +++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd @@ -0,0 +1,246 @@ +------------------------------------------------------------------------------- +-- +-- 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: P. Donker + +-- Purpose: +-- . test bench for sdp_info.vhd (and sdp_info_reg.vhd) +-- Description: +-- +-- https://plm.astron.nl/polarion/#/project/LOFAR2System/workitem?id=LOFAR2-9258 +-- https://plm.astron.nl/polarion/#/project/LOFAR2System/workitem?id=LOFAR2-8855 +-- +-- Remark: +-- . +------------------------------------------------------------------------------- + +LIBRARY IEEE, common_lib, dp_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; +USE common_lib.tb_common_mem_pkg.ALL; +USE common_lib.common_network_layers_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE work.sdp_pkg.ALL; + + +ENTITY tb_sdp_statistics_offload IS + GENERIC ( + g_statistics_type : STRING := "SST"; + g_nof_signal_inputs_per_pn : NATURAL := 4 + ); +END tb_sdp_statistics_offload; + +ARCHITECTURE tb OF tb_sdp_statistics_offload IS + CONSTANT c_dp_clk_period : TIME := 5 ns; -- 200 MHz + CONSTANT c_mm_clk_period : TIME := 20 ns; -- 50 MHz + + CONSTANT c_cross_clock_domain_latency : NATURAL := 40; + + CONSTANT c_eth_src_mac : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0) := x"123456789ABC"; + CONSTANT c_udp_src_port : STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0) := x"D001"; + CONSTANT c_ip_src_addr : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0) := x"0A090807"; + + -- used mm_adresses on mm bus + CONSTANT c_mm_addr_enable : NATURAL := 0; + + -- used test ram size: c_block_size = c_nof_data * c_data_size * (c_step_size / c_data_size) => 512 * 2 * (4 / 2) = 2048 words per pair of signal inputs; + -- with 12 signal input, 6 pairs (blocks) we will fill 2 blocks for testing 2 * 2048 = 4096 = + CONSTANT c_nof_data : NATURAL := 512; + CONSTANT c_data_size : NATURAL := 2; + CONSTANT c_step_size : NATURAL := 4; + CONSTANT c_ram_size : NATURAL := c_nof_data * c_data_size * g_nof_signal_inputs_per_pn; + CONSTANT c_ram_w : NATURAL := ceil_log2(c_ram_size); + CONSTANT c_ram_buf : t_c_mem := (c_mem_ram_rd_latency, c_ram_w, 32, 2**c_ram_w, 'X'); + + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL tb_mm_reg_end : STD_LOGIC := '0'; + + SIGNAL dp_clk : STD_LOGIC := '1'; -- digital data path clock = 200 MHz (deser factor 4); + SIGNAL dp_rst : STD_LOGIC; + + SIGNAL mm_clk : STD_LOGIC := '1'; -- MM control clock = 50 MHz + SIGNAL mm_rst : STD_LOGIC; + + SIGNAL master_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL master_miso : t_mem_miso; + + SIGNAL enable_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL enable_miso : t_mem_miso; + + SIGNAL hdr_dat_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL hdr_dat_miso : t_mem_miso; + + SIGNAL in_sosi : t_dp_sosi := c_dp_sosi_rst; + SIGNAL out_sosi : t_dp_sosi; + + -- signals used to change settings of sdp_info + SIGNAL gn_index : NATURAL := 15; + SIGNAL f_adc : STD_LOGIC := '0'; + SIGNAL fsub_type : STD_LOGIC := '0'; + + SIGNAL sdp_info : t_sdp_info; + + -- signals used for response of mm bus + SIGNAL mm_natural_response : NATURAL; + + -- signals used for starting processes + SIGNAL wr_data : STD_LOGIC_VECTOR(c_ram_buf.dat_w-1 DOWNTO 0); + SIGNAL wr_addr : STD_LOGIC_VECTOR(c_ram_buf.adr_w-1 DOWNTO 0); + SIGNAL wr_en : STD_LOGIC; + SIGNAL init_ram_done: STD_LOGIC := '0'; + +BEGIN + dp_rst <= '1', '0' AFTER c_dp_clk_period*7; + dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2; + + mm_rst <= '1', '0' AFTER c_mm_clk_period*7; + mm_clk <= (NOT mm_clk) OR tb_end AFTER c_mm_clk_period/2; + + + -- fill ram with data, data is same as address number. + p_mm_statistics_ram : PROCESS + VARIABLE addr_cnt : NATURAL := 0; + BEGIN + wr_en <= '0'; + -- initialyze + proc_common_wait_until_low(mm_clk, mm_rst); + proc_common_wait_some_cycles(mm_clk, 10); + + FOR i IN 0 TO c_ram_buf.nof_dat-1 LOOP + wr_addr <= TO_UVEC(addr_cnt, c_ram_buf.adr_w); + wr_data <= TO_UVEC(addr_cnt, c_ram_buf.dat_w); + wr_en <= '1'; + proc_common_wait_some_cycles(dp_clk, 1); + addr_cnt := addr_cnt + 1; + END LOOP; + wr_en <= '0'; + + init_ram_done <= '1'; + WAIT; + END PROCESS; + + p_in_sosi : PROCESS + BEGIN + proc_common_wait_until_high(dp_clk, init_ram_done); + -- enable common variabel delay + proc_mem_mm_bus_wr(c_mm_addr_enable, 1, mm_clk, enable_miso, enable_mosi); + proc_common_wait_some_cycles(mm_clk, c_cross_clock_domain_latency); + FOR i IN 0 TO g_nof_signal_inputs_per_pn LOOP + in_sosi.sync <= '1'; + in_sosi.valid <= '1'; + in_sosi.sop <= '1'; + proc_common_wait_some_cycles(dp_clk, 1); + in_sosi.sync <= '0'; + in_sosi.sop <= '0'; + proc_common_wait_some_cycles(dp_clk, c_nof_data*c_data_size); + in_sosi.eop <= '1'; + proc_common_wait_some_cycles(dp_clk, 1); + in_sosi.eop <= '0'; + in_sosi.valid <= '0'; + proc_common_wait_some_cycles(dp_clk, 1); + END LOOP; + WAIT; + END PROCESS; + + p_mm_reg_stimuli : PROCESS + BEGIN + --enable_mosi <= c_mem_mosi_rst; + --hdr_dat_mosi <= c_mem_mosi_rst; + + proc_common_wait_until_high(dp_clk, init_ram_done); + proc_common_wait_some_cycles(mm_clk, 100); + + -- station_id, antenna_band_index, observation_id, nyquist_zone_index, f_adc, fsub_type, beam_repositioning_flag, subband_calibrated_flag, O_si, N_si, O_rn, N_rn, block_period, beamlet_scale + sdp_info <= ( x"0001", '0', x"00000003", b"01", '0', '0', '0', '0', x"00", x"00", x"00", x"00", x"0000", x"0000"); + proc_common_wait_some_cycles(mm_clk, 1); + out_sosi.sync <= '1'; + + proc_common_wait_some_cycles(mm_clk, 100); + tb_end <= '1'; + WAIT; + END PROCESS; + + + u_ram: ENTITY common_lib.common_ram_crw_crw_ratio + GENERIC MAP ( + g_ram_a => c_ram_buf, -- settings for port a + g_ram_b => c_ram_buf -- settings for port b + ) + PORT MAP ( + -- MM read/write port clock domain + rst_a => mm_rst, + clk_a => mm_clk, + wr_en_a => master_mosi.wr, + wr_dat_a => master_mosi.wrdata(c_ram_buf.dat_w-1 DOWNTO 0), + adr_a => master_mosi.address(c_ram_buf.adr_w-1 DOWNTO 0), + rd_en_a => master_mosi.rd, + rd_dat_a => master_miso.rddata(c_ram_buf.dat_w-1 DOWNTO 0), + rd_val_a => master_miso.rdval, + + -- ST write only port clock domain + rst_b => dp_rst, + clk_b => dp_clk, + wr_en_b => wr_en, + wr_dat_b => wr_data, + adr_b => wr_addr, + rd_en_b => '0', + rd_dat_b => OPEN, + rd_val_b => OPEN + ); + + -- SDP info + u_dut: ENTITY work.sdp_statistics_offload + GENERIC MAP ( + g_statistics_type => "SST", + g_offload_time => 0, + g_beamset_id => 0 + ) + PORT MAP ( + mm_clk => mm_clk, + mm_rst => mm_rst, + + dp_clk => dp_clk, + dp_rst => dp_rst, + + master_mosi => master_mosi, + master_miso => master_miso, + + reg_enable_mosi => enable_mosi, + reg_enable_miso => enable_miso, + + reg_hdr_dat_mosi => hdr_dat_mosi, + reg_hdr_dat_miso => hdr_dat_miso, + + sdp_info => sdp_info, + gn_index => gn_index, + + in_sosi => in_sosi, + out_sosi => out_sosi, + + eth_src_mac => c_eth_src_mac, + udp_src_port => c_udp_src_port, + ip_src_addr => c_ip_src_addr + ); + +END tb; \ No newline at end of file