2015年8月30日日曜日

世界最小クラスかも知れないFPGAボード 9 (CAN IPを実装してみる 5)

I2Cのトライステートの配線が出来ない件は、原因が判明した。 こんなのRTLのバグじゃ有り得ないと思っていたのだが、悪いのは自分で、RTLの記述ミスだった。。。 orz
rx_pipe.vモジュールにCANの受信フレームをパターンマッチングで、どのレジスタ宛かを検出する部分があるのだが、そこの拡張ID部のビット幅を1bit短く記述していた。拡張ID部は18bit長なので、この部分は[17:0]でなければならない。パターンマッチングは基本ID部と拡張ID部その他IDのモードやマッチングをする/しないの情報を連結して行っていたので、それらの情報が1bit右にズレてしまっていた。そのため、今回の実装ではパターンマッチングを行わないという風に合成エンジンが解釈し、その信号が伝搬する下流の回路の生成がされないかあるいは変な状態になってしまっていたようだ。。。

修正前

修正後

修正後はLSEでもSynplifyでもトライステート部の回路は生成されるようになった。

RTL記述

LSEでの合成結果

Synplifyでの合成結果


これで両方の回路とも正常動作を期待したのだが、どうもまだ挙動が怪しい。

Zynq-CANの代わりにOpenCoresのCAN-IPを使い、ターゲットとしてうちの子(fpga_top)のRTL、合成後のゲートネットリスト、及び can-ip 単体を接続したテストベンチを作成して、OpenCoresのIPからPWMのdutyを設定するフレームを送信してちゃんと受信されるかを見てみた。

ベクタ ... pwmのdutyを0x40 (25%)に設定するフレームを5回連続して送信してみた。


結果
ref_modelはOpenCoresのCAN-IPの送受信信号で、rtl部はfpga_topのRTL、core部はcan_ip単体、gateは合成して生成されたネットリストによるものである。

Synpliftyで合成したネットの場合

RTL, gate, core 全てが同じ動作をしており、ちゃんとACK応答をしている。また、dutyも設定されている。

LSEで合成したネットの場合
gateは全く反応していない。。。  なんか変だなぁ−、まだ何かあるんだろうか?

試しに、Synplify版のビットデータを実デバイスに書いて、Zynqとの間で同様の通信をさせてみた。

Zynq側のプログラム

観測点はCANトランシーバとFPGA間の信号で、黄色は送信信号(FPGA➔Zynq)、紫は受信信号(Zynq➔FPGA)だ。
この分解能だと見辛いのでロジアナても見てみた。
採取した波形 ... 応答しない場合と応答する場合があるようだ。

