2023年7月23日日曜日

FPGAでLチカ (Spartan7の場合)

ZUMI32でモーターやA/D、D/A等の制御実験をやってみたくなり、ジャンク箱から使えそうな部品を取り出してきた。
DCモーターやHDDのスピンドルモーターや、I2C I/FのA/D、D/A、温度センサやサーミスタ、ペルチェ素子などがあった。やはり人生持つべきものはジャンク箱だ。 DCモーターのPIDによる回転数制御などもやってみたいと考えている。 以下は仮組みした状態。DCモーターの回転数をロータリーエンコーダで測り、PWMでDCモーターを制御する。
この他にも、スピンドルモータの制御やペルチェ素子の制御(温調)などもやってみたいと考えているが、今日は別のことをやってみた。

以前、このブログでFPGAでLチカというのをやった。FPGAの中にリングオシレータを作りその出力でLEDを点滅させるというものだ。 これをCMODS7のSpartan7でもやってみた。 
Vivadoでこの方法でインプリできるのか興味があったのだが、やってみたらインプリできた。 但し、XDCに set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets BTN0_IBUF] という制約を書く必要があった。 トランスペアレントラッチの数だが、色々と試行した結果、このやり方の場合は14600個が上限だった。CMODS7に搭載されているSpartan7はxc7s25csga225-1で、このデバイスのFF数は29200個だがFFでなくラッチとして使う場合は14600個が上限のようだ。
上記を合成&インプリした結果が以下。
FFの使用率は50%だがSLICEとしては全部使われている。
得られた出力波形が以下だ。
周期が15.6usecなので1素子当たりの遅延は単純計算で 15.6/2/14600 ≒ 0.534[nsec] となる。したがって、素子1個のリングオシレータにした場合は約1GHzのクロックが生成できそうだ。 Spartan7のデータシート DS189によるとスピードグレード -1 のCLBのトグル周波数 FTOGは1098MHzとなっているので、ほぼこの値に近い。
リングオシレータを1素子にし、その代わりにそれをGBUFを通してクロックとして2048個のFFによるリングカウンタを駆動して出力が得られるかを見てみたところ出力がトグルしなかった。 次に素子数を2にしてやってみたらこちらは出力された。
周波数は約192.4KHzだった。これの2048倍がクロック周波数になるので 192.4×2048 ≒ 393.2MHzとなった。これはリングオシレータの素子数が2の場合なので、1の場合はこの2倍で786.4MHz。 何故か、最初に求めた値より若干低い。 

この場合はリングカウンタを使ったが、このようにラッチではなくFFとして使う場合は上限がカタログ通りのFF数までは使えるようだ。以下のようにリングカウンタのbit数を29188個にしてもインプリできた。インプリ後のUtilizationを見るとFFの数が何故か29194になっていた。
上記は29188bitのリングカウンタの値を101010.... にしており、これを発振可能な最大周波数で駆動している。このときの消費電流を見たら635mAも流れていた。 素子数を半分にすると406mA、さらに半分にすると239mAになった。電流はUSBの電流を見ている。

2023年7月17日月曜日

自作CPUで遊ぶ 2

