Vivado/Vitis 2024.1 の MicroBalze Vを使う

Pocket

Vivado 2024.1でRISC-V ISAのMicroBalzeVが利用できるようになりました.この記事は,Vivado 2024.1 で Arty (Arty A7-100)を対象にMicroBlazeVを利用する手順のメモです.

前半では,Vivadoを使って,MicroBlaze Vを含むFPGA FWの準備をして,後半では,Vitisをclassicモードで起動して,MicroBalze V上でのプログラムの実行を試してみます.

なお,これは,Vitis/Vivado 2020.1でMicroBlazeを使う のMicroBlaze V版です.

おおまかな開発の流れ

開発の流れは次の通りです.

  • IP IntegratorでMicroBlazeVデザインを用意
  • Generate Bitstreamでbitファイルを作成
  • 「Export Hardware」で .xsa ファイルを作る
  • Vitis を classic モードで起動する
  • xsaファイルを使ってプロジェクトを作成
  • プログラムをビルドしてFPGAにロード,実行する

IP IntegratorでMicroBlaze Vデザインを用意する

プロジェクトを作成して,Create Block Design をクリックして IP Integrator を起動します.とりあえず主役(?)のMicroBlaze Vをおきます.しっかり,RISC-Vのロゴが登録されています.ちなみに,MicroBalze MCS と同じ用な用途に対応していそうな MicroBlaze MCS V も用意されているようです.

Run Block AutomationをクリックしてMicroBlaze Vの設定をします.ここでは,Local Memoryを32KBに設定.そのほかはそのままにしておきます.

Run Block Automationが終わると,クロック(clk_wiz_1)やリセット(rst_clk_wiz_1_100M)などのモジュールが追加されます.ついでに,UART(axi_uartlite_0)とGPIO(axi_gpio_0)のインスタンスも追加しておきましょう.UARTのボーレートを変更したければ,axi_uartlite_0をダブルクリックしてダイアログを開いて設定できます.デフォルトでは9600ボーでした.

clk_wiz_1の設定をします.インスタンスをダブルクリックして,Clocking Optionsペインで入力クロックをSingle ended clock capable pinに,Output Clocksペインでリセットの極性を Active Low にセットします.

設定したら,Run Connection Automationをクリックします.自動接続するダイアログで,rst_clk_wiz_1_100M以外を選択してOKをクリックします.

自動接続の対象外にしたrst_clk_wiz_1_100Mのext_reset_inをreset入力ポートに接続します.

axi_gpio_0インスタンスの設定ダイアログを開いて,GPIOをLED出力とスイッチ入力に割り当てます.

設定を変更したら,一度GPIOの先の出力ポートを削除して,Run Connection Automationを再実行.変更したGPIOの先にLEDとスイッチ用の出力ポートが追加されます.

最終的にはこんな感じのデザインができました.

メモリマップはこんな感じでした.

bitファイルを生成

IP Integratorで作ったブロックデザインのラッパーモジュールを作って合成します.ラッパーモジュールはいつものように Create HDL Wrapper で生成します.

トップモジュールをつくったら,Generate Bitstreamをクリックして,ビットファイルの生成を開始.しばらく待ちます.

ハードウェアのエクスポート

bitファイルの作成が終わったら,Vitisでのソフトウェア開発用にハードウェア情報をパックします.まずは,File → Export → Export Hardware… でウィザードを開きます.

最初は何も考えずにNextをクリック.

次は,Include bitstreamにチェックをいれてNext.

最後にファイルの出力先を決定します.特にこだわりがなければ,デフォルトのままでよいでしょう.生成されるファイルの拡張子は xsa です(以降 xsa ファイルと呼びます).

最後にサマリ情報が表示されるので,Finishで終了です.

合成結果をみてみる

Open Implemented Designで合成結果をみてみます.割当は次のようになっていました.

Rport Utlizationで確認すると,A7-100に搭載されているFPGAのSlice数15850個のうちMicroBlaze Vで541個が使用されていました.

Vitisでソフトウェア開発

Vitisのインターフェースが刷新されていますが,(よくわからないので)旧来のインターフェースで実行します.旧来のインターフェースで実行するには,

$ vitis -classic

と,-classic オプションをつけて vitisの起動コマンドを実行します.

