電子回路わからん日記

にゃーんと言いながら電子回路いじってます

Verilator、(Linterとして)はじめました。

どもです。

これから暖かくなるので、

Verilator(冷やし中華)、はじめました。w


Verilatorとは

Veripoolが開発するオープンソースVerilog/SystemVerilogシミュレータです。

www.veripool.org

テストベンチやモジュールをマルチスレッド(!)のC++コードに変換(公式ではこの変換を"Verilate"と呼んでいます)し、C++コンパイラで実行可能形式にコンパイル後、実行することで高速なシミュレーションを実現しているのがウリのようです。

名だたる半導体メーカー(WD、Intel、NXPなど)でも使用されており、Chips AllianceやLinux Foundationから支援を受けているなど、業界ではかなり有名な様子。

公式では「Synopsys(VCS)/Siemens(Questa/ModelSim)/Cadence(Xcelium/Incisive/NC-Sim)と合わせた4大シミュレータの一つ」と豪語しています(本当か?)

veripool.org

AUDIY自身、Verilatorの勉強会を数年前に受けたことがあり、個人的には興味を持っていましたが当時はC++での記述が大量に出てきて正直「これならシミュレーションはIcarus VerilogとかQuartus等に付属しているやつで良いかな」という印象でした。

connpass.com


導入方法

主に3通りの導入方法があります。

veripool.org

それぞれの導入方法でのメリット・デメリットは以下の通りとなります。

パッケージマネージャを使用する

メリット
  • 確実に安定版が導入できる
  • 依存関係も合わせてインストールしてくれる
デメリット

gitからソースコードを入手しビルドする

メリット
  • 常に最新版を導入できる
  • パッケージマネージャで自動的にバージョンアップされないので特定のバージョンを長く使用可能
デメリット
  • 依存関係を自分で調べて導入しておく必要がある
  • OSや依存関係とのバージョンの整合性が取れないときにインストールに失敗する場合がある
  • 最新版導入のたびにビルドの必要がある

Dockerを使用する

メリット
  • ビルドせずに最新版を導入可能
  • 常に最新版を導入できる
  • コンテナを利用しているので依存関係を気にしなくて良い
デメリット
  • Dockerの知識が必要
  • Verilatorでは自前の環境より動作に若干時間がかかる
  • VerilatorではVSCodeとの連携が困難

今回はVSCodeプラグインと連携させてLinter機能を使いたかったのと、AUDIYが使っているUbuntu 22.04 LTSではパッケージマネージャで配布されてるVerilatorのバージョンが4と古いので、gitからソースコードを入手しビルドしたいと思います。


ビルド方法

今回はWindowsマシン上にWSL2 + Ubuntu 22.04を構築して導入したいと思います。

WSL2の導入はこの記事が詳しいと思います。

www.aise.ics.saitama-u.ac.jp

Ubuntuが導入できたらあとは以下のページの内容の通りに依存関係を導入してインストールすれば問題ないと思います。

Ubuntu 22.04の場合では「zlibcが無い」とエラーが出ますが、その場合は無視して良いです。

veripool.org

ちなみにですが、

それ以前はC++でテストベンチ書く必要があったようですね・・・・
ちなみにC++テストベンチのサンプルコードはカオスです。

dora.bk.tsukuba.ac.jp


動かしてみる

テストベンチから実行形式を吐き出してみます。
とりあえずでてきた警告は無視させています。

github.com

 

  • verilator --cc --binary --timing --trace --trace-params --trace-structs --trace-underscore -Wno-TIMESCALEMOD -Wno-WIDTHTRUNC +1364-2005ext+v SDPRAM_SINGLECLK_tb.v

 

成功するとobj_dirというディレクトリ内に実行ファイルができますので、メモリ初期化ファイル(ram_init_file.mem)を同一ディレクトリに置いて

  • ./VSDPRAM_SINGLECLK_tb

 

vcdファイルが作成されるので、gtkwaveで読み込めば

 

vcd出力の際にオプションが必要になったり、一部のVerilog記述のシミュレーションが非対応だったり、

msyksphinz.hatenablog.com

Warningが出力される時点で実行形式は生成されない(厳しいな・・・・)ので、単純なシミュレーションだけであればIcarus Verilogの方が実行オプションも少なく使いやすい印象です。

github.com

 

WarningやErrorは結構細かい内容が網羅されている(悪く言えば制限が強い)ので、AUDIYのような「コーディングルールがフラフラしがち」な人には良い矯正ツールだと思います。


そこで考えた

「これ、Linterとして使えないか・・・?」

そこでAUDIYが使っているVSCodeVerilogプラグインを調べてみると・・・・

marketplace.visualstudio.com

・・・・・ありました。

Verilatorと連携してVSCode内のLinterとして使えます!

もう少し設定を追っていきますと・・・

 

Verilatorの実行オプションを追加できたり

WSL上に構築したVerilatorを使用することもできるようです。

それではやっていきましょう。

Verilog > Linting: Linter」を"verilator"に設定します。

