【问题标题】:VHDL - Debounce Button PressVHDL - 去抖按钮按下
【发布时间】:2014-03-11 17:35:22
【问题描述】:

我的代码中有以下按钮按下逻辑。我尝试过使用等待延迟对其进行去抖动,但编译器不允许这样做。我的 FPGA 上有四个按钮,下面的“键”数组反映了这些按钮:

process(clock)
        begin
            if rising_edge(clock) then
                if(key(3)/='1' or key(2)/='1' or key(1)/='1' or key(0)/='1') then --MY ATTEMPT AT DEBOUNCING
                    wait for 200 ns; ----MY ATTEMPT AT DEBOUNCING
                    if (key(3)='1' and key(2)='1' and key(1)='0' and last_key_state="1111" and key(0)='1') then
                        ...
                    elsif (key(3)='1' and key(2)='1' and key(1)='1' and key(0)='0' and last_key_state="1111") then  
                        ...
                    elsif (key(3)='0' and key(2)='1' and key(1)='1' and key(0)='1' and last_key_state="1111") then
                        ...
                    elsif (key(3)='1' and key(2)='0' and key(1)='1' and key(0)='1' and last_key_state="1111") then
                        ...
                    end if;
                    last_key_state<=key;
                end if;
            end if;
    end process;

谁能提供一些非常简单的示例代码,说明如何像上面的设置那样去抖动?

【问题讨论】:

    标签: switch-statement vhdl fpga


    【解决方案1】:

    好吧,如果您考虑如何使用真正的电子设备来做到这一点,您可能会使用电容器......它有充电时间。同样的想法也适用于此,只需计算出您的开关弹跳的时间(通常是时钟速度的函数),然后实际设置寄存器。

    Simple Example With a 4-Bit Shift Register

    所以你可以把它放在你的开关和任何其他逻辑块之间

    process 
      begin
       if rising_edge(clock) then --You're clock
    
         SHIFT_PB(2 Downto 0) <= SHIFT_PB(3 Downto 1); --Shifting each cycle
         SHIFT_PB(3) <= NOT PB; --PB is the pre-bounced signal
    
         If SHIFT_PB(3 Downto 0)="0000" THEN --once the bounce has settled set the debounced value
          PB_DEBOUNCED <= '1'; 
         ELSE 
          PB_DEBOUNCED <= '0'; 
       End if;
    end process;
    

    它基本上将你的信号延迟了 4 个时钟周期(你试图用等待做什么)。

    【讨论】:

    • 我对 VHDL 有点陌生,所以我不完全理解您提供的代码。什么是“clock_100Hz'EVENT”?另外,我将如何调整该代码以适应 50 MHz 时钟?
    • 这只是时钟上升和时钟下降的不同语法。使用您的电路,如果您更喜欢,可以只使用上升沿语法,我会更新答案。
    • 谢谢。几个问题:预反弹信号是指在时钟沿上升时最初采样的按钮信号吗?另外,您认为在我的情况下将“PB_DEBOUNCED”设为变量而不是信号更有意义吗?这样,我可以执行类似“if(PB_DEBOUNCED='1') then ...执行我的其余代码... end if;”之类的操作紧接在您刚刚发布的代码之后。
    • PB 是预反弹信号,是的。您可以这样做,但您也可以轻松地检查信号的逻辑电平。
    【解决方案2】:

    其他人已经用计数器展示了方法......您还需要在将信号馈送到计数器之前将信号与时钟同步,否则偶尔,信号会在不同的时间到达计数器的不同部分,并且计数器会计算错误。

    这是否重要取决于应用程序 - 如果正确操作很重要,那么正确同步很重要!

    【讨论】:

      【解决方案3】:

      您因为等待而收到错误...等待不可合成。

      我会用一个简单的计数器来做。因此,您可以通过调整计数器将相同的代码用于不同的时钟速度。

      -- adjust the counter to you special needs
      -- depending on how good your buttons are hardware debounced
      -- you can easily think in ms
      signal counter : std_logic_vector(7 DOWNTO 0) := "10000000";
      
      process 
        begin
          if rising_edge(clock) then --You're clock
            if(key(3) = '0') or (key(2) = '0') or (key(1) = '0') or (key(0) = '0') then
              start_debouncing <= '1';
              key_vector_out <= key(3) & key(2) & key(1) & key(0); 
            end if;
      
            if(start_debouncing = '1') then
              key_vector_out <= "0000";
              counter <= std_logic_vector(unsigned(counter) - 1);                        
            end if;
      
            if(counter = "00000000") then
              counter <= "10000000";
              start_debouncing <= '0';
            end if;
      end process;
      

      您的代码可能会产生另一个问题。 如果释放按钮会发生什么,因此您的输入是 .. key = "0000" .. 对,您永远不会得到输出。也许它会在 100 次中有 99 次有效,但您可能会遇到非常难以发现的错误。

      【讨论】:

      • 我认为你的意思是“等待时间”是不可综合的。 wait for rising_edge(clk) 例如
      • 你能解释一下“如果你的按钮被释放所以你的输入是.. key = "0000" ..”会发生什么?我的按钮设置为值 0 表示已按下,1 表示未按下。
      • last_key_state 分配在你的 if(key(3)... then 甚至你的 wait for xxxns 可能会发生分配无法完成的情况,因为 if 语句是错误的
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-11
      • 2014-10-09
      相关资源
      最近更新 更多