今時のデバイスだと、うちの子はどの位の周波数までいけるのかを見てみた。 具体的にはCMOD S7というSpartan7を搭載したDigilentの評価ボード向けにデザインを作ってVivadoでインプリしてタイミングエラーにならないギリギリの周波数を探した。 このCMOD S7はxc7s25csga225-1が実装されている。
インプリするアーキテクチャは以下のようにした。ZUMI32のペリフェラルはINTC(割り込みコントローラ)、TIMER、GPIO (LED & SW)、命令用メモリは8KByte、データ用メモリは4KBとした。 左側のUARTとUIは命令メモリとデータメモリにプログラムをダウンロードするためのモジュールでありZUMI32からはアクセス出来ない。
タイミングエラーにならないギリギリのクロック周波数を探った結果、上限は113MHzだった。但し、これはFPGAのスピードグレードが-1の場合であり、-2だと140MHzまでmetした。 このデザインはリソース使用率が低く、Physical viewを見るとかなり散らばって配置されているので、もっとリソース使用率が高いデザインにするともう少し上の周波数まで行けるんじゃないだろうか? という気がする。
ZYNQでも同様にしてやってみた。以下のようなアーキテクチャにした。 デバイスはxc7z010clg400-1だ。
このデザインでの上限は100MHzと、驚いたことにSpartan7よりも低い値になった。しかし、physical viewを見ると中身はスッカスカでありこれがクロック周波数を下げている要因では無いかという気がする。 もっと混んだデザインにするとmetする周波数は上がるんじゃないだろうか。
最新のデバイスではないが、Lattice MachXO2でもやってみた。ターゲットデバイスはLCMXO2-7000HC-4TG144Cにした。 結果は49MHzが上限だった。リソースの使用率は30〜40%位だった。スピードグレードを5にした場合は53MHzに上がった。
CMOD S7に戻って、プログラムを作って動かしてみた。CMOD S7には3色LEDが1つ、単色LEDが4つ搭載されているのでタイマー割り込みで単色LEDをナイトライダー風に点滅させるプログラムにした。 フォアグラウンド側はmain()でタイマーの初期設定後、割り込みを許可し、その後 while(1); ループに入る。後はタイマーに設定した周期で割り込みが入るので、割り込みハンドラーでLEDの点滅処理を行う。 このプログラムを-O2最適化オプションでコンパイルして得られたサイズは命令部が1992Byte、データ部(固定値)が24Byteだった。
実機で動かす前にシミュレーションで確認してみる。
※.シミュレーションでは割り込み周期を10usに短縮した。
上図の通りフォアグラウンドは while(1); で無限ループしているので、フォアグラウンド実行時のPC(プログラムカウンタ)は同じ番地を指している。 割り込みを検出すると割り込みベクタアドレス0x00000020をフェッチし、そこから割り込みハンドラに分岐し、処理が終わると割り込み前の番地に戻っている。
実機動作

動作周波数については、ちょっと物足りなさを感じるが全く使い物にならないレベルでは無い。 50MHz以上なら遊びに使うにはまぁまぁ十分ではないかと思う。
プログラム開発は、PC上でCでプログラムを書いてコンパイルして動かすのと同等の手順で出来る。
出来上がったマシン語列は今回のように実機にダウンロードして動かすようにも出来るし、ROM化(命令メモリに初期値として設定)することも出来る。難点はデバッグ用の仕組みをまだ入れていないことだが、今の所特に支障は無い。

このCPUでモーターとかアクチュエータを動かしてみたり、装置のユーザーインタフェース部の処理をさせたりしてみたいもんだ。


2023年7月8日土曜日

自作CPUで遊ぶ

前回まででスコア表示機能の追加が出来た。iCE40LMボードやブロック崩しゲームで次にやってみたいことや作ってみたいことが色々と頭に浮かんでいるのだが、このテーマは一旦お休みして次は自作CPUで遊んで見ることにした。