Verilog > Linting > Verilator: Arguments」に必要なオプションを追加します。
AUDIYの場合は「警告を全て出力」「遅延評価する」「Verilog記法はVerilog-2005で指定」にしました。

Verilog > Linting > Verilator: Run At File Location」と「Verilog > Linting > Verilator: Use WSL」にともにチェックを付けます。

ではLinter実行結果を見ていきましょう。


Icarus VerilogとLint結果を比較

Icarus Verilog

なるほどなるほど・・・

"syntax error"を教えてくれるのは良いんですが何がどうダメなのか・・・

この行は問題ないのにその前の行のエラーに引っ張られてエラーになってしまっています・・・

Verilator

「"="がおかしくない?」とエラー箇所を推測しています

ここも同様ですね。「"end"周辺がおかしい」とわかります。

Icarus VerilogのLint機能にはありませんでしたが、VerilatorだとWarningも出してくれます。

「順序回路の中でブロッキング代入使ってるけど大丈夫?」というWarningです。

「ファイル末尾は行を入れておくのが推奨ですよ」とまで。かなり丁寧ですね。


ということで、VerilatorをLinterとして導入しました。

AUDIYのXには

github.com

とオススメもありましたが、こちらガチガチのSystemVerilogルールでLint(wire, reg宣言すらもWarningにするほどには)してて、Verilog主体のAUDIYにはまだまだ早い感じでした(設定ファイルを編集してLintルールを細かく設定できるのでいずれは使いこなしたい)。

WindowsのみならずLinuxマシンにも導入しているので、Linterのみならずシミュレータとしても使っていければと思います。

CMOD S7でMicroBlazeやってみる(後編)

どもです。

前回はDigilent公式のベアメタルプログラミングのチュートリアルをもとに、CMOD S7にMicroBlazeとそれを動かすための周辺ブロック(メモリとかクロックとかUARTとか)を配置するところまでやりました。

digilent.com

audio-diy.hatenablog.com

今回はその続きとして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ファイル一式をダウンロードします(自動ダウンロードされるので注意してください)。

https://digilent.com/reference/lib/exe/fetch.php?tok=a49a20&media=https%3A%2F%2Fgithub.com%2FDigilent%2Fdigilent-xdc%2Farchive%2Fmaster.zip

ダウンロードされた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)"からやっていますが、

とのことなので、習慣づけの意味も込めて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")を選択した状態で、ハンマー(トンカチ?)の絵のボタンをクリックするとビルドが開始されます。

ビルドに成功すると以下のような表示がウィンドウ下部のコンソールに表示されます。


動作確認

さてさて、動作確認します。

動作確認の前に以下の環境を整えておきます。

  1. AMD FPGA用ケーブルドライバのインストール
  2. Tera term(Windows)、GTKterm(Linux)のインストール

GTKtermについては下記記事がわかりやすいと思います。

zenn.dev

ターミナル立ち上げ

GTKtermを立ち上げてUSB-UARTシリアル通信のためにポートを開けておきます。
設定は以下のようになります。ボーレートにご注意ください。

プログラムの実行

Vitisのウィンドウに戻り、Application Projectを選択して右クリック→"Run As"→"Launch Hardware (Single Application Debug)"をクリックします。

うまく行くと以下の動画の用にGTKterm上に"Entered function main"と表示され、、BTN1を押すと4つのLEDが点灯します。

ここまで完了した方、お疲れ様でした!

少し改造して、ボタンを押したときと話した時に表示するようにしたり、これからドシドシ遊んでください。


以上、Linuxマシン+CMOD S7で行うMicroBlazeチュートリアルでした。

個人的には「慣れてしまえばIntel FPGAよりもソフトウェアの開発の難易度は低いかもしれない」と感じましたが、今回の「やってみた」記事だとなかなかそのあたりは伝わりにくいかもしれません。

ぜひぜひDigilentFPGAボードを入手された方は本家チュートリアルと格闘しながら個々のボードに合わせて修正してみてください。

さてさてこれでLinuxマシンでとりあえずAMD FPGAと通信できることがわかったので、もう少しツールに慣れたらKRIA KR260と再び格闘することにしたいと思います。(自分が情報系の学部を卒業してから暫く経ってて最近のトレンドについていけていないですし、せっかくLinuxマシンを入手したのでそのあたりリハビリしたいですね)

それでは。

CMOD S7でMicroBlazeやってみる(前編)

どもです。

どうやらEfinixのFPGA書き込み用ドライバによって標準ドライバ環境を破壊されたらしく、

もう二度とメインマシンにEfinix FPGAの開発環境入れませんわ・・・・

ドライバ環境を一からやり直すとなるとWindowsクリーンインストールしかなさそうなのですが、それはそれで時間がかかって面倒くさいのと、C言語でのソフトウェア開発でLinuxマシンがないと不便なこともあり・・・・・・

・・・・・・導入しました。

今は購入したThinkPadUbuntu入れてVitisやらDockerやらC/C++コンパイラやら入れて使ってます。

やっと開発環境も整いつつあるんで、今回は前回の続きとして、

audio-diy.hatenablog.com

