0

i am trying to practice debouncing on FPGA following the approach (full count based), that introduced in the book from Volnei ("Circuit Design with VHDL third edition"). A very important feature of this circuit is the way the timer is constructed, which eliminates the need for a comparator (a large circuit). For example, for the numeric values just given, $S = 50,MHz * 20,ms= 10e6$ results, where the number of bits (DFFs) in the counter is $N= log_2(S) = 20$ implying a counter running from zero to $10e6 - 1$ = 1 1 1 1_0100_0010_00 1 1_1 1 1 1, thus requiring a comparator that is at least 12 bits wide (only the s need to be monitored), which is indeed a large circuit. This can be avoided by taking into consideration that the time does not need to be exact in debouncers, so if an extra bit (flip-flop) is included in the counter, its MSB alone can play the role of comparator; when MSB= 1 occurs, it enables the output register, so y is updated, leading subsequently to clear= 1, which zeros the counter (and therefore the MSB too) at the next positive clock edge. In summary, the counter spans a total of $ S = 2^N+ 1$ states, leading to $T{deb} = 2^N/f_{clk (50MHz)} = 21 ms$ for the numeric values given above.

However, testing the code given from this Example not giving the expected result.

Debouncing

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE IEEE.math_real.ALL;

ENTITY E13_button_debouncer IS
    GENERIC (
        T_DEB_MS : NATURAL := 25;
        f_clk : NATURAL := 50_000);
    PORT (
        clk : IN STD_LOGIC;
        rst : IN STD_LOGIC;
        b_in : IN STD_LOGIC;
        b_out : OUT STD_LOGIC
    );
END E13_button_debouncer;

ARCHITECTURE single_switch OF E13_button_debouncer IS
    CONSTANT COUNTER_BITS : NATURAL := 1 + INTEGER(ceil(log2(real(T_DEB_MS * f_clk))));

    -- ! Optional :
    SIGNAL x_reg : STD_LOGIC;

BEGIN
    proc_name : PROCESS (clk)
        VARIABLE count : unsigned(COUNTER_BITS - 1 DOWNTO 0);
    BEGIN
        IF rising_edge(clk) THEN
            IF rst = '0' THEN
                count := (OTHERS => '0');
                x_reg <= '0';
                b_out <= '0';
            ELSE
                x_reg <= b_in;
                IF b_out = x_reg THEN
                    count := (OTHERS => '0');
                ELSE
                    count := count + 1;
                END IF;
            END IF;
        END IF;

        IF falling_edge(clk) THEN
            IF count(COUNTER_BITS - 1) THEN
                b_out <= NOT b_out;
            END IF;
        END IF;

    END PROCESS proc_name;
END ARCHITECTURE;

Test Bench

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY E13_button_debouncer_tb IS
END E13_button_debouncer_tb;

ARCHITECTURE sim OF E13_button_debouncer_tb IS

    CONSTANT clk_hz : INTEGER := 50_000;
    CONSTANT clk_period : TIME := 1 sec / clk_hz;
    CONSTANT T_DEB_MS : NATURAL := 25;

    SIGNAL clk : STD_LOGIC := '1';
    SIGNAL rst : STD_LOGIC := '0';
    SIGNAL b_in : STD_LOGIC := '0';
    SIGNAL b_out : STD_LOGIC := '1';

BEGIN

    clk <= NOT clk AFTER clk_period / 2;
    bu_deboun : ENTITY work.E13_button_debouncer(single_switch)
        GENERIC MAP(f_clk => clk_hz, T_DEB_MS => T_DEB_MS)
        PORT MAP(
            clk => clk,
            rst => rst,
            b_in => b_in,
            b_out => b_out
        );

    SEQUENCER_PROC : PROCESS
    BEGIN
        WAIT FOR clk_period * 1;
        rst <= '1';
        b_in <= '1';
        WAIT FOR 1 ms;
        b_in <= '0';
        WAIT FOR 1 ms;
        b_in <= '1';
        WAIT FOR 100 ms;
        b_in <= '0';
        WAIT FOR 1 ms;
        b_in <= '1';
        WAIT FOR 10 ms;
        b_in <= '0';
        WAIT FOR 10 ms;

    END PROCESS;

END ARCHITECTURE;

Simulation

Simulation

I expepct that the code work like photo below: enter image description here

