「チャタリング除去回路1 / 安定期間がチャタリング想定期間よりも長く続いたらレベルを確定する」のVHDL版

pp.318-320

  • 入力がHi、出力がLoの時間がチャタリング継続想定時間よりも長く続いたら出力をトグルする。
  • 入力がLo、出力がHiの時間がチャタリング継続想定時間よりも長く続いたら出力をトグルする。

チャタリング除去回路1 / 安定期間がチャタリング想定期間よりも長く続いたらレベルを確定する -で試した回路をVHDLで書き換える。

この回路をそのままVHDLで表現する。ただしカウンターはパラメタライズする。

https://cdn-ak.f.st-hatena.com/images/fotolife/t/ti-nspire/20210322/20210322102109.png

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;

entity debouncer is
    generic(
        T_DEB_MS  : natural := 25; -- バウンス継続想定ミリ秒数
        F_CLK_KHZ : natural := 1000
    );
    port(
        x, clk: in  std_logic;
        y     : out std_logic
    );
end entity;

architecture rtl of debouncer is
   -- バウンス継続想定時間は厳密である必要はないのでカウンターのモジュロは2**Nでよいが、
   -- MSBをイネーブル信号として使いたいのでカウンターのビット数を1増やす。
    constant COUNTER_BITS: natural := 1 + integer(ceil(log2(real(T_DEB_MS * F_CLK_KHZ))));
    signal x_reg: std_logic;
begin
    process(clk)
        variable count: unsigned(COUNTER_BITS-1 downto 0); -- この変数をカウンターとして使う。
    begin
        if rising_edge(clk) then
            x_reg <= x;                  -- これが波形整形のための入力レジスタ。なくても、ほとんどの場合問題ない。
            if y=x_reg then              -- スイッチが確定状態にある限り、あるいは確定状態になくてもたまたま入出力が一致した場合は、
                count := (others => '0'); -- 何度でもカウンターをリセットするが、
            else
                count := count + 1;       -- スイッチが変化したら(すなわち入出力が異なる場合は)カウントアップして、
            end if;
        end if;
        
        if falling_edge(clk) then
            if count(COUNTER_BITS-1) then -- カウンターのMSBに1が立ったら(すなわち入出力の異なる状態がバウンス継続想定時間を超えたら)、
                y <= not y;                -- 出力をトグルする。
            end if;
        end if;

    end process;
end architecture;

黄が前回同様ATmega328Pで作った擬似チャタリング波形。緑がチャタリング除去後の波形。 f:id:ti-nspire:20210422143242p:plain:w500