CMOD S7にMicroBlazeを実装して動かすところから初めて、VivadoとVitisに一度触れてみたいと思います。


DigilentMicroBlazeチュートリアルを試す

DigilentFPGAボードのIntroductionを読んでいると、ページ下部に複数のチュートリアルが提供されています。

digilent.com

 

今回はこれに沿ってMicroBlazeをCMOD S7上のSpartan-7 FPGAに構築し、LチカおよびPCとのUSB-UART通信を実装してみたいと思います。


と、その前に・・・

DigilentFPGAボードですが、Digilentが公式でボードファイルを提供しているため、これを自身のVivado環境に導入します。
(多分なくてもできますが、あったほうがピン周りの配線の自動設定とかしてくれるので大変便利です。)

Digilentの"Installing Vivado, Vitis, and Digilent Board Files"にアクセスします。
(この時点でVivadoやVitisをインストールしていない方は合わせてやっちゃいましょう。)

digilent.com"Install Digilent's Board Files"の項までジャンプします。

digilent.com

そこから最新版のボードファイル一式をダウンロードするリンク("Master Branch ZIP Archive"と記載があります)をクリックするとDigilentのボードファイル一式がダウンロードされます。

ダウンロードされたZIPファイルを展開し、new/board_filesの中身をVivadoをインストールしたフォルダの/Xilinx/Vivado/<version>/data/boards/board_files内にコピー&ペーストします(board_filesフォルダがない場合は新規に作成し、その中にコピー&ペーストします)。

ここまでできたらチュートリアルを始めていきたいと思います。

本家のチュートリアルDigilentのあらゆるボードでできるようにところどころ表現がボカされていますので、ここではCMOD S7 & Ubuntuの開発環境に合わせ改変していきたいと思います。


やっていこう

以下リンク先に従ってチュートリアルをやっていきます。

digilent.com

Vivadoの立ち上げ

Vivadoを立ち上げます。

いろんなサイトを確認するとsettings64.shを使って環境変数を通してコマンドを叩いて開いていますが、Version 2023.2だとアプリケーション一覧のアイコンで開くことができました。

プロジェクトの作成

プロジェクトを作成していきます。

Quick Startから"Create Project"を選択します。

"Next"をクリックします。

プロジェクト名とプロジェクトの保存場所を決めます。
今回のプロジェクト名は"Digilent_Microblaze_Tutorial"としました。

プロジェクト形式を決めます。
"RTL Project"に設定し、"Do not specify sources at this time"のチェックボックスにチェックをつけて"Next"をクリックします。

使用するFPGAを選択します。デバイスから選択もできますが、今回はBoardから選択します。

Searchの欄に"cmod"と入力すると"Cmod S7-25"が出てくるので選択します。Digilentのボードファイルを導入していないと表示されないので注意してください。

ボードファイルを導入済みなのに出てこない場合は左下の"Refresh"をクリックしてみてください。それでも出てこない場合はボードファイルを格納した場所を再確認する必要があります。

 

以下はRefreshボタンをクリックした際の画面です。少し待ちます。

使用するボード(今回はCmod S7-25)を選択して"Next"をクリックします。

プロジェクトの概要が表示されますので、問題なければ"Finish"をクリックします。間違いがあれば"Back"をクリックして設定し直します。

ブロック図からMicroBlazeと周辺回路を構築する

現在開いているVivadoですが、RTLやIPの設定や配線、シミュレーション、ビットストリーム書き込みを行うための「AMDFPGAやSoCのハードウェアを担当するツール」となります。

ここからはCMOD S7上のSpartan-7にMicroBlazeを構築していきます。

AMD FPGAやSoCに初めて触れるかたは"MicroBlaze"や"Zynq"など混乱するかもしれませんが、

  • MicroBlazeAMD FPGAまたはSoCのユーザロジック(PL)上に構築されるCPU IP。ユーザロジックを使用するため自前のRTLを構築できる領域が減少し、動作速度も期待できないが低コスト。
  • Zynq:AMD SoC内にFPGA(PL)とは別に存在しているARMアーキテクチャのハードウェアCPU(PS)。ユーザロジックを使用せず、専用のマイコンが配置されているため動作速度はMicroBlazeより期待できるが、専用のマイコンがある分高コスト。

となります。

まぁAMDの場合はSoCそのものがZynqと命名されている(Versal除く)ため間違いは起きにくいと思いますが、今回使用するCMOD S7に配置されているSpartan-7は純粋なFPGAなので、今回はMicroBlazeを構築します(実はIntelがこのあたりちゃんと調査しないと分かりにくいんですよ・・・)

余談はこのあたりにしておきまして・・・

 

Vivado左側のメニューより"IP INTEGRATOR"一覧から"Create Block Design"を選択します。

以下のようなウィンドウが出てくるのでDesign nameを決めます。今回は"MicroBlaze_blink"としました。
DirectoryやSpecify source setの項目は何も触らず、"OK"をクリックします。
Design nameには" "(スペース)を使用しないようにしてください!代わりに"_"(アンダーバー)、"-"(ダッシュ)、キャメルケース(各単語の冒頭を大文字にする。今回のDesign nameだと"MicroblazeBlink")の使用が推奨されています。

