diff --git a/libraries/base/dp/src/vhdl/dp_block_validate_bsn_at_sync.vhd b/libraries/base/dp/src/vhdl/dp_block_validate_bsn_at_sync.vhd index fab468f1765315784e74068cc35190ef0f045678..9cd5bf76ee63f3a0911f7d3a7b29101764502354 100644 --- a/libraries/base/dp/src/vhdl/dp_block_validate_bsn_at_sync.vhd +++ b/libraries/base/dp/src/vhdl/dp_block_validate_bsn_at_sync.vhd @@ -40,6 +40,15 @@ -- in_sosi.sync counter and a number of discarded sync intervals counter, that -- can be read via the MM interface. -- Remarks: +-- . g_check_channel is needed for designs like the ring. The +-- dp_block_validate_bsn_at_sync.vhd only has to check the remote packets +-- from its neighbour ring node that is at one hop distance. The packets +-- that have traveled one hop have in_sosi.channel = g_check_channel = 1. +-- The packets at other channels from more distant PN are just passed on. +-- These packets have already been checked by the +-- dp_block_validate_bsn_at_sync.vhd on other PN. In this way it is +-- suffiicent to have one instance of dp_block_validate_bsn_at_sync.vhd per +-- PN. ------------------------------------------------------------------------------- -- REGMAP ------------------------------------------------------------------------------- @@ -80,74 +89,90 @@ END dp_block_validate_bsn_at_sync; ARCHITECTURE rtl OF dp_block_validate_bsn_at_sync IS + CONSTANT c_nof_regs : NATURAL := 2; + -- Define the actual size of the MM slave register CONSTANT c_mm_reg : t_c_mem := (latency => 1, - adr_w => ceil_log2(2), + adr_w => ceil_log2(c_nof_regs), dat_w => c_word_w, -- Use MM bus data width = c_word_w = 32 for all MM registers - nof_dat => 2, -- total counter + discarded counter + nof_dat => c_nof_regs, -- total counter + discarded counter init_sl => '0'); -- Registers in st_clk domain - SIGNAL count_reg : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0'); - - SIGNAL cnt_clr : STD_LOGIC; - SIGNAL cnt_sync : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); - SIGNAL cnt_sync_en : STD_LOGIC; - SIGNAL cnt_disc : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); - SIGNAL cnt_disc_en : STD_LOGIC; - - SIGNAL out_valid : STD_LOGIC; - SIGNAL bsn_ok : STD_LOGIC; - SIGNAL bsn_ok_reg : STD_LOGIC; - SIGNAL bsn_at_sync : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); - SIGNAL bsn_at_sync_reg : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + SIGNAL count_reg : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0'); + + SIGNAL mm_cnt_clr : STD_LOGIC_VECTOR(c_nof_regs-1 DOWNTO 0); + SIGNAL mm_cnt_clr_reg : STD_LOGIC_VECTOR(c_nof_regs-1 DOWNTO 0); + SIGNAL mm_cnt_clr_done : STD_LOGIC; + SIGNAL cnt_clr_en : STD_LOGIC; + SIGNAL cnt_clr_dat : STD_LOGIC_VECTOR(c_nof_regs-1 DOWNTO 0); + SIGNAL cnt_clr : STD_LOGIC_VECTOR(c_nof_regs-1 DOWNTO 0); + SIGNAL cnt_sync : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL cnt_sync_en : STD_LOGIC; + SIGNAL cnt_discarded : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL cnt_discarded_en : STD_LOGIC; + + SIGNAL out_valid : STD_LOGIC; + SIGNAL bsn_ok : STD_LOGIC; + SIGNAL bsn_ok_reg : STD_LOGIC; + SIGNAL bsn_at_sync : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + SIGNAL bsn_at_sync_reg : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); SIGNAL block_sosi : t_dp_sosi; BEGIN - u_common_spulse_cnt_clr : ENTITY common_lib.common_spulse + mm_cnt_clr_reg <= (OTHERS => '0') WHEN mm_rst = '1' ELSE mm_cnt_clr WHEN rising_edge(mm_clk) ELSE mm_cnt_clr_reg; + gen_err_cnt_clr : FOR I IN 0 TO c_nof_regs-1 GENERATE + mm_cnt_clr(I) <= '1' WHEN reg_mosi.rd = '1' AND TO_UINT(reg_mosi.address(c_mm_reg.adr_w-1 DOWNTO 0)) = I ELSE + '0' WHEN mm_cnt_clr_done = '1' ELSE mm_cnt_clr_reg(I); + END GENERATE; + + u_common_reg_cross_cnt_clr : ENTITY common_lib.common_reg_cross_domain PORT MAP ( in_rst => mm_rst, in_clk => mm_clk, - in_pulse => reg_mosi.rd, - in_busy => OPEN, + in_new => reg_mosi.rd, + in_dat => mm_cnt_clr, + in_done => mm_cnt_clr_done, out_rst => dp_rst, out_clk => dp_clk, - out_pulse => cnt_clr + out_dat => cnt_clr_dat, + out_new => cnt_clr_en ); + cnt_clr <= cnt_clr_dat WHEN cnt_clr_en = '1' ELSE (OTHERS => '0'); - -- sync counter - u_blk_counter : ENTITY common_lib.common_counter + -- discarded counter + cnt_discarded_en <= '1' WHEN in_sosi.sync = '1' AND bsn_ok = '0' ELSE '0'; + u_discarded_counter : ENTITY common_lib.common_counter GENERIC MAP ( g_width => c_word_w ) PORT MAP ( rst => dp_rst, clk => dp_clk, - - cnt_clr => cnt_clr, - cnt_en => in_sosi.sync, - count => cnt_sync + + cnt_clr => cnt_clr(0), + cnt_en => cnt_discarded_en, + count => cnt_discarded ); - -- discarded counter - cnt_disc_en <= '1' WHEN in_sosi.sync = '1' AND bsn_ok = '0' ELSE '0'; - u_disc_counter : ENTITY common_lib.common_counter + -- sync counter + u_blk_counter : ENTITY common_lib.common_counter GENERIC MAP ( g_width => c_word_w ) PORT MAP ( rst => dp_rst, clk => dp_clk, - - cnt_clr => cnt_clr, - cnt_en => cnt_disc_en, - count => cnt_disc + + cnt_clr => cnt_clr(1), + cnt_en => in_sosi.sync, + count => cnt_sync ); -- Register mapping - count_reg( c_word_w - 1 DOWNTO 0 ) <= cnt_disc; + count_reg( c_word_w - 1 DOWNTO 0 ) <= cnt_discarded; count_reg(2*c_word_w - 1 DOWNTO c_word_w ) <= cnt_sync; u_reg : ENTITY common_lib.common_reg_r_w_dc diff --git a/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd b/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd index dd3ce64854e4f42124a9787d1a0ae0bbcfc5ef0f..aed70a11ddc2552e71d17770c4834b6e546b1dd6 100644 --- a/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd +++ b/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd @@ -50,7 +50,8 @@ -- . . . . . -- . . . . . -- g_nof_err_counts-1 [31..0] RO err_count_index_[g_nof_err_counts-1] 0x0 --- g_nof_err_counts [31..0] RO total_block_count 0x0 +-- g_nof_err_counts [31..0] RO total_discarded_blocks 0x0 +-- g_nof_err_counts+1 [31..0] RO total_block_count 0x0 -- ==================================================================================== ------------------------------------------------------------------------------- LIBRARY IEEE, common_lib; @@ -100,24 +101,32 @@ ARCHITECTURE rtl OF dp_block_validate_err IS CONSTANT c_max_cnt : STD_LOGIC_VECTOR(g_cnt_w-1 DOWNTO 0) := (OTHERS => '1'); CONSTANT c_nof_err_ok : NATURAL := ceil_div(g_max_block_size, g_min_block_size); + CONSTANT c_nof_regs : NATURAL := g_nof_err_counts + 2; TYPE t_cnt_err_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_cnt_w-1 DOWNTO 0); -- Define the actual size of the MM slave register CONSTANT c_mm_reg : t_c_mem := (latency => 1, - adr_w => ceil_log2(g_nof_err_counts+1), + adr_w => ceil_log2(c_nof_regs), dat_w => c_word_w, -- Use MM bus data width = c_word_w = 32 for all MM registers - nof_dat => g_nof_err_counts+1, + nof_dat => c_nof_regs, init_sl => '0'); -- Registers in st_clk domain SIGNAL count_reg : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0'); - SIGNAL cnt_clr : STD_LOGIC; - SIGNAL cnt_blk : STD_LOGIC_VECTOR(g_cnt_w-1 DOWNTO 0); - SIGNAL cnt_blk_en : STD_LOGIC; - SIGNAL cnt_err : t_cnt_err_arr(g_nof_err_counts-1 DOWNTO 0); - SIGNAL cnt_err_en : STD_LOGIC_VECTOR(g_nof_err_counts-1 DOWNTO 0); + SIGNAL mm_cnt_clr : STD_LOGIC_VECTOR(c_nof_regs-1 DOWNTO 0); + SIGNAL mm_cnt_clr_reg : STD_LOGIC_VECTOR(c_nof_regs-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL mm_cnt_clr_done : STD_LOGIC; + SIGNAL cnt_clr_en : STD_LOGIC; + SIGNAL cnt_clr_dat : STD_LOGIC_VECTOR(c_nof_regs-1 DOWNTO 0); + SIGNAL cnt_clr : STD_LOGIC_VECTOR(c_nof_regs-1 DOWNTO 0); + SIGNAL cnt_blk : STD_LOGIC_VECTOR(g_cnt_w-1 DOWNTO 0); + SIGNAL cnt_blk_en : STD_LOGIC; + SIGNAL cnt_discarded : STD_LOGIC_VECTOR(g_cnt_w-1 DOWNTO 0); + SIGNAL cnt_discarded_en : STD_LOGIC; + SIGNAL cnt_err : t_cnt_err_arr(g_nof_err_counts-1 DOWNTO 0); + SIGNAL cnt_err_en : STD_LOGIC_VECTOR(g_nof_err_counts-1 DOWNTO 0); SIGNAL err_ok : STD_LOGIC; SIGNAL err_ok_reg : STD_LOGIC; @@ -131,17 +140,26 @@ ARCHITECTURE rtl OF dp_block_validate_err IS SIGNAL block_sosi_piped : t_dp_sosi; BEGIN + + mm_cnt_clr_reg <= (OTHERS => '0') WHEN mm_rst = '1' ELSE mm_cnt_clr WHEN rising_edge(mm_clk) ELSE mm_cnt_clr_reg; + gen_err_cnt_clr : FOR I IN 0 TO c_nof_regs-1 GENERATE + mm_cnt_clr(I) <= '1' WHEN reg_mosi.rd = '1' AND TO_UINT(reg_mosi.address(c_mm_reg.adr_w-1 DOWNTO 0)) = I ELSE + '0' WHEN mm_cnt_clr_done = '1' ELSE mm_cnt_clr_reg(I); + END GENERATE; - u_common_spulse_cnt_clr : ENTITY common_lib.common_spulse + u_common_reg_cross_cnt_clr : ENTITY common_lib.common_reg_cross_domain PORT MAP ( in_rst => mm_rst, in_clk => mm_clk, - in_pulse => reg_mosi.rd, - in_busy => OPEN, + in_new => reg_mosi.rd, + in_dat => mm_cnt_clr, + in_done => mm_cnt_clr_done, out_rst => dp_rst, out_clk => dp_clk, - out_pulse => cnt_clr + out_dat => cnt_clr_dat, + out_new => cnt_clr_en ); + cnt_clr <= cnt_clr_dat WHEN cnt_clr_en = '1' ELSE (OTHERS => '0'); -- block counter cnt_blk_en <= snk_in.eop WHEN UNSIGNED(cnt_blk) < UNSIGNED(c_max_cnt) ELSE '0'; @@ -153,11 +171,27 @@ BEGIN rst => dp_rst, clk => dp_clk, - cnt_clr => cnt_clr, + cnt_clr => cnt_clr(g_nof_err_counts+1), cnt_en => cnt_blk_en, count => cnt_blk ); + -- discarded block counter + cnt_discarded_en <= '1' WHEN snk_in.eop = '1' AND TO_UINT(snk_in.err(g_nof_err_counts-1 DOWNTO 0)) > 0 + AND UNSIGNED(cnt_discarded) < UNSIGNED(c_max_cnt) ELSE '0'; + u_discarded_counter : ENTITY common_lib.common_counter + GENERIC MAP ( + g_width => g_cnt_w + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + + cnt_clr => cnt_clr(g_nof_err_counts), + cnt_en => cnt_discarded_en, + count => cnt_discarded + ); + -- error counters gen_err_counters : FOR I IN 0 TO g_nof_err_counts-1 GENERATE cnt_err_en(I) <= snk_in.eop AND snk_in.err(I) WHEN UNSIGNED(cnt_err(I)) < UNSIGNED(c_max_cnt) ELSE '0'; @@ -169,19 +203,18 @@ BEGIN rst => dp_rst, clk => dp_clk, - cnt_clr => cnt_clr, + cnt_clr => cnt_clr(I), cnt_en => cnt_err_en(I), count => cnt_err(I) ); END GENERATE; -- Register mapping - -- first registers are the error counters gen_reg : FOR I IN 0 TO g_nof_err_counts-1 GENERATE count_reg((I + 1) * c_word_w - 1 DOWNTO I * c_word_w) <= RESIZE_UVEC(cnt_err(I), c_word_w); END GENERATE; - -- The last register is the block counter. - count_reg((g_nof_err_counts+1) * c_word_w - 1 DOWNTO g_nof_err_counts * c_word_w ) <= RESIZE_UVEC(cnt_blk, c_word_w); + count_reg((g_nof_err_counts+1) * c_word_w - 1 DOWNTO g_nof_err_counts * c_word_w ) <= RESIZE_UVEC(cnt_discarded, c_word_w); + count_reg((g_nof_err_counts+2) * c_word_w - 1 DOWNTO (g_nof_err_counts+1) * c_word_w ) <= RESIZE_UVEC(cnt_blk, c_word_w); u_reg : ENTITY common_lib.common_reg_r_w_dc GENERIC MAP ( diff --git a/libraries/base/dp/tb/vhdl/tb_dp_block_validate_bsn_at_sync.vhd b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_bsn_at_sync.vhd index 8d831c78942e1e986006f0d1b4d5413698c9a9c6..9483cfab0d228c49774aaaadea4e3ee978b62d30 100644 --- a/libraries/base/dp/tb/vhdl/tb_dp_block_validate_bsn_at_sync.vhd +++ b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_bsn_at_sync.vhd @@ -227,7 +227,7 @@ BEGIN ELSE -- 0 discarded sync ASSERT 0 = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong discarded sync count" SEVERITY ERROR; END IF; - proc_common_wait_some_cycles(dp_clk, 10); + proc_common_wait_some_cycles(dp_clk, 100); tb_end <= '1'; WAIT; END PROCESS; diff --git a/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd index a560cf8d1ec0ea5b08a46769060b62adf48c7bdf..9b0c20e901e1475494ae2798e9c98d159599e05e 100644 --- a/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd +++ b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd @@ -65,28 +65,32 @@ ARCHITECTURE tb OF tb_dp_block_validate_err IS CONSTANT c_dut_pipeline : NATURAL := g_nof_data_per_blk + 3; CONSTANT c_nof_sync : NATURAL := 5; CONSTANT c_nof_blk : NATURAL := g_nof_blocks_per_sync * c_nof_sync; + CONSTANT c_nof_discarded : NATURAL := c_nof_blk - ceil_div(c_nof_blk, 2**g_nof_err_counts); CONSTANT c_max_cnt : NATURAL := 2**g_cnt_w -1; - CONSTANT c_mm_addr_dp_blk_cnt : NATURAL := g_nof_err_counts; - CONSTANT c_exp_blk_cnt : NATURAL := sel_a_b(c_nof_blk < c_max_cnt, c_nof_blk, c_max_cnt); - SIGNAL dp_clk : STD_LOGIC := '1'; - SIGNAL mm_clk : STD_LOGIC := '1'; - SIGNAL rst : STD_LOGIC := '1'; - SIGNAL tb_end : STD_LOGIC := '0'; + CONSTANT c_mm_addr_dp_blk_cnt : NATURAL := g_nof_err_counts+1; + CONSTANT c_mm_addr_dp_discarded_cnt : NATURAL := g_nof_err_counts; + CONSTANT c_exp_blk_cnt : NATURAL := sel_a_b(c_nof_blk < c_max_cnt, c_nof_blk, c_max_cnt); + CONSTANT c_exp_discarded_cnt : NATURAL := sel_a_b(c_nof_discarded < c_max_cnt, c_nof_discarded, c_max_cnt); - SIGNAL stimuli_end : STD_LOGIC; - SIGNAL stimuli_sosi : t_dp_sosi; - SIGNAL stimuli_siso : t_dp_siso; - SIGNAL stimuli_cnt_reg : NATURAL; - SIGNAL stimuli_cnt : NATURAL; - SIGNAL verify_sosi : t_dp_sosi; - SIGNAL verify_siso : t_dp_siso := c_dp_siso_rdy; - SIGNAL reference_cnt : NATURAL; - SIGNAL reference_cnt_reg : NATURAL; - SIGNAL reference_sosi : t_dp_sosi; - SIGNAL reference_siso : t_dp_siso := c_dp_siso_rdy; - SIGNAL reg_mosi : t_mem_mosi := c_mem_mosi_rst; - SIGNAL reg_miso : t_mem_miso := c_mem_miso_rst; + SIGNAL dp_clk : STD_LOGIC := '1'; + SIGNAL mm_clk : STD_LOGIC := '1'; + SIGNAL rst : STD_LOGIC := '1'; + SIGNAL tb_end : STD_LOGIC := '0'; + + SIGNAL stimuli_end : STD_LOGIC; + SIGNAL stimuli_sosi : t_dp_sosi; + SIGNAL stimuli_siso : t_dp_siso; + SIGNAL stimuli_cnt_reg : NATURAL; + SIGNAL stimuli_cnt : NATURAL; + SIGNAL verify_sosi : t_dp_sosi; + SIGNAL verify_siso : t_dp_siso := c_dp_siso_rdy; + SIGNAL reference_cnt : NATURAL; + SIGNAL reference_cnt_reg : NATURAL; + SIGNAL reference_sosi : t_dp_sosi; + SIGNAL reference_siso : t_dp_siso := c_dp_siso_rdy; + SIGNAL reg_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL reg_miso : t_mem_miso := c_mem_miso_rst; BEGIN ------------------------------------------------------------------------------ @@ -204,13 +208,16 @@ BEGIN p_verify_mm : PROCESS VARIABLE v_X : INTEGER := 0; -- variable to hold 2**I * ((c_nof_blk-1) / 2**(I+1)) VARIABLE v_Y : INTEGER := 0; -- variable to hold (c_nof_blk-1) + 1 - (2 * v_X) - 2**I - -- v_N is a variable to hold the expectet cnt number for the error counter registers = v_X + v_Y for v_Y > 0, else = v_x. + -- v_N is a variable to hold the expected cnt number for the error counter registers = v_X + v_Y for v_Y > 0, else = v_x. -- this can be calculated as the dp error field is a counter up to c_nof_blk - 1. VARIABLE v_N : INTEGER := 0; BEGIN proc_common_wait_until_lo_hi(dp_clk, stimuli_end); proc_common_wait_some_cycles(dp_clk, c_dut_pipeline + 1); proc_common_wait_until_lo_hi(mm_clk, mm_clk); + proc_mem_mm_bus_rd(c_mm_addr_dp_discarded_cnt, mm_clk, reg_miso, reg_mosi); + proc_mem_mm_bus_rd_latency(1, mm_clk); + ASSERT c_exp_discarded_cnt = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong total discarded block count" SEVERITY ERROR; proc_mem_mm_bus_rd(c_mm_addr_dp_blk_cnt, mm_clk, reg_miso, reg_mosi); proc_mem_mm_bus_rd_latency(1, mm_clk); ASSERT c_exp_blk_cnt = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong total block count" SEVERITY ERROR;