2023年10月22日日曜日

自作CPUで遊ぶ 11

CNCはG-codeで制御することになるが、主軸の移動を指示するコードにG00(位置決め)とG01(直線補間)がある。G00は主軸の原点復帰等のような位置決めに使われる。この時各軸は同期せず個別の設定値で移動する。起動/停止時の加速度もそれぞれの設定値を使うので、例えばX/Y各軸の設定値が同じ場合主軸は最初に45度の方向に移動し、何れかの軸が目標位置に到達すると今度はX方向またはY方向のみ移動して目標点に到達することになる。これに対してG01の直線補間(切削送り)は現在位置から目標位置までの直線上を移動する。前々回に検討したのはこの場合になる。
で、これらの処理のFPGAのロジックとソフトウェアの分担について検討した。 パルスモータードライバーへのパルス生成方式は基本的にはHDD用スピンドルモーター駆動時の方式をベースにするのだが、とりあえず以下のような入出力で考えている。
*_pm_***はパルスモータードライバへの制御信号だ。em_stopは非常停止信号でこれが1の期間は動作を停止し*_pm_enも0にする。s_beatはビートパルス信号で、起動/停止時の加減速はこのパルスに同期して行う。*_pcntは*_pm_pulseに出力されるパルスの計数値だ。*_pm_dirの値によって増減する。*_pcntは*_clrで0にリセットされる。*_clrは原点設定時に1になる。X/Y/Z各軸のパルスモーターの回転が各軸の移動に変換されるので、*_pcnt値に1パルス当たりの移動量を乗じれば原点からの座標になる。*_accelは起動/停止時の加速度、*_speedは目標速度だ。主軸が停止状態から移動が始まるとすると、速度0から *_accelのレートで増速していき *_speedに達する部分で *_speedに固定する。また、停止時は *_speedの速度から *_accelのレートで減速して行きやがて0になる。 *_enは起動/停止を制御する。 0から1に変化すると移動を開始し1から0になると停止する。停止時は直ちに停止する訳ではなく減速しながら停止する。起動から完全停止迄の期間のパルス数が移動量になるので停止のタイミングはちゃんと計算する必要がある。 

で、FPGAのLOGIC側をこうするとすると、zumi32側の処理は少なくとも以下のことをする必要がある。
数値計算はfloatで行う必要があるが、これは問題ない。Dpを求めるのに√演算が必要になってしまった。これを何とかする必要がある。zumi32は演算用リソースとしては加減算器とバレルシフタしか持っていないのでfloatの四則演算はそれなりにステップ数を要する。√演算となると尚更だ。そこで、この部分はハード化することにした。√演算器は10年くらい前に趣味で自作した。最初のやつはパイプライン式で組んだが回路が大きくなるのでその後に非パイプライン化版も作った。これは1bit@1clockで計算する。32bit floatの仮数部の√を求めるのでトータルで26クロック掛かる。これだとちょっと掛かりすぎな気がするので、今回2bit@1clockで計算するように変更した。
この演算器をzumi32に組み込み、sqrt命令を追加することも出来るが、他のfloat系演算命令は未実装なのでこれだけ入れるのはバランスが悪すぎる。今回はfp_sqrtモジュールとしてi/o busに接続して使うことにした。また、こうするとfp_sqrtにデータを書き込んだ後、結果がでるまでzumi32で他の処理をさせることも可能で処理を並列化することも出来る。といってもfp_sqrtのレイテンシーは13なのでその期間だけの話だが。。。 以下は動作確認のために現状のプロジェクトに組み込んだ様子。
zumi32のプログラムは以下のようにした。
simulationの結果
vivadoでimplementして見た。100MHzで動作させるがタイミングエラーは無くMetした。回路規模も意外と小さい。

0 件のコメント:

コメントを投稿

自作CPUで遊ぶ 25

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