ブロック図にMicroBlazeを配置する

いよいよMicroBlazeを構築していきます。

まずはMicroBlazeを動作させるためのクロックを設定します。

Diagramの隣にある小さなウィンドウから"Board"を選択し、"Clocks"一覧の"System Clock"を右クリックして"Connect Board Component"を選択します。

以下のウィンドウが出てくるので"clock_CLK_IN1"にのみチェックがついていることを確認して"OK"をクリックします。

外部リセットを自動で配置します。Diagram上に緑色のバーで表示されている"Run Connection Autometion"をクリックします。

以下のようなウィンドウが出てきます。左側のresetにチェックがついていることを確認します。Digilentのほとんどのボードで自動でリセットに繋がれるポートが選択されるので"OK"をクリックします(CMOD S7では基板上のBTN0をリセットとして配置します)。

ここで、Diagram上の"Clocking Wizard"をダブルクリックしてみます。

IPの設定画面が出てきます。詳細は割愛しますがリセットの極性やIP動作モード、出力数、出力クロックの周波数など細かく設定できます。

Output Clocksのタブをクリックするとクロック周波数や出力数がわかります。現在の設定では100MHzをclk_out1から出力します。

今回は何も設定を変更しないので、"Cancel"をクリックしてウィンドウを閉じます。

次にMicroBlazeを配置します。Diagramから上列の"+"ボタンをクリックします。
検索欄が出てくるので、"microblaze"と入力し、"MicroBlaze"をダブルクリックすると・・・

MicroBlazeが配置されます。
必要な周辺IPを配置する必要がありますがここはVivadoにまかせてしまいます。緑色のバーに表示されている"Run Block Alutomation"をクリックします。

以下のようなウィンドウが出てきます。MicroBlazeの設定に合わせ周辺ブロックも自動設定してくれます。

今回のチュートリアルをCMOD S7で行う場合は以下のように設定します。l

  • Preset: None
  • Local Memory: 32KB
  • Local Memory ECC: None
  • Cache Configuration: None
  • Debug Module: Debug Only
  • Peripheral AXI Port: Enabled
  • Interrupt Controller: チェックをつける
  • Clock Connection: /clk_wiz_0/clk_out1 (100MHz)

各項目の設計基準は以下のようになります(本家チュートリアルより抜粋)。

OKをクリックすると周辺ブロックの配置および配線が自動で行われます(すげぇなVivado!)

次にPCとのUSB-UART通信部を配置します。Diagram横の小さなウィンドウから"Board"タブを選択し、"UART"から"USB UART"を右クリックして"Connect Board Component"をクリックします。

以下のウィンドウが出てきます。"AXI Uartlite"下部にある"UART"を選択し、"OK"をクリックします。

Diagram上にUART通信部が配置されるので、緑色のバーに表示される"Run Connection Automation"をクリックします。

以下のウィンドウが出てきます。画面左側の"S_AXI"にチェックが入っていることを確認し、あとは設定を変更せず"OK"をクリックします。

こんな感じのブロック図になっていると思います(ブロックの位置や配線は環境により異なるかもしれません。)


ちょうど公式チュートリアルが半分進んだ感じなので、今回はここまでとします。

Vivadoのブロックの自動配置・配線機能は大変ありがたい機能に感じました。
ただ、各ブロックの接続が基本AXIなのと、触れないであろうブロックまで表示されるので全体の視認性は少々悪く感じます(それ故に自動配置の機能があるんだと思いますが)。

次回はボタンやLED等に接続されるGPIOの配置、コンパイルの制約、コンパイル、ビットストリームの生成、VitisでのLチカソフトウェア実装とソフトウェアの書き込みをやっていきます。

 

KRIA KR260 Robotics Starter Kitを購入しましたが・・・・

皆様明けましておめでとうございます。

昨年はどのような1年でしたか?
私は転職騒ぎから始まりましたが結局そのままの職場に残り現状はまぁまぁなんとかうまくやれております。

2024年もどうぞよろしくお願いいたします。


KRIA KR260をついに購入

ついに買ってしまいました。

購入した理由としては

  • FPGA & CPU & その他アクセラレータを組み合わせたシステム構築を勉強したい
  • GPIOが豊富
  • 同クラス単体FPGA評価ボードを買うより安価
  • いい加減AMD(旧Xilinx)のデバイス設計にも触れたい(Intel→Efinix→Gowinと来てAMDやってない)

というのがあります。


そもそもKRIAとは

AMDが公式に販売しているZynq Ultrascale+ MPSoCを搭載したSoM(System on Module)です。

japan.xilinx.com

Zynq Ultrascale+ MPSoCとほぼ確実に組み合わせて使うであろうDDRメモリや電源、TPM等の周辺部品をモジュール化して販売することで、開発者は基板設計の工数を削減できるという特徴を持ちます。(DDRなんかは設計も大変なので・・・)

