どもです。
前回はDigilent公式のベアメタルプログラミングのチュートリアルをもとに、CMOD S7にMicroBlazeとそれを動かすための周辺ブロック(メモリとかクロックとかUARTとか)を配置するところまでやりました。
今回はその続きとしてLEDを光らせるためのボタンやLEDとFPGAの接続(GPIO)やVitisを使用したMicroBlaze上で動かすソフトウェアの実装と書き込み、実際の動作確認までやっていきたいと思います。
それでは早速いきましょー
前回の続き
GPIOをブロックに追加する
今回はボード上のコンポーネント(LEDとか)からGPIOブロックを接続していきます。
Diagramの左にある小さなウィンドウの"Board"タブより"GPIO"の一覧から"4LEDs"を右クリックして、「Connect Board Component」を選択します。
以下のようなウィンドウが開くので、"AXI GPIO"一覧の"GPIO"を選択し"OK"をクリックします。
追加されたGPIOブロック"axi_gpio_0"をクリックすると、左下にBlock Propertiesが表示されますので、
Nameに"AXI_GPIO_LED"とすると名前が変化します。今後オリジナルのプロジェクトを作る際に、わかりやすい名前のブロックにしておくために覚えておくと良いと思います。
次はBoard Componentからではなく、Block DiagramからGPIO IPを追加してBTN1(タクトスイッチ)と接続してみます。Block Diagram上列の"+"ボタンをクリックします。
検索欄が出てくるので"gpio"と入力し、表示される"AXI GPIO"をダブルクリックします。
AXI_GPIO_LEDと同様に、このブロックの名前を変更します。BTN1と接続するので、"AXI_GPIO_BTN1"としました。
Digilent用XDCファイルをダウンロードする
ここで一回Vivadoから離れて、環境設定に移りたいと思います。
なんとDigilentは販売しているFPGAボードに合わせたXDCファイルも準備してくれています。
www.acri.c.titech.ac.jpこれを入れておくとだいぶ楽になるので、入れておきたいと思います。
まず、以下のリンク先からXDCファイル一式をダウンロードします(自動ダウンロードされるので注意してください)。
ダウンロードされたZIPファイルを展開し、紛失しないよう任意の場所に保存しておきます。
Vivadoに戻り、左側のメニューの"PROJECT MANAGER"一覧から"Add Sources"を選択します。
以下のようなウィンドウが表示されるので、"Add or create constraints"を選択し、"Next"をクリックします。
"Add Files"を選択します。
XDCファイル一式を保存したフォルダに移動し、使用するボードに対応したXDCファイル(今回の場合は"Cmod-S7-25-Master.xdc")を選択し"OK"をクリックします。
ファイルが選択されたら"Copy constraints files into project"にチェックを入れ"Finish"を選択します(チェックを入れておくことで今回使っているプロジェクト用にXDCファイルがコピーされ、ダウンロードしたXDCファイルが上書きされるのを防ぎます。なんという親切設計!)。
AXI_GPIO_BTN1とBTN1を接続する
Block Diagramの左側のショウウィンドウから"Sources"タブを選択し、"Constraints"から、先程追加したXDCファイルをダブルクリックすると、Block Diagramと同じウィンドウにXDCファイルが表示されます。
btn[1]だけコメントアウト("#")を外します。
Block Diagramに戻り、AXI_GPIO_BTN1の"GPIO"の文字列を右クリックし、"Make External"を選択します。
するとブロックが何か出力っぽいものと配線されます。
つながった先は"GPIO_0"になっているかと思いますので、IPのブロック名変更と同様の手順で、XDCに記載されているボタンのネット名"btn"にしておきます。
ここから少し作業が細かくなってきます。AXI_GPIO_BTN1ブロックを拡大し、"GPIO"の横にある"+"をクリックすると・・・
こんな感じで"gpio_io_i[31:0]"、"gpio_io_o[31:0]"、"gpio_io_t[31:0]"が見えるようになります。
このままだと32bitのGPIOとして認識されますので、BTN1の数となるように調整する必要があります。
AXI_GPIO_BTN1をダブルクリックして、IP設定画面を開きます。
"IP Configuration"のタブを開き、"All Inputs"にチェックを入れて、"GPIO_Width"を1に設定し、"OK"をクリックします。
GPIOブロックとMicroBlazeや周辺ブロックと自動で接続してしまいます。Diagram内の"Run Connection Automation"をクリックします。
"All Automation"にチェックを入れ、"OK"をクリックします。
デザインを検証する
ここまで設計したデザインが問題ないか確認します。Block Diagramの"Validate Design"をクリックします。
問題がなければ以下のようなメッセージが表示されます。
HDL Wrapperを生成する
Validate Designで問題なければHDL Wrapperを生成します。
Diagram左のウィンドウから"Sources"タブを選択し、"Microblaze_blink"を右クリックして"Create HDL Wrapper..."を選択します。
以下のようなウィンドウが出てきます。"Let Vivado manage wrapper and auto-update"を選択して"OK"をクリックします。
コンパイルする
コンパイルします。左側のメニューから"Generate Bitstream"を選択します。
今回の例では論理合成や配置配線をしないまま選択するので以下のようなメッセージが表示されますが、"Yes"をクリックします。
論理合成・配置配線されていない場合はそこから始めてくれます。
コンパイル(論理合成・配置配線)の設定ウィンドウが開きます。
"Launch directory"はそのまま、Optionsは"Launch runs on local host"(開発環境のCPUパワーのみを使う)にします。
"Number of jobs"はコンパイルに使用するCPUのスレッド数です。多いほど早く終了しますが、他のソフトウェアがフリーズする可能性もあるため、マルチタスク(コンパイルしながら資料を作るなど)する場合は注意が必要です。今回は実際に扱うLinuxマシンで最大の"12"に設定して時間を測ってみます。
設定が完了したら"OK"をクリックします。
・・・・と思ったらVivadoが落ちました。デフォルトの"6"で再度試します。
エラーが出ました。3 errorsの部分をクリックしてメッセージを表示してみます。
なんか長いのが出てきてますが、「btn_tri_i[0]が配線されていない」といったメッセージでした。XDCファイルを開き直して、btn[1]をbtn_tri_io[0]にして再度コンパイルをやり直してみます。
コンパイル完了しました。正直XDC周りがよくわかっていないのがお恥ずかしい限りです・・・(やってみた記事なので寛容にみていただけると幸いです。)
コンパイルにかかった時間は2分弱です。
何をするかを選び"OK"をクリックするか、そのまま何もしない場合は"Cancel"をクリックします。
Hardware Platformを出力する
Vivadoで作成したハードウェア情報をVitisで使用できるようにHardware Platform(XSAファイル)を出力します。
これがあるとVitis側からソフトウェアとハードウェアをまとめて書き込むことが可能です。
Vivadoのメニューから"File"→"Export"→"Export Hardware"を選択します。
以下のウィンドウが開きますので"Next"をクリックします。
"Include Bitstream"を選択し、"Next"をクリックします。
出力するXSAファイル名と出力先を選択し、"Next"をクリックします。
最終確認の画面が出ますので、保存場所や出力形式に間違いがなければ"Finish"をクリックします。
これにてVivado側での作業は終了です。熱いお茶と和菓子で一服しましょう。笑
Vitisでソフトウェアを設計する
最近知ったんですが「ヴィティス」じゃなくて「ヴァイティス」だそうです。
Vitisを立ち上げる
Vitisを立ち上げてソフトウェアを開発していきます。
VitisはVisual Studio Codeベースの"Vitis Unified IDE"とEclipseベースの"Vitis Classic"があります。Vitis ClassicはDeprecatedとなっているため、近い将来に使用不可能と鳴る可能性があります。
今回、Vitis Unified IDEでの開発を試みましたが、この記事を書いている時点でビルドに失敗する状況なので、公式チュートリアルどおりにVitis Classicで開発していきたいと思います。
以下の"Vitis Classic 2023.2"が今回使用するVitis(以下Vitis ClassicをVitisと呼びます)です。
Workspaceを選択する
Vitisを立ち上げると、ソフトウェアの開発に必要なファイル一式を保存する場所(これを"Workspace"と呼びます)を選択する画面が立ち上がります。
今回はVivadoプロジェクト保存場所"Digilent_Microblaze_Tutorial"の直下に"Vitis_Workspace_Classic"というフォルダを作りWorkspaceに指定しました。
VitisではWorkspace指定後にVitis Unified IDEへの移行を促すメッセージがでますが、今回は無視して"Continue With classic Vitis"を選択します。
Application Projectを作成する
Vitisの初期画面が表示されますので、"Create Application Project"を選択します。
プロジェクト作成フローの説明画面が出てきます。"Next"をクリックします。
Platform選択画面に移ります。今回はVivadoで出力したXSAファイルを使用しますので、"Create a new platform from hardware (XSA)"のタブを選択し"Browse"ボタンをクリックして、
XSAファイルを指定し、"Next"をクリックします。
Application Projectの名前を決めます。基本的に半角スペースや特殊文字がなければどんな名前でも良いと思います。今回は"Microblaze_blink_app"としました。
名前を入力したら"Next"をクリックします。
Domainを決めます。今回はMicroBlazeをベアメタルで動かすので、Operating Systemの欄が"standalone"、Processorの欄が"microblaze_0"になっていることを確認し、"Next"をクリックします。
設計するソフトウェアをテンプレートから設計できます。Digilent公式では"Empty Aplication (C)"からやっていますが、
実はMicroBlazeはinit_platformなくても動くんですが(Zynqはこれ呼ばないと動きません)、一番基本となるhello worldアプリケーション内でも記述されているので書いた方が安心だと思います
— 🦖 (@fcr0842361) February 4, 2024
とのことなので、習慣づけの意味も込めてHello Worldを選択し"Finish"をクリックします。
すると必要なファイルが自動で生成され、以下のような画面表示になります(うーん、がっつりEclipse!)。
プログラムを作成する
Hello Worldからプロジェクトを生成すると、自動で"helloworld.c"というエントリポイントが作られるので開いてみます。
コレとDigilent公式チュートリアルのプログラムを合体させて、以下のようなソースコードにしました。
プログラムを一部修正する
公式チュートリアルからボードが違っていたり、変数・定数名が変わっていたりするので修正します。
"xparameters.h"を確認し、ボタンとLEDに対応するGPIOのデバイスID定数名をエントリポイント側で変更します。
AUDIYの場合は、"XPAR_AXI_GPIO_BUTTONS_DEVICE_ID"を"XPAR_AXI_GPIO_BTN1_DEVICE_ID"に変更する必要がありました。
また、"helloworld.c"内の"BTN_MASK"の値を0b1111から0b0001に変更します。
これは公式チュートリアルで使用するボタン数の想定が4なのに対し、今回はBTN1の1つしか使用しないためです。
ここまでできたらhelloworld.cを保存します。
プログラムをビルドする
Systemの項目(今回の例では"Microblaze_blink_app_system")を選択した状態で、ハンマー(トンカチ?)の絵のボタンをクリックするとビルドが開始されます。
ビルドに成功すると以下のような表示がウィンドウ下部のコンソールに表示されます。
動作確認
さてさて、動作確認します。
動作確認の前に以下の環境を整えておきます。
GTKtermについては下記記事がわかりやすいと思います。
ターミナル立ち上げ
GTKtermを立ち上げてUSB-UARTシリアル通信のためにポートを開けておきます。
設定は以下のようになります。ボーレートにご注意ください。
プログラムの実行
Vitisのウィンドウに戻り、Application Projectを選択して右クリック→"Run As"→"Launch Hardware (Single Application Debug)"をクリックします。
うまく行くと以下の動画の用にGTKterm上に"Entered function main"と表示され、、BTN1を押すと4つのLEDが点灯します。
すったもんだしつつもLinux環境でMicroBlaze動きましたわね pic.twitter.com/RCWSHL7rKc
— AUDIY (@AUDIY14) February 4, 2024
ここまで完了した方、お疲れ様でした!
少し改造して、ボタンを押したときと話した時に表示するようにしたり、これからドシドシ遊んでください。
プログラム少し改造したよ pic.twitter.com/JYTzn7kRK8
— AUDIY (@AUDIY14) January 21, 2024
以上、Linuxマシン+CMOD S7で行うMicroBlazeのチュートリアルでした。
個人的には「慣れてしまえばIntel FPGAよりもソフトウェアの開発の難易度は低いかもしれない」と感じましたが、今回の「やってみた」記事だとなかなかそのあたりは伝わりにくいかもしれません。
ぜひぜひDigilentのFPGAボードを入手された方は本家チュートリアルと格闘しながら個々のボードに合わせて修正してみてください。
さてさてこれでLinuxマシンでとりあえずAMD FPGAと通信できることがわかったので、もう少しツールに慣れたらKRIA KR260と再び格闘することにしたいと思います。(自分が情報系の学部を卒業してから暫く経ってて最近のトレンドについていけていないですし、せっかくLinuxマシンを入手したのでそのあたりリハビリしたいですね)
それでは。