Ahmad Asmndr
  • 187
  • 1
  • 7
  • You might want to add more signals to the Wave view to debug your debouncer. -- Unrelated, just to make sure: I assume you are aware that the shown diagram ("_photo_") counts just to 4, while your design counts to 2048, aren't you? – the busybee Nov 16 '22 at 07:53
  • process begin report "COUNTER_BITS = "& integer'image(COUNTER_BITS); wait; end process; The counter is 22 bits, count could be a signal instead of a variable and provide a useful clue. – user16145658 Nov 16 '22 at 08:20
  • 1
    You reset b_out with a rising clock edge, but toggle it with the falling clock edge. This is possible in simulation but not possible in real hardware. Your condition for toggling is "count(COUNTER_BITS - 1)" which has the type unsigned, but you need boolean, for example: count(COUNTER_BITS - 1)='1' – Matthias Schweikart Nov 16 '22 at 10:47
  • @thebusybee yes I am aware . – Ahmad Asmndr Nov 16 '22 at 19:11
  • @MatthiasSchweikart I don't see any reason why it shouldn't work in real hw? the condition is working fine i've test it. you don't need a boolean. – Ahmad Asmndr Nov 17 '22 at 06:31
  • There are no real flip-flops you can clock with both edges. Your `b_out` is synchronously reset with the raising edge, but toggled with the falling edge. You might want to change your design to an asynchronous reset. – the busybee Nov 17 '22 at 06:48
  • @thebusybee it is not a normal flip-flop the it is a TFF (toggle flip flop) which is constructed from a DFF. – Ahmad Asmndr Nov 17 '22 at 06:57
  • Yes, sure. But how do you _realize_ the clocking by both edges? This is OT for your issue, but it would be interesting to see a working circuit. I doubt it exists. – the busybee Nov 17 '22 at 06:59
  • @thebusybee I am not triggering the same flip-flop with both edges if you see the last diagram in my question, just the output Flip Flop is triggered by the falling edge. – Ahmad Asmndr Nov 17 '22 at 07:16
  • Your code says something else: `IF rising_edge(clk) THEN [...] b_out <= '0';` – the busybee Nov 17 '22 at 07:19
  • @thebusybee did you see the ` IF rst = '0' THEN` ? – Ahmad Asmndr Nov 17 '22 at 07:22
  • Yes, but it is **inside** the `IF rising_edge(clk) THEN`. Therefore, this is a synchronous reset, needing a circuit that changes its state on the raising edge, not on the level of `rst`. – the busybee Nov 17 '22 at 07:25
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/249687/discussion-between-ahmad-asmndr-and-the-busybee). – Ahmad Asmndr Nov 17 '22 at 07:29

1 Answers1

0

to solve the problem first to avoid errors when synthesize it need the changes to the code thanks to (@thebusybee, @user16145658,@MatthiasSchweikart):

    BEGIN
        IF rising_edge(clk) THEN
            IF rst = '0' THEN
                count := (OTHERS => '0');
                x_reg <= '0';
            ELSE
                x_reg <= b_in;
                IF b_out = x_reg THEN
                    count := (OTHERS => '0');
                ELSE
                    count := count + 1;
                END IF;
            END IF;
        END IF;

        IF falling_edge(clk) THEN
            IF rst = '0' THEN
                b_out <= '0';
            ELSE
                REPORT "we are in falling edge and the counter value : " & INTEGER'image(to_integer(count));
                IF count(COUNTER_BITS - 1) THEN
                    b_out <= NOT b_out;
                END IF;
            END IF;
        END IF;

    END PROCESS proc_name;
END ARCHITECTURE;

the problem was here:

    GENERIC (
        T_DEB_MS : NATURAL := 25;
        f_clk : NATURAL := 50_000);
    PORT (
        clk : IN STD_LOGIC;
        rst : IN STD_LOGIC;
        b_in : IN STD_LOGIC;
        b_out : OUT STD_LOGIC
    );
END E13_button_debouncer;

ARCHITECTURE single_switch OF E13_button_debouncer IS
    CONSTANT COUNTER_BITS : NATURAL := 1 + INTEGER(ceil(log2(real(T_DEB_MS * f_clk))));

which result in N=21 that mean the debounce time will be 41 Second. so to solve it i should do it like this : 0.025 * fclk = 1250 => result in N= 10 => +1 =11. then the counter will count till 2048 resulting in debounce time von 40 ms. which is ok for my application.

enter image description here

Ahmad Asmndr
  • 187
  • 1
  • 7