11年位前にこのブログで32bit CPU(zumi32)を開発した。このCPUはハーバード・アーキテクチャのRISC型32bit CPUで、パイプライン数は3段だ。割り込みや例外にも対応している。レジスタは17個ありR0は値0の固定値、R15はPC(プログラムカウンタ)、R1からR14は汎用レジスタだ。この他に割り込みや例外発生時の戻り番地を格納するEPCレジスタも持っている。フラグはキャリーフラグとゼロフラグを持っている。命令実行のスループットは、load/store/swapを除いて1命令/1cycleで実行する。分岐時は最小でも2サイクルパイプラインがストールする。また、分岐は遅延分岐になる。乗除算命令は持っていないが、その代わりにシフト命令(バレルシフタ)を持たせた。プログラム開発は、CPU開発時に簡易アセンブラも作って当初はそれでプログラムを作成していた。その後、C言語でもプログラミング出来るようにしたくなったのだが、独自の命令セットにしたので既存CPU用のGCCを流用することが出来ずにgcc-4.5.2をzumi32用にポーティングした。GCCの資料が難解でこれには1〜2年ぐらいかかった。
当時はzumi32をインプリしたデザインをSpartan3E、Spartan6、Cyclone IIIに実装して動かした。 割り込みも使えるのでファグラウンドでマンデルブロート集合を描画し、タイマ割り込みでを使ってその中に周期的に文字列を描画させたりしていた。マンデルブロート集合の計算は固定小数で計算した。
zumi32はSYSCALL(ソフトウェア例外)命令も実装したので、次にリアルタイムモニタ(FreeRTOS)を実装してみた。マンデルブロート集合を描画するタスクと、FPGAボードのLEDを点滅させるタスクの2つのタスクを動かし、フォアグラウンドのIdleタスクでは別のLEDを点滅させた。この実装でzumi32の遅延割り込みのバグが見つかったが無事修正できた。
・・・と、長々と説明してきたが、今度はこのCPUで何か作って動かしてみたいと考えている。




2023年7月2日日曜日

iCE40LMボードで遊ぶ 3

一応フォントのデザインは出来たのでこのデータをiCE40LMのBRAMの初期値データに変換した。BRAMに初期値を設定してROMとして使う。 この初期値の設定方法だがiCEcube2の場合はインスタンスするBRAMのParameterとして設定する必要がある。そのため、Cのchar型の配列としてフォントを定義し、プログラムでこれをパラメータ文に変換した。
で、最終的に出来たfont_romのコードがこれ。
このゲームはVRAMを使っていない。syncgenはHSYNCやVSYNC等のVIDEO同期信号を生成しているが、掃引している座標値も同時に出力している。 ゲームの各部はこの座標値と自分の座標位置を常に比較しており、自分の領域に来たらフラグを立てる。ビデオデータ出力段はこれらのフラグを見て最終的に出力するデータを決定している。フォントの表示もこの方法で処理している。
以下は、実際に動かしたところ。フォントは16x16にして正解だった。8x8だと小さすぎて見にくかっただろうと思う。 表示している内容だが、右上は消したブロックの数にした。左上の数字はゲームの残り回数だ。このゲームは元々5回まではブロックの状態を引き継いでゲームを続けられるようにしていたので、その残り回数を表示するようにした。この値が0になると全ブロックが復活する仕様だ。
RTLの合成は成功した。タイミングエラーも出ていない。リソース使用率もまだまだ余裕がある。
以下は動作環境。奥の3段重ねの基板はiCE40LMのConfigROMプログラム用の基板だ。一番上のボードにFT2232HLが載っている。Lattice DiamondのProgrammerを使って書き込む。左下の赤黒のコードが付いている黒い物体はゲーム開始用のプッシュスイッチだ。その右側はビープ音再生用のスピーカー。さらにその右側はラケット(バー)を左右に動かすためのロータリーエンコーダーだ。
で、実際にプレイしてみた。実に楽しいのだが、自分の反射神経が驚くほど衰えていることに愕然としている。実機評価にならない(笑)。でも、なかなか楽しい。

ということで、文字表示は成功した。 \(^_^)/

2023年6月18日日曜日

iCE40LMボードで遊ぶ 2

以前作ったブロック崩しゲームにスコアを表示させようとしている訳だが、そのためにはフォントが必要だ。その大きさはどの位がいいのか検討した。ゲーム面の画素数は640×480なので、8x8のフォントにした場合は横方向は80文字になる。しかし、8x8のサイズだと見た目がちょっと物足りないかも知れないので倍の16x16にしようと思う。16x16にすると線を2ドットで表現できるので"0"や"8"等の文字の角を欠けさせることも出来る。フォントデータはBRAMに持たせることになるが、0〜9まで10種なので、データ数としては16x16x10 = 2560bitになる。iCE40LMのBRAMは4Kbitなので1個に入る。
そして、次に検討する必要があるのは何を表示するか?ということだ。ただ漠然とスコアと表現して来たが、言うてもブロック崩しゲームなので、"残っているブロックの数"とか、"各ブロックに点数の重みを付けて崩したブロックの重みの合計”とかがあり得る。ブロックの数は横20×立て8の計160個なので、ブロック数の場合は表示桁数は3桁。10進カウンタ3個でのカウントが楽そうだ。 重みの合計の場合は10進値だと計算が面倒なのでカウンタはバイナリにしてその値を表示するところでBIN2BCD変換するか。 また、単にそれらの値を表示しただけでは何か物足りない。プレイ時間に制限時間を設けて、”プレイの残り時間”とかを表示させた方が良いのかもしれない。
Roundを重ねる毎にボールのスピードを上げて難易度を上げていくというのも有りかな。

