0

嗨,我正在尝试使用 VHDL 实现一台机器,但我需要消除按钮按下的抖动。我的问题是我不确定应该在哪里实现去抖动。我现在的工作是这样的:

process(clk)
begin
    if(clk' event and clk = '1') then
        if rst = '1' then
            curr_state <= state0;
        else
            curr_state <= next_state;
        end if;
    end if;
end process;

process(curr_state, op1,op0,rst)  --here op1,op0 and rst are all physical buttons and I need to debounce op1 and op0
begin
    if rst = '1' then
        ...some implementation
    else
        ...implement the debounce logic first
        ...process some input
        case curr_state is
            when state0=>...implementation
            ...similar stuff
        end case; 
end process;

我不确定我是否以正确的方式做事。在第二个过程中,我应该像这样放置第一个处理,还是应该在 state0 阻塞时将它放在里面?另外,由于去抖动的处理需要计数,我是否像这样把它放在 case 块之外?谢谢!

4

2 回答 2

2

我会使用一个完全独立的代码块来消除任何按钮信号的抖动,让您的状态机进程只关注状态机,而不必担心其他任何事情。

您可以使用这样的过程来消除输入的抖动。您当然可以在此示例中为信号交换变量(使用相关的赋值运算符替换)。

process (clk)
  constant DEBOUNCE_CLK_PERIODS : integer := 256;  -- Or whatever provides enough debouncing
  variable next_button_state : std_logic := '0';  -- Or whatever your 'unpressed' state is
  variable debounce_count : integer range 0 to DEBOUNCE_CLK_PERIODS-1 := 0;
begin
  if (rising_edge(clk)) then
    if (bouncy_button_in /= next_button_state) then
      next_button_state := bouncy_button_in;
      debounce_count := 0;
    else
      if (debounce_count /= DEBOUNCE_CLK_PERIODS-1) then
        debounce_count := debounce_count + 1;
      else
        debounced_button_out <= next_button_state;
      end if;
    end if;
  end if;
end process;

另一种选择bouncy_button_in是以慢速采样:

process (clk)
  constant DEBOUNCE_CLK_DIVIDER : integer := 256;
  variable debounce_count : integer range 0 to DEBOUNCE_CLK_DIVIDER-1 := 0;
begin
  if (rising_edge(clk)) then
    if (debounce_count /= DEBOUNCE_CLK_DIVIDER-1) then
      debounce_count := debounce_count + 1;
    else
      debounce_count := 0;
      debounced_button_out <= bouncy_button_in;
    end if;
  end if;
end process;

第一种方法的优点是它会拒绝输入中的毛刺。在任何一种情况下,您都可以在状态机中使用debounced_button_out(或者任何您想调用的名称,也许是rst),然后其代码仅包含核心状态机功能。

如果您想要更多的去抖动,您可以使用另一个计数器为上述过程创建一个启用信号,以有效地分频时钟速率。这可能比将除法常数设置为一个非常高的数字要好,因为如果计数器超出特定大小,您可能无法满足计时要求。

你甚至可以在一个单独的文件中创建一个去抖动实体,它可以为每个按钮实例化。在上述过程中,它可以具有常量的泛型。

还有硬件去抖动,但我想这超出了这个问题的范围。

于 2015-09-15T16:06:22.543 回答
0

在第二个过程中,我应该像这样放置第一个处理,还是应该在 state0 阻塞时将它放在里面?

只把它放在 State0 块中

另外,由于去抖动的处理需要计数,我是否像这样把它放在 case 块之外?

计数需要在时钟过程中完成。由于您正在执行两个进程状态机,因此您不能在 case 块中执行此操作。无论如何,我通常将这些资源放在一个单独的时钟进程中。

对于状态,您需要:IS_0、TO_1、IS_1、TO_0。
TO_1 和 TO_0 是您的过渡状态。当我看到 1 持续 16 毫秒时,我从 TO_1 转换到 IS_1。当我看到 0 持续 16 毫秒时,我从 TO_0 转换到 IS_0。当您处于 TO_1 或 TO_0 状态时运行您的计数器。当您处于 IS_1 或 IS_0 状态时清除您的计数器。

这应该让你说明。

于 2015-09-15T16:09:36.300 回答