Verilogでチャタリング除去を理解しよう!7つの詳細サンプルコード付き – Japanシーモア

Verilogでチャタリング除去を理解しよう!7つの詳細サンプルコード付き

Verilogチャタリング除去ガイドのイメージVerilog
この記事は約10分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

このサービスは複数のSSPによる協力の下、運営されています。

この記事では、プログラム(回路記述)の基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Verilogという言語を使って、チャタリング除去の処理をどのように実装するか学びましょう。

Verilogはハードウェア記述言語であり、電子回路の設計に使用されます。

本記事では、Verilogを使ってチャタリングを除去する方法について、理論から実践まで詳しく解説します。

また、各種の入力デバイスに適用可能な7つのサンプルコードも提供します。

●Verilogとは

Verilogは、1980年代初頭にGateway Design Automationによって開発されたハードウェア記述言語(HDL)です。

デジタル回路の設計と検証に広く使用されています。

○Verilogの基本構造

Verilogのプログラムは「モジュール」と呼ばれる部品の集合で構成されます。

それぞれのモジュールは、特定の機能を持つ電子部品(たとえばゲート、レジスタ等)を表現します。

module example(input a, input b, output y);
  assign y = a & b;
endmodule

このコードでは、入力aと入力bの論理積(AND)を計算するモジュールを定義しています。

この例では、二つの入力(aとb)と一つの出力(y)を持つモジュールが作成されています。

●チャタリング(バウンス)とは

チャタリング、またはバウンスとは、スイッチやボタン等の機械的な接触器がON/OFF切り替え時に一瞬だけ複数回の接触を繰り返す現象を指します。

デジタル回路においては、この現象が誤動作を引き起こす可能性があります。

○チャタリングが生じる原因

チャタリングは、スイッチやボタンが閉じるときや開くときに、接触面が完全に固定される前に一時的に複数回の接触・非接触を繰り返すことで発生します。

この挙動は通常、数ミリ秒から数十ミリ秒の非常に短い時間で起こります。

●Verilogでのチャタリング除去

Verilogでは、デバウンス(チャタリング除去)の処理を実装することでこの問題を解消することができます。

○サンプルコード1:基本的なチャタリング除去

簡単なデバウンスのVerilogコードを紹介します。

module debounce(
    input wire clk, reset, in,
    output wire out
);

reg [19:0] counter; // 20ビットカウンタ
reg state;          // 現在のスイッチ状態

