Microblaze MCSをSpartan6で動かす(ISE)
FPGAを使っていると、ソフトウェアCPUを組み込みたくなることがあります。
CPUを組み込むことで複雑な分岐の処理などを楽に作ることができます。
今回はSpartan-6 FPGAにMicroblaze MCSを実装する方法を説明します。
前提条件としてFPGAでLチカができる程度の基礎知識はあるものとします。
まずISEを開き、プロジェクトを作ったら、新規IPをプロジェクトに追加します。
IPの選択でMicroblaze MCSのコアを選択します。
IPが作成出来たらIPの設定画面が開きます。
ここではMicroblazeの設定をします。RAM容量や使用するペリフェラルなどを選択することができます。
注意する点としては、インスタンスネームの指定では実際にインスタンシエートするモジュールのパスを入力する点です。
例えば、topの下にcpu0という名前でmicroblazeをインスタンス化する場合は、Instance Hierarcical Design Nameの欄にcpu0と入力します。
次にペリフェラルの設定をします。
今回はLED点灯を試すため、GPOを使用する設定にします。
GPO1に4bitの出力ポートを作っておきます。
OKを押してIPの設定を終了します。
次にMicroblazeをインスタンス化します。
topモジュールを適当に作り、その下にMicroblazeをインスタンス化します。
メニューのView Instantiation Templateからテンプレートを取得できます。
topに図のようなコードを追加しました。
module top( input Clk, input Reset, output [3:0] GPO1 ); mb_mcs cpu0 ( .Clk(Clk), // input Clk .Reset(Reset), // input Reset .GPO1(GPO1) // output [3 : 0] GPO1 ); endmodule
ここまで来たら一度シンセサイズを行い問題なく通ることを確認します。
次に、Implement Designを正しく行うため、tclスクリプトを実行します。
TCLコンソールを使いますが、コンソールウインドウが初期設定では表示されていないので、図のようにView-Panelsから設定して表示させます。
次にtclコンソールで下記のコマンドを実行します。
source ipcore_dir/microblaze_mcs_setup.tcl
なお、このtclスクリプトはデフォルトではipcore_dirディレクトリの中にあります。
注意としては、カレントディレクトリがプロジェクトルートの状態でtclファイルを指定しないとTranslateでコケます。
ここまでやったら通常と同様にbitファイル作成まで行います。
これでハードウェアの生成は完了です。
SDKでソフトウェアを作成する
次にソフトウェアを作成します。
tclコンソールでxsdkと入力しSDKを起動します。
BSPの作成
起動したらまずはBSPを作成します。
メニューからCreate BSP Projectを選択します。
ipcore_dirの中にハードウェア情報が入ったxmlファイルがあるため、hardware specificationに指定します。
BMMファイルも同じフォルダに入っているため、同様に指定します。
OSはスタンドアロンを選択します。
ここまでの手順でボードサポート部までは完成です。
アプリケーションプロジェクトの作成
次にアプリケーションプロジェクトを作成します。
基本デフォルトで良いですが、以前作ったBSPを選択するようにします。
コーディングする
実際にLチカをさせるプログラムを記載していきます。
microblaze上のペリフェラルはすべてXIOModuleというモジュール経由で操作するようになっています。
下記のようにXIOModuleのドライバ経由でGPOを制御しました。
waitのカウンタは動作周波数に応じて適宜調整してください。
#include "platform.h" #include "xparameters.h" #include "xiomodule.h" void wait(void) { volatile int cnt = 100000; while(cnt--); } int main() { XIOModule xio; init_platform(); XIOModule_Initialize(&xio, XPAR_IOMODULE_0_DEVICE_ID); while(1){ XIOModule_DiscreteWrite(&xio, 1, 0xF); wait(); XIOModule_DiscreteWrite(&xio, 1, 0); wait(); } return 0; }