diff --git a/libraries/base/common/src/vhdl/common_variable_delay.vhd b/libraries/base/common/src/vhdl/common_variable_delay.vhd index 847bb54e531d2bc300783c1f2431f25fcef1b97f..510f22ac51fe8c3841a3f65578495c143aa938a1 100644 --- a/libraries/base/common/src/vhdl/common_variable_delay.vhd +++ b/libraries/base/common/src/vhdl/common_variable_delay.vhd @@ -18,13 +18,12 @@ -- -------------------------------------------------------------------------- -- Author: --- . Pieter Donker +-- . Pieter Donker, Eric Kooistra -- Purpose: --- . Delay input pulse by number of given delay cycles +-- . Delay input pulse by delay number of cycles -- Description: --- . delay input pulse by delay number of cycles --- . output pulse is derived from low-high transition of input pulse. --- . the actual pulse delay will be delay + 1, due to implementation latency of 1 clk cycle +-- . The actual pulse delay will be delay + 1, due to implementation latency +-- of 1 clk cycle -- -------------------------------------------------------------------------- LIBRARY IEEE, technology_lib; @@ -36,41 +35,51 @@ ENTITY common_variable_delay IS g_max_delay : NATURAL := 200 * 10**6 ); PORT ( - rst : IN STD_LOGIC; - clk : IN STD_LOGIC; + rst : IN STD_LOGIC; + clk : IN STD_LOGIC; - delay : IN NATURAL RANGE 0 TO g_max_delay := 0; - enable : IN STD_LOGIC := '0'; - in_val : IN STD_LOGIC; - out_val : OUT STD_LOGIC + delay : IN NATURAL RANGE 0 TO g_max_delay := 0; + enable : IN STD_LOGIC := '0'; + in_pulse : IN STD_LOGIC; + out_pulse : OUT STD_LOGIC ); END common_variable_delay; ARCHITECTURE rtl OF common_variable_delay IS - SIGNAL i_out_val : STD_LOGIC; - SIGNAL nxt_out_val : STD_LOGIC; - SIGNAL delay_cnt : NATURAL; - SIGNAL nxt_delay_cnt : NATURAL; - SIGNAL prev_in_val : STD_LOGIC; + SIGNAL i_out_pulse : STD_LOGIC; + SIGNAL nxt_out_pulse : STD_LOGIC; + SIGNAL cnt_en : STD_LOGIC; + SIGNAL nxt_cnt_en : STD_LOGIC; + SIGNAL delay_cnt : NATURAL; + SIGNAL nxt_delay_cnt : NATURAL; BEGIN - out_val <= i_out_val; + out_pulse <= i_out_pulse; - p_delay: PROCESS(enable, in_val, prev_in_val, delay, delay_cnt) + p_delay: PROCESS(enable, in_pulse, delay, cnt_en, delay_cnt) BEGIN - nxt_out_val <= '0'; - nxt_delay_cnt <= 0; + nxt_out_pulse <= '0'; + nxt_cnt_en <= '0'; + nxt_delay_cnt <= 0; IF enable = '1' THEN - IF in_val = '1' AND prev_in_val = '0' THEN -- detect rising edge of in_val - IF delay = 0 THEN - nxt_out_val <= '1'; + -- Use cnt_en to avoid that toggling enable causes an out_pulse + nxt_cnt_en <= cnt_en; + IF cnt_en = '1' THEN + nxt_delay_cnt <= delay_cnt + 1; + IF delay_cnt + 1 = delay THEN + nxt_out_pulse <= '1'; + nxt_cnt_en <= '0'; END IF; ELSE - nxt_delay_cnt <= delay_cnt + 1; - IF delay_cnt+1 = delay THEN - nxt_out_val <= '1'; + -- Accept new in_pulse when idle, ignore new in_pulse when busy + IF in_pulse = '1' THEN + IF delay = 0 THEN + nxt_out_pulse <= '1'; -- out_pulse immediately + ELSE + nxt_cnt_en <= '1'; -- apply out_pulse after delay + END IF; END IF; END IF; END IF; @@ -79,13 +88,13 @@ BEGIN p_clk : PROCESS(rst, clk) BEGIN IF rst = '1' THEN - i_out_val <= '0'; + i_out_pulse <= '0'; + cnt_en <= '0'; delay_cnt <= 0; - prev_in_val <= '0'; ELSIF rising_edge(clk) THEN - i_out_val <= nxt_out_val; + i_out_pulse <= nxt_out_pulse; + cnt_en <= nxt_cnt_en; delay_cnt <= nxt_delay_cnt; - prev_in_val <= in_val; END IF; END PROCESS; diff --git a/libraries/base/common/tb/vhdl/tb_common_variable_delay.vhd b/libraries/base/common/tb/vhdl/tb_common_variable_delay.vhd index 8e91b07b721c6b83b4b9ecf236eb27fa77624b20..0227f26201ab4c4b1aff7a8b9989ea7469407e46 100644 --- a/libraries/base/common/tb/vhdl/tb_common_variable_delay.vhd +++ b/libraries/base/common/tb/vhdl/tb_common_variable_delay.vhd @@ -41,8 +41,13 @@ ARCHITECTURE tb OF tb_common_variable_delay IS CONSTANT c_clk_period : TIME := 10 ns; CONSTANT c_trigger_interval : NATURAL := 40; -- in clk's CONSTANT c_trigger_latency : NATURAL := 1; -- in clk's - CONSTANT c_delay_arr : t_natural_arr(0 TO 3) := (0, 1, 3, 12); + + -- Use a delay > c_trigger_interval to check wiht exp_triggers_cnt that new + -- triggers are ignored when a delay is already busy + CONSTANT c_delay_arr : t_natural_arr(0 TO 5) := (0, 1, 3, 12, c_trigger_interval * 3, 10); + SIGNAL stimuli_done : STD_LOGIC := '0'; + SIGNAL tb_end : STD_LOGIC := '0'; SIGNAL rst : STD_LOGIC; SIGNAL clk : STD_LOGIC := '0'; @@ -51,13 +56,19 @@ ARCHITECTURE tb OF tb_common_variable_delay IS SIGNAL enable : STD_LOGIC := '0'; SIGNAL trigger : STD_LOGIC := '0'; SIGNAL trigger_dly : STD_LOGIC := '0'; + + -- Use triggers_cnt to verify that triggers only occur when enable = '1' + -- and when the delay is not busy + SIGNAL triggers_cnt : NATURAL := 0; + SIGNAL exp_triggers_cnt : NATURAL := c_delay_arr'LENGTH; + BEGIN clk <= (NOT clk) OR tb_end AFTER c_clk_period/2; rst <= '1', '0' AFTER c_clk_period*4; - -- generate trigger signal - proc_common_gen_pulse(c_trigger_interval/2, c_trigger_interval, '1', rst, clk, trigger); + -- generate trigger pulse signal + proc_common_gen_pulse(1, c_trigger_interval, '1', rst, clk, trigger); p_in_stimuli : PROCESS VARIABLE clk_cnt : NATURAL := 0; @@ -66,15 +77,12 @@ BEGIN enable <= '0'; WAIT UNTIL rst = '0'; - WAIT UNTIL rising_edge(clk); - -- If enable = 0, no trigger_dly is expected, see wave-window - proc_common_wait_some_cycles(clk, 50); + -- If enable = 0, no trigger_dly is expected + proc_common_wait_some_cycles(clk, c_trigger_interval * 3); - + -- Enable trigger output and count clk's between trigger and trigger_dly enable <= '1'; - -- enable trigger output and count clk's between trigger lo-hi and trigger_dly lo-hi - -- check if counted clk's = c_trigger_latency + delay FOR i IN c_delay_arr'RANGE LOOP delay <= c_delay_arr(i); clk_cnt := 0; @@ -83,28 +91,32 @@ BEGIN clk_cnt := clk_cnt + 1; proc_common_wait_some_cycles(clk, 1); END LOOP; - ASSERT clk_cnt = c_trigger_latency + delay REPORT "delay failure, got " & int_to_str(clk_cnt) & ", expect " & int_to_str(c_trigger_latency+delay) SEVERITY ERROR; + -- Verify that expected delay was applied + ASSERT clk_cnt = c_trigger_latency + delay REPORT "delay failure, got " & int_to_str(clk_cnt) & ", expect " & int_to_str(c_trigger_latency+delay) SEVERITY ERROR; proc_common_wait_some_cycles(clk, 10); END LOOP; - enable <= '0'; - proc_common_wait_some_cycles(clk, 10); + proc_common_wait_some_cycles(clk, c_trigger_interval * 3); + ASSERT triggers_cnt = exp_triggers_cnt REPORT "wrong number of trigger_dly." SEVERITY ERROR; - tb_end <= '1'; + proc_common_wait_some_cycles(clk, 10); + tb_end <= '1'; WAIT; END PROCESS; + triggers_cnt <= triggers_cnt + 1 WHEN rising_edge(clk) AND trigger_dly = '1'; + -- device under test u_dut : ENTITY work.common_variable_delay PORT MAP ( - rst => rst, - clk => clk, + rst => rst, + clk => clk, - delay => delay, - enable => enable, - in_val => trigger, - out_val => trigger_dly + delay => delay, + enable => enable, + in_pulse => trigger, + out_pulse => trigger_dly ); END tb; diff --git a/libraries/base/common/tb/vhdl/tb_mms_common_variable_delay.vhd b/libraries/base/common/tb/vhdl/tb_mms_common_variable_delay.vhd index 39d08e87c644510a4d667ccc4a25de279487df3a..4727523f9249a25f53bbfb1b44cc53fc0652b191 100644 --- a/libraries/base/common/tb/vhdl/tb_mms_common_variable_delay.vhd +++ b/libraries/base/common/tb/vhdl/tb_mms_common_variable_delay.vhd @@ -88,8 +88,8 @@ BEGIN WAIT; END PROCESS; - -- generate trigger signal - proc_common_gen_pulse(c_trigger_interval/2, c_trigger_interval, '1', rst, clk, trigger); + -- generate trigger pulse signal + proc_common_gen_pulse(1, c_trigger_interval, '1', rst, clk, trigger); -- device under test u_dut : ENTITY work.mms_common_variable_delay