XilinxのCPLDをはじめよう
経験まるで無しからはじめるたLSI開発
CPLDは複雑なディジタル回路が必要な時に良く使われるデバイスです。今回はXillinxのCPLDを使えるようになるため、XC9572のテストボードを作成し、CPLDに簡単な回路を書き込んで動かしてみようと思います。
・・・とはいうものの中学の技術の授業以来、半田ごてを握っていなかったので、いきなりボードを作りはじめるわけにはいききません。そこで、参考のためにCPLDを搭載した評価ボードを購入することにしました。CPLDや電子回路について、ある程度理解し、動かせるようになれば、実機の作り方もみえてくるでしょう。自作した実機上ではテスト用にストップウオッチを実装して遊んでみました。
↓はじめてのCPLD入門セットXC-EDU ビーアイティ、¥25000、若松通商で購入。
CPLDの評価ボードに4つの入力ボタンと7セグメントLED×4の付いたサブボードのセットです。専用の簡易ダウンロードケーブルが付いてきます。入力クロックは16MHzを8段階に分周してます(最低クロックは62.5kHz)。
コレだけなのに2万5千円。若松通商の店員さんもこんなものホントに買うの?って顔をしてました。悪かったな。
XilinxサイトのCPLDのページによると、XC9572は1600ゲート相当のフラッシュメモリタイプのCPLDです。FF(フリップフロップ)が72個あります。規模としてはCPUみたいな演算回路を作るには小さいですが、タイミング調整とかクロックの分周のような簡単な論理回路には十分なサイズです。電子工作として単体で使うのなら、カウンタを使ったタイマーとかストップウオッチっといったところでしょう。
とりあえず、ボードで実験してみて、レベルアップしていこうとおもいます。
↓XC9572-PC44
XilinxのCPLDの開発環境として、XilinxからISE WebPACKが提供されています。これは、デバイスの設計、検証、フィッティング、ダウンロードまで対応した統合ツールです。開発環境としてはISE WebPACKで十分です。
ISEはXilinxの新製品に合わせて頻繁にバージョンアップします。あんまり頻繁なので、しばらく使ってないと設定の場所を忘れます。
簡単な回路を設計して、CPLDに書き込んでみます。 ANDしかない回路のRTLをVHDLで記述しました。
--test.vhd 2000.11.10 hijiri~ -- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity test is Port( ain : in std_logic; bin : in std_logic; yout : out std_logic); end test; architecture rtl of test is begin yout <= ain and bin; end rtl;
VHDLには直接ソースに入出力Pin情報を記述することができるみたいですが、あまり一般的な方法ではないようです。
Pin情報はISEWebPACKの制約ファイル(UCFファイル)に記述します。このボードのピン配置を考慮して以下のようにテキストで制約を記述します。
//UCF file created by Project Navigator #PINLOCK_BEGIN #Tue Mar 28 13:58:54 2000 NET "ain" LOC = "P11"; NET "bin" LOC = "P24"; NET "yout" LOC = "P1"; #PINLOCK_END
※RTL側のPin名は小文字でなければならないようです。
これをつかってISE WebPACKでフィッティングした後、デバイスにダウンロードします。
ダウンロードが終わると直ぐに動作が開始されます。すでに別の回路が焼きこんである場合はErase設定を忘れると書き込めないのであしからず。私はしばらくそれで悩んでいました。
ダウンロードすると左の7セグメントLEDの上が点灯し、左から1,2番目ボタンを押すと消灯されました。出力HiでLEDが消灯、Lowで点灯ですだから、AND回路がちゃんと実現されています。
今回購入した評価ボードには4つのボタンと4つの7セグメントLEDが有るので、時計やタイマーも考えましたが、一番簡単そうなストップウオッチにしました。ABELで記述されたストップウオッチのサンプルが評価ボードに付属していて動作します。これなら余程のことが無い限りVHDLででも大丈夫だろうとおもって挑戦しました。
7セグメントLEDが載った評価ボードには、たいていストップウォッチのサンプルがあります。大抵の人はこれから入門していくのでしょうね。
まず動作から考えました。
仕様: 初期状態は0000で停止する。 start/stopボタンを押すとクロック分周回路が動作しカウンタ部へクロック(clk)が供給される。 もう一度start/stopボタンを押すと停止する。 clearボタンを押すと初期状態に戻る。
クロック分周回路はCPLDボードの最低入力周波数が62.5kHZなので、625回カウントしてclkのHiとLowを切り替えています。これで1ms単位のカウントができます。肝心のストップウォッチのカウンタは10進カウンタを4つ作って、それぞれ10ms、100ms、1s、10sにあてます。10進カウンタの出力は4bitのBSD(2進化十進数)になります。これを7セグメントLED用にデコードしてI/Oから出力します。LEDはLowになれば点灯です。
スタート・ストップに同じボタンを割り当てると、押した瞬間と離す瞬間に発生するチャタリングが問題になります。チャタリングが発生すると実際押して離すまでスタートかストップか決定しません。これでは役に立たないので対策を考えます。ボードをいじるのも手ですが、高価なボードなので余りてを加えたくはありません(涙)。CPLD上でなんとかします。 ボタンを押してからしばらくは入力を受け付けないようにすればOKなので、入力を受け付けない時間を設定します。この入力を受け付けない時間の値に関しては、迷うことなくこの数値が思い浮かびました。
1秒間に16連打つまり0.0625secだ!
この数値に何の技術的な理由が無いことは明らかですが、普通の人間がこれ以上連打できるとは考えにくいので、取り合えずボタンの反応後にこの時間内のON/OFFを無視するようにしました。このような適当な設計は、大抵うまくいきませんが実際にやってみるまではわかりません。そして案の定上手く行かきませんでした。この回路では高○名人には対応できないようです。うーん。基準を変えて、私の通常の連打が1秒間に8連打(迷○組曲で計った)なので、0.125secに設定しました。すると嘘のように上手くいくじゃありませんか(笑)。ボタンのチャタリングは1msぐらいあるということなのでしょう。
この回路を連打しているときに、ふと思いました。
そうか、だからストップウォッチは壁にボタンを当ててまで連打しても、0.01秒にはならないのか。
・・・そういえば迷宮○曲って知ってる?
↓動いてます。後ろの2桁の動きが速すぎて88に見えますけど
ストップウォッチのサンプル
stopwatch110.lzh
中身: stopwatch.vhd ストップウォッチのRTL本体 decode7seg.vhd 7セグメントデコーダモジュール stopwatch.ucf ストップウォッチの制約ファイル
このソースでフィッティングした結果は以下の通り。
Macrocells Used | 68 / 72 ( 94%) |
Product Terms Used | 218 /360 ( 60%) |
Registers Used | 40 / 72 ( 55%) |
Pins Used | 31 / 34 ( 91%) |
Function Block Inputs Used | 96 /144 ( 66%) |
残りマクロセルはあと4つ。この回路で後なにができる?
もうちょっと小型化しなければ…。
VHDLだけの変更ではこれ以上の小型化は無理なんじゃないかと思っていましたが、7セグメントLEDをダイナミックコントロールする手があることを知りました。ダイナミック制御とは各LEDを順番に光らせる方法です。人間の目にとまらないスピードなら、同時に光らせた場合と同じように見えます。
前述のサンプルでは、各7セグメントLEDにデコーダをつけています。この7セグメントデコーダは単体でフィッティングした結果、マクロセルの消費量が上記のフィッティング結果の3割近く占めていました。ダイナミックコントロールにすれば、これを1/4になるはずです。あとはダイナミックコントロールの回路をできるだけ小型化できればトータルで小さくなる可能性があります。
思い立ったが吉日。さっくりとやってみました
ダイナミックコントロール版 ストップウォッチのサンプル
stopwatch120.lzh
中身: stopwatch.vhd ストップウォッチのRTL本体 decode7seg.vhd 7セグメントデコーダモジュール stopwatch.ucf ストップウォッチの制約ファイル
↓そして肝心のフィッティング結果。
Macrocells Used | 70 / 72 ( 97%) |
Product Terms Used | 258 /360 ( 71%) |
Registers Used | 42 / 72 ( 58%) |
Pins Used | 31 / 34 ( 91%) |
Function Block Inputs Used | 103/144 ( 71%) |
なんか増えてやがる。
ちなみに変更前のスタティックコントロール版の回路サイズをもう一度みると。
Macrocells Used | 68 / 72 ( 94%) |
Product Terms Used | 218 /360 ( 60%) |
Registers Used | 40 / 72 ( 55%) |
Pins Used | 31 / 34 ( 91%) |
Function Block Inputs Used | 96 /144 ( 66%) |
ダイナミックコントロール回路の大きさがが3つのデコーダより大きくなったみたいで、
変更前より大きくなってしまいました(涙)。
うがー。
マクロセルの消費はマクロセルの一部でも使われた場合に算出されます。7セグメントデコーダを単独でフィッティングして回路規模を1/3ぐらいだろうと思っていたのですが、どうやら7セグメントデコーダはマクロセルの特定の部分しか使っていないようで、実際はもっと小さかった模様。
つまり、小型化の検討が甘かったってことのようです。