今回購入したKR260にはK26ベースのSoMが搭載されており、使用されているデバイスはLUT数やビデオコーデックが搭載されていることからZU5EVと言われています。

Zynq Ultrascale+ MPSoC Selection Guide(XMP104)より抜粋

ZU5EVのデバイス概要ですが

  • CPU:Quad-Core ARM Cortex-A53
  • RPU:Dual-Core ARM Cortex-R5F
  • GPU:ARM Mali-400
  • PL(FPGA):256K Logic Cells, 1248 DSP Slices, 3.5Mb RAM, 187Mb UltraRAM

・・・・いやフルで使いこなせる気がしません。


さっそく動かしてみようとしますが・・・

こいつ(KR260)、これまで触ってきたFPGAとだいぶ気色が違います。

まず、チュートリアルが「Lチカ」なんて生易しいものではなく「KR260でOS(LinuxやROS2)を動かす前提」のものがほとんどです。

xilinx.github.io

しかもチュートリアルの多くはプロジェクト立ち上げからやる感じではなく、ビルド済のアプリケーションをKRIA SoM本体に組み込んで動かす感じです(コレはチュートリアルというより動作確認では・・・・)

AMD FPGAが初めてな私にとっては最初に購入するものを間違えてしまった感がすごいです・・・


とりあえず資料を読み漁る

かといって何もしなかったら何もできないままKR260がホコリを被ってしまいますから、すでにKR260を使用している先輩のアウトプットを探してみます。

すると、面白そうなものがありました。

zenn.dev

KR260ではなくKV260(ビジョンAI向け開発キット)ではありますが、個人的にはやっぱりこの手順から始めていきたいところです。

あと、AVNETのブログがこのあたり積極的にまとめはじめているようで、

www.avnet.com

Petalinuxを使ったり、Pynqを使ったり、デジタル信号処理(←!!)したりとなかなか充実度が高そうな内容です。

ただPetalinuxを使っているので、やはりPetalinux開発環境は整えないといけないですね(重い腰を上げますかー)


以上、KR260の購入報告&わけわからん報告でした。

公式資料ばかり見ててもちゃんと習得できるか怪しいので、DigilentのZynqボードのドキュメントとかも参考資料としていきたいところです。

なんかKRIA、「ハードウェア設計者のためのSoC」というよりも「ソフトウェア設計者がFPGA使ってハードウェアアクセラレーションをすぐに実装できるように作られたもの」という感じがしてきました・・・

2024年新年のご挨拶

どもです。

まず初めに、令和6年能登半島地震に被災された皆様に心よりお見舞い申し上げます。
だいぶ離れた地に住んでいますが、義援金等できることを少しずつ協力したく思います。


2024年・・・

皆様、新年あけましておめでとうございます。

元日からとんでもない事件や事故が続いた印象がありますが、皆様が無事に新年を迎えることができたのであれば幸いです。

ちなみにAUDIYは2023年の12月30~31日に原因不明の体調不良(腹痛、下痢、軽い吐き気、手先足先のしびれ)に遭い災難でした。

さて、今年はAUDIYが現在の職場に新卒入社して5年目に突入します。
2025年の4月に「入社5年の所感」を書けるようしっかりと一つ一つのできごとをまとめておければと思います。

audio-diy.hatenablog.com

今週のお題「2024年にやりたいこと」

ここでは2024年の目標を列挙して有言実行するための場として新年の挨拶にかえさせていただきたいと思います。


応用情報技術者の取得

AUDIYは一つ取得したい資格があります。
それは「エンベデッドシステムスペシャリスト」です。

www.ipa.go.jp

大学・大学院で情報工学を学んだ経験を回路設計(ハードウェア設計)に活かすことを考えたときに、その専門知識を証明する資格として最も近い資格の一つだとAUDIYは考えています。(というか回路設計が密接に関わる資格が少なすぎでは?)

その足がかりとして応用情報技術者を2024年10月取得めざして活動していきたいと思っています。

www.ipa.go.jp


デジタルフィルタIPの汎用性向上

2023年はPCM用の2倍オーバーサンプリングデジタルフィルタIPを公開しました。

github.com

現状は2倍オーバーサンプリングのみ行えるIPですので、「1/2デシメーション」および「フィルタリングのみ」が行えるよう修正して汎用性を高めたいところです。


SystemVerilogの習得

現在AUDIYはVerilog + PSLでRTL開発を行っていますが、これをSystemVerilog + SVAに昇華させたいです。

検証関係の機能がSystemVerilogのほうが充実しているのが最大の理由です。

www.accellera.org


アサーションベース検証本(?)の執筆

Intel FPGAの開発環境(Quartus Prime Lite)に標準付属のRTLシミュレータがModelSimからQuestaに変更になり、アサーションベース検証機能(SVA、PSL)が標準付属となりました。

これによって今までは環境の導入が高額であったアサーションベース検証の敷居がグッと低くなったと思います。

www.paltek.co.jp

AUDIYもこれに伴いアサーションを導入しましたので、そろそろ学んだことをアウトプットする機会を設けたいところです。


