diff --git a/libraries/base/common/src/vhdl/common_pulse_delay.vhd b/libraries/base/common/src/vhdl/common_pulse_delay.vhd index 497a50dcadf2e2d0dccb40749bf09aefbf6b7957..9abbe074a6bac3f8adabdb6507a3663ce8389ce3 100644 --- a/libraries/base/common/src/vhdl/common_pulse_delay.vhd +++ b/libraries/base/common/src/vhdl/common_pulse_delay.vhd @@ -22,27 +22,94 @@ -- . Daniel van der Schuur -- Purpose: -- . Produce pulse_out pulse_delay clk cycles after pulse_in --- Description: --- . LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; +USE work.common_pkg.ALL; ENTITY common_pulse_delay IS + GENERIC ( + g_pulse_delay_max : NATURAL; -- Maximum delay value supported; determines internal counter width. + g_register_out : BOOLEAN -- TRUE adds output register, adding 1 cycle of delay to the pulse_delay setting. + ); PORT ( clk : IN STD_LOGIC; rst : IN STD_LOGIC; pulse_in : IN STD_LOGIC; - pulse_delay : IN STD_LOGIC; + pulse_delay : IN STD_LOGIC_VECTOR(ceil_log2(g_pulse_delay_max)-1 DOWNTO 0); pulse_out : OUT STD_LOGIC ); END ENTITY common_pulse_delay; -ARCHITECTURE rtl OF common_pulse_delay IS +ARCHITECTURE str OF common_pulse_delay IS + + CONSTANT c_pulse_delay_max_width : NATURAL := ceil_log2(g_pulse_delay_max); + SIGNAL common_counter_cnt_en : STD_LOGIC; + SIGNAL common_counter_count : STD_LOGIC_VECTOR(c_pulse_delay_max_width-1 DOWNTO 0); + + SIGNAL nxt_pulse_out : STD_LOGIC; BEGIN + ------------------------------------------------------------------------------- + -- Switch to start counter @ pulse_in, and stop counter @ pulse_out. + ------------------------------------------------------------------------------- + u_common_switch : ENTITY work.common_switch + GENERIC MAP ( + g_or_high => TRUE, + g_priority_lo => FALSE + ) + PORT MAP ( + clk => clk, + rst => rst, + switch_high => pulse_in, + switch_low => nxt_pulse_out, + out_level => common_counter_cnt_en + ); + + ------------------------------------------------------------------------------- + -- Count delay cycles relative to pulse_in + -- . We're using the load input to start counting at 1 instead of 0. + -- . Starting with zero makes it difficult to tell the difference between + -- common_counter's count output value (0) at reset and the first valid + -- output count value after cnt_en (also 0). + ------------------------------------------------------------------------------- + u_common_counter : ENTITY work.common_counter + GENERIC MAP ( + g_width => c_pulse_delay_max_width + ) + PORT MAP ( + clk => clk, + rst => rst, + cnt_ld => pulse_in, -- Clear (load "1") the counter on every pulse_in + cnt_en => common_counter_cnt_en, + load => TO_UVEC(1, c_pulse_delay_max_width), + count => common_counter_count + ); + + ------------------------------------------------------------------------------- + -- Assign nxt_pulse_out + ------------------------------------------------------------------------------- + nxt_pulse_out <= pulse_in WHEN pulse_delay=TO_UVEC(0, c_pulse_delay_max_width) ELSE -- 0 cycles delay + '1' WHEN common_counter_count=pulse_delay ELSE '0'; -- >=1 cycles delay + ------------------------------------------------------------------------------- + -- Optional output register + ------------------------------------------------------------------------------- + gen_register : IF g_register_out=TRUE GENERATE + p_clk : PROCESS (rst, clk) + BEGIN + IF rst = '1' THEN + pulse_out <= '0'; + ELSIF rising_edge(clk) THEN + pulse_out <= nxt_pulse_out; + END IF; + END PROCESS; + END GENERATE; -END rtl; + no_register : IF g_register_out=FALSE GENERATE + pulse_out <= nxt_pulse_out; + END GENERATE; + +END str; diff --git a/libraries/io/ppsh/src/vhdl/mms_ppsh.vhd b/libraries/io/ppsh/src/vhdl/mms_ppsh.vhd index c6279edcd22be6baea0d2718b416627027d5fae8..a7e033137c954a108d047bb28c03d2984ca97801 100644 --- a/libraries/io/ppsh/src/vhdl/mms_ppsh.vhd +++ b/libraries/io/ppsh/src/vhdl/mms_ppsh.vhd @@ -33,8 +33,9 @@ ENTITY mms_ppsh IS GENERIC ( g_technology : NATURAL := c_tech_select_default; g_cross_clock_domain : BOOLEAN := TRUE; -- use FALSE when mm_clk and st_clk are the same, else use TRUE to cross the clock domain - g_st_clk_freq : NATURAL := 200*10**6 -- clk frequency in Hz - ); + g_st_clk_freq : NATURAL := 200*10**6; -- clk frequency in Hz + g_pps_delay_max : NATURAL := 10 -- Maximum number of clk cycles that pps can be delayed + ); PORT ( -- Clocks and reset mm_rst : IN STD_LOGIC; -- reset synchronous with mm_clk @@ -70,7 +71,7 @@ ARCHITECTURE str OF mms_ppsh IS SIGNAL st_capture_edge : STD_LOGIC; SIGNAL st_expected_cnt : STD_LOGIC_VECTOR(ceil_log2(g_st_clk_freq)-1 DOWNTO 0); -- expected number of clk clock cycles between subsequent pps_ext pulses - SIGNAL st_pps_delay : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL st_pps_delay : STD_LOGIC_VECTOR(ceil_log2(g_pps_delay_max)-1 DOWNTO 0); -- MM registers in mm_clk domaim for pin_pps support SIGNAL mm_pps_toggle : STD_LOGIC; @@ -85,7 +86,8 @@ BEGIN u_ppsh : ENTITY work.ppsh GENERIC MAP ( g_technology => g_technology, - g_clk_freq => g_st_clk_freq + g_clk_freq => g_st_clk_freq, + g_pps_delay_max => g_pps_delay_max ) PORT MAP ( rst => st_rst, @@ -110,7 +112,8 @@ BEGIN u_mm_reg : ENTITY work.ppsh_reg GENERIC MAP ( g_cross_clock_domain => g_cross_clock_domain, - g_st_clk_freq => g_st_clk_freq + g_st_clk_freq => g_st_clk_freq, + g_pps_delay_max => g_pps_delay_max ) PORT MAP ( -- Clocks and reset diff --git a/libraries/io/ppsh/src/vhdl/ppsh.vhd b/libraries/io/ppsh/src/vhdl/ppsh.vhd index 595d1c3846c30670ff38bfb8a06f68c60298106d..e5be8451be53d4ab3a32b59aa5354b2111909b3b 100644 --- a/libraries/io/ppsh/src/vhdl/ppsh.vhd +++ b/libraries/io/ppsh/src/vhdl/ppsh.vhd @@ -55,8 +55,9 @@ USE technology_lib.technology_select_pkg.ALL; ENTITY ppsh IS GENERIC ( - g_technology : NATURAL := c_tech_select_default; - g_clk_freq : NATURAL := 200 * 10**6 -- clock frequency of clk in Hz + g_technology : NATURAL := c_tech_select_default; + g_clk_freq : NATURAL := 200 * 10**6; -- clock frequency of clk in Hz + g_pps_delay_max : NATURAL := 10 -- Maximum number of clk cycles that pps can be delayed ); PORT ( rst : IN STD_LOGIC; @@ -71,14 +72,14 @@ ENTITY ppsh IS pps_stable_ack : IN STD_LOGIC := '0'; -- pps stable acknowledge in clk domain capture_edge : IN STD_LOGIC := '0'; -- when '0' then clock pps_ext on rising edge of clk, else use falling edge of clk expected_cnt : IN STD_LOGIC_VECTOR(ceil_log2(g_clk_freq)-1 DOWNTO 0) := (OTHERS=> '1'); -- expected number of clk clock cycles between subsequent pps_ext pulses - pps_delay : IN STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0) := (OTHERS=>'0') -- Number of clk cycles of delay applied to pps_sys + pps_delay : IN STD_LOGIC_VECTOR(ceil_log2(g_pps_delay_max)-1 DOWNTO 0) := (OTHERS=>'0') -- Number of clk cycles of delay applied to pps_sys ); END ppsh; ARCHITECTURE rtl OF ppsh IS - CONSTANT c_pipeline_output : NATURAL := 3; + CONSTANT c_pipeline_output : NATURAL := 100; SIGNAL pps_ext_delayed : STD_LOGIC_VECTOR(0 DOWNTO 0); SIGNAL pps_ext_falling : STD_LOGIC_VECTOR(0 DOWNTO 0); @@ -163,15 +164,18 @@ BEGIN ); -- Apply a number of clk cycles of delay to pps_ext_revt - pps_ext_revt_dly <= pps_ext_revt; - - - - - - - - + u_common_pulse_delay : ENTITY common_lib.common_pulse_delay + GENERIC MAP ( + g_pulse_delay_max => g_pps_delay_max, + g_register_out => TRUE + ) + PORT MAP ( + clk => clk, + rst => rst, + pulse_in => pps_ext_revt, + pulse_delay => pps_delay, + pulse_out => pps_ext_revt_dly + ); u_capture_cnt : ENTITY common_lib.common_interval_monitor GENERIC MAP ( diff --git a/libraries/io/ppsh/src/vhdl/ppsh_reg.vhd b/libraries/io/ppsh/src/vhdl/ppsh_reg.vhd index d2a38e5b591358e6a35f6875b2244620953863d8..81267f08dd1471f8ce866bf0b3369af55008f211 100644 --- a/libraries/io/ppsh/src/vhdl/ppsh_reg.vhd +++ b/libraries/io/ppsh/src/vhdl/ppsh_reg.vhd @@ -44,8 +44,9 @@ USE common_lib.common_mem_pkg.ALL; ENTITY ppsh_reg IS GENERIC ( g_cross_clock_domain : BOOLEAN := TRUE; -- use FALSE when mm_clk and st_clk are the same, else use TRUE to cross the clock domain - g_st_clk_freq : NATURAL := 200 * 10**6 -- clock frequency of st_clk in Hz - ); + g_st_clk_freq : NATURAL := 200 * 10**6; -- clock frequency of st_clk in Hz + g_pps_delay_max : NATURAL := 10 -- Maximum number of clk cycles that pps can be delayed + ); PORT ( -- Clocks and reset mm_rst : IN STD_LOGIC; -- reset synchronous with mm_clk @@ -66,7 +67,7 @@ ENTITY ppsh_reg IS st_capture_edge : OUT STD_LOGIC; st_expected_cnt : OUT STD_LOGIC_VECTOR(ceil_log2(g_st_clk_freq)-1 DOWNTO 0); -- expected number of clk clock cycles between subsequent pps_ext pulses - st_pps_delay : OUT STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0) + st_pps_delay : OUT STD_LOGIC_VECTOR(ceil_log2(g_pps_delay_max)-1 DOWNTO 0) ); END ppsh_reg; @@ -91,7 +92,7 @@ ARCHITECTURE rtl OF ppsh_reg IS SIGNAL mm_capture_cnt : STD_LOGIC_VECTOR(ceil_log2(g_st_clk_freq)-1 DOWNTO 0); SIGNAL mm_expected_cnt : STD_LOGIC_VECTOR(ceil_log2(g_st_clk_freq)-1 DOWNTO 0); - SIGNAL mm_pps_delay : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL mm_pps_delay : STD_LOGIC_VECTOR(ceil_log2(g_pps_delay_max)-1 DOWNTO 0); BEGIN @@ -131,7 +132,7 @@ BEGIN mm_expected_cnt <= sla_in.wrdata(mm_expected_cnt'RANGE); WHEN 2 => -- Write pps_delay - mm_pps_delay <= sla_in.wrdata(c_word_w-1 DOWNTO 0); + mm_pps_delay <= sla_in.wrdata(ceil_log2(g_pps_delay_max)-1 DOWNTO 0); WHEN OTHERS => NULL; -- not used MM addresses END CASE; @@ -152,7 +153,7 @@ BEGIN sla_out.rddata(29 DOWNTO 0) <= RESIZE_UVEC(mm_expected_cnt, 30); WHEN 2 => -- Read back pps_delay - sla_out.rddata(c_word_w DOWNTO 0) <= mm_pps_delay; + sla_out.rddata(ceil_log2(g_pps_delay_max)-1 DOWNTO 0) <= mm_pps_delay; WHEN OTHERS => NULL; -- not used MM addresses END CASE; END IF;