| 1 | --=======================================================================================
|
|---|
| 2 | -- TITLE : Pulse generation with programmable delay
|
|---|
| 3 | -- DESCRIPTION : Generate pulse from an input with a programmable delay and width
|
|---|
| 4 | -- FILE : time_counter.vhd
|
|---|
| 5 | -- COMPANY : Micro-Cameras & Space Exploration SA
|
|---|
| 6 | --=======================================================================================
|
|---|
| 7 | -- CREATION
|
|---|
| 8 | -- DATE AUTHOR PROJECT REVISION
|
|---|
| 9 | -- 02/03/2011 JGi FTM 110302a
|
|---|
| 10 | --=======================================================================================
|
|---|
| 11 | -- MODIFICATION HISTORY
|
|---|
| 12 | -- DATE AUTHOR PROJECT REVISION COMMENTS
|
|---|
| 13 | -- 02/03/2011 JGi FTM 110302a Description
|
|---|
| 14 | --=======================================================================================
|
|---|
| 15 | -- Library Definition
|
|---|
| 16 | library ieee;
|
|---|
| 17 | use ieee.std_logic_1164.all;
|
|---|
| 18 | use ieee.numeric_std.all;
|
|---|
| 19 |
|
|---|
| 20 | library unisim;
|
|---|
| 21 | use unisim.vcomponents.all;
|
|---|
| 22 |
|
|---|
| 23 | -- Entity Definition
|
|---|
| 24 | entity delayed_pulse is
|
|---|
| 25 | generic( pulse_width : integer range 0 to 15 := 10);
|
|---|
| 26 | port( --clock
|
|---|
| 27 | clk_250MHz : in std_logic;
|
|---|
| 28 | --control
|
|---|
| 29 | delay : in std_logic_vector(9 downto 0);
|
|---|
| 30 | --I/O
|
|---|
| 31 | input : in std_logic;
|
|---|
| 32 | output : out std_logic);
|
|---|
| 33 | end delayed_pulse;
|
|---|
| 34 |
|
|---|
| 35 | -- Architecture Definition
|
|---|
| 36 | architecture RTL of delayed_pulse is
|
|---|
| 37 |
|
|---|
| 38 | type t_reg is record
|
|---|
| 39 | -- Internal register declaration
|
|---|
| 40 | delayed_input : std_logic;
|
|---|
| 41 | enable : std_logic_vector(3 downto 0);
|
|---|
| 42 | delay : std_logic_vector(9 downto 0);
|
|---|
| 43 | delay_counter : std_logic_vector(9 downto 0);
|
|---|
| 44 | delay_value_reached : std_logic_vector(2 downto 0);
|
|---|
| 45 | delay_0_done : std_logic_vector(1 downto 0);
|
|---|
| 46 | delay_1_done : std_logic;
|
|---|
| 47 | pulse_shifter : std_logic_vector(pulse_width downto 0);
|
|---|
| 48 | -- Ouput register declaration
|
|---|
| 49 | output : std_logic_vector(1 downto 0);
|
|---|
| 50 | end record;
|
|---|
| 51 |
|
|---|
| 52 | signal i_next_reg : t_reg := (delayed_input => '0',
|
|---|
| 53 | enable => (others => '0'),
|
|---|
| 54 | delay => (others => '0'),
|
|---|
| 55 | delay_counter => (others => '0'),
|
|---|
| 56 | delay_value_reached => (others => '0'),
|
|---|
| 57 | delay_0_done => (others => '0'),
|
|---|
| 58 | delay_1_done => '0',
|
|---|
| 59 | pulse_shifter => (others => '0'),
|
|---|
| 60 | output => (others => '0'));
|
|---|
| 61 | signal i_reg : t_reg := (delayed_input => '0',
|
|---|
| 62 | enable => (others => '0'),
|
|---|
| 63 | delay => (others => '0'),
|
|---|
| 64 | delay_counter => (others => '0'),
|
|---|
| 65 | delay_value_reached => (others => '0'),
|
|---|
| 66 | delay_0_done => (others => '0'),
|
|---|
| 67 | delay_1_done => '0',
|
|---|
| 68 | pulse_shifter => (others => '0'),
|
|---|
| 69 | output => (others => '0'));
|
|---|
| 70 |
|
|---|
| 71 | signal i_shifted_data : std_logic;
|
|---|
| 72 |
|
|---|
| 73 | begin
|
|---|
| 74 |
|
|---|
| 75 | -- Generate shift register depending on pulse width generic
|
|---|
| 76 | -- defined in ftm_definitions
|
|---|
| 77 | -- Shifter logic
|
|---|
| 78 | gen_shifter_0: if pulse_width = 0 generate
|
|---|
| 79 | process(clk_250MHz)
|
|---|
| 80 | variable shifter : std_logic := '0';
|
|---|
| 81 | begin
|
|---|
| 82 | if rising_edge(clk_250MHz) then
|
|---|
| 83 | shifter := i_reg.output(0) and not(i_reg.output(1));
|
|---|
| 84 | end if;
|
|---|
| 85 | i_shifted_data <= shifter;
|
|---|
| 86 | end process;
|
|---|
| 87 | end generate gen_shifter_0;
|
|---|
| 88 | gen_shifter_1: if pulse_width > 0 generate
|
|---|
| 89 | process(clk_250MHz)
|
|---|
| 90 | variable shifter : std_logic_vector(pulse_width downto 0) := (others => '0');
|
|---|
| 91 | begin
|
|---|
| 92 | if rising_edge(clk_250MHz) then
|
|---|
| 93 | shifter := shifter(pulse_width-1 downto 0) & (i_reg.output(0) and not(i_reg.output(1)));
|
|---|
| 94 | end if;
|
|---|
| 95 | i_shifted_data <= shifter(pulse_width);
|
|---|
| 96 | end process;
|
|---|
| 97 | end generate gen_shifter_1;
|
|---|
| 98 |
|
|---|
| 99 | -- Combinatorial logic
|
|---|
| 100 | process(input, delay, i_shifted_data, i_reg)
|
|---|
| 101 | variable v_reg : t_reg := (delayed_input => '0',
|
|---|
| 102 | enable => (others => '0'),
|
|---|
| 103 | delay => (others => '0'),
|
|---|
| 104 | delay_counter => (others => '0'),
|
|---|
| 105 | delay_value_reached => (others => '0'),
|
|---|
| 106 | delay_0_done => (others => '0'),
|
|---|
| 107 | delay_1_done => '0',
|
|---|
| 108 | pulse_shifter => (others => '0'),
|
|---|
| 109 | output => (others => '0'));
|
|---|
| 110 | begin
|
|---|
| 111 | v_reg := i_reg;
|
|---|
| 112 | --===================================================================================
|
|---|
| 113 |
|
|---|
| 114 | --===================================================================================
|
|---|
| 115 | -- Delay Counter management
|
|---|
| 116 | --===================================================================================
|
|---|
| 117 | -- Register delay
|
|---|
| 118 | v_reg.delay := delay;
|
|---|
| 119 |
|
|---|
| 120 | -- Count delay when input (master trigger) rising edge detected
|
|---|
| 121 | if i_reg.enable(0) = '1' then
|
|---|
| 122 | v_reg.delay_counter(3 downto 0) := std_logic_vector(unsigned(i_reg.delay_counter(3 downto 0))+1);
|
|---|
| 123 | if i_reg.delay_0_done(1) = '1' then
|
|---|
| 124 | v_reg.delay_counter(7 downto 4) := std_logic_vector(unsigned(i_reg.delay_counter(7 downto 4))+1);
|
|---|
| 125 | end if;
|
|---|
| 126 | if i_reg.delay_1_done = '1' then
|
|---|
| 127 | v_reg.delay_counter(9 downto 8) := std_logic_vector(unsigned(i_reg.delay_counter(9 downto 8))+1);
|
|---|
| 128 | end if;
|
|---|
| 129 | else
|
|---|
| 130 | v_reg.delay_counter := (others => '0');
|
|---|
| 131 | end if;
|
|---|
| 132 |
|
|---|
| 133 | v_reg.delayed_input := input;
|
|---|
| 134 |
|
|---|
| 135 | -- Detect input (master trigger) rising edge to enable counting
|
|---|
| 136 | if input = '1' and i_reg.delayed_input = '0' then
|
|---|
| 137 | v_reg.enable := (others => '1');
|
|---|
| 138 | end if;
|
|---|
| 139 |
|
|---|
| 140 | -- Generate partial comparison between counter and setting
|
|---|
| 141 | if i_reg.delay_counter(3 downto 0) = i_reg.delay(3 downto 0) then
|
|---|
| 142 | v_reg.delay_value_reached(0) := i_reg.enable(1);
|
|---|
| 143 | else
|
|---|
| 144 | v_reg.delay_value_reached(0) := '0';
|
|---|
| 145 | end if;
|
|---|
| 146 | if i_reg.delay_counter(7 downto 4) = i_reg.delay(7 downto 4) then
|
|---|
| 147 | v_reg.delay_value_reached(1) := i_reg.enable(1);
|
|---|
| 148 | else
|
|---|
| 149 | v_reg.delay_value_reached(1) := '0';
|
|---|
| 150 | end if;
|
|---|
| 151 | if i_reg.delay_counter(9 downto 8) = i_reg.delay(9 downto 8) then
|
|---|
| 152 | v_reg.delay_value_reached(2) := i_reg.enable(1);
|
|---|
| 153 | else
|
|---|
| 154 | v_reg.delay_value_reached(2) := '0';
|
|---|
| 155 | end if;
|
|---|
| 156 |
|
|---|
| 157 | -- Generate partial counter enable
|
|---|
| 158 | if i_reg.delay_counter(3 downto 0) = "1101" then
|
|---|
| 159 | v_reg.delay_0_done(0) := i_reg.enable(2);
|
|---|
| 160 | else
|
|---|
| 161 | v_reg.delay_0_done(0) := '0';
|
|---|
| 162 | end if;
|
|---|
| 163 | v_reg.delay_0_done(1) := i_reg.delay_0_done(0) and i_reg.enable(2);
|
|---|
| 164 |
|
|---|
| 165 | if i_reg.delay_counter(7 downto 4) = "1111" then
|
|---|
| 166 | v_reg.delay_1_done := i_reg.delay_0_done(0) and i_reg.enable(2);
|
|---|
| 167 | end if;
|
|---|
| 168 | --===================================================================================
|
|---|
| 169 |
|
|---|
| 170 | --===================================================================================
|
|---|
| 171 | -- Pulse Counter management
|
|---|
| 172 | --===================================================================================
|
|---|
| 173 | -- Enable output when delay is reached, and disable it after shift register
|
|---|
| 174 | -- has finished
|
|---|
| 175 | if i_shifted_data = '1' then
|
|---|
| 176 | v_reg.output(0) := '0';
|
|---|
| 177 | elsif i_reg.delay_value_reached = "111" and i_reg.enable(3) = '1' then
|
|---|
| 178 | v_reg.output(0) := '1';
|
|---|
| 179 | v_reg.pulse_shifter(0) := '1';
|
|---|
| 180 | end if;
|
|---|
| 181 |
|
|---|
| 182 | -- Once the output falls, reset enable
|
|---|
| 183 | if i_reg.output(1) = '1' and i_reg.output(0) = '0' then
|
|---|
| 184 | v_reg.enable := (others => '0');
|
|---|
| 185 | end if;
|
|---|
| 186 |
|
|---|
| 187 | v_reg.output(1) := i_reg.output(0);
|
|---|
| 188 | --===================================================================================
|
|---|
| 189 |
|
|---|
| 190 | --===================================================================================
|
|---|
| 191 | -- Drive register input
|
|---|
| 192 | i_next_reg <= v_reg;
|
|---|
| 193 |
|
|---|
| 194 | --===================================================================================
|
|---|
| 195 | -- Output assignation
|
|---|
| 196 | output <= i_reg.output(0);
|
|---|
| 197 | --===================================================================================
|
|---|
| 198 | end process;
|
|---|
| 199 |
|
|---|
| 200 | -- Sequential logic
|
|---|
| 201 | process(clk_250MHz)
|
|---|
| 202 | begin
|
|---|
| 203 | if rising_edge(clk_250MHz) then
|
|---|
| 204 | i_reg <= i_next_reg;
|
|---|
| 205 | end if;
|
|---|
| 206 | end process;
|
|---|
| 207 |
|
|---|
| 208 | end RTL; |
|---|