デバウンスとは何か
デバウンス(debounce)とは、スイッチ入力などの物理的信号に含まれる微小な振動やノイズを取り除き、安定した信号だけを取り扱うための処理である。機械式スイッチを押した瞬間、接点が一度で切り替わらず、数十マイクロ秒から数ミリ秒の間に複数回ON/OFFを繰り返す現象をチャタリング(chattering)という。これをそのままデジタル回路で扱うと、一度の押下を複数回のイベントとして誤検出してしまう。
デバウンスはこのチャタリング期間を吸収し、一定時間信号が安定してから押下・離上を確定させることで誤動作を防ぐ技術である。
FPGAにおけるデバウンスの必要性
FPGA(Field Programmable Gate Array)はクロック同期で動作するハードウェアであるため、スイッチ入力もクロックに同期して取り込む必要がある。ところが、外部入力は非同期信号であり、タイミングの不一致によってメタステーブル状態が発生する可能性がある。さらに、物理スイッチのチャタリングが重なると、論理的に不安定な状態が生じる。
そのため、FPGAではまずフリップフロップを数段重ねて同期化し、次にカウンタを用いて一定期間信号が変化しないことを確認してから確定させる、という二段構えの処理が一般的である。これによって、チャタリング除去とメタステ対策の両方を実現できる。
デバウンス処理の実装例
以下に、Verilogでの代表的なデバウンス実装例を示す。入力信号 btn_i は機械スイッチに接続されており、50 MHz のクロックを基準に 1 ms のデバウンス時間を設けている。
module debounce (
input wire clk,
input wire rstn,
input wire btn_i,
output wire btn_o
);
reg [2:0] sync;
reg [15:0] counter;
reg stable;
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
sync <= 3'b000;
counter <= 16'd0;
stable <= 1'b0;
end else begin
sync <= {sync[1:0], btn_i}; // 非同期入力を同期化
if (sync[2] == stable)
counter <= 16'd0; // 安定していればカウンタリセット
else if (counter == 16'd49999)
stable <= sync[2]; // 1ms経過後に状態確定
else
counter <= counter + 1;
end
end
assign btn_o = stable;
endmodule
この実装では、入力信号を3段フリップフロップで同期化し、チャタリング期間中は出力を更新しない。カウンタが閾値に達した時点で信号が安定していると判断し、最終出力を更新する。クロック周波数とカウンタ値の積がデバウンス時間を決定するため、動作環境に応じて柔軟に調整できる。
FPGA設計における設計上の考慮点
デバウンスの時間設定は、システムのクロック周波数と入力デバイスの特性に依存する。スイッチのチャタリングは数百マイクロ秒から数ミリ秒程度で収束することが多いため、一般的には0.5〜5 ms程度が妥当な設定である。クロックが125 MHzで62500クロックのデバウンスを設ける場合、約0.5 msの安定時間を確保できる。
また、複数のスイッチ入力を扱う場合は、各入力に独立したデバウンス回路を設けるのが望ましい。共通カウンタを用いた実装も可能だが、スイッチごとの入力タイミングが異なると干渉が生じるため、シンプルに独立設計する方が保守性が高い。
デジタル回路以外でのデバウンス手法
アナログ回路でのデバウンスも古くから利用されている。RCフィルタとシュミットトリガを組み合わせた手法では、コンデンサの充放電特性によって短いスパイクを除去できる。ソフトウェア的にも、マイコン側で入力変化後一定時間入力を無視する方式が使われるが、FPGAのようにリアルタイム性が求められる環境ではハードウェア実装がより適している。
まとめ
デバウンスは一見単純な機能であるが、入力安定化という観点で非常に重要な要素である。特にFPGAのような高速デジタルシステムでは、入力の同期化と安定化が設計品質を大きく左右する。実際のシステム設計では、入力デバイスの特性を考慮しつつ、適切なデバウンス時間を設定することが求められる。FPGAの強みはこのような低レベルの処理を確実かつ並列に行える点にあり、デバウンスはその基本動作を理解するための最良の題材でもある。