【VHDL】チャタリング除去回路

機械式スイッチを使用すると必ず発生するチャタリング。トグルスイッチやプッシュスイッチとFPGAが直結の場合はFPGA内部で対処するしかありません。

チャタリングについて

チャタリング自体の説明は以下ページが分かりやすいです。
スイッチのチャタリング – マルツオンライン

FPGAでのチャタリング防止回路

FPGAで防止回路を実装する場合は、「一定期間値が安定したのを確認したら出力へ入力を反映する」という回路を実装すればOKです。

チャタリング 防止 除去 回路

ソースコード(チャタリング除去回路)

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity chattering_elimintaion is
    generic (
        -- クロック周期に合わせてカウント数を設定
        -- 今回は100MHzで除去時間を1msに設定
        eliminate_clock :   std_logic_vector (31 downto 0) := x"000186a0"
        );
    port   (
        -- sync reset/clock
        srstn_i : in    std_logic;
        clk_i   : in    std_logic;
        -- input/output
        sig_i   : in    std_logic;
        sig_o   : out   std_logic
    );
end chattering_elimintaion;

architecture rtl of chattering_elimintaion is

signal count    :   std_logic_vector (31 downto 0);
signal sig      :   std_logic;

begin

process (clk_i) begin
    if (rising_edge(clk_i)) then
        if (srstn_i = '0') then
            count   <= (others => '0');
        else
            if (sig /= sig_i) then    -- 入出力が異なる場合だけカウント
                count   <= count + 1;
            else                      -- 入出力が同じ場合はカウント停止
                count   <= (others => '0');
            end if;
        end if;
    end if;
end process;

process (clk_i) begin
    if (rising_edge(clk_i)) then
        if (srstn_i = '0') then
            sig <= sig_i;
        else
            -- 入出力が異なる時間が設定値を超えたら入力を出力へ反映
            if (count >= eliminate_clock-1) then
                sig <= sig_i;
            end if;
        end if;
    end if;
end process;

sig_o   <= sig;

end rtl;

シミュレーション

今回は「入力の変化点で100us周期のチャタリングが発生する」と想定して、1ms間同じ入力値となった場合に入力を結果へ反映します。※実際のチャタリング波形はこんなに綺麗ではないです。

  • テストベンチ
  • library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_unsigned.all;
    
    entity testbench is
    end testbench;
    
    architecture rtl of testbench is
    
    component chattering_elimintaion is
        generic (
            eliminate_clock :   std_logic_vector (31 downto 0) := x"000186a0"
            );
        port   (
            -- sync reset/clock
            srstn_i : in    std_logic;
            clk_i   : in    std_logic;
            -- input/output
            sig_i   : in    std_logic;
            sig_o   : out   std_logic
        );
    end component;
    
    signal srstn_i  :   std_logic;
    signal clk_i    :   std_logic;
    signal sig_i    :   std_logic;
    signal sig_o    :   std_logic;
    
    begin
    
    process begin
        srstn_i <= '0';
        wait for 100 ns;
        srstn_i <= '1';
        wait;
    end process;
    
    process begin
        clk_i   <= '0';
        wait for 5 ns;
        clk_i   <= '1';
        wait for 5 ns;
    end process;
    
    process begin
        sig_i  <= '0';
        wait until (srstn_i = '1');
        -- 100us周期のチャタリングが500us間発生したと想定
        for i in 0 to 4 loop
            wait for 50 us;
            sig_i  <= '0' after 1 ps;
            wait for 50 us;
            sig_i  <= '1' after 1 ps;
        end loop;
        -- その後highに安定
        wait for 2 ms;
        -- 100us周期のチャタリングが500us間発生したと想定
        for i in 0 to 4 loop
            wait for 50 us;
            sig_i  <= '1' after 1 ps;
            wait for 50 us;
            sig_i  <= '0' after 1 ps;
        end loop;
        -- その後lowに安定
        sig_i   <= '0';
        wait;
    end process;
    
    u_ce    :   chattering_elimintaion
        generic map (
            -- クロック周期に合わせてカウント数を設定
            -- 今回は100MHzで除去時間を1msに設定
            eliminate_clock => x"000186a0"  --:   std_logic_vector (31 downto 0) := x"000186a0"
            )
        port map   (
            -- sync reset/clock
            srstn_i => srstn_i,     --: in    std_logic;
            clk_i   => clk_i,       --: in    std_logic;
            -- input
            sig_i   => sig_i,       --: in    std_logic;
            sig_o   => sig_o        --: out   std_logic
        );
    
    end rtl;

  • シミュレーション結果
  • 入力値の変化点でチャタリングが生じていますが、出力では綺麗に変化しています。
    チャタリング シミュレーション

    デメリット

    入力の変化点から出力が変化するまでの間に、設定時間だけ遅延が発生します。デメリットというほどでもないかもしれませんが、仕様として明記すべき内容ではあると思います。

    シェアする

    • このエントリーをはてなブックマークに追加

    フォローする