我试图实践在FPGA的方法(完全计数的基础上),这是在书中介绍的Volnei (“电路设计与VHDL第三版”)。这个电路的一个非常重要的特点是定时器的构造方式,它不需要一个比较器(一个大的电路)。例如,对于刚才给出的数值,$S = 50,MHz * 20,ms= 10e6$结果,其中计数器中的比特数是$N= log_2(S) = 20$,这意味着一个计数器从0到$10e6 - 1$ =111 1_0100_0010_00 1 1_1 1 1 1,因此需要至少12位宽的比较器(只需要监视s),这确实是一个大电路。这可以避免,考虑到时间不需要是准确的,因此,如果计数器中包含额外的位(触发器),那么它的MSB本身就可以扮演比较器的角色;当MSB= 1发生时,它启用输出寄存器,从而更新y,从而导致clear= 1,它在下一个正时钟边缘对计数器(因此也是MSB )进行零点。总之,计数器总共跨越$S= 2^N+ 1$状态,导致$T{deb} = 2^N/f_{clk (50 Ms)}= 21 ms$,用于上面给出的数值。
但是,测试本例中给出的代码,没有给出预期的结果。
脱弹
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;试验台
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;模拟

我认为代码的工作原理如下所示:

发布于 2022-11-17 06:48:18
为了解决这个问题,在合成时首先要避免错误,它需要修改代码(@thebusybee,@ need 16145658,@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;问题就在这里:
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))));这将导致N=21,这意味着溃败时间将是41秒。因此,为了解决这个问题,我应该这样做: 0.025 * fclk = 1250 =>,N= 10 => +1 =11。然后计数器计数到2048年,从而产生40 ms的破除时间。这对我的申请来说没问题。

https://stackoverflow.com/questions/74456100
复制相似问题