1. はじめに
この記事では、Nios® II システムを解析する際に役立つ Signal Tap の設定方法と、各種ペリフェラルの信号の探し方、トリガーの取り方や解析方法を記載しています。
【図 1】のように、Nios® II Plug-in 機能を使用すれば Nios® II で実行されているアセンブラも Signal Tap の波形として確認できるので、FPGA 側のロジックの状態とソフトウェアの状態を同時にデバッグできます。
Nios® II SBT の デバッグ機能を使って Nios® II のレジスターの状態や定義した変数の値から動作状態を解析するだけでなく、今回ご紹介する Signal Tap を使うことで、波形レベルでの解析が可能になり、Nios® II システム全体の動作を把握しやすくなります。
Signal Tap に関するコンテンツはこちらをご参照ください。
参考:Quartus® Prime はじめてガイド - Signal Tap ロジック・アナライザの使い方
特に、Sginal Tap に割り当てられる FPGA の RAM やロジック容量は、作成したデザインに依存しますので、ご自身の環境に適した Signal Tap を作成してください。
【図 1】 Signal Tap 測定例
2. Nios® II と Signal Tap の関係性
Signal Tap は Quartus® Prime に標準搭載されたデバッグツールです。ボード上で動作する FPGA の内部信号の状況をキャプチャーおよび表示ができる機能になります。
従って、FPGA のロジックを使用して動作する Nios® II や 各種ペリフェラルの内部信号をモニタリングできるため、Nios® II システム全体の動作をより把握できるようになります。
Nios® II SBT と連動した機能は特にありませんが、Nios® II Plug-in 機能が用意されています。
Nios® II の実行ファイルである ELF ファイルを Signal Tap に登録することで、キャプチャーした Nios® II の命令コードをアセンブラ言語に表示してくれる機能です。objdump ファイルと比較することで Nios® II がどのような命令を実行しているか確認しながら、各種波形をモニタリングできます。
今回使用するデザインの Signal Tap の設定の完成形を【図 2】に示します。
【図 2】 完成形の Signal Tap 信号
3. Signal Tap における各種信号の取得方法
ここからは、各種 ペリフェラルの信号を Signal Tap に追加していく方法について解説します。基本的には、Avalon Bus の信号や割り込み信号、Reset 信号、Export 信号などを取得していきます。
Node Finder で波形を取得していきますが、Options の Filter 条件を "Signal Tap: pre-synthesis" にして "List" を押すと、信号名がわかりやすい状態で設定できます(この場合、Analysis & Synthesis は実行しておく必要があります)。
【図 3】のように Signal Tap の空白部分を右クリックして、"Add Nodes ... " をクリックすると Node Finder が表示されます。
【図 3】 Node Finder の Filter 条件
ペリフェラルによって各種信号の名称が異なることがあり、【図 4】のように Platform Designer の Block Symbol を確認すると各種ペリフェラルの信号名がわかりやすくなります。
【図 4】 Platform Designer Block Symbol
今回使用する Platform Designer の構成は【図 5】の通りです。赤枠で示した信号を取得していきます。
【図 5】 使用する Platform Designer の構成
今回使用する Platform Designer の内部に PLL があり、50MHz(Nios® II System 動作 Clock)を生成しています。PLL の Lock が解除されている時に Nios® II を動作させないために、locked 信号を Nios® II System の Reset 信号に入力させています。(*推奨の構成ではありません)
参考として、トップ階層の RTL Viewer の画像を【図 6】に示します。
【図 6】 トップ階層の RTL Viewer
PLL が Lock され、locked 信号が High になると、Nios® II System の Reset が解除されます。
PLL の 入力 Reset 信号は、チャタリング除去モジュールを介して外部スイッチに繋がっています。
3-1. Reset / Clock と サンプリング周波数 / 深さについて
3-1-1. Reset と Clock 信号の取得
Nios® II System に入力している Reset 信号や各種ペリフェラルに入力されている Reset 信号は取得しておきましょう。Reset が原因で System が動かないとか、Nios® II SBT でデバッグできないなどが発生した時に Reset が原因でないことを確認できます(Reset 系統が同じである Reset 信号は、どれか一つ取得しておけば問題ありません)。
また、Nios® II System の Clock 信号も取得しておくと、Clock が入っているかを確認できます(サンプリング周波数より低い周波数でないと Clock は取得できません)。
Nios® II SBT でデバッグできない場合は、下記のコンテンツをご参照ください。
参考:Nios® II の Run 実行時にエラーになる原因 "Downloading ELF process failed"
今回、Reset と Clock に関する信号は下記の信号を取得します。
* Signal Tap 信号名:Platform Designer 信号名(信号の種類)で記載しています。
<clk_0>
・clk_clk:clk_in(Clock Input)
・reset_reset_n:clk_in_reset(Reset Input)
<pll_0>
・pll_0_reset_reset:reset(Reset Input)
・pll_0|outclk_0:outclk0(Clock Output)
・pll_0_locked_export:locked(Conduit)
【図 7】 Nios® II System の Reset 信号 と Clock 信号
3-1-2. サンプリング周波数 / 深さの設定について
Signal Tap で設定するサンプリング周波数は、取得したい信号の動作周波数の整数倍を指定しておくことが重要です。Nios® II System 動作周波数の整数倍の周波数を使用しましょう。
<例>
・Nios® II System:50 MHz 、サンプリング周波数:50 MHz or 100 MHz ...etc
・Nios® II System:100 MHz、サンプリング周波数:100 MHz or 200 MHz ...etc
もし、Nios® II System の中で動作周波数が整数倍ではない信号を取得したい場合は、
同時取得するとサンプリング周波数とのずれが原因で波形がずれてしまうので、参考程度に取得するか、クロック系統ごとにインスタンスを分けて設定しましょう。
参考:Quartus Prime はじめてガイド - Signal Tap ロジック・アナライザの使い方 #P8:インスタンスについて
今回は Platform Designer の外で生成した PLL の 100 MHz をサンプリング周波数として使用しますので、【図 8】のように Signal Configuration の Clock 欄に該当の Clock 信号を設定します。
<今回使用する Clock>
・Nios® II System:50 MHz 、サンプリング周波数:100 MHz
サンプリングの深さは、「Signal Tap に割り当てられる FPGA の RAM と ロジック 容量」と「どのぐらいの長さ波形を取得したいか」によって決まってきます。理想としては 1k ~ 4k 程度取得できると、トリガーの前後の波形を確認できます。
ご自身のデザインの RAM とロジックの残容量を考慮して決めてください。
今回は 4k を設定しますので、【図 8】のように Signal Configuration の Sample depth 欄を設定します。
【図 8】 Signal Tap のサンプリング周波数とサンプリングの深さの設定
3-2. Nios® II 各種信号の取得
Nios® II の動作を確認する際に取得しておきたい信号は、以下のものになります。
* Signal Tap 信号名:Platform Designer 信号名(信号の種類)で記載しています。
<Nios® II>
・d_****:data_master(Avalon Memory Mapped Master)
・i_****:instruction_master(Avalon Memory Mapped Master)
・irq:irq(Interrupt Reciever)
・Nios® II Plug-in
注記:
IRQ 信号の取得の仕方に注意があります。
IRQ Mapper を取得してしまうと、割り込み番号がずれてしまうので、IRQ 信号を正しく取得するようにしてください。IRQ 信号は 32bit ありますが接続していない信号は削除しておくことで容量を削減できます。
【図 9】 Signal Tap で取得する Nios® II の信号
Nios® II Plug-in 信号は、Nios® II の実行ファイルである ELF ファイルを Signal Tap に登録することで、キャプチャーした Nios® II の命令コードをアセンブラ言語に表示してくれる機能です。次の手順で設定します。
Signal Tap の空白部分を右クリックして、"Add Nodes with Plug-in" をクリックすると、【図 10】のように設定ができます。その際に ELF ファイルを指定しますので、Nios® II SBT で Build を完了させ、ELF ファイルを生成しておく必要があります。検証する時は、Nios® II SBT で Debug AS や Run As で 同じ ELF ファイルを実行 RAM にダウンロードして検証します。
注記:
もし、Flash ROM にすでに HEX ファイル(ELF を HEX に変換したファイル)を書き込んでいて、スタンドアロンで Nios® II が起動している際の波形をモニタリングする場合、Flash ROM に書き込んでいる HEX ファイルと同じ ELF ファイルを指定して、動作している ELF ファイルと指定する ELF ファイルを整合させる必要があります。
【図 10】 Nios® II Plug-in 設定方法
3-3. 実行 RAM 領域の各種信号の取得
Nios® II の実行領域 の Avalon 信号を取得しておくと、命令コードを読み取っている状態を確認できます。
Nios® II の実行領域は、On Chip RAM、そして EMIF を使用して接続する DDR や、Generic Tristate Controller を使用して接続する SDRAM などがあります。必要に応じて Avalon 信号を取得してください。
今回は、On Chip RAM を実行領域とした構成を例にご紹介します。
On Chip RAM で取得しておく信号は、下記のものになります。
* Signal Tap 信号名:Platform Designer 信号名(信号の種類)で記載しています。
<On Chip Work Memory>
・address:s1(Avalon Memory Mapped Slave)
・byteenable:s1(Avalon Memory Mapped Slave)
・chipselect:s1(Avalon Memory Mapped Slave)
・clken:s1(Avalon Memory Mapped Slave)
・readdata:s1(Avalon Memory Mapped Slave)
・write:s1(Avalon Memory Mapped Slave)
・writedata:s1(Avalon Memory Mapped Slave)
【図 11】 Signal Tap で取得する On Chip RAM の信号
3-4. 接続する IP の各種信号の取得
Nios® II に接続されているその他 IP として、ここでは PIO Core をご紹介します。
今回 PIO Core は、割り込みが発生する入力信号として使用した KEY スイッチと、出力信号として使用した LED の2種類として使用しています。
取得するのは下記の信号になります。
* Signal Tap 信号名:Platform Designer 信号名(信号の種類)で記載しています。
<KEY>
・address:s1(Avalon Memory Mapped Slave)
・chipselect:s1(Avalon Memory Mapped Slave)
・readdata:s1(Avalon Memory Mapped Slave)
・write_n:s1(Avalon Memory Mapped Slave)
・writedata:s1(Avalon Memory Mapped Slave)
・irq:irq(Interrupt Sender)
・key_external_connection_ecport:external_connection(Conduit)
<LED>
・led_external_connection_export:external_connection(Conduit)
【図 12】 Signal Tap で取得する PIO Core の信号
3-5. Flash Controller 各種信号の取得
今回は Flash Controller として、Intel FPGA Serial Flash Controller II Core を使用します。
Nios® II は AS Interface を使⽤して Configuration ROM から Boot するため、AS Interface 信号も取得しておきます。AS Interface 信号は ASMI Block というモジュール内部にあるため、モジュールに入力されている信号及びレジスターを取得します。
取得するのは下記の信号になります。
* Signal Tap 信号名:Platform Designer 信号名(信号の種類)で記載しています。
<Flash Controller>
・avl_csr_***:avl_csr(Avalon Memory Mapped Slave)
・avl_mem_***:avl_mem(Avalon Memory Mapped Slave)
・atom_ports_ncs:ASMI 信号(AS Interface の nCS 信号に該当)
・atom_ports_dclk:ASMI 信号(AS Interface の DCLK 信号に該当)
・outgoing_data [3:0]:ASMI 信号レジスター(AS Interface の Data 0~4 における、出力信号に該当)
・incoming_data [3:0]:ASMI 信号レジスター(AS Interface の Data 0~4 における、入力信号に該当)
注記:
atom_ports_dataout [3:0] や atom_ports_datain [3:0] を取得すると、Quartus® Prime のコンパイルでエラーが発生する可能性がありますので、outgoing_data [3:0] と incoming_data [3:0] を設定します。
【図 13】 Signal Tap で取得する Flash Controller の信号
信号の取得が完了したら、【図 14】のように Alias にわかりやすい名称を付けておきましょう。
また、今回使用するデザインの Signal Tap の完成形は【図 2】を参照してください。
【図 14】 Alias の設定
4. Nios® II SBT と Signal Tap のトリガー設定
ここからは、Nios® II の動作を確認する際に役立つトリガーの取り方をご紹介します。
特に、4-3. PIO Core の出力信号をトリガーにして任意のソフトウェア処理部分の波形を取得する
方法を活用すると、ソフトウェアの好きな箇所にトリガーを挿入できるため解析しやすいです。
今回、Nios® II SBT の Run As や Debug As にて Nios® II を動作させて波形を観測します。
4-1. Avalon 信号をトリガーにしてアクセスの波形を取得する
Nios® II の実行領域として使用している On Chip RAM の Avalon 信号をトリガーにして、実行領域から命令コードを読み取っている様子を観測してみましょう。
まず、観測したい命令コードのアドレスを調べます。
Nios® II SBT で Build して生成された ***.objdump ファイルを開いて、観測したい命令のアドレスを確認できます。今回は main 文の一番最初の命令を観測したいと思います。【図15】に示したように、***.objdump ファイルから命令コードと格納されているアドレスを確認すると、0x402_028C 番地であることがわかります。
【図 15】 ***objdump ファイル と ソースコード
このアドレスは、Master の Nios® II から見たアドレスなので、On Chip RAM のアドレスとしてトリガーをかけてもうまく測定できません。次の計算方法で On Chip RAM 上のアドレスを別途算出する必要があります。
On Chip RAM のベースアドレスである 0x0402_0000 を引くと、On Chip RAM 上の命令コードのアドレスは 0x028C になります。更に、Master と Slave の Addressing の関係性は【表 1】のようになるので、Platform Designer の内部配線で Byte Addressing から Word Addressing への変換が自動で行われています。従って実際に観測するアドレスを 4 で割る必要があり、0x028C を 4 で割った 0x00A3 が実際に On Chip RAM の Avalon 信号に伝達されるアドレスになります。
今回は、この 0x00A3 をトリガーに使用していきます。
参考:Intel Quartus Prime Pro Edition User Guide: Platform Designer
Table 99. Avalon Memory Mapped Signal Roles の address の項目をご参照ください。
【表 1】 Master と Slave の Addressing の関係性 (Slave Data Width= 32 bit の場合)
Master / Slave | Addressing | Bit | Address 例 | Addressign の計算式 |
Master | Byte | 8 bit | 0x0402_028C |
Slave Address = (Master Address - Slave BASE Address) / 4 |
Slave | Word | 32 bit | 0x0000_00A3 |
Signal Tap のトリガー条件を【図 16】のように設定します。
・onchip_work_memory|chipselect の 立ち上がりエッジ
・onchip_work_memory|address [14..0] が 00A3h になった時
【図 16】 On Chip RAM の Avalon 信号をトリガーとするときの条件例
実際に実行すると【図 17】のように、Nios® II Instruction Master が On Chip RAM から命令コード 0xDEFFFE04 を読み取っていることがわかります。
【図 17】 観測結果と objdump ファイルの関係性
4-2. 割り込み信号をトリガーにして割り込み処理の波形を取得する
割り込み信号をトリガーにすることで、割り込み処理部分をキャプチャーできます。割り込み処理中の Nios® II の挙動を Nios® II Plug-in で確認してみましょう。
トリガーとして使用する IRQ 信号は、Nios® II の 割り込み入力信号 irq [31:0] でも良いですし、Slave IP の割り込み出力信号 でも問題ありません。
今回は、【図 18】のように Slave IP の割り込み出力信号をトリガーにします。
・u0|Nios_System_KEY:key|irq の立ち上がりエッジ
Nios® II の 割り込み入力信号 irq [31:0] は、入力されている割り込み信号の番号を確認する目的で使用します。
【図 18】 IRQ 信号をトリガーにする際の条件
実際に実行すると【図 19】のように、割り込み信号がアサートされた後 alt_itq_entry.S が呼び出され、割り込み処理がスタートしていることがわかります。
【図 19】 観測結果と Nios® II Plug-in の挙動 ~割り込み処理実行開始箇所~
【図 20】にて Nios® II Plug-in の処理内容を吹き出しで記載していますので、その後の挙動を追ってみます。
alt_irq_entry.S が呼び出された後、alt_irq_handler.c が呼び出され、登録した PIO 割り込みハンドラーの処理に到達していることがわかります。
更に、割り込みハンドラーの処理が終わったことを示すために、割り込みハンドラーの最後に PIO Core の割り込み信号を落とす処理を入れているため、PIO 割り込みハンドラーから抜ける前に割り込み信号が落ちていることも読み取ることができます。
PIO Core における割り込み処理の実装方法は、以下のコンテンツをご参照ください。
参考:Embedded Peripherals IP - PIO Core サンプル
その後は順番通りに、alt_irq_handler.c と alt_irq_entry.S に戻った後、元の処理に戻ります。
このように Nios® II Plug-in を取得しておくと、トリガー周辺の Nios® II の動作を確認しながら解析できます。
【図 20】 観測結果と Nios® II Plug-in の挙動 ~割り込み処理中の Nios® II Plug-in の状態~
割り込み処理時間を短縮させたい方は、下記コンテンツをご参考に、Vectored Interrupt Controller (VIC) をご検討ください。
(VIC は alt_irq_handler.c と alt_irq_entry.S を使用せず、ハードウェアで割り込みを処理します)
参考:5-1. Internal Interrupt Controller(IIC)と Vectored Interrupt Controller(VIC)について
4-3. PIO Core の出力信号をトリガーにして任意のソフトウェア処理部分の波形を取得する
ソフトウェアの観測したい箇所に PIO Core の状態を変化させる処理を入れ、PIO Core の出力信号をトリガーにすることで好きな箇所で Signal Tap を止められます。
今回は、Intel FPGA Serial Flash Controller II Core (SFC_II)のサンプルを使用して、Flash Controller ソフトウェアの好きな箇所をトリガーとして設定し、Flash Controller の As Interface の挙動を確認してみましょう。
参考:Embedded Peripherals IP - Flash Controller サンプル
まずトリガーにしたい箇所を決め、PIO Core にトリガー値を出力する処理を記述します。
ここでは Flash ROM からデータを Read している挙動を確認したいと思いますので、【図 21】のように、SFC_II の Nios® II HAL API である、**_bsp/drivers/src/altera_epcq_controller2.c の alt_epcq_controller2_read() 関数の中にトリガー処理を入れます。
下記のように、IOWR( Base_Address , Offset , Data ); を記載します。
-
-
- BASE Address は System.h に記載の PIO Core Base Address を使用します。
- Offset は PIO Core の Data レジスターが 0 番地なので、0 を設定します。
- Data は トリガーにしたいデータを設定します。今回は 0xAA にしています。
-
PIO Core の詳細については、下記のコンテンツをご参照ください。
参考:Embedded Peripherals IP - PIO Core サンプル
/*** Add Trigger ***/
IOWR(0x4041050,0,0xAA);
/*** Add Trigger ***/
注記:
Nios® II HAL API は、Generate BSP を実行しますと、インストール・ディレクトリーのデフォルトファイルに書き換わってしまいますので、編集箇所を別途保存しておく等注意が必要です。
【図 21】 alt_epcq_controller2_read() 関数 にトリガーを挿入
Signal Tap のトリガー条件は【図 22】のように、PIO Core の Export 信号にトリガー値とした 0xAA を設定します。
・u0|led_external_connection_export[7..0] が AAh になった時
【図 22】 PIO 信号をトリガーにする際の条件
実際に実行すると【図 23】のような波形を取得できます。
あらかじめ Flash ROM には 0x0001_0000 番地に 0xABACADAE というデータを書き込んでおり、そのデータを Read した時の波形になります。
SFC_II は Quad Read コマンドである 0xEB を発行し、Address と Dummy Cycle の後、QUAD でデータを Read できており、Avalon Bus にて 0xAEADACAB が 返ってきていることがわかります(データはスワップされて見えます)。
【図 23】 Flash Controller の Read 波形観測結果
5. まとめ
Signal Tap を使用して、Nios® II の挙動を解析する方法について解説しました。
何か Nios® II の動作が思い通りにいかない時に、今回ご紹介した信号を Signal Tap に追加して、Nios® II の挙動を追うことで、Nios® II SBT Debug ではわからなかった原因を見つけ出せる可能性があります。
是非、お試しください。
注記:
ご紹介した信号をすべて取得できるかどうかは、作成しているデザインに依存しますので、ご自身の環境に適した Signal Tap を作成してください。
おすすめコンテンツ
弊社では Nios® II に関する各種情報をまとめた「Nios® II まとめページ」をご用意しております。
本記事以外にも有用な情報が満載ですので、こちらも併せてご確認ください。