diff --git a/libraries/base/dp/dp.peripheral.yaml b/libraries/base/dp/dp.peripheral.yaml index 23ed67a9ea89b4d4af72a7c355e6e2ecb07e24b6..fe9527c02280374ecc1c3604f7e2355c3520e8e1 100644 --- a/libraries/base/dp/dp.peripheral.yaml +++ b/libraries/base/dp/dp.peripheral.yaml @@ -451,18 +451,22 @@ peripherals: # MM port for dp_strobe_total_count.vhd - mm_port_name: REG_DP_STROBE_TOTAL_COUNT mm_port_type: REG - mm_port_span: ceil_pow2(g_nof_counts_max*2 + 1) * MM_BUS_SIZE # = 32 * MM_BUS_SIZE + mm_port_span: ceil_pow2(g_nof_counts_max*2 + 2) * MM_BUS_SIZE # = 32 * MM_BUS_SIZE mm_port_description: "" fields: - - field_name: counts - field_description: "Total number of strobes counters." + field_description: "Total number of strobes counters, updated at internal sync." number_of_fields: g_nof_counts address_offset: 0 user_width: 64 radix: uint64 access_mode: RO - - field_name: clear - field_description: "Read or write this register to clear all counters." + field_description: "Read or write this register to clear all counts." + address_offset: (g_nof_counts_max*2 + 0) * MM_BUS_SIZE # 30 * MM_BUS_SIZE + access_mode: RW + - - field_name: flush + field_description: "Flush current strobe counter values into the counts." address_offset: (g_nof_counts_max*2 + 1) * MM_BUS_SIZE # 31 * MM_BUS_SIZE access_mode: RW diff --git a/libraries/base/dp/src/vhdl/dp_components_pkg.vhd b/libraries/base/dp/src/vhdl/dp_components_pkg.vhd index 994b5988181f6921038a36ca7ca57313c2ff9716..308d866dfcd8196c1874da22e3c3db0c1445f871 100644 --- a/libraries/base/dp/src/vhdl/dp_components_pkg.vhd +++ b/libraries/base/dp/src/vhdl/dp_components_pkg.vhd @@ -36,11 +36,12 @@ PACKAGE dp_components_pkg IS CONSTANT c_dp_bsn_monitor_v2_reg_adr_w : NATURAL := ceil_log2(7); -- = 3 CONSTANT c_dp_bsn_monitor_v2_reg_adr_span : NATURAL := 2**c_dp_bsn_monitor_v2_reg_adr_w; -- = 8 - CONSTANT c_dp_strobe_total_count_reg_nof_words : NATURAL := 15*2 + 1; -- = 31 + CONSTANT c_dp_strobe_total_count_reg_nof_words : NATURAL := 15*2 + 2; -- = 32 CONSTANT c_dp_strobe_total_count_reg_adr_w : NATURAL := ceil_log2(c_dp_strobe_total_count_reg_nof_words); -- = 5 CONSTANT c_dp_strobe_total_count_reg_adr_span : NATURAL := 2**c_dp_strobe_total_count_reg_adr_w; -- = 32 CONSTANT c_dp_strobe_total_count_reg_nof_counts_max : NATURAL := 2**c_dp_strobe_total_count_reg_adr_w / 2 - 1; -- = 15 CONSTANT c_dp_strobe_total_count_reg_clear_adr : NATURAL := c_dp_strobe_total_count_reg_nof_counts_max*2; -- after counters in REGMAP + CONSTANT c_dp_strobe_total_count_reg_flush_adr : NATURAL := c_dp_strobe_total_count_reg_nof_counts_max*2 + 1; END dp_components_pkg; diff --git a/libraries/base/dp/src/vhdl/dp_strobe_total_count.vhd b/libraries/base/dp/src/vhdl/dp_strobe_total_count.vhd index 3af79f73d603f7213c2cd4afb502b653521c62f1..ff6d5e6ebdbabb2c33e5b271b5672c3259785828 100644 --- a/libraries/base/dp/src/vhdl/dp_strobe_total_count.vhd +++ b/libraries/base/dp/src/vhdl/dp_strobe_total_count.vhd @@ -61,13 +61,18 @@ -- (c_nof_counts_max-1)*2 [31..0] RO count[c_nof_counts_max-1] 0x0 -- (c_nof_counts_max-1)*2 + 1 [63.32] -- c_nof_counts_max*2 [31..0] RW clear 0x0 --- c_nof_counts_max*2 + 1 [31..0] RO rsvd 0x0 +-- c_nof_counts_max*2 + 1 [31..0] RW flush 0x0 -- =========================================================================== -- -- Remark: -- * This dp_strobe_total_count could have been a common_strobe_total_count -- component, because it does not use sosi/siso signals. However it is fine -- to keep it in dp_lib, to avoid extra work of moving and renaming. +-- * Use clear to clear the total counters +-- * The MM counter values are held at sync. Use flush to force the current +-- last counter values into the MM counter values. This is useful if the +-- ref_sync stopped already. + LIBRARY IEEE, common_lib; USE IEEE.std_logic_1164.all; USE IEEE.numeric_std.all; @@ -102,6 +107,7 @@ ARCHITECTURE rtl OF dp_strobe_total_count IS -- Fixed by REGMAP CONSTANT c_nof_counts_max : NATURAL := c_dp_strobe_total_count_reg_nof_counts_max; CONSTANT c_clear_adr : NATURAL := c_dp_strobe_total_count_reg_clear_adr; + CONSTANT c_flush_adr : NATURAL := c_dp_strobe_total_count_reg_flush_adr; -- Define the size of the MM slave register CONSTANT c_mm_reg : t_c_mem := (latency => 1, @@ -118,7 +124,9 @@ ARCHITECTURE rtl OF dp_strobe_total_count IS SIGNAL in_strobe_reg_arr : STD_LOGIC_VECTOR(g_nof_counts-1 DOWNTO 0) := (OTHERS=>'0'); SIGNAL in_strobe_reg2_arr : STD_LOGIC_VECTOR(g_nof_counts-1 DOWNTO 0) := (OTHERS=>'0'); SIGNAL rd_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; + SIGNAL mm_cnt_clear : STD_LOGIC; + SIGNAL mm_cnt_flush : STD_LOGIC; + SIGNAL cnt_flush : STD_LOGIC; SIGNAL cnt_clr : STD_LOGIC; SIGNAL cnt_en : STD_LOGIC := '0'; SIGNAL cnt_en_arr : STD_LOGIC_VECTOR(g_nof_counts-1 DOWNTO 0); @@ -131,17 +139,28 @@ BEGIN ASSERT g_count_w <= g_mm_w*2 REPORT "Too wide counter to fit REGMAP." SEVERITY FAILURE; -- Only clear on MM write, to allow MM read of all register fields without clear - mm_cnt_clr <= reg_mosi.wr WHEN TO_UINT(reg_mosi.address(c_mm_reg.adr_w-1 DOWNTO 0)) = c_clear_adr ELSE '0' ; + mm_cnt_clear <= reg_mosi.wr WHEN TO_UINT(reg_mosi.address(c_mm_reg.adr_w-1 DOWNTO 0)) = c_clear_adr ELSE '0'; + mm_cnt_flush <= reg_mosi.wr WHEN TO_UINT(reg_mosi.address(c_mm_reg.adr_w-1 DOWNTO 0)) = c_flush_adr ELSE '0'; - u_common_spulse : ENTITY common_lib.common_spulse - PORT MAP ( - in_rst => mm_rst, - in_clk => mm_clk, - in_pulse => mm_cnt_clr, - out_rst => dp_rst, - out_clk => dp_clk, - out_pulse => cnt_clr - ); + u_common_spulse_clear : ENTITY common_lib.common_spulse + PORT MAP ( + in_rst => mm_rst, + in_clk => mm_clk, + in_pulse => mm_cnt_clear, + out_rst => dp_rst, + out_clk => dp_clk, + out_pulse => cnt_clr + ); + + u_common_spulse_flush : ENTITY common_lib.common_spulse + PORT MAP ( + in_rst => mm_rst, + in_clk => mm_clk, + in_pulse => mm_cnt_flush, + out_rst => dp_rst, + out_clk => dp_clk, + out_pulse => cnt_flush + ); -- Register inputs to ease timing closure -- . register ref_sync to ease timing closure for ref_sync fanout @@ -192,13 +211,14 @@ BEGIN END GENERATE; -- Hold counter values at ref_sync_reg2 to have stable values for MM read - -- for comparision between nodes + -- for comparision between nodes. Use mm_cnt_flush/cnt_flush to support + -- observing the current counter values via MM. p_hold_counters : PROCESS(dp_clk) BEGIN IF rising_edge(dp_clk) THEN IF cnt_clr = '1' THEN hold_cnt_arr <= (OTHERS=>(OTHERS=>'0')); - ELSIF ref_sync_reg2 = '1' THEN + ELSIF ref_sync_reg2 = '1' OR cnt_flush = '1' THEN hold_cnt_arr <= cnt_arr; END IF; END IF;