このあいだのXbeeの電力ロガーのデータはテキストデータで定型なので、少しでもエラーがあると目立つのだが、どこまでも綺麗に出力される(前は、3回に一回はどこかしらデータの乱れがあった)。いやあ満足、満足である。勢いに乗って消費リソースを調べてみた。今度のソースコード全体のスライスは366、前は382だった。差はわずかだが、このスライス量はすべてのルーチン(UART受信、SRAMアクセス、ビデオ信号、SPI、10進変換など)を含んでいる。送信UARTだけならスライス量は80程度と考えられ、それでこの差は大幅な削減だ。調子に乗って、またソースコードを公開してしまうことにした。送信の部分だけだが、Latticeの環境では、間違いなく雑誌のコードより信頼性の高いVerilogHDLソースである。コメントに日本語が入っているが、これは公開のために追加したもので、Latticeのエディターでは日本語は化けてしまうので注意されたい。(日)FPGAのSPIインターフェース遂に完成ここ1週間ばかり、お盆休みをとっていたのだが、外にもでかけず(まあ猛暑だったこともあるが)FPGAのSPI(スレーブ)インターフェースのデバッグに夢中になっていた。先ほど、やっとのことでバグの原因が判明し、清々しい気分でこのブログを書いている。今度も、日頃からお世話になっているkugaさんのヒントで解決したのだが、最後の最後になっても細かいエラーが取れず、今回も苦労した。苦労が多ければ多いほどその喜びは大きい。人間というのは因果なものである。XP2基板のSPIインターフェースは、フォトフレームプロジェクトの第5ステップにあたり、送り側のARMプロセッサー(STM32F103)のSDカードデータを送るSPI(マスター)インターフェース(第6ステップ)は、既に完成している。前にも書いたように、FPGAのSPIスレーブインターフェースは、fpga4fun.comから拝借したソースコードを使わせてもらっている。テスト環境ではARMからデータを送った後、FPGAのUARTのリターンキーを押せば、SRAMに蓄積されていたデータがUART端末に表示される。前記事にもあるように、30バイト程度の短いメッセージならほぼ正しく帰ってくるが、少しデータが増えると、カウンターがおかしくなるらしく、表示が止まらなくなる。UARTで結果が見えるように、テストデータはキャラクターで、SDカードの中のテキストファイルを選んで送信するのだが、派手に字化けする。データはともかく、カウンターに目茶目茶な数字がはいっているようだ。切れ切れに見えるメッセージもあちこちでデータが化け、特に日本語の2バイト文字は悲惨な結果になる。プログラムの最初はこんなものだ。不具合を直していこう。データの中味をチェックする前に、先にデータカウンターの部分を直さないとテストがやりにくい。いちいちリセットしているのではたまらない。FPGAはいわゆるprintfデバッグ(変数を途中で出力させて調べること)が出来ない。カウンターの数字を知る方法は何かないかと考えていたら、以前7セグLEDテストのときにバイナリから十進4桁データに変換するモジュールを開発したのを思い出した。デバッグ対象のコードにさらに不確定要素を加えるのは、デバッグの常道にはずれるが、この際、背に腹は代えられない。何とか組んでカウンターの数字をUARTに出してみた。ASCIIの数字キャラクターは、バイナリに0x30を加えるだけなので楽である('1'=0x31,'2'=0x32...)。テストのためにまずカウンターを固定して、モジュールから数字を取り出す。あれえ、全く違う数字が出る。SPIが読んだ時の数字(でたらめだが)のようだ。やれやれ、こいつのデバッグもしなければいけないのか。うはあ、こいつはマスタークロックで何十回かループしないと結果がでないソースコードだった。10進数字を取り出す前に計算終了のフラグをテストするループを加えて、やっと決め打ちした数字がUARTにでた。このモジュールが出す読み込んだデータの数は予想通り支離滅裂な数字だった。unsigned変数は0から1を引くと、最大数になり、止まらなくなる。カウンターが0になったときに備えて、0からこれ以上引かないような姑息なロジックも入れるが、これも関係なし。リセットした直後は、まあまあのデータが出るが、続けるとまるで駄目である。SPIってこんなに不安定なのか。おかしなことに8ビットフレームを1ビットでも間違えれば、あとはすべて狂うはずだが、奇妙なことに正しいデータが復活する時がある。STM32側のデータはロジアナで追って、バイト数が合っていることを確認した。中味は30バイトほど調べて少なくとも間違っていなかった。この不具合はすべてFPGA側が原因だろう。前にも書いたが、このfpga4funのコードは一風変わっている。各変数のあとにひとつづつクロック単位に動くalways文がついている。SCKの立ち上がりは、3ビットのシフトレジスターを動かし、そのデータが01Xになった時、つまりSCKが立ち上がったときに1になるよう変数を定義し、その変数を使って8ビットデータを拾う。このコードは、SPIの入力をマスタークロックでサンプリングして、ビットの立ち上がりを調べている。SPIのSCKクロックで動かす方がより正確なデータがとれるような気がするのだが、人さまの書いたソースなので、原因究明の方法の糸口が見つけられない。FPGAのクロック33Mhzと、最初設定したSPIの速度9Mhzの差が近いので、サンプリングが上手く行っていないのかも知れないと、クロックを半分の4.5Mhz(計算ではSCKの1パルスに3回以上サンプリングできる)に落としたが、結果は変わらなかった。これ以上何をやって良いのか見当がつかなくなった。サンプリングだとデバッグしにくいので、むしろSCKのクロックに合わせた回路の方が安全のように思えてきた。考えた末、遂にfpga4funのソースをあきらめ、自前で作ることにする。スレーブコードを書き始めた。思ったより早くコードが完成した。おお、fpga4funのコードより消費スライスも少ない。