Skip to content
Snippets Groups Projects
Commit cd960890 authored by Daniel van der Schuur's avatar Daniel van der Schuur
Browse files

-Instantiated common_pulse_delay on ppsh.vhd;

-Added generics for counter width and optional output registers;
-Verified OK using tb_ppsh and tb_mms_ppsh.
parent 47007506
No related branches found
No related tags found
No related merge requests found
......@@ -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;
......@@ -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
......
......@@ -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 (
......
......@@ -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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment