uchanのアイコン画像
uchan 2021年09月18日作成 (2021年09月27日更新)
セットアップや使用方法 セットアップや使用方法 閲覧数 4915
uchan 2021年09月18日作成 (2021年09月27日更新) セットアップや使用方法 セットアップや使用方法 閲覧数 4915

FPGAでスイッチ入力を受けるときにregを使うと安定する

FPGA でスイッチ入力を受け取るときに、そのまま受け取るのではなく、reg を経由すると安定することを実験で確かめました。

スイッチ接続回路

今回使った FPGA ボードは Tang Nano で、スイッチは次の回路によって FPGA に接続されています。

Tang Nano のスイッチ接続回路

上記の回路図は Tang Nano の回路図 から抜粋しました。チャタリングを緩和するために 0.1μF のコンデンサと 10kΩ の抵抗が接続されています。

動作の様子

Tang Nano には赤・青・緑の 3 色フルカラー LED が搭載されていて、各色の ON/OFF を切り替えることで 2^3 = 8 通りの色を作り出せます。今回作った実験プログラムは、スイッチを 1 回押す毎に、LED の点灯状態が「緑→青緑→青→赤→赤緑→赤青→白→消灯」と切り替わることを意図しています。

reg 無し版の動作

ここに動画が表示されます

reg を使わない場合、スイッチ B を 8 回クリックしても点灯状態が 1 巡しません。1 巡しないというか、1 回のクリックが複数回のクリックに誤認識されているように見えます。そして、押したときだけ反応して欲しいのに、離したときも反応していますね。とても不安定です。

reg 有り版の動作

ここに動画が表示されます

reg を経由してスイッチ信号を扱うようにした場合、意図通り 8 回のクリックで 1 巡するようになりました。かなり安定しています。

実験プログラム

実験に用いた Verilog プログラムを紹介します。まずは reg を使わないバージョンです。

module Counter(
  input sys_clk,
  input rst_n_async,
  input swb_n_async,
  output [2:0] led_n
);

reg [2:0] led;
assign led_n = ~led;

always @(negedge swb_n_async or negedge rst_n_async) begin
  if (!rst_n_async)
    led <= 3'd0;
  else
    led <= led + 3'd1;
end

endmodule

swb_n_async はスイッチ入力を受け取る信号名です。回路図の IOB3B に繋がっています。_n は信号が論理反転していることを、_async はスイッチが非同期入力であることを表します。ちなみに rst_n_asyncも同様のスイッチ入力で、こちらは回路のリセット信号として使っています。

led はフルカラー LED です。led[0] が緑、led[1] が青、led[2] が赤に接続されています。negedge swb_n_async のときに LED の点灯状態を切り替えるようにしているので、スイッチを押したときには切り替わり、離したときは何も起きないで欲しいです。しかし、現実はそうはなりませんでした。

次に reg を使うバージョンを示します。

module Counter(
  input sys_clk,
  input rst_n_async,
  input swb_n_async,
  output [2:0] led_n
);

reg rst_n;
reg swb_n;

always @(posedge sys_clk) begin
  rst_n <= rst_n_async;
  swb_n <= swb_n_async;
end

reg [2:0] led;
assign led_n = ~led;

always @(negedge swb_n or negedge rst_n) begin
  if (!rst_n)
    led <= 3'd0;
  else
    led <= led + 3'd1;
end

endmodule

非同期入力である swb_n_asyncを、クロックの立ち上がりで swb_n に書き込み、以降の部分では swb_n を使うようにしました。その他は reg 無し版と同じです。

生成される回路

reg 無し版と reg 有り版のプログラムを論理合成して生成される回路を示します。

reg 無し版の回路

reg 無し版では、スイッチ入力が NOT ゲートを通しただけで直接利用されていることが分かります。

reg 有り版の回路

reg 有り版では、スイッチ入力の後ろに D-FF が生成されました。

メタステーブル

FPGA に詳しいわけではないのですが、これはおそらく「メタステーブル」という状態が発生しているのだと思います。非同期信号を同期回路で扱う場合に発生しがちな状態だそうです。

メタステーブルは reg を挿入することで緩和できるそうで、今回のスイッチ入力もバッチリ改善しました。ただ、挿入する reg が 1 つで足りる保証は無いようで、場合によっては 2 個、3 個と挿入する必要があるとのことです。今回は 1 個で十分でしたが、不安定なら reg を増やしてみたら如何でしょうか?

Tang Nano の開発元が提供するサンプルプログラム ではスイッチ入力をそのまま利用しているのですが、これはリセット信号だからなんとかなっているものの、一般のスイッチ入力では通用しないことが分かりました。

チャタリング

2021/09/26 追記

メタステーブルではなく単なるチャタリングではないか、という指摘をいただきました。その可能性も気になっていたところではありましたので、実際に波形を見てみました。見てびっくり、とても汚い波形だったのでここで紹介します。

