diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg index ca25589a29083e166f4d1bf4f0f87483bebddfc2..3567f0d5d02b2ca3164d74771f1fffe7a8db9749 100644 --- a/libraries/base/dp/hdllib.cfg +++ b/libraries/base/dp/hdllib.cfg @@ -28,6 +28,9 @@ synth_files = src/vhdl/dp_pipeline.vhd src/vhdl/dp_pipeline_arr.vhd src/vhdl/dp_pipeline_ready.vhd + src/vhdl/dp_force_data.vhd + src/vhdl/mms_dp_force_data.vhd + src/vhdl/mms_dp_force_data_arr.vhd src/vhdl/dp_paged_sop_eop_reg.vhd src/vhdl/dp_packet_detect.vhd src/vhdl/dp_shiftreg.vhd @@ -204,6 +207,7 @@ test_bench_files = tb/vhdl/tb_dp_folder.vhd tb/vhdl/tb_dp_switch.vhd tb/vhdl/tb_dp_counter_func.vhd + tb/vhdl/tb_mms_dp_force_data_arr.vhd tb/vhdl/tb_mms_dp_gain_arr.vhd tb/vhdl/tb_mms_dp_gain_serial_arr.vhd @@ -238,6 +242,7 @@ test_bench_files = tb/vhdl/tb_tb_dp_split.vhd tb/vhdl/tb_tb_dp_sync_checker.vhd tb/vhdl/tb_tb_dp_sync_insert.vhd + tb/vhdl/tb_tb_mms_dp_force_data_arr.vhd tb/vhdl/tb_tb_mms_dp_gain_arr.vhd tb/vhdl/tb_tb_mms_dp_gain_serial_arr.vhd @@ -281,6 +286,7 @@ regression_test_vhdl = tb/vhdl/tb_tb_dp_sync_checker.vhd tb/vhdl/tb_mms_dp_sync_checker.vhd tb/vhdl/tb_tb_dp_sync_insert.vhd + tb/vhdl/tb_tb_mms_dp_force_data_arr.vhd tb/vhdl/tb_tb_mms_dp_gain_arr.vhd tb/vhdl/tb_tb_mms_dp_gain_serial_arr.vhd diff --git a/libraries/base/dp/src/vhdl/dp_force_data.vhd b/libraries/base/dp/src/vhdl/dp_force_data.vhd new file mode 100644 index 0000000000000000000000000000000000000000..87c0511d8b79a0e7a5331cdbc1df4cdf883445f4 --- /dev/null +++ b/libraries/base/dp/src/vhdl/dp_force_data.vhd @@ -0,0 +1,133 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2017 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +------------------------------------------------------------------------------- +-- +-- Author: E. Kooistra, 7 apr 2017 +-- Purpose: +-- Pass the sosi data fields or force them to zero. All other sosi fields +-- are passed on unchanged. +-- Description: +-- Default the force value is constant, but using the generics it can be +-- made to automatically increment for every valid and restart at sync or +-- sop. +-- Usage: +-- . DSP tests: Constant (zero) data is useful for DSP tests to be able to +-- recognize a particular data stream in an array of streams. +-- . Data move test: Incrementing data or a combination of constant re and +-- incrementing im is useful for data move test when the data gets +-- reordered. +-- Remarks: +-- . Ready latency = 1 +-- . When force_en='0' then this dp_force_data is equivalent to dp_pipeline. + +LIBRARY IEEE, common_lib; +USE IEEE.std_logic_1164.all; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE work.dp_stream_pkg.ALL; + +ENTITY dp_force_data IS + GENERIC ( + g_dat_w : NATURAL := 32; -- must be <= 32 to fit INTEGER range + g_increment_data : INTEGER := 0; + g_increment_re : INTEGER := 0; + g_increment_im : INTEGER := 0; + g_restart_on_sync : BOOLEAN := FALSE; + g_restart_on_sop : BOOLEAN := FALSE + ); + PORT ( + rst : IN STD_LOGIC; + clk : IN STD_LOGIC; + -- MM control + force_en : IN STD_LOGIC := '0'; + force_data : IN INTEGER := 0; -- used for sosi.data + force_re : IN INTEGER := 0; -- used for sosi.re + force_im : IN INTEGER := 0; -- used for sosi.im + -- 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_force_data; + + +LIBRARY IEEE, common_lib; +USE IEEE.std_logic_1164.all; +USE work.dp_stream_pkg.ALL; + +ARCHITECTURE str OF dp_force_data IS + + SIGNAL data_in : t_dp_sosi; + SIGNAL data_out : t_dp_sosi; + +BEGIN + + p_comb : PROCESS(snk_in, force_data, force_re, force_im, data_out) + BEGIN + data_in <= snk_in; + IF force_en='1' THEN + -- default force value + data_in.data <= TO_DP_SDATA(force_data); + data_in.re <= TO_DP_DSP_DATA(force_re); + data_in.im <= TO_DP_DSP_DATA(force_im); + -- optional increment + IF g_increment_data/=0 THEN + data_in.data <= RESIZE_DP_SDATA(STD_LOGIC_VECTOR(SIGNED(data_out.data(g_dat_w-1 DOWNTO 0)) + g_increment_data)); + END IF; + IF g_increment_re/=0 THEN + data_in.re <= RESIZE_DP_DSP_DATA(STD_LOGIC_VECTOR(SIGNED(data_out.re(g_dat_w-1 DOWNTO 0)) + g_increment_re)); + END IF; + IF g_increment_im/=0 THEN + data_in.im <= RESIZE_DP_DSP_DATA(STD_LOGIC_VECTOR(SIGNED(data_out.im(g_dat_w-1 DOWNTO 0)) + g_increment_im)); + END IF; + -- optional restart increment + IF g_restart_on_sync=TRUE AND snk_in.sync='1' THEN + data_in.data <= TO_DP_SDATA(force_data); + data_in.re <= TO_DP_DSP_DATA(force_re); + data_in.im <= TO_DP_DSP_DATA(force_im); + END IF; + IF g_restart_on_sop=TRUE AND snk_in.sop='1' THEN + data_in.data <= TO_DP_SDATA(force_data); + data_in.re <= TO_DP_DSP_DATA(force_re); + data_in.im <= TO_DP_DSP_DATA(force_im); + END IF; + END IF; + END PROCESS; + + u_dp_pipeline : ENTITY work.dp_pipeline + GENERIC MAP ( + g_pipeline => 1 + ) + PORT MAP ( + rst => rst, + clk => clk, + -- ST sink + snk_out => snk_out, + snk_in => data_in, + -- ST source + src_in => src_in, + src_out => data_out + ); + + src_out <= data_out; +END str; diff --git a/libraries/base/dp/src/vhdl/mms_dp_force_data.vhd b/libraries/base/dp/src/vhdl/mms_dp_force_data.vhd new file mode 100644 index 0000000000000000000000000000000000000000..e38dffcb8dc5ce378c6a61b45cfdb0b5e71b2f27 --- /dev/null +++ b/libraries/base/dp/src/vhdl/mms_dp_force_data.vhd @@ -0,0 +1,151 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2017 +-- 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/>. +-- +------------------------------------------------------------------------------- +-- +-- Author : E. Kooistra, 7 apr 2017 +-- Purpose : Control force data per stream via MM +-- Description: +-- Address Data Access Description +-- 0 [0] R/W force enable or default disable for data pass on +-- 1 [31:0] R/W force sosi data +-- 2 [31:0] R/W force sosi re +-- 3 [31:0] R/W force sosi im +-- +-- The actual sosi data, re and im width integer is constrained by g_dat_w. +-- Synthesis will optimize away unused bits from the full integer 32b range. +-- + +LIBRARY IEEE, common_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE work.dp_stream_pkg.ALL; + + +ENTITY mms_dp_force_data IS + GENERIC ( + g_dat_w : NATURAL := 32; -- must be <= 32 to fit INTEGER range + g_increment_data : INTEGER := 0; + g_increment_re : INTEGER := 0; + g_increment_im : INTEGER := 0; + g_restart_on_sync : BOOLEAN := FALSE; + g_restart_on_sop : BOOLEAN := FALSE + ); + PORT ( + -- Clocks and reset + mm_rst : IN STD_LOGIC; + mm_clk : IN STD_LOGIC; + dp_rst : IN STD_LOGIC; + dp_clk : IN STD_LOGIC; + -- MM control + reg_force_data_mosi : IN t_mem_mosi := c_mem_mosi_rst; + reg_force_data_miso : OUT t_mem_miso; + -- 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 mms_dp_force_data; + +ARCHITECTURE str OF mms_dp_force_data IS + + -- TYPE t_c_mem IS RECORD + -- latency : NATURAL; -- read latency + -- adr_w : NATURAL; + -- dat_w : NATURAL; + -- nof_dat : NATURAL; -- optional, nof dat words <= 2**adr_w + -- init_sl : STD_LOGIC; -- optional, init all dat words to std_logic '0', '1' or 'X' + CONSTANT c_mm_reg : t_c_mem := (1, 2, g_dat_w, 4, 'X'); + + CONSTANT c_mm_reg_init : STD_LOGIC_VECTOR(c_mem_reg_init_w-1 DOWNTO 0) := (OTHERS=>'0'); + + SIGNAL reg_force_data_wr : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0); + SIGNAL reg_force_data_rd : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0'); + + SIGNAL force_en : STD_LOGIC := '0'; + SIGNAL force_data : INTEGER := 0; -- used for sosi.data + SIGNAL force_re : INTEGER := 0; -- used for sosi.re + SIGNAL force_im : INTEGER := 0; -- used for sosi.im + +BEGIN + + -- wires + force_en <= reg_force_data_wr(0); + reg_force_data_rd(0) <= reg_force_data_wr(0); -- other bits are not used and will read '0' + force_data <= TO_SINT(reg_force_data_wr(2*c_mm_reg.dat_w-1 DOWNTO c_mm_reg.dat_w)); + reg_force_data_rd(2*c_mm_reg.dat_w-1 DOWNTO c_mm_reg.dat_w) <= reg_force_data_wr(2*c_mm_reg.dat_w-1 DOWNTO c_mm_reg.dat_w); + force_re <= TO_SINT(reg_force_data_wr(3*c_mm_reg.dat_w-1 DOWNTO 2*c_mm_reg.dat_w)); + reg_force_data_rd(3*c_mm_reg.dat_w-1 DOWNTO 2*c_mm_reg.dat_w) <= reg_force_data_wr(3*c_mm_reg.dat_w-1 DOWNTO 2*c_mm_reg.dat_w); + force_im <= TO_SINT(reg_force_data_wr(4*c_mm_reg.dat_w-1 DOWNTO 3*c_mm_reg.dat_w)); + reg_force_data_rd(4*c_mm_reg.dat_w-1 DOWNTO 3*c_mm_reg.dat_w) <= reg_force_data_wr(4*c_mm_reg.dat_w-1 DOWNTO 3*c_mm_reg.dat_w); + + u_common_reg_r_w_dc_re : ENTITY common_lib.common_reg_r_w_dc + GENERIC MAP ( + g_cross_clock_domain => TRUE, + g_readback => FALSE, + g_reg => c_mm_reg, + g_init_reg => c_mm_reg_init + ) + PORT MAP ( + -- Clocks and reset + mm_rst => mm_rst, + mm_clk => mm_clk, + st_rst => dp_rst, + st_clk => dp_clk, + + -- Memory Mapped Slave in mm_clk domain + sla_in => reg_force_data_mosi, + sla_out => reg_force_data_miso, + + -- MM registers in st_clk domain + reg_wr_arr => OPEN, + reg_rd_arr => OPEN, + out_reg => reg_force_data_wr, -- readback via ST clock domain + in_reg => reg_force_data_rd + ); + + u_dp_force_data : ENTITY work.dp_force_data + GENERIC MAP ( + g_dat_w => g_dat_w, + g_increment_data => g_increment_data, + g_increment_re => g_increment_re, + g_increment_im => g_increment_im, + g_restart_on_sync => g_restart_on_sync, + g_restart_on_sop => g_restart_on_sop + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + -- MM control + force_en => force_en, + force_data => force_data, + force_re => force_re, + force_im => force_im, + -- ST sink + snk_out => snk_out, + snk_in => snk_in, + -- ST source + src_in => src_in, + src_out => src_out + ); +END str; + diff --git a/libraries/base/dp/src/vhdl/mms_dp_force_data_arr.vhd b/libraries/base/dp/src/vhdl/mms_dp_force_data_arr.vhd new file mode 100644 index 0000000000000000000000000000000000000000..2fa99c5c96e9a5c7090cb7860df0941698cd33e9 --- /dev/null +++ b/libraries/base/dp/src/vhdl/mms_dp_force_data_arr.vhd @@ -0,0 +1,116 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2017 +-- 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/>. +-- +------------------------------------------------------------------------------- +-- +-- Author : E. Kooistra, 7 apr 2017 +-- Purpose : Control force data per stream via MM +-- Description: +-- Stream Address Data Access Description +-- 0 0 [0] R/W force enable or default disable for data pass on +-- 0 1 [31:0] R/W force sosi data, re +-- 0 2 [31:0] R/W force sosi im +-- 0 3 - R/W not used, reads 0 +-- 1 4:7 idem +-- 2 8:11 idem +-- etc. + +LIBRARY IEEE, common_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE work.dp_stream_pkg.ALL; + + +ENTITY mms_dp_force_data_arr IS + GENERIC ( + g_nof_streams : NATURAL := 1; + g_dat_w : NATURAL := 32; -- must be <= 32 to fit INTEGER range + g_increment_data : INTEGER := 0; + g_increment_re : INTEGER := 0; + g_increment_im : INTEGER := 0; + g_restart_on_sync : BOOLEAN := FALSE; + g_restart_on_sop : BOOLEAN := FALSE + ); + PORT ( + -- Clocks and reset + mm_rst : IN STD_LOGIC; + mm_clk : IN STD_LOGIC; + dp_rst : IN STD_LOGIC; + dp_clk : IN STD_LOGIC; + -- MM control + reg_force_data_mosi : IN t_mem_mosi := c_mem_mosi_rst; + reg_force_data_miso : OUT t_mem_miso; + -- ST sink + snk_out_arr : OUT t_dp_siso_arr(g_nof_streams-1 DOWNTO 0); + snk_in_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + -- ST source + src_in_arr : IN t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy); + src_out_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) + ); +END mms_dp_force_data_arr; + + +ARCHITECTURE str OF mms_dp_force_data_arr IS + + SIGNAL reg_force_data_mosi_arr : t_mem_mosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>c_mem_mosi_rst); + SIGNAL reg_force_data_miso_arr : t_mem_miso_arr(g_nof_streams-1 DOWNTO 0); + +BEGIN + + u_mem_mux : ENTITY common_lib.common_mem_mux + GENERIC MAP ( + g_nof_mosi => g_nof_streams, + g_mult_addr_w => 2 + ) + PORT MAP ( + mosi => reg_force_data_mosi, + miso => reg_force_data_miso, + mosi_arr => reg_force_data_mosi_arr, + miso_arr => reg_force_data_miso_arr + ); + + gen_nof_streams : FOR I IN 0 TO g_nof_streams-1 GENERATE + u_mms_dp_force_data : ENTITY work.mms_dp_force_data + GENERIC MAP ( + g_dat_w => g_dat_w, + g_increment_data => g_increment_data, + g_increment_re => g_increment_re, + g_increment_im => g_increment_im, + g_restart_on_sync => g_restart_on_sync, + g_restart_on_sop => g_restart_on_sop + ) + PORT MAP ( + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + -- MM control + reg_force_data_mosi => reg_force_data_mosi_arr(I), + reg_force_data_miso => reg_force_data_miso_arr(I), + -- ST sink + snk_out => snk_out_arr(I), + snk_in => snk_in_arr(I), + -- ST source + src_in => src_in_arr(I), + src_out => src_out_arr(I) + ); + END GENERATE; +END str; + diff --git a/libraries/base/dp/tb/vhdl/tb_mms_dp_force_data_arr.vhd b/libraries/base/dp/tb/vhdl/tb_mms_dp_force_data_arr.vhd new file mode 100644 index 0000000000000000000000000000000000000000..c759470e0f356f5660dfca407661392ea770e6ac --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_mms_dp_force_data_arr.vhd @@ -0,0 +1,349 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2017 +-- 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/>. +-- +------------------------------------------------------------------------------- + +-- Author: E. Kooistra, 10 Apr 2017 +-- Purpose: Verify mms_dp_force_data_arr and mms_dp_force_data +-- Description: +-- Usage: +-- > as 10 +-- > run -all +-- In wave window view sosi.data,re,im in radix decimal +-- The tb is self stopping and self checking. + + +LIBRARY IEEE, common_lib, technology_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_lfsr_sequences_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE common_lib.tb_common_mem_pkg.ALL; +USE work.dp_stream_pkg.ALL; +USE work.tb_dp_pkg.ALL; +USE technology_lib.technology_select_pkg.ALL; + + +ENTITY tb_mms_dp_force_data_arr IS + GENERIC ( + g_flow_control_stimuli : t_dp_flow_control_enum := e_active; -- always active or random stimuli valid flow control + g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always active or random verify ready flow control + g_nof_streams : NATURAL := 1; -- >= 1 + g_dat_w : NATURAL := 5; -- must be <= 32 to fit INTEGER range + g_force_stream : INTEGER := 0; -- must be < g_nof_streams, force data on this stream + g_force_data : INTEGER := -1; + g_force_re : INTEGER := 2; + g_force_im : INTEGER := -3; + g_increment_data : INTEGER := 1; + g_increment_re : INTEGER := -5; + g_increment_im : INTEGER := 5; + g_restart_on_sync : BOOLEAN := FALSE; + g_restart_on_sop : BOOLEAN := FALSE + ); +END tb_mms_dp_force_data_arr; + + +ARCHITECTURE tb OF tb_mms_dp_force_data_arr IS + + CONSTANT c_mm_clk_period : TIME := 20 ns; + CONSTANT c_dp_clk_period : TIME := 10 ns; + CONSTANT c_cross_clock_domain_latency : NATURAL := 20; + + CONSTANT c_init_data : INTEGER := 0; + CONSTANT c_init_channel : INTEGER := 11; -- use recognizable value, will not change + CONSTANT c_init_error : INTEGER := 12; -- use recognizable value, will not change + CONSTANT c_nof_data_per_block : INTEGER := 17; + CONSTANT c_nof_block_per_sync : INTEGER := 10; + CONSTANT c_nof_blocks_per_test : INTEGER := c_nof_block_per_sync*3; + + CONSTANT c_mm_reg_nof_dat : NATURAL := 4; + CONSTANT c_force_en : NATURAL := 1; + CONSTANT c_force_dis : NATURAL := 0; + + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL mm_clk : STD_LOGIC := '1'; + SIGNAL mm_rst : STD_LOGIC := '1'; + SIGNAL dp_clk : STD_LOGIC := '1'; + SIGNAL dp_rst : STD_LOGIC := '1'; + + SIGNAL random_valid : STD_LOGIC_VECTOR(15 DOWNTO 0) := (OTHERS=>'0'); -- use different lengths to have different random sequences + SIGNAL random_ready : STD_LOGIC_VECTOR(16 DOWNTO 0) := (OTHERS=>'0'); -- use different lengths to have different random sequences + SIGNAL stimuli_en : STD_LOGIC := '0'; + SIGNAL verify_en : STD_LOGIC := '0'; + SIGNAL force_en : STD_LOGIC := '0'; + + SIGNAL snk_out : t_dp_siso; + SIGNAL snk_in : t_dp_sosi; + SIGNAL snk_in_dly : t_dp_sosi; + SIGNAL snk_out_arr : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL snk_in_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL src_in_arr : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL src_out_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL prev_src_out_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL src_in : t_dp_siso; + + SIGNAL reg_force_data_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL reg_force_data_miso : t_mem_miso; + +BEGIN + + dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2; + mm_clk <= (NOT mm_clk) OR tb_end AFTER c_mm_clk_period/2; + dp_rst <= '1', '0' AFTER c_dp_clk_period*7; + mm_rst <= '1', '0' AFTER c_mm_clk_period*7; + + random_valid <= func_common_random(random_valid) WHEN rising_edge(dp_clk); + random_ready <= func_common_random(random_ready) WHEN rising_edge(dp_clk); + + stimuli_en <= random_valid(random_valid'HIGH) WHEN g_flow_control_stimuli=e_random ELSE '1'; + src_in.ready <= random_ready(random_ready'HIGH) WHEN g_flow_control_verify =e_random ELSE '1'; + src_in.xon <= '1'; + + src_in_arr <= (OTHERS=>src_in); + + ------------------------------------------------------------------------------ + -- DATA GENERATION + ------------------------------------------------------------------------------ + p_stimuli_st : PROCESS + VARIABLE v_sosi : t_dp_sosi := c_dp_sosi_rst; + BEGIN + -- Initialisations + v_sosi.bsn := TO_DP_BSN(0); + v_sosi.data := TO_DP_SDATA(0); + + snk_in <= c_dp_sosi_rst; + proc_common_wait_until_low(dp_clk, mm_rst); + proc_common_wait_until_low(dp_clk, dp_rst); + proc_common_wait_some_cycles(dp_clk, 5); + + -- Generate packets + WHILE tb_end='0' LOOP + v_sosi.sync := sel_a_b((UNSIGNED(v_sosi.bsn) MOD c_nof_block_per_sync) = 0, '1', '0'); -- insert sync starting at BSN=0 and with period g_sync_period + v_sosi.data := RESIZE_DP_DATA(v_sosi.data(g_dat_w-1 DOWNTO 0)); -- wrap when >= 2**g_dat_w + -- Send block + proc_dp_gen_block_data(g_dat_w, c_init_data, c_nof_data_per_block, c_init_channel, c_init_error, v_sosi.sync, v_sosi.bsn, dp_clk, stimuli_en, snk_out, snk_in); + -- Prepare for next block + v_sosi.bsn := INCR_UVEC(v_sosi.bsn, 1); + v_sosi.data := INCR_UVEC(v_sosi.data, c_nof_data_per_block); + END LOOP; + + WAIT; + END PROCESS; + + u_snk_in_dly : ENTITY work.dp_pipeline + GENERIC MAP ( + g_pipeline => 1 -- latency of DUT + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + snk_out => OPEN, + snk_in => snk_in, + src_in => src_in_arr(0), + src_out => snk_in_dly + ); + + snk_out <= snk_out_arr(0); -- use stream 0 for flow control, all tb streams have same flow control + snk_in_arr <= (OTHERS=>snk_in); -- apply same default tb data to all streams + + p_stimuli_mm : PROCESS + VARIABLE v_force_data : INTEGER := g_force_data; + BEGIN + proc_common_wait_until_low(dp_clk, mm_rst); + proc_common_wait_until_low(dp_clk, dp_rst); + proc_common_wait_some_cycles(mm_clk, 5); + + -- Test default pass on the data unchanged + verify_en <= '1'; + FOR I IN 0 TO c_nof_blocks_per_test-1 LOOP + proc_common_wait_until_hi_lo(dp_clk, snk_in.eop); + END LOOP; + verify_en <= '0'; + + -- Test force data on stream g_force_stream + force_en <= '1'; + proc_mem_mm_bus_wr(g_force_stream*c_mm_reg_nof_dat + 0, c_force_en, mm_clk, reg_force_data_miso, reg_force_data_mosi); + proc_mem_mm_bus_wr(g_force_stream*c_mm_reg_nof_dat + 1, g_force_data, mm_clk, reg_force_data_miso, reg_force_data_mosi); + proc_mem_mm_bus_wr(g_force_stream*c_mm_reg_nof_dat + 2, g_force_re, mm_clk, reg_force_data_miso, reg_force_data_mosi); + proc_mem_mm_bus_wr(g_force_stream*c_mm_reg_nof_dat + 3, g_force_im, mm_clk, reg_force_data_miso, reg_force_data_mosi); + proc_common_wait_some_cycles(mm_clk, c_cross_clock_domain_latency); + proc_common_wait_some_cycles(dp_clk, c_cross_clock_domain_latency); + + proc_common_wait_until_hi_lo(dp_clk, snk_in.eop); + verify_en <= '1'; + FOR I IN 0 TO c_nof_blocks_per_test-1 LOOP + proc_common_wait_until_hi_lo(dp_clk, snk_in.eop); + END LOOP; + verify_en <= '0'; + + -- Test default pass on the data unchanged + force_en <= '0'; + proc_mem_mm_bus_wr(g_force_stream*c_mm_reg_nof_dat + 0, c_force_dis, mm_clk, reg_force_data_miso, reg_force_data_mosi); + proc_common_wait_some_cycles(mm_clk, c_cross_clock_domain_latency); + proc_common_wait_some_cycles(dp_clk, c_cross_clock_domain_latency); + + verify_en <= '1'; + FOR I IN 0 TO c_nof_blocks_per_test-1 LOOP + proc_common_wait_until_hi_lo(dp_clk, snk_in.eop); + END LOOP; + verify_en <= '0'; + + tb_end <= '1'; + WAIT; + END PROCESS; + + -- capture previous valid src_out_arr to verify increments + prev_src_out_arr <= src_out_arr WHEN rising_edge(dp_clk) AND snk_in_dly.valid='1'; + + p_verify : PROCESS(dp_clk) + VARIABLE v_exp_data : INTEGER; + VARIABLE v_exp_re : INTEGER; + VARIABLE v_exp_im : INTEGER; + BEGIN + IF rising_edge(dp_clk) THEN + IF verify_en='1' AND snk_in_dly.valid='1' THEN + FOR I IN 0 TO g_nof_streams-1 LOOP + -- verify unchanged sosi fields (= pipeline) + ASSERT src_out_arr(I).sync = snk_in_dly.sync REPORT "Unexpected sync" SEVERITY ERROR; + ASSERT src_out_arr(I).sop = snk_in_dly.sop REPORT "Unexpected sop" SEVERITY ERROR; + ASSERT src_out_arr(I).eop = snk_in_dly.eop REPORT "Unexpected eop" SEVERITY ERROR; + ASSERT src_out_arr(I).valid = snk_in_dly.valid REPORT "Unexpected valid" SEVERITY ERROR; + ASSERT SIGNED(src_out_arr(I).bsn) =SIGNED(snk_in_dly.bsn) REPORT "Unexpected bsn" SEVERITY ERROR; + ASSERT SIGNED(src_out_arr(I).channel)=SIGNED(snk_in_dly.channel) REPORT "Unexpected channel" SEVERITY ERROR; + ASSERT SIGNED(src_out_arr(I).err) =SIGNED(snk_in_dly.err) REPORT "Unexpected err" SEVERITY ERROR; + + IF force_en='0' OR I/=g_force_stream THEN + -- verify default data pass on (= pipeline) + ASSERT SIGNED(src_out_arr(I).data) =SIGNED(snk_in_dly.data) REPORT "Unexpected data" SEVERITY ERROR; + ASSERT SIGNED(src_out_arr(I).re) =SIGNED(snk_in_dly.re) REPORT "Unexpected real" SEVERITY ERROR; + ASSERT SIGNED(src_out_arr(I).im) =SIGNED(snk_in_dly.im) REPORT "Unexpected imag" SEVERITY ERROR; + ELSE + -- verify default force data on stream I=g_force_stream + v_exp_data := TO_SINT(INCR_DP_SDATA( prev_src_out_arr(I).data, g_increment_data, g_dat_w)); + v_exp_re := TO_SINT(INCR_DP_DSP_DATA(prev_src_out_arr(I).re, g_increment_re, g_dat_w)); + v_exp_im := TO_SINT(INCR_DP_DSP_DATA(prev_src_out_arr(I).im, g_increment_im, g_dat_w)); + + -- .data + IF g_increment_data=0 THEN + ASSERT TO_SINT(src_out_arr(I).data)=g_force_data REPORT "Unexpected force data" SEVERITY ERROR; + ELSE + IF g_restart_on_sync=TRUE AND snk_in_dly.sync='1' THEN + ASSERT TO_SINT(src_out_arr(I).data)=g_force_data REPORT "Unexpected restart force data at sync" SEVERITY ERROR; + ELSIF g_restart_on_sop=TRUE AND snk_in_dly.sop='1' THEN + ASSERT TO_SINT(src_out_arr(I).data)=g_force_data REPORT "Unexpected restart force data at sop" SEVERITY ERROR; + ELSE + ASSERT TO_SINT(src_out_arr(I).data)=v_exp_data REPORT "Unexpected increment data" SEVERITY ERROR; + END IF; + END IF; + + -- .re + IF g_increment_re=0 THEN + ASSERT TO_SINT(src_out_arr(I).re)=g_force_re REPORT "Unexpected force re" SEVERITY ERROR; + ELSE + IF g_restart_on_sync=TRUE AND snk_in_dly.sync='1' THEN + ASSERT TO_SINT(src_out_arr(I).re)=g_force_re REPORT "Unexpected restart force re at sync" SEVERITY ERROR; + ELSIF g_restart_on_sop=TRUE AND snk_in_dly.sop='1' THEN + ASSERT TO_SINT(src_out_arr(I).re)=g_force_re REPORT "Unexpected restart force re at sop" SEVERITY ERROR; + ELSE + ASSERT TO_SINT(src_out_arr(I).re)=v_exp_re REPORT "Unexpected increment re" SEVERITY ERROR; + END IF; + END IF; + + -- .im + IF g_increment_im=0 THEN + ASSERT TO_SINT(src_out_arr(I).im)=g_force_im REPORT "Unexpected force im" SEVERITY ERROR; + ELSE + IF g_restart_on_sync=TRUE AND snk_in_dly.sync='1' THEN + ASSERT TO_SINT(src_out_arr(I).im)=g_force_im REPORT "Unexpected restart force im at sync" SEVERITY ERROR; + ELSIF g_restart_on_sop=TRUE AND snk_in_dly.sop='1' THEN + ASSERT TO_SINT(src_out_arr(I).im)=g_force_im REPORT "Unexpected restart force im at sop" SEVERITY ERROR; + ELSE + ASSERT TO_SINT(src_out_arr(I).im)=v_exp_im REPORT "Unexpected increment im" SEVERITY ERROR; + END IF; + END IF; + END IF; + END LOOP; + END IF; + END IF; + END PROCESS; + + ------------------------------------------------------------------------------ + -- DUT + ------------------------------------------------------------------------------ + + gen_one : IF g_nof_streams=1 GENERATE + u_dut_one : ENTITY work.mms_dp_force_data + GENERIC MAP ( + g_dat_w => g_dat_w, + g_increment_data => g_increment_data, + g_increment_re => g_increment_re, + g_increment_im => g_increment_im, + g_restart_on_sync => g_restart_on_sync, + g_restart_on_sop => g_restart_on_sop + ) + PORT MAP ( + -- Clocks and reset + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + -- MM control + reg_force_data_mosi => reg_force_data_mosi, + reg_force_data_miso => reg_force_data_miso, + -- ST sink + snk_out => snk_out_arr(0), + snk_in => snk_in_arr(0), + -- ST source + src_in => src_in_arr(0), + src_out => src_out_arr(0) + ); + END GENERATE; + + gen_arr : IF g_nof_streams>1 GENERATE + u_dut_arr : ENTITY work.mms_dp_force_data_arr + GENERIC MAP ( + g_nof_streams => g_nof_streams, + g_dat_w => g_dat_w, + g_increment_data => g_increment_data, + g_increment_re => g_increment_re, + g_increment_im => g_increment_im, + g_restart_on_sync => g_restart_on_sync, + g_restart_on_sop => g_restart_on_sop + ) + PORT MAP ( + -- Clocks and reset + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + -- MM control + reg_force_data_mosi => reg_force_data_mosi, + reg_force_data_miso => reg_force_data_miso, + -- ST sink + snk_out_arr => snk_out_arr, + snk_in_arr => snk_in_arr, + -- ST source + src_in_arr => src_in_arr, + src_out_arr => src_out_arr + ); + END GENERATE; + +END tb; diff --git a/libraries/base/dp/tb/vhdl/tb_tb_mms_dp_force_data_arr.vhd b/libraries/base/dp/tb/vhdl/tb_tb_mms_dp_force_data_arr.vhd new file mode 100644 index 0000000000000000000000000000000000000000..833d348534192dbeb068ff2c7ed175c5ae59cd00 --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_tb_mms_dp_force_data_arr.vhd @@ -0,0 +1,63 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2017 +-- 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/>. +-- +-------------------------------------------------------------------------------- + +-- Author: E. Kooistra, 10 Apr 2017 +-- Purpose: Multi-testbench for mms_dp_force_data_arr +-- Description: +-- Verify mms_dp_force_data_arr +-- Usage: +-- > as 4 +-- > run -all + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE work.tb_dp_pkg.ALL; + +ENTITY tb_tb_mms_dp_force_data_arr IS +END tb_tb_mms_dp_force_data_arr; + +ARCHITECTURE tb OF tb_tb_mms_dp_force_data_arr IS + + SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' + +BEGIN + +-- g_flow_control_stimuli : t_dp_flow_control_enum := e_active; -- always active or random stimuli valid flow control +-- g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always active or random verify ready flow control +-- g_nof_streams : NATURAL := 1; -- >= 1 +-- g_dat_w : NATURAL := 32; -- must be <= 32 to fit INTEGER range +-- g_force_stream : INTEGER := 0; -- must be < g_nof_streams, force data on this stream +-- g_force_data : INTEGER := -1; +-- g_force_re : INTEGER := 2; +-- g_force_im : INTEGER := -3; +-- g_increment_data : INTEGER := 0; +-- g_increment_re : INTEGER := 0; +-- g_increment_im : INTEGER := 0; +-- g_restart_on_sync : BOOLEAN := FALSE; +-- g_restart_on_sop : BOOLEAN := FALSE + + u_act_force_data_1 : ENTITY work.tb_mms_dp_force_data_arr GENERIC MAP (e_active, e_active, 1, 16, 0, -1, 2, -3, 0, 0, 0, FALSE, FALSE); + u_rnd_force_data_3 : ENTITY work.tb_mms_dp_force_data_arr GENERIC MAP (e_random, e_random, 3, 16, 0, -1, 2, -3, 0, 0, 0, FALSE, FALSE); + u_rnd_force_data_incr_3 : ENTITY work.tb_mms_dp_force_data_arr GENERIC MAP (e_random, e_random, 3, 16, 0, -1, 2, -3, 1, 1, 1, FALSE, FALSE); + u_rnd_force_data_incr_sync_3 : ENTITY work.tb_mms_dp_force_data_arr GENERIC MAP (e_random, e_random, 3, 16, 0, -1, 2, -3, 1, 1, 1, TRUE, FALSE); + u_rnd_force_data_incr_sop_3 : ENTITY work.tb_mms_dp_force_data_arr GENERIC MAP (e_random, e_random, 3, 16, 0, -1, 2, -3, 1, 1, 1, FALSE, TRUE); + +END tb;