上述のSynplify版ネットリストでのシミュレーション波形と比較してみた。
上がシミュレーションの波形、下がロジアナで採取した波形で、1発目の通信の部分だ。
FPGA側がACKやCRCエラー等で一切応答しないために、タイムアウトエラーとなっているようだ。Zynq((及びref_model)から送信されるフレームはどちらも同じなのでそこは問題なさそうだ。 

何かしらの応答をしている箇所を見てみた。 FPGAから応答がないのでZynqからのエラーフレームに反応する形でこちらのFPGAもエラーフレームを出している。。。ということはエラーの検出はしているようなのだが???

と、言うわけでまだまだ先は長そうだ。 うーむ・・・でも、楽しい。

2015年8月16日日曜日

世界最小クラスかも知れないFPGAボード 8 (CAN IPを実装してみる 4)

ZYBO側の基板も出来た。


ZYNQでCANを使うためのデザインを作った。今回はPL側は使用せずPS側だけを使う。
久しぶりにvivadoを使うので、過去のデザインを流用するのではなく、使い方の復習を兼ねて最初から作成してみた。




最初から、とは言いつつ、私のVivado環境はZYBOのボードが選択出来るように細工してある(http://bravo-fpga.blogspot.jp/2014/10/zybo-6.html)ので、ここではZYBOボードを選択する。

IPインテグレータでブロックデザインをする。

PL部は使わないので配置するのはZYNQ7 Processing Systemのみだ。


CAN0を使えるようにする。

IO PeripheralsのCAN 0をクリックするとMIO Configuration画面が開いた。

CAN 0にチェックを入れた。使用するMIOは10,11にした。クロックは内部のリファレンスクロックを使うのでMIO CLKにはチェックを入れていない。

次にClock Configuration画面でCAN CLKの周波数を24MHzに設定した。


PLを使わないのでPL Fabric Clockは全てチェックを外した。

DMAやHP Slave AXI Interface、GP Master AXI Interfaceもチェックを外した。



すると、こんなにスッキリしたデザインになった。



ブロックデザインの生成ができたらラッパーモジュールを生成する。


生成できたら、合成した。
PL部は使っていないので実際は回路はなにも生成されない。

HardwareをExportしてSDKを立ち上げる。




プロジェクトを一つ作成した。



まず、このデザインがちゃんと動作するか確認したかったのでPS側のGPIOに接続されているLEDを点滅するプログラムを書いて動かしてみた。


大丈夫そうだ。
いよいよCANのプログラムに入る訳だが、system.mssをみるとCANの例題プログラムがあるようなので、見てみることにした。


このプログラムは診断用プログラムで、CANをループバックモードで1回だけ動作させていた。ビットレートは40Kbpsだ。
このプログラムをノーマルモードの1Mbpsで動作するように改造して動かしてみた。
CAN busの信号波形を確認したところ信号が出ていた。

ZYNQ側は、CANを動かすのはとても簡単にできそうだ。

と言うことで、自作IPの基板側との通信の確認に着手した。
ここからはXilinxとLatticeの開発ツール両方を使いながらの作業になる。

まず、Zynq側から自作IP側へPWMを設定するフレームを送信してみているのだが反応しない。
Zynqからの送信信号は受信モジュールまでは到達しているのだが、ACKやエラー等を一切返さない。どうもステートマシンがどこかで止まってしまっているようだ。
シミュレーションでは動作しているのだが・・・


そこで、今度は自作IP側から一定周期でフレームを送信するようにして動作するかを見てみたが、こちらもRTLシミュレーションでは動作するが実機では全く動作しない。RTLのバグにしては有り得ない現象なので、iCEcube2が生成したネットリストでSDFはアノテートせずにゲートシミュレーションをしてみたところCAN部が全く動作していないことが判った。どうも論理合成が正しく行われていない気がする。 ICEcube2では論理合成エンジンとしてSynplifyとLSEのどちらかを選択できるようになっていて、今まではLSEの方で合成をしていた。 これを、Synplifyに変えて合成し、生成されたネットリストでゲートシミュレーションを実行してみた。

結果は、CAN部は動作した。
こちらは、同じRTLをLSEで合成したネットリストでのシミュレーション結果だ。

LSEの場合には何か設定が必要なんだろうか????
また、SynplifyではCAN部が動作する回路が生成されてはいるが他に問題がある。上記波形でI2C_SDAが不定となっている。ネットリストを確認したところ、トライステートバッファの接続が不完全になっていた。Synplifyだとトライステートバッファの回路が旨く生成されず、LSEだとCANの回路がまともに生成されない・・・ うーむ。記述の仕方が悪いのかな???

取り敢えず、I2C_SDAの部分は置いといてSynplifyで合成して出来上がったビットマップファイルを実デバイスに流し込んで動作を見てみたところ、送信信号が出力された。


ということで、合成エンジンはSynplifyを使うことにして、トライステートバッファの件の解決策があるか試行錯誤してみようと思う。

自作CPUで遊ぶ 25

まだ制御ソフトが完成していないので今まではスピンドルを移動するために一々簡単なプログラムを書いて移動させていたのだが、非常に面倒なのでCNCペンダント的なものを作ることにした。 右側の縦に2つ並んでいるスイッチ...