--======================================================================================= -- TITLE : Pulse generation with programmable delay -- DESCRIPTION : Generate pulse from an input with a programmable delay and width -- FILE : time_counter.vhd -- COMPANY : Micro-Cameras & Space Exploration SA --======================================================================================= -- CREATION -- DATE AUTHOR PROJECT REVISION -- 02/03/2011 JGi FTM 110302a --======================================================================================= -- MODIFICATION HISTORY -- DATE AUTHOR PROJECT REVISION COMMENTS -- 02/03/2011 JGi FTM 110302a Description --======================================================================================= -- Library Definition library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library unisim; use unisim.vcomponents.all; -- Entity Definition entity delayed_pulse is generic( pulse_width : integer range 0 to 15 := 10); port( --clock clk_250MHz : in std_logic; --control delay : in std_logic_vector(9 downto 0); --I/O input : in std_logic; output : out std_logic); end delayed_pulse; -- Architecture Definition architecture RTL of delayed_pulse is type t_reg is record -- Internal register declaration delayed_input : std_logic; enable : std_logic_vector(3 downto 0); delay : std_logic_vector(9 downto 0); delay_counter : std_logic_vector(9 downto 0); delay_value_reached : std_logic_vector(2 downto 0); delay_0_done : std_logic_vector(1 downto 0); delay_1_done : std_logic; pulse_shifter : std_logic_vector(pulse_width downto 0); -- Ouput register declaration output : std_logic_vector(1 downto 0); end record; signal i_next_reg : t_reg := (delayed_input => '0', enable => (others => '0'), delay => (others => '0'), delay_counter => (others => '0'), delay_value_reached => (others => '0'), delay_0_done => (others => '0'), delay_1_done => '0', pulse_shifter => (others => '0'), output => (others => '0')); signal i_reg : t_reg := (delayed_input => '0', enable => (others => '0'), delay => (others => '0'), delay_counter => (others => '0'), delay_value_reached => (others => '0'), delay_0_done => (others => '0'), delay_1_done => '0', pulse_shifter => (others => '0'), output => (others => '0')); signal i_shifted_data : std_logic; begin -- Generate shift register depending on pulse width generic -- defined in ftm_definitions -- Shifter logic gen_shifter_0: if pulse_width = 0 generate process(clk_250MHz) variable shifter : std_logic := '0'; begin if rising_edge(clk_250MHz) then shifter := i_reg.output(0) and not(i_reg.output(1)); end if; i_shifted_data <= shifter; end process; end generate gen_shifter_0; gen_shifter_1: if pulse_width > 0 generate process(clk_250MHz) variable shifter : std_logic_vector(pulse_width downto 0) := (others => '0'); begin if rising_edge(clk_250MHz) then shifter := shifter(pulse_width-1 downto 0) & (i_reg.output(0) and not(i_reg.output(1))); end if; i_shifted_data <= shifter(pulse_width); end process; end generate gen_shifter_1; -- Combinatorial logic process(input, delay, i_shifted_data, i_reg) variable v_reg : t_reg := (delayed_input => '0', enable => (others => '0'), delay => (others => '0'), delay_counter => (others => '0'), delay_value_reached => (others => '0'), delay_0_done => (others => '0'), delay_1_done => '0', pulse_shifter => (others => '0'), output => (others => '0')); begin v_reg := i_reg; --=================================================================================== --=================================================================================== -- Delay Counter management --=================================================================================== -- Register delay v_reg.delay := delay; -- Count delay when input (master trigger) rising edge detected if i_reg.enable(0) = '1' then v_reg.delay_counter(3 downto 0) := std_logic_vector(unsigned(i_reg.delay_counter(3 downto 0))+1); if i_reg.delay_0_done(1) = '1' then v_reg.delay_counter(7 downto 4) := std_logic_vector(unsigned(i_reg.delay_counter(7 downto 4))+1); end if; if i_reg.delay_1_done = '1' then v_reg.delay_counter(9 downto 8) := std_logic_vector(unsigned(i_reg.delay_counter(9 downto 8))+1); end if; else v_reg.delay_counter := (others => '0'); end if; v_reg.delayed_input := input; -- Detect input (master trigger) rising edge to enable counting if input = '1' and i_reg.delayed_input = '0' then v_reg.enable := (others => '1'); end if; -- Generate partial comparison between counter and setting if i_reg.delay_counter(3 downto 0) = i_reg.delay(3 downto 0) then v_reg.delay_value_reached(0) := i_reg.enable(1); else v_reg.delay_value_reached(0) := '0'; end if; if i_reg.delay_counter(7 downto 4) = i_reg.delay(7 downto 4) then v_reg.delay_value_reached(1) := i_reg.enable(1); else v_reg.delay_value_reached(1) := '0'; end if; if i_reg.delay_counter(9 downto 8) = i_reg.delay(9 downto 8) then v_reg.delay_value_reached(2) := i_reg.enable(1); else v_reg.delay_value_reached(2) := '0'; end if; -- Generate partial counter enable if i_reg.delay_counter(3 downto 0) = "1101" then v_reg.delay_0_done(0) := i_reg.enable(2); else v_reg.delay_0_done(0) := '0'; end if; v_reg.delay_0_done(1) := i_reg.delay_0_done(0) and i_reg.enable(2); if i_reg.delay_counter(7 downto 4) = "1111" then v_reg.delay_1_done := i_reg.delay_0_done(0) and i_reg.enable(2); end if; --=================================================================================== --=================================================================================== -- Pulse Counter management --=================================================================================== -- Enable output when delay is reached, and disable it after shift register -- has finished if i_shifted_data = '1' then v_reg.output(0) := '0'; elsif i_reg.delay_value_reached = "111" and i_reg.enable(3) = '1' then v_reg.output(0) := '1'; v_reg.pulse_shifter(0) := '1'; end if; -- Once the output falls, reset enable if i_reg.output(1) = '1' and i_reg.output(0) = '0' then v_reg.enable := (others => '0'); end if; v_reg.output(1) := i_reg.output(0); --=================================================================================== --=================================================================================== -- Drive register input i_next_reg <= v_reg; --=================================================================================== -- Output assignation output <= i_reg.output(0); --=================================================================================== end process; -- Sequential logic process(clk_250MHz) begin if rising_edge(clk_250MHz) then i_reg <= i_next_reg; end if; end process; end RTL;