[英]Boucing effect vhdl in a fpga
我正在实习,我的公司希望我为 fpga 学习 vhdl。 我正在使用 lattice diamond 来编码和编译我的项目并使用 questasim 进行模拟。 我还有一个用于训练的小板:Lattice 的 MachXO3LF。
我做了一个项目:当我按下一个按钮时,一个 LED 灯亮了 2 秒然后变暗。 (在模拟中工作,但由于弹跳效果而使用卡片。
我的导师给了我一个新项目:编写代码和测试台以避免弹跳效应,当我按下按钮时,LED 点亮 2 秒,当我再次按下按钮时,10 秒内没有任何动作。
我不知道如何用我的起始代码避免弹跳效果....弹跳效果是错误触发或多次触发的结果,例如多次按下按钮
这是我的代码
use ieee.std_logic_1164.ALL;
use ieee.numeric_std.ALL;
entity bouton_led_debounce is
Port (btn : in std_logic;
reset : in std_logic;
clock : in std_logic;
led : out std_logic
);
end bouton_led_debounce;
architecture Behavioral of bouton_led_debounce is
signal m1 : std_logic := '1';
signal m2 : std_logic:= '1';
signal int : std_logic:= '1';
signal buffer_led : std_logic := '1';
signal cptr : std_logic_vector (27 downto 0) := (others => '0');
begin
process(clock,reset)
begin
if(reset = '0') then
buffer_led <= '1';
m1 <= '1';
m2 <= '1';
int <= '1';
cptr <= (others => '0');
elsif rising_edge(clock) then
buffer_led <= '1';
m1 <= btn;
m2 <= m1;
int <= m2;
if( (int = '1') and (m2 = '0') ) then
cptr <= (others => '0');
cptr(0) <= '1';
buffer_led <= '0';
end if;
if( unsigned(cptr) /= 0) then
cptr <= std_logic_vector(unsigned(cptr)+1);
buffer_led <= '0';
end if;
if( unsigned (cptr) = (24000000-1) )then
cptr <= (others => '0');
end if;
end if;
end process;
led <= buffer_led;
end Behavioral;
还有我的测试台:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity bouton_led_debounce_tb is
end bouton_led_debounce_tb;
architecture Behavioral of bouton_led_debounce_tb is
component bouton_led_debounce is
port( btn : in STD_LOGIC;
reset : in STD_LOGIC;
clock : in STD_LOGIC;
led : out STD_LOGIC);
end component;
signal btn : STD_LOGIC := '1' ;
signal led : STD_LOGIC;
signal reset : STD_LOGIC := '1';
signal clock : STD_LOGIC := '0';
begin
uut: bouton_led_debounce
port map(
btn => btn,
led => led,
clock => clock,
reset => reset);
btn_sti : process
begin
btn <= '1';
wait for 500 ns;
btn <= '0';
wait for 50 ns;
btn <= '1';
wait for 30 ns;
btn <= '0';
wait for 50 ns;
btn <= '1';
wait for 30 ns;
btn <= '0';
wait for 30 ns;
btn <= '1';
wait;
end process btn_sti;
rst_sti : process
begin
reset <= '1';
wait for 1 us;
reset <= '0';
wait for 1 us;
reset <= '1';
wait;
end process rst_sti;
clock_sti : process
begin
clock <= '0';
wait for 83.33 ns;
clock <= '1';
wait for 83.33 ns;
end process clock_sti;
end Behavioral;
对您的设计的一些评论
buffer_led <= '1';
我假设你的 LED 是低电平有效驱动的? 尽管如此,对于曾经阅读过您的代码的人来说,这可能并不明显,应该进行相应的处理。 在你的情况下,因为你从来没有读过buffer_led
我会用这个信号作为逻辑信号的表示并做
led <= not(buffer_led);
反而。
我在您的剪辑中没有看到任何按钮反弹。 你做什么
m1 <= btn;
m2 <= m1;
int <= m2;
输入同步完全没问题,但与去抖动无关。 正如评论中提到的,去抖有不同的 forms,一个相当简单的方法是降低按钮的采样率。 例如,创建一个频率为 1kHz 的启用脉冲并仅在启用时检查,您可以在您的过程中执行此操作。
if clken_1kHz then
m1 <= btn;
m2 <= m1;
if m1 = '1' and m2 = '1' then
int <= '1';
else
int <= '0';
end if;
end if;
使用上面的代码片段,如果相隔 1ms 的样本m1
和m2
都评估为 1 ,则int
信号只会变为1
。 当然,这远非完美,还有更复杂的去抖动变体,但它肯定会改善你的情况。 您还可以调整采样率,将 1kHz 降低到例如 10Hz 以获得更多去抖动。
此外,使用最有意义的信号类型,大量转换没有附加价值,如果你有一个计数器,直接使用unsigned
而不是来回转换。 使用如上定义的int
信号,您的代码的 rest 将类似于
if int = '1' and cptr(cptr'left) = '0' then
led_buffer <= '1';
cptr <= cptr-1;
else
led_buffer <= '0';
if int = '0' then
cptr <= to_unsigned(24000000-1, cptr'length);
end if;
end if;
通过向下计数而不是向上计数,我们可以简单地检查下溢,注意我们需要一个带有一个额外位的计数器,但比较也只是 1 位而不是全尺寸。 因此,只要按下按钮并且计数器没有下溢,就会设置led_buffer
,一旦释放按钮或计数器已经过去,我们关闭 LED,如果按钮也已释放,我们可以安全地重置柜台。
免责声明:没有测试过,只是头脑编译
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.