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

VHDL:Mealy状态机中的按钮去抖动,vhdl,fsm,debouncing,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;

嗨,我正在尝试使用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;
过程(clk)
开始
如果(clk'事件和clk='1'),则
如果rst='1',则

curr_state我将使用一个完全独立的代码块来消除任何按钮信号的影响,允许您的状态机进程只关注状态机,而不必担心其他任何事情

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

第一种方法的优点是它将拒绝输入中的小故障。在任何一种情况下,您都可以在状态机中使用“取消公告”按钮(或者您想叫它什么,也许是“代码>rst”
),其代码只包含核心状态机功能

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

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

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

在第二个过程中,我应该这样放置rst处理,还是 当state0阻塞时我应该把它放进去吗

只把它放在State0块中

另外,由于 debounce需要计数,我会把它放在箱子外面吗 这个

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

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


这应该让你明白。

不确定所有合成器都能正确处理你的第一个过程。我建议将
按钮状态
转换为一个信号,并将最后一个信号分配移到流程之外。谢谢@RenaudPacalet,我想我已经编辑了答案,因为你写了这个,如果不让我知道的话。
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;
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;