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
I expepct that the code work like photo below:
CodePudding user response:
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.