ソフトウェアプログラミングも積極的に

2023年はFPGAやRTL一辺倒でしたが、2024年はマイコンやPCアプリケーションの開発も合間を縫って積極的に行っていきたいところです。

github.com

github.com


転職活動

今すぐ転職するとかではないですが、何かあったときのために日頃から履歴書・職務経歴書は作成・更新しておきたいところです。

良さげなサービスを見つけたので試してみようかしら・・・

rirekisho.yagish.jp


と、2024年もやりたいことが満載でございます。w

もちろんこの中でできること、できないことは出てくるでしょうがそれはまた2024年の年末にでも振り返りたいと思います。

一番難易度が高いのは応用情報技術者試験の合格だと思いますので、ここを重点的に行なっていければと思います。

 

2024年もよろしくお願いいたします。

 

 

PCM用自作オーバーサンプリングデジタルフィルタ"FIR_x2"の使用方法について

どもです。

昨日は"FIR_x2"について実装の工夫点をいくつかお話しましたが、今回はシミュレーションと実際の使用方法についてまとめていきたいと思います。

audio-diy.hatenablog.com


ディレクトリ構成

ディレクトリ構成は以下の通りとなります。

github.com

FIR_x2のGitHubディレクトリ構成
  • 01_DPRAM_CONT
    シンプルデュアルポートRAMをリングバッファとして機能させるためのコントローラ
  • 02_DATA_BUFFER
    SPRAM_CONTとシンプルデュアルポートRAMを組み合わせて構成したリングバッファ
  • 03_SPROM_CONT
    シングルポートROMから任意のフィルタ係数を出力するためのコントローラ
  • 04_FIR_COEF
    SPROM_CONTとシングルポートROMを組み合わせて構成したFIRフィルタ係数出力部
  • 05_MULT
    DATA_BUFFERから出力されたPCMデータとFIR_COEFから出力されたFIRフィルタ係数を乗算する乗算器
  • 06_ADD
    MULTから出力された乗算結果を積分する加算器
  • 07_FIR_x2
    上記のDPRAM_CONTからADDモジュールを接続して構成したオーバーサンプリングデジタルフィルタのトップモジュール
  • 08_hex
    シンプルデュアルポートRAMとシングルポートROMのデータ初期化用16進数ファイル
  • 09_txt
    シミュレーション用PCMデータ格納ファイル
  • 10_Example
    各種FPGA評価ボード用サンプルプロジェクト
    2023年12月25日現在で「Terasic DE10-Lite」「Terasic DE0-Nano」「Efinix Trion T20 BGA256 Development Kit」「Sipeed Tang Primer 20K」の4種類のボード向けサンプルを保存しています。

    www.terasic.com.tw

    www.terasic.com.tw

    www.efinixinc.com

    wiki.sipeed.com


シミュレーション方法

各モジュールのディレクトリに入ると「(モジュール名).v」と「(モジュール名)_TB.v」が保存されていますので、基本的には各自お持ちのシミュレータで「(モジュール名)_TB.v」を実行すればOKです。

ただし、いくつか注意点がありますのでご注意ください。

  1. シングルポートROM(SPROM.v)とデュアルポートRAM(SDPRAM_SINGLECLK.v)はサンプルプロジェクトで推論されることを確認済ですが、各ベンダーのIPを使ったほうがいろんな面で良いと思います。
  2. FIRフィルタ長は(マスタークロック周波数)÷(サンプリング周波数)で計算してください。
  3. 一部モジュールでは別ディレクトリのモジュールも合わせて呼び出す必要がありますので、実行前に対象のモジュールをよくご確認ください。
  4. 一部モジュールでは「08_hex」や「09_txt」内のファイルを使用しますので、その際はシミュレーションを実行するディレクトリに保存した上で実行してください。
  5. 開発時にQuesta - Intel FPGA Starter Editionで手作業でシミュレーションしたため。vcdファイル保存やシミュレーションの終了タイミングが記述されていません。必要な場合は各自記述ください。

以下にQuesta - Intel FPGA Starter Editionで実行する手順を示しておきます。
ちなみに、シミュレーション実行ファイル(*.do)のPull Request大歓迎です!

  1. 必要なモジュールとテストベンチをプロジェクトにインポートし、コンパイルする。このとき、hexファイルやtxtファイルで必要なものもテストベンチが保存されているフォルダに保存しておく。

    FIR_x2実行時のQuestaプロジェクト
  2. テストベンチファイルを選択し、最適化オプションやその他オプションを設定して実行する。(一部モジュールにはPSLアサーションが記述してあるのでアサーション検証も可能です。)

    テストベンチファイルを選択して実行


  3. 観測したい信号をwaveウィンドウに追加し、Transcriptウィンドウ内にてrunコマンドを入力してシミュレーションを実行する。(実行時間は30万~40万nsあれば十分です。)

    あとは各種検証をお楽しみください。

    波形表示を変更した場合



実機での確認方法

