Electronic – Set a constant high signal to low

state-machinesvhdl

I have a keypad circuit, when I press and hold a key, the signal "key_pressed" is always high, as long as I keep the key pressed, which is normal, when I leave it, it gets low again. But I don't want this signal to be constantly high, no matter how long I press the key, I would like to be detected as a single short press. In other means I should find a way to set this key_pressed to low after lets say 10ms. I'm doing everything in VHDL, no resistors capacitors… I also can't wait for a falling edge then it makes no sense, no key will be displayed on the LCD until the key is released which does not make sense.

Best Answer

You need a rising edge detector. This is done by generating a delayed input that is 1 clock cycle later than the actual input.

For example:

               ____     ____     ____     ____     ____     ____     ____     ____      
CLock      ___/    \___/    \___/    \___/    \___/    \___/    \___/    \___/    \

               _______________________________
Input      ___/                               \____________________________________
                        _______________________________
Input_z    ____________/                               \___________________________ 

                 ^ You want to detect this point, where the signals are not the
                   same. Input has gone high, but because Input_z is delayed, it 
                   isn't high yet 

The delayed input is generated as follows:

gen_input_z : process(clk,rst) 
begin
    if (rst = '1') then
        Input_z <= '0';
    elsif (rising_edge(clk)) then
        Input_z <= Input;
    end if;
end process

Now you want to detect your rising edge:

gen_edge_det : process(clk,rst) 
begin
    if (rst = '1') then
        Edge_detect <= '0';
    elsif (rising_edge(clk)) then
        if (Input = '1' and Input_z = '0') then
            Edge_detect <= '1';
        else 
            Edge_detect <= '0';
        end if;
    end if;
end process

But now our edge detect is only one clock cycle:

               ____     ____     ____     ____     ____     ____     ____     ____      
CLock      ___/    \___/    \___/    \___/    \___/    \___/    \___/    \___/    \

               _______________________________
Input      ___/                               \____________________________________
                        _______________________________
Input_z    ____________/                               \___________________________ 
                        ________
Edge_det   ____________/        \__________________________________________________

To modify that, add in a counter which only makes edge detect fall after a certain number of clock cycles:

-- Port Declarations
signal clk         : in std_logic;
signal rst         : in std_logic;
signal input       : in std_logic;

-- Signal declarations
signal input_z     : std_logic;
signal edge_detect : std_logic;
signal counter     : unsigned(31 downto 0); -- include numeric_std for this


gen_edge_det : process(clk,rst) 
begin
    if (rst = '1') then
        Edge_detect <= '0';
        counter     <= '0';
        input_z     <= '0';
    elsif (rising_edge(clk)) then
        input_z <= input;
        if (Input = '1' and Input_z = '0') then
            Edge_detect <= '1';
            counter     <= (others => '0');
        elsif (counter < 2) then          -- we want an edge detect of 2 clock cycles 
            Edge_detect <= '1';
            counter     <= counter + "1"; -- declare counter as unsigned.
        else
            Edge_detect <= '0';
        end if;
    end if;
end process

Now it's doing what we want:

               ____     ____     ____     ____     ____     ____     ____     ____      
CLock      ___/    \___/    \___/    \___/    \___/    \___/    \___/    \___/    \

               _______________________________
Input      ___/                               \____________________________________
                        _______________________________
Input_z    ____________/                               \___________________________ 
                        _____________
Edge_det   ____________/             \_____________________________________________