always @(posedge clk or posedge reset) begin
    if(reset) begin
        counter <= 0;
        state <= 0;
    end else if(in != state) begin
        if(counter == 20'hFFFFF) begin
            state <= in;
            counter <= 0;
        end else begin
            counter <= counter + 1;
        end
    end else begin
        counter <= 0;
    end
end

assign out = state;

endmodule

このコードでは、20ビットのカウンタと現在のスイッチ状態を保持するレジスタを用いてチャタリング除去を実現しています。

スイッチの状態が変わったとき、カウンタはインクリメントされます。

カウンタが上限に達すると、スイッチ状態が更新され、カウンタはリセットされます。

この手法により、短時間のチャタリングは無視され、スイッチの状態が安定したときのみ状態が更新されます。

●チャタリング除去の詳細な使い方

次に、チャタリング除去処理を具体的な入力デバイスの例に適用してみましょう。

下記のサンプルコードでは、ボタン入力、スイッチ入力、ロータリーエンコーダ入力の3つの例を表します。

○サンプルコード2:チャタリング除去を応用したボタン入力

下記のコードは、チャタリング除去をボタン入力に適用した例です。

ボタンが押されると、LEDが点灯します。

module button_input(
    input wire clk, reset, button,
    output wire led
);

reg button_debounced;  // チャタリング除去後のボタン状態

debounce debounce_inst(
    .clk(clk),
    .reset(reset),
    .in(button),
    .out(button_debounced)
);

assign led = button_debounced;

endmodule

ここで、先程のdebounceモジュールを使ってボタンの状態をデバウンスしています。

ボタンが押されたとき、つまりbutton_debouncedが真となったとき、LEDが点灯します。

○サンプルコード3:チャタリング除去を応用したスイッチ入力

次に、チャタリング除去をスイッチ入力に適用した例を表します。

スイッチがオンになると、LEDが点灯します。

module switch_input(
    input wire clk, reset, switch,
    output wire led
);

reg switch_debounced;  // チャタリング除去後のスイッチ状態

debounce debounce_inst(
    .clk(clk),
    .reset(reset),
    .in(switch),
    .out(switch_debounced)
);

assign led = switch_debounced;

endmodule

ここでも、debounceモジュールを使ってスイッチの状態をデバウンスしています。

スイッチがオンのとき、つまりswitch_debouncedが真のとき、LEDが点灯します。

○サンプルコード4:チャタリング除去を応用したロータリーエンコーダ入力

ロータリーエンコーダもスイッチの一種で、回転方向と回転量をデジタル信号で出力します。

下記のコードは、チャタリング除去をロータリーエンコーダ入力に適用した例です。

module rotary_encoder_input(
    input wire clk, reset, encoder_a, encoder_b,
    output wire cw, ccw
);

reg encoder_a_debounced, encoder_b_debounced;  // チャタリング除去後のエンコーダ信号

debounce debounce_inst_a(
    .clk(clk),
    .reset(reset),
    .in(encoder_a),
    .out(encoder_a_debounced)
);

debounce debounce_inst_b(
    .clk(clk),
    .reset(reset),
    .in(encoder_b),
    .out(encoder_b_debounced)
);

always @(posedge clk) begin
    if(encoder_a_debounced && !encoder_b_debounced) begin
        cw <= 1;
        ccw <= 0;
    end else if(!encoder_a_debounced && encoder_b_debounced) begin
        cw <= 0;
        ccw <= 1;
    end
end

endmodule

このコードでは、ロータリーエンコーダからの2つの信号(encoder_aencoder_b)をそれぞれデバウンスしています。

エンコーダの回転方向は、これらのデバウンス後の信号から決定します。

時計回り(cw)と反時計回り(ccw)のどちらの方向で回転しているかが出力されます。

●応用例とサンプルコード

チャタリング除去は、さまざまなデバイスと組み合わせて使用することができます。

カウンタ、フリップフロップ、FPGAといったデバイスにチャタリング除去を適用した例を紹介します。

○サンプルコード5:カウンタにチャタリング除去を適用

下記のコードは、チャタリング除去をカウンタに適用した例です。

ボタンが押されると、カウンタがインクリメントされます。

module counter_input(
    input wire clk, reset, button,
    output wire [7:0] count
);

reg button_debounced;  // チャタリング除去後のボタン状態
reg [7:0] count_reg;  // 8ビットカウンタ

debounce debounce_inst(
    .clk(clk),
    .reset(reset),
    .in(button),
    .out(button_debounced)
);

always @(posedge clk) begin
    if(button_debounced) begin
        count_reg <= count_reg + 1;
    end
end

assign count = count_reg;

endmodule

このコードでは、ボタンが押されたとき(button_debouncedが真のとき)、8ビットのカウンタ(count_reg)がインクリメントされます。

○サンプルコード6:フリップフロップにチャタリング除去を適用

次に、チャタリング除去をフリップフロップに適用した例を紹介します。

ボタンが押されると、フリップフロップの状態がトグルします。

module flipflop_input(
    input wire clk, reset, button,
    output wire q
);

reg button_debounced;  // チャタリング除去後のボタン状態
reg q_reg;             // フリップフロップの状態

debounce debounce_inst(
    .clk(clk),
    .reset(reset),
    .in(button),
    .out(button_debounced)
);

always @(posedge clk) begin
    if(button_debounced) begin
        q_reg <= ~q_reg;
    end
end

assign q = q_reg;

endmodule

このコードでは、ボタンが押されたとき(button_debouncedが真のとき)、フリップフロップの状態(q_reg)がトグルします。

○サンプルコード7:FPGAにチャタリング除去を適用

最後に、チャタリング除去をFPGAに適用した例を紹介します。

ボタンが押されると、FPGA上のLEDが点灯します。

module fpga_input(
    input wire clk, reset, button,
    output wire led
);

reg button_debounced;  // チャタリング除去後のボタン状態

debounce debounce_inst(
    .clk(clk),
    .reset(reset),
    .in(button),
    .out(button_debounced)
);

assign led = button_debounced;

endmodule

このコードでは、ボタンが押されたとき(button_debouncedが真のとき)、FPGA上のLEDが点灯します。

●注意点と対処法

チャタリング除去にはいくつか注意点があります。

デバウンス処理は遅延を引き起こす可能性があり、特に高速な信号で問題となる可能性があります。

また、デバウンス処理が不適切な場合、誤った信号が生成される可能性もあります。

これらの問題を避けるためには、適切なデバウンス時間を設定し、回路の性能を確認することが重要です。

また、Verilogでは、モジュール間の信号伝播に遅延が生じる可能性があるため、デバウンス処理による遅延を適切に管理する必要があります。

まとめ

本記事では、Verilogでのチャタリング除去について、基本から応用までを詳細に解説しました。

初心者でも理解しやすいように、7つの詳細なサンプルコードを紹介しました。

理論と実践を通じて、Verilogでのチャタリング除去に必要な全知識を手に入れたことでしょう。

これからのプロジェクトにぜひ活用してみてください。