(日々の記録)デジタルオシロを買った。順序回路の4桁十進変換が動いた(3/31/2010)FPGAの初の自作プログラムで7セグLEDのカウンターがやっと動き始めた。次のステップはUART機能の組み込みである。UARTは、これまでの雑誌にいくつかサンプルコードがある。これをコピーするだけで簡単に動くはずだ。UARTの目的は、コーディングの練習以外にもある。これを通してモニターのようなものをFPGAで動かし、デバッグツールにできないかということである。いわゆるステートマシンにしてUARTからの入力を受付け、指示された(内部変数の表示、メモリダンプ)処理を行い、次の外付けメモリ(SRAM)接続ステップのデバッグに使いたい。雑誌のソースコードを丸写ししているだけでは経験値を上げられない。いうこともあって、今動いている7セグLEDのカウンターをもう少し拡張することにした。このカウンターは、16ビットのバイナリ入力を7セグLED4桁に十進表示する機能だったが、バイナリーから10進数(BCD)への変換が思ったように動かず、ウェブで、2桁の10進表示の組み合わせ回路を見つけて、それを3桁に拡張して何とか動かした。4桁あるLEDのひとつは0の定数のままで、まだ全部動いていない。このままでは気分が悪い。この変換は最初、割り算が2の倍数でしか出来ないというのでwhileを使って引き算を繰り返すロジックにしたら、ISEが暴走するという騒ぎを起こしたいわくつきのロジックである。このときはわけもわからず組み合わせ回路にwhileを入れたが、あとから考えると恐ろしいことをしていたということがわかる。その後、沢山ある雑誌の特集記事を精読し(デジタルデザインテクノロジのHDL超入門の号はソフト屋には眼から鱗で面白い)、HDLが大分、分かり始めた。みかけはソフトウエアに見えるが、あくまでもフリップフロップやセレクターなどの論理回路を組み立てるための道具なのだ。これを常に頭に入れておかないと、さっきのようなことが起きる。それはとにかく、4桁の十進表示である。考えてみたら33Mhzものクロックが入っている。@(クロック)の構文を使えば、割り算の代わりに、引き算を繰り返せばあっという間に計算が出来るはずである。バイナリの入力が変化したのをトリガーにクロックごとに引き算をして、1位の桁が出たところで止めればよい。うむ、うまく行きそうだ。引き算構文の前にフラグを立て、このフラグを1位の桁のところで下ろせば、そのときは望みの10進デジット(BCD)が揃っている。このフラグは、別のalwaysでバイナリー値が変わるたびに上げてやればよい。一種のステートマシンだ。よし、コーディングに入る。良いぞ、組み合わせ回路よりステップ数も少ない。勇んで論理合成に入った。おやあ、エラーが沢山でてくる。drivers.というエラーだ。別の独立したループの間で共通の変数はいじれないようだ。これが出来ないならステートマシンという考え方が成り立たないはずだ。雑誌記事をさらに読み込む。うーむ、なにやら難しいことをしている。それぞれが、リクエストフラグとビジーフラグを持ち、それを見合いながら動いている。こんな割り算のような簡単なロジックにいれるには大げさすぎる。確かに、ハード回路を組む時に、一本のロジック線に別々のところからの信号を一緒にすることは出来ないはずなので理屈はわかる。マイコンプログラムでは苦もなく出来るしかけが、ここでは出来ないというのはどうも納得できない。出来ないとなると何とかしてやろうといういつもの悪い癖が出る。簡便な方法があるはずだ。2日ばかり、暇さえあれば考え、何度かコーディングまで行ったが、やっぱり、同じエラーではねられるか、LEDはカウントアップしてくれない。昨日の深夜、寝る前に入った風呂の中で、突然閃いた。2つのalwaysで変数を共有するからいけないのだ。ひとつのalwaysの中に入れてしまえばそもそも共有を考える必要がない。それに入力が変化したことは、alwaysのセンシティビティリストに入れなくても、常に前の入力を保存しておけばよい。今まで共有しようとして苦労したが、それをせずに済む方法があった。これだ、クロックの度に動くalwaysで、入力を以前、BCDを出した時にセーブした値と比較し、同じならスルー、違えば、1位の桁が出るまでループ、1位の桁がでたところでセーブした値を今出した入力値に変える。うまいぞ、できそうだ。次の日、喜び勇んでコードを作り直す。出来たコードの確認ももどかしく論理合成をかける。良かった、エラーはでない。コンフィギュレーションする。祈る気持ちで、タクトスイッチを押す。