実機の場合はベンダーによりいろいろなお作法があるので一概に「これ!」といった方法はお伝えしにくいですが、

  1. ディレクトリのモジュールをFPGAプロジェクトにインポートする
  2. FIR_x2以外の周辺モジュールを設計し接続する
  3. タイミング制約の記述
  4. ピンアサインの設定
  5. コンパイル

という基本的な流れは変わらないと思います。

以下実機確認の注意点になります。

  1. シングルポートROM(SPROM.v)とデュアルポートRAM(SDPRAM_SINGLECLK.v)はサンプルプロジェクトで推論されることを確認済ですが、各ベンダーのIPを使ったほうがいろんな面で良いと思います。
  2. FIRフィルタ長は(マスタークロック周波数)÷(サンプリング周波数)で計算してください。
  3. 「10_Example」内のサンプルプロジェクトではI2S入力、16bit Right-Justified出力で、Amanero Combo384とPT8211Sを組み合わせて確認しています。

    www.tec-sol.com

    audio-diy.hatenablog.com

    各自使用するDACやオーディオデータ形式に合わせて別途モジュールを準備ください。

サンプルプロジェクトの対応ボードを所有されている方は一度試されるとなんとなくわかるかと思います。


ライセンスについて

そこそこの時間と気合を入れて作ったものですので、ライセンスについてもお話させていただければと思います。

AUDIYが調べた限りでは今回のようなHDLのライセンスはMITライセンスやApacheライセンスで公開されているものが多いようですが、

ということでいろいろ調べた結果、以下のライセンスにたどり着きました。

cern-ohl.web.cern.ch

CERN(欧州原子核研究機構)が制定したライセンスで、ハードウェアのみならずソフトウェアにも適用できるそうです(なぜに原子力関係の機関が・・・・)

https://ohwr.org/project/cernohl/wikis/FAQ#q-my-project-includes-hardware-and-software-how-do-i-make-sure-the-whole-product-is-distributed-together-and-stays-open-source

また、ライセンスの継承についても3段階に区分されていて、制限が強い順に

  1. CERN-OHL-S v2
    ソフトウェアにおけるGPL3に相当する。
    このライセンスによる著作物を使用したプロジェクトはCERN-OHL-S v2でライセンスする必要がある。
    回路等の物理的な著作物にのみ適用可(ソースコード不可)。
  2. CERN-OHL-W v2
    ソフトウェアにおけるLGPL3に相当する。
    このライセンスによる著作物を使用したものはCERN-OHL-W v2またはCERN-OHL-S v2でライセンスする必要がある。
    CERN-OHL-S v2でライセンスする場合は、各自で作成したものについても動作に必要なものは全てCERN-OHL-S v2で公開する必要がある。
    CERN-OHL-W v2でライセンスする場合は、各自で作成したもののライセンスについては問わない(別ライセンスでも良い)。
    ソフトウェアやHDLにも適用可。
  3. CERN-OHL-P v2
    ソフトウェアにおけるApache 2.0ライセンスに相当。
    このライセンスによる著作物を使用したもののライセンスは問わない(CERN-OHLを継承せず別ライセンスを適用しても良い)。

その他「商用利用可」や「保証の要求不可」などは一般的なオープンソースソフトウェアライセンスと類似しています。

ohwr.org

今回はそこそこ時間をかけて開発したことや、個人的にも思い入れがあるのでライセンスの継承だけはしていただきたくCERN-OHL-W v2でライセンスすることにしました。

もし本プロジェクトが何かに使えそうな場合はご一報いただけるとAUDIYが喜びます。w


以上、FIR_x2の中身と使用方法についてでした。

Advent Calenderなのに自分の成果物の発表になってしまいましたが、皆様に教えられるようなHDL関係の知識があるかもビミョーだったので成果物を発表することにしました。

せっかくQuartus付属のシミュレータがModelSimからQuestaに変更になったので、2024年のAdvent Calenderは本記事でも少し触れたアサーション検証についてアウトプットしたいところです。(1年あるのでそれまでに有益な情報が出るかもしれませんね。)

www.paltek.co.jp

 

では皆様、良い年末年始をお過ごしください。

2024年もどうぞよろしくお願いいたします。

 

PCM用2倍オーバーサンプリングデジタルフィルタのIP"FIR_x2"を公開しました

どもです。

8月の夏休みから4ヶ月ほどかけてやっと動作確認までできたので公開します。

PCMデータを2倍オーバーサンプリングするFIRデジタルフィルタIPです。

github.com


きっかけ

AUDIYがFPGAに興味を持ったのは以下のビデオがきっかけです。

CHORDというオーディオメーカーFPGAフリップフロップを使用してDAコンバータを実現している、ということを知り、自分でもDAコンバータの構造を知りたく、FPGAを使用したオーディオ信号処理に興味が湧いたのでした。

大学・大学院では信号処理について勉強こそすれどその実装はソフトウェアばかりで、興味こそ持ちつつもなかなか手が出せなかったのですが偶然にも就職してハードウェア設計を行うことになりました。

「・・・コレは良い機会だ!」

 

ということで、オーディオ信号処理で多用されることの多いオーバーサンプリングFIRフィルタの実装に着手したのでした。


