VHDL:Mealy状态机内的按钮去抖动

时间:2015-09-15 15:28:09

标签: vhdl fsm debouncing

您好我正在尝试使用VHDL实现mealy机器,但我需要去按钮按下按钮。我的问题是我不确定应该在哪里实施去抖动。我目前的工作是这样的:

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块之外?谢谢!

2 个答案:

答案 0 :(得分: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),其代码只包含核心状态机功能。

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

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

还有硬件去抖动,但我认为这不属于这个问题的范围。

答案 1 :(得分:0)

  

在第二个过程中,我应该像这样进行第一次处理,或者   我应该在state0阻止时把它放进去吗?

只将它放在State0块

  

另外,作为处理   debounce需要计数,我把它放在case块之外   这个?

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

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

这应该让你说明。