FRAMにアクセス (協調シミュレーション編)
NIOSを含めたシミュレーションの実行になります。
シミュレーション環境の構築方法とNiosのシミュレーション用コードの生成方法、及びシミュレーション波形を添付します。
NIOSプログラムやテストベンチは、前回の記事をご参照ください。
シミュレーション環境構築
シミュレーション環境を構築しますが、必要なファイルなどのリストを作成するのが面倒なので、Platform Designer で環境を作成し、生成されたスクリプトファイルを改造して使用します。
実行スクリプトファイル生成
Quartusを起動し、「Platform Designer」を立ち上げて作成したQsysファイルを読み込みます。
その後、[Generate]→[Generate Tesetbench System]を選択します。
「Generation」Windowが表示され、"Generate"ボタンをクリックします。
以下の選択内容で十分です。(生成されたテストベンチは使用しないので。。。)
"Generate"ボタンをクリックすると、Quartus実行フォルダに以下のフォルダが出来上がります。
フォルダ
<Platform Designerで作成したモジュール名>/testbench/mentor
このフォルダに実行スクリプトファイル(ファイル名:msim_setup.tcl)が出来上がります。
このスクリプトファイルは、「Platform Designerで作成したモジュール」をトップとしたシミュレーション環境になるため、FPGA TOPからシミュレーションする場合は、改造が必要になります。
尚、Platform Designerで作成した必要なIPのリストはあるので、あとは、ユーザの作成したソースを追加するだけとなります。
スクリプトファイルの修正
msim_setup.tclの修正内容を説明します。
1、NIOSプログラムファイルのコピー元を変更
Nios II - Eclipseでコンパイルしたデータのコピー元を変更します。
2、テストベンチのコメントアウト
Platform Designerが生成したテストベンチをコメントアウトします。
3、ユーザー回路の追加
ユーザー回路を追加し、テストベンチや必要なファイルを追加します。
私の場合、alias comとは別に、新しいaliasを作成して追加します。
尚、TB_TOP.vとFRAM_SPI.v(FRAMモデル)は、シミュレーション実行フォルダにあります。
4、elab修正
alias elabでは、vsimを実行しています。
このままの実行では、Platform Designerが生成したテストベンチとなっているため、修正します。
TB_TOP.vがテストベンチとなるため、$TOP_LEVEL_NAMEを「TB_TOP」に修正します。
以上で、msim_setup.tclの修正は終了となります。
NIOSプログラム
NIOSのプログラムデータは、CPU_MEMに格納されるようになっています。
このファイルを作成する方法を説明します。
オプション設定
「Nios II - Eclipse」を起動し、プロジェクトを読み込みます。
シミュレーション用のコードにするため、オプションを設定します。
「BSP Editor」を起動し、"enable_sim_option"にチェックを入れます。
※入れない場合は、シミュレーションでNiosが動き出すまでに時間がかかります。
また、「Debug Level」と「Optimization level」を変更するともっと速くなります。
以下は、私の設定です。
コード生成
上記設定を行った後、再度コンパイルを行います。
その後、[Make Targets]→[Build]を選択し、「mem_init_generate」を選択して、"Build"ボタンをクリックします。
NiosのCソースを変更し、シミュレーションする場合は必ず実行する必要があります。
また、ここで生成したファイルは「msim_setup.tcl」のfile_copyでシミュレーション環境にコピーされます。
以上までが、シミュレーションを実行するまでの準備となります。
シミュレーションの実行
ModelSimを起動し、シミュレーションを実行します。
実行方法は、以下の通りです。
1、[File] → [Change Directory]で、
<Platform Designerで作成したモジュール名>/testbench/mentor
に移ります。
2、msim_setup.tclを実行します。
2通りあります。
[Tools] → [Tcl] → [Execute Macro]から実行する。
"Transcript"から実行する。
3、コンパイルと実行
msim_setup.tclを実行後、"Transcript"でコンパイルし、エラボレートします。
尚、msim_setup.tclを実行すると、file_copyが実行されています。
コマンドの順番は以下の通りです。
> com
> com_user
> com_tb
> elab
となります。
あとは、"run"してシミュレーションを実行するだけです。
シミュレーション結果
シミュレーション波形を添付します。
全体波形
Niosソース内で、port_aにステップ番号を出力しているので、それを目安にどの部分を実行しているか分かります。
波形の「port_a_export」がそれにあたります。
リセット解除後、約400usでNIOSの動作が開始します。(port_aが0x00 → 0x01に変化)
また、ソースの終了は、port_a=0xFFになり、FRAM_WP_N=1になると終了となります。
(0xFFの期間が長いのは、printfを実行しているためです。)
マスタモード Load
リセット解除後、マスタモードによるロード動作になります。
入力信号MST_SLVとPRM_???はテストベンチからforceで値を入力し、動作させています。(ブート制御回路を作成するのが面倒だったので、外部から動かしました。)
ここでは、FRAMのDevice ID、Serial No、特殊セクタ、通常メモリをメモリPARAMETERに保存しています。
ステータスリード
FRAMのステータスレジスタをリードし、メモリPARAMETERの指定した番地へ保存し、リードしていることが確認できます。(変数FramSTは、メモリPARAMETERの0x920番地に関連付け)
尚、データバス幅は32bitとなるため、アドレスは「÷4」した値になります。
Device ID及びSerial No確認
メモリPARAMETERの指定した番地をリードしています。
データ書き換え
メモリPARAMETERの指定した番地をリードし、リードしたデータを加工し書き戻しています。
尚、FramSS,FramDTも書き換えています。
メモリPARAMETERからFRAM I/Fへ転送
メモリPARAMETERの指定した番地をリードし、FRAM I/Fへライトしています。
FRAM I/FからメモリPARAMETERへ転送
FRAM I/Fからデータをリードし、メモリPARAMETERへ保存しています。
メモリPARAMETERの保存は、FramTMとなります。
割り込み動作
FRAMへのアクセスが完了し、割り込み(irq[0])が発生。
その後、割り込みクリアして割り込みが解除されます。
比較結果
Niosソース及びテストベンチでの比較結果は、動作が終了するとerror数を表示します。
以下が結果表示内容です。
比較結果のerror数が0を表示したため、データエラーは無しになります。
最後に
実機があれば、SignalTapでFPGAの内部波形を確認してデバッグが可能ですが、上記のように接続関係や基本動作を確認する上では、シミュレーションが速いと思います。
SignalTapでは、保存する信号と保存期間はRAMの空き容量に依存し、見たい所が見れない場合もあります。
また、クロックが何系統もあると、保存クロックに悩んでしまいます。
今回、「__attribute__」を使って別メモリに変数を関連付けました。
それが思い通りになっているかも、波形で確認ができます。
「FRAMにアクセス」をテーマに、半導体(FPGAですが)を実機で動かす手前までの工程をざっくりですがブログに記載しました。
ここまで2回のシミュレーションを行い、動作確認をしています。
FRAM I/Fブロックのシミュレーションでは、ブロック自体にバグが無いかの確認のため。
FPGA TOPからのシミュレーションでは、各ブロックの接続関係と矛盾点が無いかの確認のため。
このあとは、基板上のデバイス間接続を確認するため、Niosコードをそれ用に変更していきます。
もし上記シミュレーション無しで、基板で確認すると、どこが悪いのかの切り分けができず、余計に時間がかかります。
Niosを含めたシミュレーション環境構築は非常に簡単です。
もし実機で動かない場合は、シミュレーションで確認してみるのも良いかもしれません。