先に紹介したスイッチの回路の IOB3B 端子の電圧を観測したところ、次の波形を得ました。

スイッチを押したときの電圧変化

スイッチを押すと電圧が下がる回路ですので、トリガは立ち下がりエッジを検出する設定とし、左から 3 メモリの位置(0.3μs)に置きました。縦軸は 1 メモリ 1V、GND レベルは下から 2 メモリの設定です。ボタンを押していないときは 3.3V であることが分かります。

ボタンを押すと 3.3V から 1.2V 程度まで一気に下降した後、1.8V 付近まで揺り戻しがあり、そこから細かい上下を繰り返しながら 0.1μs ほどで GND レベルに落ちています。GND に落ちた後もそこで止まらず、ゆらゆらと電圧が変動しています。完全に落ち着くのに 1μs 程度かかるようです。

当初、私は次のような波形になると予想していたので、実測波形は予想外の形でした。

予想していたスイッチ信号

先に示した実測波形は、何度かボタンを押して波形を観測した中でもよく出てくる形です。次に示すのは、数割ほどの頻度で見られた特徴的な波形たちです。

目立った実測波形その1

目立った実測波形その2

スイッチの立ち下がりエッジで反応するようにプログラムしたため、上記の波形では複数回のスイッチ入力として処理されるのも納得です。

このままでもチャタリングの証拠が十分に掴めたわけですが、ついでにもっと細かく波形を見てみることにします。先ほどより 10 倍の分解能(横軸を 1 メモリ 10ns)で観測してみた結果をいくつか示します。

詳細な実測波形その1

「詳細な実測波形その1」は多く見られた波形です。次に、数割ほどの頻度で発生した目立った波形を示します。

詳細な実測波形その2

FPGA 視点では高速に何度もスイッチが押されたのと区別ができませんよね。

詳細な実測波形その3

この波形なんて、瞬間の電圧が 6V を超えていて、チャタリングどころか、FPGA に損傷を与えないかどうかの点でひやひやしてきました。

以上、チャタリングの簡単な検証でした。

手元にあったタクトスイッチで詳細な検証をしたので、興味があればこちらもどうぞ タクトスイッチのチャタリングを検証

4
uchanのアイコン画像
本業はプログラマですが、昔から電子工作は趣味でやってます。初めてのプログラミング言語はPICアセンブラです。 モジュールを買ってきて組み合わせるだけでなく、部品の動作原理をきちんと理解して回路を設計することに楽しさを感じます。 2021年より「uchanの電子工作ラボ」という施設を運営しています。はんだごてや測定器が使えます。 https://uchan.net/lab/ 2021年3月22日に「ゼロからのOS自作入門」を出版しました。Amazon→ https://amzn.to/2NP3FUj
  • uchan さんが 2021/09/18 に 編集 をしました。 (メッセージ: 初版)
  • uchan さんが 2021/09/18 に 編集 をしました。 (メッセージ: タグを追加)
  • Opening
    AoiSayaのアイコン画像 AoiSaya 2021/09/19

    FPGAを使う全員に知っておいてほしいトピック。
    自分は会社で習ったのでこういうところに投稿した方がいいことに気づけませんでした。こういう記事が増えるといいですね。
    ご参考までに、regですが、一般的には2個以上入れます。クロック周波数が高い場合は3個以上入れることもあります。regの間には極力回路は入れません。
    こちらの記事を参考になさってください。
    https://www.macnica.co.jp/business/semiconductor/articles/intel/2130/

    0 件の返信が折りたたまれています
  • uchan さんが 2021/09/19 に 編集 をしました。 (メッセージ: 論理合成結果の回路図を追加)
  • Opening
    ozwkのアイコン画像 ozwk 2021/09/21

    メタステーブルではなく、単なるチャタリングかと思います。

    0 件の返信が折りたたまれています
  • uchan さんが 2021/09/26 に 編集 をしました。 (メッセージ: チャタリングの検証を追加)
  • uchan さんが 2021/09/26 に 編集 をしました。 (メッセージ: タグを追加)
  • Opening
    idt12312のアイコン画像 idt12312 2021/09/26

    IOB3B 端子の電圧を数ms~数十msの時間幅でオシロで測定するとチャタリング波形が見えるかもしれないです。チャタリングは機械的な振動なので、ms以上のオーダーでの振動になりそうです。
    オシロで1目盛り10nsで測定したときの振動は0.1nFと配線のインダクタ成分で共振している波形じゃないかと思いました。それにしても、瞬間的にFPGAを壊しそうなくらいの電圧がでていることがあることには驚きました。

    0 件の返信が折りたたまれています
  • uchan さんが 2021/09/27 に 編集 をしました。 (メッセージ: チャタリング検証記事へのリンクを追加)
ログインしてコメントを投稿する