起動コマンドを実行すると,作業ディレクトリを尋ねられます.ここでは,Vivadoプロジェクトを作成したディレクトリと同じ場所に,Vitisというディレクトリを作ることにしました.Launchをクリックすると,Vitis IDE(classic)はDeprecatedですというダイアログがでてきますが,気にせずに,Continue With classic Vitisで次にすすみます.

Vitisが起動してきました.Eclipseで作られたGUIですね.Create Application Projectをクリックして,プロジェクトの作成ウィザードを開始します.

プロジェクトの作成

作成したハードウェア情報のxsaファイルを読み込んでプロジェクトを作成します.最初の画面は,Next>で次にすすみます.

次のPlatformでは,Create a new platform from hardware (XSA)タブを選択して,Browse... から作成したxsaファイルを選択します.

Application Project Detailsでは,プロジェクト名とプロセッサの指定です.プロジェクト名は,hello_worldとつけておきます.プロセッサが microblaze_riscv_0 になっていて,たしかにRISC-Vが使われている雰囲気が味わえますね.

DomainではOSやアーキテクチャの指定をします.デフォルトのままで Next>をクリックしましょう.

最後に,Templatesで,プロジェクトのテンプレートを選択できます.Hello Worldを選択して,Finishをクリックします.

無事にプロジェクトが作成できました.

プログラムのビルドと実行

Hello Worldテンプレートでプロジェクトを作成したので,helloworld.cが用意されています.まずは,ツールバーのハンマーアイコンでプロジェクトをビルドします.Consoleペインに表示される実行ログを見ると,riscv64-unknown-elf-gccでプログラムがビルドされることがわかります.

ビルドしたソフトウェアを実行する前にFPGAをコンフィギュレーションしましょう.メニューから,Vitis → Program FPGAとたどってダイアログを起動します.

FPGAのコンフィギュレーションダイアログです.xsaにビットファイルを含めていますのでデフォルトのままで適切にFPGAをコンフィギュレーションできます.もちろん,プロセッサやメモリ構成が同じであれば別のビットファイルを読み込んでも構いません.ProgramをクリックしてFPGAをコンフィギュレーションします.

FPGAのコンフィギュレーションが終わったら実行しましょう.Hello Worldの出力を確認するために,別途シリアル接続用のターミナルを開いておきます.ボーレートは 9600 です.プログラムを実行するは,ビルドしてできた,Explorerペインで,Binariesの下にある,hello_world.elfを選択した状態で,ツールバーの再生アイコンをクリックします.

実行環境の選択ダイアログでてきますので,Launch Hardware (Single Application Debug)を選択して,OKをクリックします.

無事に実行できると,Hello Worldが表示されます.

GPIO経由でLチカする

GPIO経由でLチカしてみましょう.GPIOはIP Integratorで確認したところによると,0x40000000 にマッピングされています.たとえば,次のようにプログラムのmain関数を変更してみましょう.

int main()
{
    init_platform();

    print("Hello World\n\r");
    
    volatile unsigned int * led = (volatile unsigned int*)0x40000000;
    int i = 0;
    for(int i = 0; i < 256; i++){
    	*led = i;
    	xil_printf("%d\n\r", i);
    	usleep(500000);
    }
    
    print("Successfully ran Hello World application");
    cleanup_platform();
    return 0;
}

編集したらファイルを保存して,先程と同様にハンマーアイコンをクリックしてビルドします.ビルドがおwったら,今度は,デバッガを使って実行してみましょう.デバッガを使って実行するには,ツールバーの虫アイコンをクリックします.

デバッガの元でプログラムの実行が開始され,デフォルトでブレークポイントが設定されていたinit_platform()のところで一時停止します.ツールバー上部のResumeアイコンをクリックして,プログラムを再開します.

プログラムが再開すると,シリアルコンソールに,1,2,3,4,…と50m秒ごとに出力されるとともに,下位4bitの値に従ってFPGAボード上のLEDが点灯する様子を確認できます.最後に,Successfully ran Hello World applicationと表示されておしまいです.

まとめ

というわけで,MicroBlazeVを味見してみました.従来のMicroBlaze同様の手順でハードウェア・ソフトウェア開発ができることが確認できました.ユーザガイドによるとFPGAならではの専用命令として,AXI4-Streamとのアクセス命令 GETPUTが用意されているようです.試してみたいですね.