質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.93%

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

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 3,213

score 6

前提・実現したいこと

Verilog HDLにて、参考書のチャタリング処理を理解すること。

理解できない問題

下記、ソースの処理が理解できない。
ご教授いただければ助かります。

module debounce (
    input       CLK,
    input       RST,
    input       BTNIN,
    output  reg BTNOUT
);

/* 125MHzを分周し40Hzを作成 */
reg [21:0] cnt22;

wire en40hz = (cnt22==22'd3125000-1);

always @( posedge CLK ) begin
    if ( RST )
        cnt22 <= 22'h0;
    else if ( en40hz )
        cnt22 <= 22'h0;
    else
        cnt22 <= cnt22 + 22'h1;
end

/* スイッチ入力をFF2個で受ける */
reg ff1, ff2;

always @( posedge CLK ) begin
    if ( RST ) begin
        ff1 <= 1'b0;
        ff2 <= 1'b0;
    end
    else if ( en40hz ) begin
        ff2 <= ff1;
        ff1 <= BTNIN;
    end
end

/* 立ち上がり検出し、FFで受ける */
wire temp = ff1 & ~ff2 & en40hz;

always @( posedge CLK ) begin
    if ( RST )
        BTNOUT <= 1'b0;
    else
        BTNOUT <= temp;
end

endmodule

該当のソースコード

私の理解は、スイッチ入力をFF2個で受けとり
スイッチの値が前値が0で、現在の値が1であるから立ち上がった値である。
そして、40Hzの間隔でCLK1上がった時のタイミングである。
それのタイミングをANDしている。とソースから推測しました。

40Hz間隔のCLK1周期で、1回分の値でスイッチが押された?ってなんでそれが正しい値なのかが
自分にはわからないです。たとえばノイズだったりとかでも誤動作しないのか?
など考えてしまい。この処理で良いのかがわからないです。

/* スイッチ入力をFF2個で受ける */
reg ff1, ff2;

always @( posedge CLK ) begin
    if ( RST ) begin
        ff1 <= 1'b0;
        ff2 <= 1'b0;
    end
    else if ( en40hz ) begin
        ff2 <= ff1;
        ff1 <= BTNIN;
    end
end

/* 立ち上がり検出し、FFで受ける */
wire temp = ff1 & ~ff2 & en40hz;

マイコンでのチャタリング処理

void *func_thread(void* args) {
    static int last=0;        //前回のスイッチの確定値
    static int sw1=0;        //今回のスイッチの読取り値
    static int sw2=0;        //前回のスイッチの読取り値
    static int sw3=0;        //前々回のスイッチの読取り値
    static int cnt=0;        //スイッチ読取りのタイミング調製用カウンタ

    printf("thread start\n");
    while(1){

        if(kill == 1) break;
        if(cnt==9){                            //10ms間隔で読み取る
            cnt = 0;
            sw3 = sw2;                        //前々回のスイッチの読取り値を保存する
            sw2 = sw1;                        //前回のスイッチの読取り値を保存する
            sw1 = get_sw();                    //今回のスイッチの読取り値を保存する
            if((sw3==sw2) && (sw2==sw1)) now = sw1;        //今回と前回と前々回のスイッチの読取り値が
                                                        //等しければ、それを現在のスイッチの確定値とする
            if(now!=last){                    
                if(now & ~last){            //前回と今回(現在)のスイッチの確定値が異なる場合
                    up |= switch_on;        //立上がり(スイッチの押下)検出
                    if(up & 0x1){
                        rew = now;
                    }
                }
                last = now;                    //今回のスイッチの確定値を(最後の値として)保存する
            }

        }else{
            cnt++;
        }
    }
    return 0;
}

三回スイッチの値を取得して、一致したら、立ち上がり処理をしています。
VerilogHDLでは、値を三回取得してから、立ち上がり処理などしなくていいのかが分からないです。

ハザード処理について

always @( posedge CLK ) begin
    if ( RST )
        BTNOUT <= 1'b0;
    else
        BTNOUT <= temp;
end


これで回避できる理由が理解できなくて、説明が欲しいです。
どうしても納得ができなくて、先に進めなく、ご教授いただけると助かります。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

チャタリングで不安定になっている時間はen40hzの間隔より十分短いので
en40hzに同期して値を取ればチャタリングの影響を除去できます。

各種タイミングでの波形(L=_, H=*)

BTNIN  _____________*_*_***__****************************************
ff1    ________________________**************************************
ff2    _________________________________________*********************
en40hz _______*________________*________________*________________*___
temp   ________________________*_____________________________________
BTNIN  _____________________*_*_**__*********************************
ff1    _________________________________________*********************
ff2    __________________________________________________________****
en40hz _______*________________*________________*________________*___
temp   _________________________________________*____________________
BTNIN  ______________________*_*_**__********************************
ff1    ________________________**************************************
ff2    _________________________________________*********************
en40hz _______*________________*________________*________________*___
temp   ________________________*_____________________________________

ハザード

ffの出力からtempへの入力までには配線遅延があって
例えば仮にff2(~ff2)の入力がen40hzより遅れるとtempにヒゲが出ます。
しかし配線遅延は1クロック内(より短い)に収まるように配線されるので
(配線されなかったとき:タイミングエラー)
FFで受ければヒゲが消えます。

CLK        /                 /
ff1     ***********************
ff2     ___********************
en40hz  ___******************__

ff1'    ***********************
ff2'    _____________**********
en40hz' ________***************
temp    ________*****__________
BTNOUT  _______________________

(/は立ち上がりエッジ)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/11 10:56

    詳細に記載していただき、ありがとうございます。
    本を色々読み漁っている段階で、理解がまだいろいろ追いついていってなく
    凄く助かりました。

    あと一つ質問してもよろしいでしょうか?
    チャタリング処理の参考書を読んでいるとメタステーブル対策をしているかと書かれていまして。
    DFFを複数段入れること不安定な値が伝搬しなくなる。

    と書いてあり、同じことなのか?理解できていません。
    同じことなのでしょうか?

    キャンセル

  • 2019/12/11 11:09 編集

    フリップフロップへの入力がちょうど読み取りのタイミングで変化してしまうと
    フリップフロップの出力が不安定になります。(0と1を行ったり来たりしてそのうちどちらかに収束する)

    質問文のハザードの話はFFで受けたあとの話ですから別の話です

    [メタステーブル参考](https://dora.bk.tsukuba.ac.jp/~takeuchi/?%E9%9B%BB%E6%B0%97%E5%9B%9E%E8%B7%AF%2FHDL%2F%E9%9D%9E%E5%90%8C%E6%9C%9F%E4%BF%A1%E5%8F%B7%E3%82%92%E6%89%B1%E3%81%86%E3%81%9F%E3%82%81%E3%81%AE%E5%8D%B1%E3%81%86%E3%81%84Verilog%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA#t82a0ca1)

    キャンセル

+1

チャタリング処理というのは、ある程度の時間をおいて定期的に状態を読み、2回(あるいはそれ以上の回数)以上の変化がない場合にその値をスイッチの状態として返す、ということを行います
#状態が変化した場合はその値を捨てて前の状態のママにする

それを頭において、動作を追いかけていきましょう

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.93%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る