-
Notifications
You must be signed in to change notification settings - Fork 5
FPGA
ここではFPGAのHDLおよびNios IIのファームウェアについて解説する。 補足資料として本基板のFPGAにどのようなICや部品が接続されているかについてPhoenix FPGAインターフェース編 - BlankaLilioで解説されている。
IntelのFPGAの情報は代理店であるマクニカの技術情報サイトで多く見つかるので参考にすると良いだろう。
- 技術コンテンツ - Nios II
- Nios®II はじめてガイド Nios®II 簡易チュートリアル
- Nios® II - Vectored Interrupt Controller の実装手法
- [Nios II] オンチップ・メモリからの起動 ~時短編~ コンパイル済みのデザイン中のNios IIのバイナリだけ更新する
- FPGA/App
Applicationモードのプロジェクト- hdl
-
top.sv
トップレベルデザイン (このHDLのポートがFPGAのI/Oピンになる) - pll.ppf, pll.qip, pll.v
PLL (IP Catalogで生成) -
avalon_st_clock_bridge.sv, avalon_st_clock_bridge_hw.tcl
Avalon-STの信号をクロックを跨いで伝送する (フリップフロップをケチっている) -
cdb_module.vhd
信号をクロックを跨いで伝送する osafune/misc_hdl_moduleより -
reset_synchronizer.sv
非同期リセット信号のデアサートをクロック同期させる -
deglitch.sv
デグリッチフィルタ -
control_pulse_gen.sv
IMUへ32kHzのパルスを出力し、IMUから出力された割り込み信号からFPGA内部のタイミング信号を生成する -
ltc2320.sv
LTC2320に制御信号を出力し変換値を受け取る -
serial_to_parallel.sv
パラレルシリアル変換ICを制御する -
current_cic_filter.sv
電流センスアンプの出力を前段でフィルタリングするCICフィルタ -
current_fir_filter.sv
電流センスアンプの出力を後段でフィルタリングするFIRフィルタ -
motor_controller.sv, motor_controller_hw.tcl
ドリブルモーターをAvalon-MMで制御する -
pwm_driver.sv
シングルスロープPWM -
ds_pwm_driver.sv
デュアルスロープPWM -
clarke_transform.sv
クラーク変換 (vector_controller.svで使用) -
park_transform.sv
パーク変換および逆パーク変換 (vector_controller.svで使用) -
pi_controller.sv
PIコントローラ (vector_controller.svで使用) -
position_estimator.sv
ホールセンサとエンコーダから回転角度を推定する (vector_controller.svで使用) -
quadrature_decoder.sv
直交エンコーダのデコーダ (vector_controller.svで使用) -
space_vector_modulator.sv
空間ベクトル変調 (vector_controller.svで使用) -
vector_controller.sv
ベクトル制御モーターコントローラ -
vector_controller_master.sv, vector_controller_master_hw.tcl
4つのvector_controllerをAvalon-MMから制御する
-
top.sv
- ip
- avalon_st_uart_tx/avalon_st_uart_tx.sv
8bit幅のAvalon-STをUARTで送信するIP - float32to16/float32to16.sv
IEEE754準拠の32bit浮動小数点数を16bit浮動小数点数に変換するカスタム命令IP - i2c_master/i2c_master.sv
レジスタベースのアクセスが可能なI2CマスターIP - imu_spim/imu_spim.sv
IMUの測定値を自動でフェッチするSPIマスターIP
- avalon_st_uart_tx/avalon_st_uart_tx.sv
- controller.qsys
モーター制御を行うNios IIを含むPlatform Designerのシステムファイル - controller
controller.qsysから生成されるHDLを含むディレクトリ - controller.sopcinfo
controller.qsysから生成されるシステムの情報 (Nios IIのBSPの生成に用いる) - output_files
- output_file.cof
Convert Programming Filesのセットアップデータ
PhoenixFPGA.jic
とPhoenixFPGA_auto.rpd
を生成する - PhoenixFPGA.sof
生成されたビットストリーム - PhoenixFPGA.jic
ProgrammerでJTAGからフラッシュメモリに書き込むデータ - PhoenixFPGA_auto.rpd
リモートアップデートでフラッシュメモリに書き込むデータ
- output_file.cof
- hdl
- FPGA/Factory
Factoryモードのプロジェクト- hdl
-
top.sv
Factoryモードのトップレベルデザイン
-
top.sv
- output_files
- output_file.cof
Factoryモード用のConvert Programming Filesのセットアップデータ
PhoenixFPGA.jic
を生成する - PhoenixFPGA.sof
Factoryモード用のビットストリーム - PhoenixFPGA.jic
Factoryモード用のJTAG経由でフラッシュメモリに書き込むデータ
- output_file.cof
- hdl
ファイル名が"_hw.tcl"で終わるファイルは作ったHDLをPlatform DesignerでIPとして扱えるようにIP情報を記述するファイルである。
以下にトップレベルのブロック図を示す。クロックドメインブリッジやシンクロナイザ等の細かいモジュールは省略している。
以下にvector_controllerの内部構造のブロック図を示す。 dq電流のPI制御をする部分までベクトル制御のアルゴリズムをハードウェア化している。 muxed_park_tranformモジュールは一つのpark_transformモジュールを順変換と逆変換で使いまわすためのものである。
- FPGA/App/software
- controller
- include
このディレクトリのファイルはphoenix-jetsonから参照される-
shared_memory.hpp
共有メモリのデータ構造を定義する構造体の定義 -
status_flags.hpp
ステータスフラグの定義 -
stream_data.hpp
UARTで送られるデータ構造を定義する構造体の定義とストリームIDの定義
-
shared_memory.hpp
- source
-
main.cpp
各種ペリフェラルの初期化を行う
以降のモーター制御などはすべて割り込みで処理されるためmain関数でやることはない -
board.hpp
基板や車体に関する定数などを定義する -
centralized_monitor.hpp, centralized_monitor.cpp
モーター制御ループの実行を制御する。フォルト状態を検知してモーター制御を止める -
data_holder.hpp, data_holder.cpp
センサーや制御に関するデータを格納する -
shared_memory_manager.hpp, shared_memory_manager.cpp
共有メモリの管理を行う -
stream_transmitter.hpp, stream_transmitter.cpp
UARTでJetsonへ定期的にデータを送る -
dribble_controller.hpp, dribble_controller.cpp
ドリブルモーターを制御する -
wheel_controller.hpp, wheel_controller.cpp
車輪モーターを制御する -
fpu.hpp
FPUのカスタム命令を呼び出す関数の宣言 - filter
-
lpf.hpp
ソフトウェアIIR LPFフィルタ -
gravity_filter.hpp
重力加速度を分離するMahonyフィルタ -
velocity_filter.cpp, velocity_filter.hpp
エンコーダとIMUから車体速度を推定するカルマンフィルタ -
acceleration_limitter.cpp, acceleration_limitter.hpp
加速度制限器 -
const_matrix.hpp
コンパイル時行列演算クラス
-
lpf.hpp
- driver
-
adc2.hpp, adc2.cpp
ADS1015を制御するドライバ -
imu.hpp, imu.cpp
ICM-42688-Pを制御するドライバ -
pin_name.hpp
PIOに繋がっている信号名とビットの対応を定義する -
led.hpp
LEDを制御するドライバ -
load_switch.hpp
エンコーダとホールセンサーのロードスイッチを制御するドライバ -
critical_section.hpp
クリティカルセクションを作るクラス
-
adc2.hpp, adc2.cpp
- peripheral
-
msgdma.hpp, msgdma.cpp
mSGDMAドライバの再実装 (純正ドライバがビジーループやalt_printfの呼び出しを含むため排除したかった) -
i2c_master.hpp
i2c_master.svのドライバ -
imu_spim.hpp
imu_spim.svのドライバ -
motor_controller.hpp
motor_controller.svのドライバ -
vector_controller.hpp
vector_controller_master.svのドライバ
-
msgdma.hpp, msgdma.cpp
-
main.cpp
- include
- controller_bsp
controllerのBSP (HAL、API、リンカースクリプトなどをまとめた自動生成されるパッケージ)
- controller
FPGAにはJetsonからSPI経由でアクセス可能な共有メモリ(data_ram_1)が実装されている。
この領域にパラメータを書き込むことでロボットに指令値と制御パラメータなどを与えることができる。
また後述するがエラーフラグ、フォルトフラグといったステータスフラグの確認とエラーフラグの解除にも使われる。
共有メモリの構造はshared_memory.hppで定義されている。
struct SharedMemory {
uint32_t error_flags;
uint32_t fault_flags;
uint32_t head_checksum;
struct Parameters {
uint32_t frame_number;
<<<パラメータ本体>>>
} parameters;
uint32_t tail_checksum;
};
共有メモリにパラメータを書き込む際、パラメータ本体とframe_numberを合わせたデータのチェックサムを計算し、その値をhead_checksumとtail_checksumにパラメータと一緒に書き込む。この手順により書き換え途中の共有メモリからNios IIがパラメータを読み出すことを防いでいる。frame_numberはパラメータを書き込むたびにインクリメントすることでパラメータの更新をNios IIに伝える。
Jetsonから見た共有メモリーのベースアドレスは0x00000000番地である。
SPI経由でのメモリーアクセス方法はSPI Slave/JTAG to Avalon Master Bridge Coresで部分的に解説されている。
制御プログラムのテストのためにNios IIの命令メモリ(instruction_rom_0)は共有メモリと同じくSPI経由で書き換えられるようになっている。 命令メモリはJetsonから見て0xA5A50000番地をベースにマッピングされている。 Nios IIの実行中にこれを書き換えると非常に危ないので書き換えている最中はFPGA_MODEピンをLowに駆動してNios IIとその周辺機能にリセットをかけること。
FPGAをFactoryモードに入れることでJetson NanoからFPGAのビットストリームが格納されたフラッシュメモリにアクセス可能になる。
フラッシュメモリにはFactoryモードのイメージとApplicationモードのイメージの2つが格納されていて、FPGAのリセット時にはまずFactoryイメージからコンフィギュレーションが行われる。
FactoryモードではFPGA_MODEピンがLowに駆動されていなければApplicationモードのイメージでのリコンフィギュレーションが行われる。もしFPGA_MODEピンがLowに駆動されていればその間、FPGAはJetson Nanoとの間のSPI信号をフラッシュメモリにバイパスする。
これによりJetson Nanoはフラッシュメモリの書き換えが可能になる。
フラッシュメモリは2MBの容量があり、Factoryイメージは前半の1MB、Applicationイメージは後半の1MBに格納される。
ライトプロテクトを設定するつもりはないので間違ったイメージを書き換えないように注意すること。
UART経由でFPGAで測定したデータや制御情報をJetsonに一方的に転送している。
送るデータの構造はstream_data.hppで定義されている。
データはAvalon-ST Packets to Bytes ConverterによってAvalon-STのパケットからバイトストリームに変換されてUART上を流れる。データを送信する処理はmSGDMAによって行われるためCPUの負荷を少なく抑えることができている。
UARTのボーレートはJetsonの上限である4Mbps、フレーム形式はデータ8ビット、ストップビット2ビット、パリティなしである。Avalon-STのパケットをバイトストリームに変換する際、エスケープ処理によってペイロードは最大で2倍に膨れ上がるため使用する帯域は182KB/s以下にする必要がある。帯域が限られているため32bit浮動小数点数は16bit浮動小数点数に変換して転送している。
CentralizedMonitorは異常検知の情報を集約し異常発生時にモーターを停止させる。異常には2種類あり軽微なものは「エラー」、重度のものは「フォルト」として扱いを変えている。
エラーとは以下に挙げる異常である。
エラーフラグはSPI経由で解除でき、ロボットの動作を再開させられる。
- ModuleSleep
Jetsonがスリープ状態である - FpgaStop
GreenPAKから停止指示が発されている - Dc48vUnderVoltage
DC/DCコンバータの出力電圧低下
過負荷時に起きるかもしれない - Dc48vOverVoltage
DC/DCコンバータの出力電圧超過
モーターを急減速した際の回生発電により発生するおそれがある - Motor[n]OverCurrent
n番目のモーターの軽度の過電流 - Motor[n]HallSensor
n番目のモーターのホールセンサー異常、断線
フォルトとは以下に挙げる異常である。
フォルトフラグはロボットの電源を入れなおす(あるいはNios IIをリセットする)ことでしか解除できない。
- Adc2Timeout
ADC2からデータが取得できない - ImuTimeout
IMUからデータが取得できない - Motor[n]OverTemperature
n番目のモータードライバの過熱シャットダウン
DRV8312のnOTWがLowになると検知される - Motor[n]OverCurrent
n番目のモータードライバの過電流シャットダウン
DRV8312のnFAULTがLowになると検知される - FaultCauseMotor[n]LoadSwitch
ホールセンサー、エンコーダのロードスイッチの過電流
ホールセンサーやエンコーダの配線がショートすると起きるかもしれない
なおエンコーダの異常や断線を検知する機能は盛り込んでいないため覚悟すること。
エラーフラグを解除するにはJetsonから共有メモリーのerror_flagsに0xFFFFFFFFを書き込む。 するとエラーフラグの解除が試みられ、解除に成功すればこの値が0になる。 0にならない場合はエラーの原因が残っていることを意味する。 新たに有効なパラメータを共有メモリーに書き込むとロボットはモーター制御を再開する。
FPGAは基板の辺に設けられている5つのLEDの点灯パターンで現在の状態を表現している。
点灯パターン | モード | 意味 |
---|---|---|
弱く点灯 | 起動していない | FPGAがコンフィギュレーションに失敗した。 Applicationモードのコンフィギュレーションに失敗したときになることもある。 |
時計回りにLEDが1つずつ点灯 | Factory | リモートプログラミング可能である。 |
時計回りにLEDが4つずつ点灯 | Factory | Applicationモードのコンフィギュレーションに失敗した。 |
すべて消灯 | Application | モーター制御をしていない。 |
すべて点灯 | Application | モーター制御をしている。 |
すべて点滅 | Application | 全般的な異常が発生した。 48Vバス電圧の異常, ADC2の異常, IMUの異常が考えられる。 |
一部が点滅 | Application | 該当箇所のモーターに異常が発生した。 軽度の過電流, ホールセンサーの断線, モータードライバの過電流, モータードライバの過熱, ホールセンサー・エンコーダ用電源の過電流が考えられる。 |