繁体   English   中英

fpga 中的弹跳效果 vhdl

[英]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 的样本m1m2都评估为 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM