From be60be4ea9a72d65d0e9feb82970707ce883d369 Mon Sep 17 00:00:00 2001 From: Reinier van der Walle <walle@astron.nl> Date: Thu, 22 Apr 2021 17:58:42 +0200 Subject: [PATCH] initial commit of dp_sync_insert_v2 --- libraries/base/dp/hdllib.cfg | 3 + .../base/dp/src/vhdl/dp_sync_insert_v2.vhd | 154 ++++++++++++ .../base/dp/tb/vhdl/tb_dp_sync_insert_v2.vhd | 235 ++++++++++++++++++ .../dp/tb/vhdl/tb_tb_dp_sync_insert_v2.vhd | 54 ++++ 4 files changed, 446 insertions(+) create mode 100644 libraries/base/dp/src/vhdl/dp_sync_insert_v2.vhd create mode 100644 libraries/base/dp/tb/vhdl/tb_dp_sync_insert_v2.vhd create mode 100644 libraries/base/dp/tb/vhdl/tb_tb_dp_sync_insert_v2.vhd diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg index 3e1217f8e0..8e1ea30462 100644 --- a/libraries/base/dp/hdllib.cfg +++ b/libraries/base/dp/hdllib.cfg @@ -133,6 +133,7 @@ synth_files = src/vhdl/dp_offload_tx_legacy.vhd src/vhdl/dp_offload_tx_len_calc.vhd src/vhdl/dp_sync_insert.vhd + src/vhdl/dp_sync_insert_v2.vhd src/vhdl/dp_field_blk.vhd src/vhdl/dp_concat_field_blk.vhd @@ -253,6 +254,7 @@ test_bench_files = tb/vhdl/tb_mms_dp_xonoff.vhd tb/vhdl/tb_dp_xonoff_reg_timeout.vhd tb/vhdl/tb_dp_sync_insert.vhd + tb/vhdl/tb_dp_sync_insert_v2.vhd tb/vhdl/tb_dp_folder.vhd tb/vhdl/tb_dp_switch.vhd tb/vhdl/tb_dp_counter_func.vhd @@ -304,6 +306,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_dp_sync_insert_v2.vhd tb/vhdl/tb_tb_mms_dp_force_data_parallel_arr.vhd tb/vhdl/tb_tb_mms_dp_force_data_serial_arr.vhd tb/vhdl/tb_tb_mms_dp_gain_arr.vhd diff --git a/libraries/base/dp/src/vhdl/dp_sync_insert_v2.vhd b/libraries/base/dp/src/vhdl/dp_sync_insert_v2.vhd new file mode 100644 index 0000000000..327c73530a --- /dev/null +++ b/libraries/base/dp/src/vhdl/dp_sync_insert_v2.vhd @@ -0,0 +1,154 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2021 +-- 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 vd Walle +-- Purpose : * Insert extra sync pulses. +-- Description: +-- Every nof_blk_per_sync block a sync pulse is created at the output. The block +-- counter resets if a sync arrives at the input or when nof_blk_per_sync is reached. +-- nof_blk_per_sync is controllable using M&C. +-- +-- Remarks: +-- . There is no support for back pressure. +-- . It does not compensate for missing data or extra data. There is NO reset function. It assumes that the +-- incoming data is perfectly aligned. Use a dp_sync_checker to assure the incoming data is perfect. +------------------------------------------------------------------------------- + +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_mem_pkg.ALL; +USE work.dp_stream_pkg.ALL; + +ENTITY dp_sync_insert_v2 IS + GENERIC ( + g_nof_streams : NATURAL := 1; + g_nof_blk_per_sync : NATURAL := 200000; + g_nof_blk_per_sync_min : NATURAL := 19530 + ); + 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 bus access in memory-mapped clock domain + reg_mosi : IN t_mem_mosi := c_mem_mosi_rst; + reg_miso : OUT t_mem_miso := c_mem_miso_rst; + + -- Streaming sink + in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + -- Streaming source + out_sosi_arr: OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) + + ); +END dp_sync_insert_v2; + + +ARCHITECTURE rtl OF dp_sync_insert_v2 IS + + TYPE t_reg IS RECORD -- local registers + blk_cnt : NATURAL RANGE 0 TO g_nof_blk_per_sync; + nof_blk_per_sync : NATURAL RANGE 0 TO g_nof_blk_per_sync; + in_sosi_arr_reg : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + out_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + END RECORD; + + CONSTANT c_reg_rst : t_reg := ( 0, 0, (OTHERS => c_dp_sosi_rst), (OTHERS => c_dp_sosi_rst)); + CONSTANT c_mm_reg_w : NATURAL := ceil_log2(g_nof_blk_per_sync+1); + CONSTANT c_nof_blk_per_sync_reg : t_c_mem := (1, 1, c_mm_reg_w, 1, 'X'); + CONSTANT c_init_reg : STD_LOGIC_VECTOR(c_mem_reg_init_w-1 DOWNTO 0) := TO_UVEC(g_nof_blk_per_sync, c_mem_reg_init_w); + + -- Define the local registers in t_reg record + SIGNAL r : t_reg; + SIGNAL nxt_r : t_reg; + + SIGNAL reg_nof_blk_per_sync : STD_LOGIC_VECTOR(c_mm_reg_w -1 DOWNTO 0); + +BEGIN + + out_sosi_arr <= r.out_sosi_arr; + + p_clk : PROCESS(dp_rst, dp_clk) + BEGIN + IF dp_rst='1' THEN + r <= c_reg_rst; + ELSIF rising_edge(dp_clk) THEN + r <= nxt_r; + END IF; + END PROCESS; + + p_comb : PROCESS(r, in_sosi_arr, reg_nof_blk_per_sync) + VARIABLE v : t_reg; + BEGIN + v := r; + v.in_sosi_arr_reg := in_sosi_arr; + v.out_sosi_arr := r.in_sosi_arr_reg; + + v.nof_blk_per_sync := TO_UINT(reg_nof_blk_per_sync); + IF TO_UINT(reg_nof_blk_per_sync) < g_nof_blk_per_sync_min THEN + v.nof_blk_per_sync := g_nof_blk_per_sync_min; + END IF; + + IF r.in_sosi_arr_reg(0).sop = '1' THEN + v.blk_cnt := r.blk_cnt + 1; + + IF r.blk_cnt = r.nof_blk_per_sync-1 OR r.in_sosi_arr_reg(0).sync = '1' THEN + v.blk_cnt := 0; + FOR I IN 0 TO g_nof_streams-1 LOOP + v.out_sosi_arr(I).sync := '1'; + END LOOP; + END IF; + END IF; + + nxt_r <= v; + END PROCESS; + + + u_common_reg_r_w_dc : ENTITY common_lib.common_reg_r_w_dc + GENERIC MAP ( + g_cross_clock_domain => TRUE, + g_readback => FALSE, + g_reg => c_nof_blk_per_sync_reg, + g_init_reg => c_init_reg + ) + 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_mosi, + sla_out => reg_miso, + + -- MM registers in st_clk domain + reg_wr_arr => OPEN, + reg_rd_arr => OPEN, + in_reg => reg_nof_blk_per_sync, + out_reg => reg_nof_blk_per_sync + ); + +END rtl; diff --git a/libraries/base/dp/tb/vhdl/tb_dp_sync_insert_v2.vhd b/libraries/base/dp/tb/vhdl/tb_dp_sync_insert_v2.vhd new file mode 100644 index 0000000000..8dbd0634e1 --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_dp_sync_insert_v2.vhd @@ -0,0 +1,235 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2021 +-- 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 vd Walle +-- Purpose: Verify dp_sync_insert_v2 +-- Description: +-- Usage: +-- > as 8 +-- > run -all +-- +-- * The tb is self stopping because tb_end will stop the simulation by +-- stopping the clk and thus all toggling. +------------------------------------------------------------------------------- + +LIBRARY IEEE, common_lib, dp_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE common_lib.common_lfsr_sequences_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE dp_lib.tb_dp_pkg.ALL; + + +ENTITY tb_dp_sync_insert_v2 IS + GENERIC ( + g_nof_streams : NATURAL := 2; + g_block_size_input : NATURAL := 16; + g_nof_blk_per_sync_input : NATURAL := 32; + g_gap_size_during_block : NATURAL := 0; + g_gap_size_between_block : NATURAL := 0; + g_nof_blk_per_sync : NATURAL := 8; + g_nof_blk_per_sync_min : NATURAL := 2; + g_nof_repeat : NATURAL := 14 + ); +END tb_dp_sync_insert_v2; + + +ARCHITECTURE tb OF tb_dp_sync_insert_v2 IS + + CONSTANT c_dut_latency : NATURAL := 2; + CONSTANT c_nof_replicated_sync : NATURAL := g_nof_blk_per_sync_input/g_nof_blk_per_sync; + + CONSTANT c_dp_clk_period : TIME := 5 ns; + CONSTANT c_mm_clk_period : TIME := 8 ns; + + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL mm_clk : STD_LOGIC := '1'; + SIGNAL dp_clk : STD_LOGIC := '1'; + SIGNAL rst : STD_LOGIC := '1'; + + -- DUT + SIGNAL ref_sosi : t_dp_sosi := c_dp_sosi_rst; + SIGNAL ref_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL out_sosi : t_dp_sosi; + SIGNAL out_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + + SIGNAL reg_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL reg_miso : t_mem_miso := c_mem_miso_rst; + + -- Verification + SIGNAL dly_valid_arr : STD_LOGIC_VECTOR(0 TO c_dut_latency) := (OTHERS=>'0'); + SIGNAL dly_ref_sosi_arr : t_dp_sosi_arr(0 TO c_dut_latency) := (OTHERS => c_dp_sosi_rst); + SIGNAL exp_sync : STD_LOGIC := '0'; + SIGNAL out_hold_sop : STD_LOGIC := '0'; + SIGNAL exp_size : NATURAL := g_block_size_input; + SIGNAL cnt_size_arr : t_natural_arr(0 TO g_nof_streams-1); + +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; + rst <= '1', '0' AFTER c_dp_clk_period*7; + + ------------------------------------------------------------------------------ + -- STIMULI + ------------------------------------------------------------------------------ + + p_stimuli : PROCESS + BEGIN + proc_common_wait_until_low(dp_clk, rst); + proc_common_wait_some_cycles(dp_clk, 5); + + FOR I IN 0 TO g_nof_repeat-1 LOOP + -- Generate first block with sync + ref_sosi.sync <= '1'; + ref_sosi.sop <= '1'; + ref_sosi.valid <= '1'; + ref_sosi.bsn <= TO_DP_BSN(23+I); + proc_common_wait_some_cycles(dp_clk, 1); + ref_sosi.sync <= '0'; + ref_sosi.sop <= '0'; + + -- Optionally apply valid='0' during block of data + ref_sosi.valid <= '0'; + proc_common_wait_some_cycles(dp_clk, g_gap_size_during_block); + ref_sosi.valid <= '1'; + + proc_common_wait_some_cycles(dp_clk, g_block_size_input-2); + ref_sosi.eop <= '1'; + proc_common_wait_some_cycles(dp_clk, 1); + ref_sosi.eop <= '0'; + ref_sosi.valid <= '0'; + + -- Optionally apply valid='0' between block of data + proc_common_wait_some_cycles(dp_clk, g_gap_size_between_block); + + -- Generate next blocks after sync + FOR I IN 0 TO g_nof_blk_per_sync_input-2 LOOP + ref_sosi.sop <= '1'; + ref_sosi.valid <= '1'; + proc_common_wait_some_cycles(dp_clk, 1); + ref_sosi.sync <= '0'; + ref_sosi.sop <= '0'; + + -- Optionally apply valid='0' during block of data + ref_sosi.valid <= '0'; + proc_common_wait_some_cycles(dp_clk, g_gap_size_during_block); + ref_sosi.valid <= '1'; + + proc_common_wait_some_cycles(dp_clk, g_block_size_input-2); + ref_sosi.eop <= '1'; + proc_common_wait_some_cycles(dp_clk, 1); + ref_sosi.eop <= '0'; + ref_sosi.valid <= '0'; + + -- Optionally apply valid='0' between block of data + proc_common_wait_some_cycles(dp_clk, g_gap_size_between_block); + END LOOP; + END LOOP; + + -- End of stimuli + proc_common_wait_some_cycles(dp_clk, 100); + tb_end <= '1'; + WAIT; + END PROCESS; + + ref_sosi.data <= INCR_UVEC(ref_sosi.data, 1) WHEN rising_edge(dp_clk); + ref_sosi.re <= INCR_UVEC(ref_sosi.re, 2) WHEN rising_edge(dp_clk); + ref_sosi.im <= INCR_UVEC(ref_sosi.im, 3) WHEN rising_edge(dp_clk); + + gen_streams : FOR I IN 0 TO g_nof_streams-1 GENERATE + ref_sosi_arr(I) <= ref_sosi; + END GENERATE; + + ------------------------------------------------------------------------------ + -- DUT + ------------------------------------------------------------------------------ + u_dut: ENTITY work.dp_sync_insert_v2 + GENERIC MAP ( + g_nof_streams => g_nof_streams, + g_nof_blk_per_sync => g_nof_blk_per_sync, + g_nof_blk_per_sync_min => g_nof_blk_per_sync_min + ) + PORT MAP ( + mm_rst => rst, + mm_clk => mm_clk, + dp_rst => rst, + dp_clk => dp_clk, + + reg_mosi => reg_mosi, + reg_miso => reg_miso, + + -- Streaming sink + in_sosi_arr => ref_sosi_arr, + -- Streaming source + out_sosi_arr => out_sosi_arr + ); + + ------------------------------------------------------------------------------ + -- Verification + -- . use some DUT specific verification + -- . use some general Verification means from tb_dp_pkg.vhd, dp_stream_verify.vhd + ------------------------------------------------------------------------------ + dly_ref_sosi_arr(0) <= ref_sosi; + dly_ref_sosi_arr(1 TO c_dut_latency) <= dly_ref_sosi_arr(0 TO c_dut_latency-1) WHEN rising_edge(dp_clk); + + p_exp_sync : PROCESS(dp_clk) + VARIABLE blk_cnt : NATURAL := 0; + BEGIN + IF rising_edge(dp_clk) THEN + exp_sync <= '0'; + IF dly_ref_sosi_arr(c_dut_latency-1).sop = '1' THEN + IF dly_ref_sosi_arr(c_dut_latency-1).sync = '1' OR blk_cnt >= g_nof_blk_per_sync-1 THEN + blk_cnt := 0; + exp_sync <= '1'; + ELSE + blk_cnt := blk_cnt+1; + END IF; + END IF; + END IF; + END PROCESS; + + p_verify_out_sosi : PROCESS(dp_clk) + BEGIN + IF rising_edge(dp_clk) THEN + FOR I IN 0 TO g_nof_streams-1 LOOP + ASSERT out_sosi_arr(I).valid = dly_ref_sosi_arr(c_dut_latency).valid REPORT "Wrong out_sosi.valid" SEVERITY ERROR; + ASSERT out_sosi_arr(I).sop = dly_ref_sosi_arr(c_dut_latency).sop REPORT "Wrong out_sosi.sop" SEVERITY ERROR; + ASSERT out_sosi_arr(I).eop = dly_ref_sosi_arr(c_dut_latency).eop REPORT "Wrong out_sosi.eop" SEVERITY ERROR; + ASSERT out_sosi_arr(I).bsn = dly_ref_sosi_arr(c_dut_latency).bsn REPORT "Wrong out_sosi.bsn" SEVERITY ERROR; + ASSERT out_sosi_arr(I).sync = exp_sync REPORT "Wrong out_sosi.sync" SEVERITY ERROR; + END LOOP; + END IF; + END PROCESS; + + -- Verify output packet ctrl + gen_verify_ctrl : FOR I IN 0 TO g_nof_streams-1 GENERATE + proc_dp_verify_sop_and_eop(dp_clk, out_sosi_arr(I).valid, out_sosi_arr(I).sop, out_sosi_arr(I).eop, out_hold_sop); + -- Verify output packet block size + proc_dp_verify_block_size(exp_size, dp_clk, out_sosi_arr(I).valid, out_sosi_arr(I).sop, out_sosi_arr(I).eop, cnt_size_arr(I)); + END GENERATE; + + + +END tb; diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_sync_insert_v2.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_sync_insert_v2.vhd new file mode 100644 index 0000000000..8d3cb5d468 --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_sync_insert_v2.vhd @@ -0,0 +1,54 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2021 +-- 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 vd Walle +-- Purpose: Verify multiple variations of tb_dp_sync_insert_v2 +-- Description: +-- Usage: +-- > as 3 +-- > run -all +------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; + +ENTITY tb_tb_dp_sync_insert_v2 IS +END tb_tb_dp_sync_insert_v2; + +ARCHITECTURE tb OF tb_tb_dp_sync_insert_v2 IS + SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' +BEGIN + +-- g_nof_streams : NATURAL := 2; +-- g_block_size_input : NATURAL := 16; +-- g_nof_blk_per_sync_input : NATURAL := 32; +-- g_gap_size_during_block : NATURAL := 0; +-- g_gap_size_between_block : NATURAL := 0; +-- g_nof_blk_per_sync : NATURAL := 8; +-- g_nof_blk_per_sync_min : NATURAL := 2; +-- g_nof_repeat : NATURAL := 14 + + u_no_gaps : ENTITY work.tb_dp_sync_insert_v2 GENERIC MAP(2, 16, 32, 0, 0, 8, 2, 14); + u_gap : ENTITY work.tb_dp_sync_insert_v2 GENERIC MAP(2, 16, 32, 1, 3, 8, 2, 14); + u_large_blk_per_sync : ENTITY work.tb_dp_sync_insert_v2 GENERIC MAP(2, 16, 32, 0, 0, 999, 2, 14); + u_fract_blk_per_sync : ENTITY work.tb_dp_sync_insert_v2 GENERIC MAP(2, 16, 32, 0, 0, 7, 2, 14); + +END tb; -- GitLab