うーむ。どっちが良いかね〜

2023年6月3日土曜日

iCE40LMボードで遊ぶ

ZynqBerryが壊れてしまったのでこれで遊ぶ気が失せた。。
ブログ再開早々ズッコケてしまったが、気を取り直して次にいこうと思う。

8年位前に自作のLatticeのiCE40LM搭載ボードにブロック崩しゲームを実装して遊んだが、点数を表示していなかったので、今回はその機能を追加しようと思う。このボードで使用したFPGAはボールピッチ0.35mmの25pin BGA品で形状としては当時世界最小クラスのFPGAだった。 当時、一辺が2mmにも満たないこのデバイスで何か作ってみたい思ってデバイスを入手したのだが、このボールピッチだとそれ用の基板は容易に作れないのでデバイスを裏返して各ボールに手半田でリード線を半田付けした。手付でワイヤーボンディングしたような感じだ。
3セット実装し、その内2セットを配線して完成させた。 
このボードにCAN busのIPを実装してZyboと通信させてみたり、Breakout(ブロック崩し)ゲームを実装して遊んだ。ゲームはビープ音も出していたのだが、点数の表示機能は実装しなかった。 で、今回これに点数表示機能を追加しようと言うわけだ。
そこで、iCE40の開発ツールであるiCEcube2の最新版(iCEcube2.2020.12)のLinux版をLattice社のサイトからダウンロードしてインストールした。インストールは問題なく出来たのだが、起動してみるとlibpng-1.2.7が見つからないと言って起動しなかった。今使用している開発マシンはLinux Mint 20.2 Umaなのだが、このOSのlibpngのバージョンは16.37だ。仕方がないので16.37を1.2.7としてシンボリックリンクを貼った。そしたらiCEcube2は起動したのだが、何故かツールバーのアイコン関係が表示されかった。うーむ、必ず何かしら問題が起きるな。
メニューバーからの操作だけでも開発作業は出来そうなのだが、やっぱちゃんとしていないと気持ち悪いのでWindows版をダウンロードしてWine(Windows emulator)環境でインストールしてみたらこっちは正常に起動した。なので、開発はWine環境で行うことにした。
それから、実機(ボード)は長期間放置してあったので動くかどうか確認する必要がある。前述の通り、2セット配線して可動状態にしてあったのだが、今日確認したら1枚は壊れていた。オシロスコープで波形観測すると起動時のconfig ROMからのコンフィグデータの読み出しは行われておりdone信号も1になっているのだが何故か動作しない。 PCからCRAMへ直接ダウンロードしたらVerify Errorになったがその前のデバイス検出には成功しているようなので、はんだ付けした配線が切れているとかでは無いようだ。 もう1枚の方は無事動作した。よかった。よかった。
さて、デザインの方だが、スコアを表示するためには数字の図形情報をBRAMに持つ必要があるが現状のリソース使用率は以下のような状況なのでリソース的には実装は可能と考えている。


ERROR: Failed to spawn fakeroot worker to run ...

なにかと忙しくてなかなか趣味の時間を確保できない。 ...orz  家の開発機のOSはLinux Mintなのだが、最近バージョンを22に更新したところ、myCNC用のpetalinuxをビルドできなくなってしまった。ビルドの途中で ERROR: Failed to spawn ...