参考資料

実際にオーバーサンプリングデジタルフィルタを実装するにあたり、参考とした資料はリンク先のPDFです。

https://shop.cqpub.co.jp/hanbai/books/I/I000139/I000139kou.pdf

 

トランジスタ技術2014年12月号~2015年1月号にかけて特集された記事の一部のようです。

 

PDF上の図では「RAM、ROM、乗算器、加算器1つずつでできる」とありますが、実際にそれっぽく動くようになるまでには複数のハードルがありましたので、Verilogコードのリンク先とともに共有させていただきます。


ポリフェーズ・フィルタ

乗算器、加算器を1チャンネルあたり1つしか使わないということであれば、自ずとポリフェーズ・フィルタの実装になります。

edn.itmedia.co.jp

今回はオーディオ用のマスタークロック(多くの場合で22.5792MHzとか24.576MHzの整数倍だと思います。)を使用して、サンプリング周波数の整数倍だけFIRフィルタのタップ数を格納する方式にしました。


RAMのアドレス制御

オーバーサンプリングデジタルフィルタに使用するRAMですが、

  1. 入力はサンプリング周波数のレートでデータを保存していく
  2. 出力はマスタークロックに合わせ保存したデータを呼び出していく
  3. 最も古いデータが保存されていた場所に最新のデータを保存していく
  4. 入力するアドレスと出力するアドレスが重複するのは禁止

必要があります。

つまり、入力はFIFO(シフトレジスタ)のように扱いつつも出力は任意のデータを呼び出せるようにしなければなりません。

本IPではRAMがリングバッファとなるようにRAMコントローラIPを設計し、上記仕様を実現しました。

ufcpp.net

今回リングバッファを実現する方法ですが、

  1. 最も古いデータのアドレスを記憶しておく
  2. データ出力の先頭アドレスを「最も古いデータのアドレス」から一つ進め、アドレスをインクリメントさせる
  3. データ書き込み先のアドレスに「最も古いデータのアドレス」を指定する。
  4. 「最も古いデータのアドレス」を一つインクリメントさせる
  5. 1に戻る

を繰り返すことで実現します。

github.com


ROMアドレスの指定方法

オーバーサンプリングの説明ではよく「データの間に0を挿入してFIRフィルタを畳み込む」と説明がなされるかと思います(上記PDFにもあります)。

ただ、コレを律儀にFPGAに実装すると以下のように無駄が生じてしまいます。

  1. ゼロデータとFIRフィルタ係数の乗算が発生する。
  2. マスタークロック周波数が一定なので、1により加算できる有効データ数が減少する

ということで、今回のオーバーサンプリングデジタルフィルタではフィルタ係数を出力するためのアドレスを「奇数で一巡→偶数で一巡」と繰り返す仕様にすることで0データとの乗算が行われたことと等価の処理を実現しています。(個人的にここが最大のキモだと思います。)

github.com

ROMに格納するデータを並び替えればこんなことせずにアドレスを1ずつ増やすこともできますが、データの準備が面倒ですしね・・・・


新たなビットクロックとワードクロック

FPGAで処理する以上は最終的に外部のDAコンバータICにデータを送り出すためのビットクロックとワードクロック(サンプリング周波数のクロック)が必要です。

本IPではROMアドレスの任意ビットをそのまま出力することでコレを実現しています。
(マスタークロックの分周は危険なのでやめました)

ひょっとしたらRAMのアドレスでも同じことを実現できるかもしれませんが、ROMのほうが計算の始点・終点がハッキリしているのでこのようにしました。

github.com


積分器のリセット

デジタルフィルタでは畳み込みの実現のために積分器を使用しますが、入力データを積分し続ける一般的な積分器とは少し挙動が異なります。

FIRフィルタとデータの乗算が完了したらデータが更新されるため、FIRフィルタの係数を全て使用したら積分データをリセットする必要があります。

本IPでは先述の「新たなワードクロック」の立ち上がりエッジを検出することで「全てのFIRフィルタの係数が入力データと乗算された」として積分データをリセットすることで実現しています。

github.com


できる限りのクロックドメインクロッシングの排除

本IPは内部の処理が全てマスタークロックの立ち上がりエッジまたはたち下がりエッジに同期して動作します。

逆位相でフリップフロップを駆動する箇所があるため非同期設計が無いわけではありませんが、ビットクロックやワードクロックを一切使用していないだけでもだいぶトラブルは起こりにくい仕様になっていると思います。

www.macnica.co.jp

I2Sで出す場合はビットクロックのたち下がりエッジに同期してデータが出力されるのが標準仕様となっています。

https://www.nxp.com/docs/en/user-manual/UM11732.pdf

かといって完全同期のためにODDRとか使い出すとベンダー依存が強くなるので考えどころではあります・・・・

ビットクロック:マスタークロックの比を1:2以上にすればODDRも必要にならないのでそれが最適解ですかね・・・

docs.xilinx.com


以上、実装上の工夫を今回は共有しました。

次回はRTLシミュレーションと実際にFPGAで動かす例を記したいと思います。