ここ2日間、Verilogでのプログラムの仕方でずーっと迷ってた。
というのも、今はA/D変換用の回路を書いているのだが、例えばあるレジスタにA/D変換スタート・ストップ・ビットを作っておいて、それを1に書き込んだらA/D変換を開始する、というようにしているのだが、問題はそれのクリアだ。
(・Θ・)としては、A/D変換が終了したら勝手にレジスタのスタート・ストップ・ビットは0になって欲しいんだが、それが難しい。
どう考えてもVerilogのalways文ではできない。
というのも、always文の中でレジスタに代入した場合、別のalwaysで同じレジスタに値を代入することもできず、A/D変換終了をキャッチするた めに、同じalways文の中に、CPUからのWrite_n信号とAD_convert_endをセンシティビティ・リストに入れたとしても、どちらか の優先順位を上げておかねばならず、タイミングによってはどちらかの信号の立ち上がりエッジを無視する可能性がある。
何とかできないものかと2日間考えまくった結論としては、できない。
回路レベルで考えてみても、優先順位の高い方がフリップフロップのCLEAR, PRESETに割り当てられ、低い方がCLOCKに割り当てられることになる。実際Verilogにより合成された回路はそうなっていた。つまり、 CLOCK側はタイミングによっては無視される可能性があるということだ。
それ以外に何か良い方法はあるだろうか?
多分ない、と思う。
まぁ、何としてもこういうことをやりたい場合、バスクロックに同期した順序回路にして、クロックの立下りとかで自動的にスタート・ストップビットをリセットする以外に手はないように思う。
或いはA/D変換モジュールともクロック同期させて、全面的に同期回路にするかどうか。
だが、そこまでやるとバスクロックのあるシステムにしか使えなくなるし、A/D変換速度もそれに限定されるので、そうはしたくない。
まぁ、A/D変換回路から割り込み処理が来たら、CPUがその都度スタート・ストップビットレジスタに0を一度書き込んでやれば良いだけのことだが。
こんなどうせ誰も見ないようなところでどうにかスマートに作れないかと悩む時間は無駄な気もするが、お陰でalways関連について、どういう風にセンシティビティ・リストを作成すると、どういう回路が生成されるのかが分かるようになった。
「HDLによりソフトウェアで回路が組めるようになったから、何でも簡単にハードウェアにできるじゃん。」みたいにたまに言われたりするが、全く違うものなので、そんな簡単ではない。
HDLの本には、良く「ソフトウェア技術者はVHDLやVerilogを勉強しても回路を組めるようにはならない。(だから、ハードウェア技術者であるあなたのためのものなのだ!)」などと書いてあったりするが、それはあながち嘘でもない。
C言語などと違い、文法的に合っていればコンパイルできるものではなく、文法が合っていても合成できなかったり、合成できてもタイミングの問題などでマトモに動かない回路はいくらでもある。といより、C言語の感覚で組んだHDLは、まずマトモに動かないと思ってイイ。
結局、VHDLやVerilogは言語によりハードウェア回路図を記述することができるだけのものなのだ。ダテにHDL(ハードウェア記述言語)と呼ばれているわけではない。
C言語のプログラムみたいなのを書いたら、それをやってくれるハードウェアを勝手に作ってくれるような良いものではないのだ。