Efinix Trion T20でSoC開発ことはじめ（その１～事前準備編）

Efinix社のTrion FPGAにRISC-VのSoCを構築し、Lチカをさせてみました。
# はじめに
Efinixは最近増えてきた新興FPGAメーカーの一つです。
電子工作趣味の題材としてなかなか魅力的なのですが、いざ始めてみようとすると情報源が少なく、それならばということでメモとして残すことにしました。

# Trion FPGAについて
ローエンド寄りミドルクラスFPGAになります。
https://www.efinixinc.com/products-trion.html
ラインナップとしては、ロジックエレメント（LE）数で4K（T4）～120K（T120）クラスということで、例として挙げてみるなら、AlteraのMAX10シリーズ（2K～50K LEs）に近いか、それよりちょっと上の規模感でしょうか。

機能的には内蔵PLLやLVDS対応はもちろんのこと、パッケージによりますがMIPIやDDR-DRAMコントローラも内蔵していたりと、個人的な感覚では現代的なFPGAの要素は一通り満たしてるかな？と感じています。
コンフィグレーションは外部SPI FLASHに格納する方式で、他にもホストマイコンからSPI通信でコンフィグレーションを受け取る使い方もできるようです。
MAX10やMicrosemi、LatticeのようにFLASH内蔵のタイプではありませんが、汎用のSPI FLASHが使えるので安価に回路を構築できそうで、この点でもなかなか好印象。

# 評価ボード
今回、Trion社純正の
Trion T20 BGA256 Development Kit
https://www.efinixinc.com/products-devkits-triont20.html
を題材に選んでみました。20K LUTクラスのものですね。
ボード単体でイーサネット通信できないのは少し物足りないですが、256MBのSDRAMが搭載されておりSoCを構築してソフトを動かして遊んでみるには十分な規模感と思われます。

Trion社のキットは日本の商社からも購入できるようです。ネットで検索してぱっと出てくるのはこちらの商社さんでしょうか。
https://www.zaikostore.com/zaikostore/special/EFINIX
FPGAの紹介やチュートリアルなど色々と情報公開されていますね。参考にさせていただきました。

ちなみにお財布に優し8K LUTクラスのT8のキットもあるのですが、この規模だとSoCで遊ぼうとなるとかなり限定的になりそうです。

一方、上の方にはT120のキットもあり、これならかなり遊び甲斐がありそうです。が、ポケットマネーで遊ぶにはなかなか躊躇するお値段ということでこちらは諦め、ぎりぎり個人が趣味で購入できる価格の、上記T20のキットを使ってみることとなりました。

なお、電源はDC5VをDCジャックから供給するタイプです。電源アダプタはキットに付属されていないため、別途手配する必要があります。メーカー推奨は4Aの供給能力があるもの、とのことです。
# 開発環境
Efinity Software V2024.2
https://www.efinixinc.com/products-efinity.html
を使用します（2024年12月時点での最新バージョン）。

SoC（RISC-V）のソフトウェア開発IDEは独立していて、Eclipseベースの
Efinity® RISC-V Embedded Software IDE
https://www.efinixinc.com/products-efinity-riscv-ide.html
になります。

どちらもフリーライセンスなのですが、ダウンロードするにはユーザー登録する必要があります。サポートページ
https://www.efinixinc.com/support/index.php
に飛ぶと、各種ダウンロードページへのリンクがあるのですがロックがかかっていて、サインインするかアカウントを作成するか聞いてきます。
ライセンス条件の利用許諾が受け入れられれば一通り情報を入力し、メール認証することでアカウントを作成できます。

この時、ついでにサンプルデザインやデータシート、評価ボードのユーザーガイドなどダウンロードしておけば良いでしょう。これ以降の説明は下記ユーザーガイドを参照にしました。
https://www.efinixinc.com/support/docsdl.php?s=ef&pn=T20F256-DK-UG

# 環境構築
インストーラは私のWindows PC環境ですと
efinity-2024.2.294-windows-x64.msi
efinity-riscv-ide-2024.2.0.1-windows-x64.msi`
になります。

>なお、このメモを書いた時点では丁度Efinity SoftwareがV2024.1からV2024.2に切り替わった時期のようで、最新バージョンへの差分パッチは無かったのですが、パッチを当てる必要がある場合の手順（Windows PCの場合）について軽く触れます。
>
>まず最初にインストールフォルダの下にあるbinフォルダに置かれているバッチファイルsetup.batを実行します。これは事前にWindowsのパス設定などを行うためのもののようです。
>次にダウンロードしたパッチ（zipファイル）を適当なテンポラリフォルダに解凍し、この中にあるバッチファイルrun.batを実行します。このバッチファイルでファイルが上書きされ最新のものに置き換えられます。

Efinity Softwareですがライセンスファイルの認証手続きのようなものは無いようです。一応、有効期限一年のサブスクリプションになっているようですが、一年経過後にどうなるかは確認していません。
## 波形ビューワ（とシミュレータ）のインストール
Efinityも他のFPGA開発ツールと同様、内部信号プローブ機能（ロジックアナライザ機能）を持っています。内部信号を選択してRAMに溜めこみ、波形ビューワで表示させる機能です。AlteraのQuartusで言うならSignal Tapのような機能でしょうか。ほぼ必須の機能で、これがあると無いとではデバッグの効率が段違いです。

これが用意されているのは助かりますが、しかしEfinityでは波形を表示するビューワ部分は含まれておらず、オープンソースの波形ビューワであるGTKWaveを別途インストールし、こちらと連携するようになっています。
https://gtkwave.sourceforge.net/

ネット情報によるとビルド済みGTKWaveを使いたいなら、Icarus Verilogにバンドルされたものを利用するのが楽だよ、とのことだったので、早速Icarus Verilogをインストールします。
https://bleyer.org/icarus/

シミュレータもEfinityにはバンドルされておらず、別途Aldec HDL Simulatorなどサードパーティー製のものを使用してくださいね、とのことだったので一石二鳥でしょうか。
ちなみに、シミュレーションモデルはEfinityのインストールフォルダの中に用意されているので、こちらを利用できるようです。

なお、EfinityからGTKWaveを起動するために、Windowsの環境変数で gtkwave.exe が置かれたフォルダへのパスを通さないとならないようなので、設定しておきます。
>Icarus Verilogインストール時に設定されるようです。

これで波形ビューワとシミュレータのインストールは完了です。
## JAVAのインストール
「RISC-V（Sapphire SoC）もしくはDMAコントローラを生成するためには」という但し書き（限定条件）付きではありますが、JAVAの64ビット版ランタイムが必要になります。これらが必要無ければスキップできる項目ですが、今回、SoCを生成しますのでJAVA（JAVA8）のインストールをしておきます。
> すでにJAVAやJAVA JDKがインストール済で、ランタイムが構築されている環境であればこの作業は不要です。
## USBドライバのインストール
評価ボードにはFTDIチップ（FT2232H）が搭載されていてMicro USBで開発用PCと接続できるようになっています。WindowsはFTDIをUSB Serial Portとして自動認識するのですが、ここではJTAGとSPIのインタフェース用ポートとして使用するため、デバイスドライバの置き換え作業が必要になります。

ユーザーガイドでUSBドライバ置き換えツールとしてZadigというアプリケーションの使用が案内されています。
https://zadig.akeo.ie/#google_vignette
インストーラ不要なフリーのGUIアプリケーションです。早速このアプリを実行し、ドライバを置き換えます。

先ずはFPGAボードをUSBでPCと接続し、DCジャックに5V電源を供給、DCジャックの隣にある電源スイッチ（スライドスイッチ）をONにします。

この状態でzadig-2.9.exeを実行します。起動時は何も表示されませんが、Option⇒List All Deviceを有効にすると、認識されているUSBデバイスの一覧が表示されますようになります。
![Trion T20環境構築6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/49c83b35-8d7d-037f-b9bd-1027e2f47d31.png)

この中に *Trion T20 Development Board* で始まるエントリが2つ（*Interface 0*と*Interface 1*）あるはずなので、一つずつ *libusb-win32* を選んでReplace Deviceボタンを押す作業を実施します。

![Trion T20環境構築7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/4f1bee5b-7f59-00d0-c9a0-df7fdbe7580b.png)

Installing Driver…というダイアログの後、The driver was installed successfully.というダイアログが出れば成功です。こちらのツールは終了し、メインの作業に移ります。
# プロジェクト作成
事前準備は終わりましたので、早速Efinity Softwareを起動します。
![Trion T20環境構築4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/84f827f4-a7e6-5342-a0c2-29b59155d3be.png)

ここからFile⇒Create Project…でプロジェクト作成ダイアログを開きます。

Projectタブ
| 項目 | 設定 |
|:-:|:-:|
| Name  | プロジェクト名。適当にsoc_test_1としました（任意）  |
| Location  | 取り敢えずデフォルトのフォルダに  |
| Family  | Trion  |
| Device  | T20F256  |
| Timing Model  | I4  |

:::note info
Timing Modelは開発キットに実装されているFPGAチップにI4の刻印があったので、これに合わせました。
:::

Designタブ
| 項目 | 設定 |
|:-:|:-:|
| Top Module/Entity  | top  |

:::note info
トップ階層名はデフォルトでプロジェクト名（soc_test_1）になっていたのですが、私の好み（流儀？）でtopとしました。以下この設定で解説を進めますが、お好みで。
:::

プロジェクトの設定は作成後も変更できるので、ここでは必要最小限のみ。OKボタンを押して終わらせます。
## トップ階層デザインファイルの作成
取り敢えずファイルだけ作っておきましょう。画面左側dashuboardの下にあるProjectタブの中のDesignにカーソルを合わせ右クリックします。
![Trion T20環境構築9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/bae01767-28c4-b44d-48c7-db2bd3b36d5e.png)
Add／Create／Packageと3つのメニューが出ますので、この中からCreateを選びます。

表示されるCreate Project FileダイアログでFile Nameに**top**と入力しOKボタンを押します。
![Trion T20環境構築10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/6c25a123-77e0-e985-336e-505d5ea24f0d.png)

>ここのダイアログでは拡張子（.v）は入れなくて良いです（良く間違えます…）

ProjectタブのDesignの下にファイルが追加されました。
![Trion T20環境構築11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/ff1a54c3-5ac3-03c7-7412-79d2014f6c6f.png)

この時点でデザインファイルの中身は空の状態ですが、記述していく前に他の作業を進めてしまいます。

>EfinityはVHDLとVerilog、両方のHDLに対応しています。個人的な好みはVHDL…なのですが、サンプルデザインを流用する関係から、Verilogを選択しました。

## IPの追加（SDRAMコントローラ）
使用するIPを追加していきます。最初にSDRAMコントローラを追加します。

IPの追加はIP Catalogツールで行います。Tools ⇒ Open IP Catalog を実行します。立ち上がったIP CatalogツールでSDRAM Controllerを選びNext>>ボタンを押します。
![Trion T20環境構築12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/5c0cbd06-4e54-38b4-7c00-76199783e39d.png)

IP Configuration画面が立ち上がるので、必要な情報を入力していきます。Module Nameはsdram0とします。
![Trion T20環境構築13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/a0354620-c7f0-bf58-989a-61b37c1877ce.png)

ここで必要なのが、SDRAMのスペックや回路設計に応じてパラメータを入力していくという、地味に骨の折れる作業なのですが、素晴らしいことにパラメータのデフォルト値が、今回使用するT20F256 Development Kit（Evalution Board）に合わせて設定してあるようなのです。
このため、試行錯誤を繰り返して正しい値を探っていく作業をスキップすることができました。
>パラメータ入力はデータシートから特性やモードを拾ってくる作業ですが、メーカーによって表現が違ったり、Min./Typ./Maxどの値を採用したら良いのか悩んだり、なかなか一発では正解を引き当てられない作業です。

ちなみにSDRAMチップはINSIGNTS社のNDS36PT5-20ETが載っています。

基本的に設定の変更は必要ないのですが、一つだけ、Deliverablesタブの中にあるExample Design (T20F256_devkit)ですが、こちらにチェックが入っていることを確認します。
![Trion T20環境構築14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/99760e50-5db8-fcf0-8c29-dabfac3f69fd.png)

Generateボタンを押すと確認のダイアログが表示されるので、再びGenerateを押します。
今度は生成が成功した旨を示すダイアログが出るので、OKボタンを押して作業を終了します。
![Trion T20環境構築15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/740ebe21-8a8c-64a8-b91e-1e73e19ea936.png)
メイン画面のProjectタブに追加したIP : sdram0が追加されました。
## SDRAMのキャリブレーション
SDRAM自体のタイミング特性はIP Configurationで設定できるのですが、これに加えプリント基板の遅延を補正する必要があり、このためのキャリブレーション作業を行います。

>デフォルト状態で既に、今回のFPGA基板の特性に合うようなパラメータ設定となっているらしく、実際のところこの作業は不要なのですが、チュートリアルを兼ねて実施してみます。

と、その前にプロジェクトのフォルダ構成を軽く解説。
生成したIPのデザインはIPフォルダ以下に展開されます。作成したエンティティ毎にフォルダが作成されます。先ほど追加したSDRAMコントローラはエンティティ名sdram0というフォルダ名です。

![Trion T20環境構築16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/0b5c5b47-0a72-876d-5a4c-dfd2fdc4ffa9.png)

このフォルダの直下にはIPのデザインファイル（sdram0.v）、タイミング制約ファイル、テンプレートファイルなどが置かれます。またシミュレーション用のテストベンチ関連のファイルがTestbenchフォルダ以下に配置されます。

そして今回、IP生成時にDeliverablesタブの中にあるExample Designにチェックを入れたため、T20F256_devkitというフォルダが作成されています。

このフォルダがSDRAMコントローラテスト用デザインのプロジェクトになっています。このデザインを使って動作を確認するのがキャリブレーション作業となります。

![Trion T20環境構築17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/fd5ddba9-a274-e3b2-4a9b-8c8254ca3273.png)

| ファイル名 | 機能 |
|:-:|:-:|
| axi4_debug_top.v  | JTAGデバッグモジュールIP  |
| axi4_sdram_controller.peri.xml  | IP Manager生成IO制約ファイル  |
| axi4_sdram_controller.xml  | Efinityプロジェクトファイル  |
| axi4_sdram_controller_test.sdc  | タイミング制約ファイル  |
| axi4_sdram_controller_test.v  | SDRAMコントローラテストのトップ階層  |
| debug_profile.json  | デバッガ |
| sdram0.v  | SDRAMコントローラモジュールIP |
| sdram0_define.vh  | SDRAMコントローラIP定義ファイル  |

作成中のプロジェクトをいったん中断し（Efinity Softwareをもう一つ立ち上げてもいいです） File⇒Open Project... でSDRAMコントローラテスト用デザインのプロジェクトファイル、axi4_sdram_controller.xmlを選択して開きます。

> EfinityではプロジェクトファイルやIO制約ファイルはxmlファイルそのままの形で運用されているようです。個人的には、敢えて独自の拡張子としないのは好ましい管理方法かな？という印象を受けました。

「Open Interface Designer」でInterface Designerを開きピン設定を確認します。
![Trion T20環境構築21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/1cfb47c5-8af9-810b-f81d-3bc678950529.png)

IO設定画面がこちら。
![Trion T20環境構築22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/c0ac98c2-b1c5-edf6-d457-685e3726b3a9.png)

ここでやりたいのが、少しばかり面倒なSDRAM関連のIO設定をこのサンプルデザインから流用してしまおうという作業です。File⇒Export Degisnを選びエクスポートします。
![Trion T20環境構築24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/a74291f8-7ee5-5ff1-843c-a631f163c3c4.png)

OKボタンを押すと拡張子.isfというファイル形式でエクスポートされます。このファイルは後ほど使用します。Interface Designerはこれで終了します。

Efinity Softwareに戻り、論理合成からビットストリーム生成まで一気にやってしまいます。
Efinityではデザインフローは左上のdashboardと書かれた青く囲まれている部分で行います。

![Trion T20環境構築18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/034951bd-7774-51ed-c376-bd91ba2324dd.png)

下の方に並んでいる5つのアイコンがそれぞれ、左から「Synthesize」「Place」「Route」「Generate Bitstream」「Stop Flow」のデザインフローに対応しています。この辺りはツールによってGUIデザインは違いますがお馴染みの内容かと思います。

右上のアイコンは各ステップをシングルステップ（ステップバイステップ）で行うか、最後まで自動で一気通貫に行うかの切り替えるトグルボタンです。
ここではAutomated（トグルボタンに色が付いた状態）でデザインフローを回します。一番左のSynthesizeボタン（ボルトとナットの意匠のアイコン）を押します。

![Trion T20環境構築19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/77ff7eba-d931-2cb3-d26f-cc431e798602.png)

何事も無ければ論理合成からビットストリーム生成まで順次進んでいき、コンソールにビットストリームの生成が完了した旨の出力と、ダッシュボードの各アイコンに緑色のチェックマークがつく状態になるはずです。

![Trion T20環境構築25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/8519f151-2c97-7759-00ad-224880e9f3a3.png)

確認できたらデバッガを起動します。メニューからTools⇒Open Debugerを選択するか、緑色の虫のアイコンをクリックします。デバッガの画面がこちらになります。

![Trion T20環境構築26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/59a8a7de-cf85-96d1-df05-33e366364456.png)

ターゲットボードとの接続を最初にやります。Development Boardの電源を入れ（もちろんUSB接続した状態で）、右上のConfigurationのところにある「USB Target」の右の方にある「Refresh USB Target」ボタンを押します。認識されれば、USB Targetに「Trion T20 Development Board」が表示されます（あらかじめ電源を入れた状態でデバッガを起動すれば最初から表示されます）。

![Trion T20環境構築27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/379cee29-a313-c36e-abb9-18e9200d997f.png)

次にその下にある「Bitstream」に先程生成した「axi_sdram_controller.bit」を選択して、右の方にある「Start programming」ボタンを押します。

![Trion T20環境構築28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/7c4a9b27-5683-09be-3d03-5861277b011e.png)

するとプログラムの転送が始まり、完了するとDevice Statusが緑色に変わります。デザインに埋め込まれたデバッガのロジックが動作している状態です。

![Trion T20環境構築29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/df0b88e0-d801-5b18-3429-d823e34fc7ed.png)

プログラムの転送完了後、（別のプログラムで動いていた状態ならば）ボード上のUSER LEDの表示パターンが変わったはずです。このデザインはSDRAMのテストをしていて、
D3が点滅
D4とD5が消灯
D8からD10までが点灯
であればSDRAMへ書き込んだパターンが正しく読み出せている状態です。

仕上げにJTAG経由でのデバッガとの接続をします。「Debugging」の右の方にある「Connect Debugger」ボタンを押します。すると画面左側、「Core Status」の「Idle」が緑色に変化します。これでデバッグの準備ができました。

![Trion T20環境構築31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/324eab07-0a70-bd8e-e506-34019872e02f.png)

## デバッガの使い方
SDRAMキャリブレーションの続きです。
基本的な使い方はAlteraのSignal Tapなど他のツールとほぼ変わりありません。
最初にトリガのセットアップをします。「Trigger Setup」タブの「Add trigger condition」ボタンを押します。「Add Probes」というダイアログが表示されますので、ここから「valid」信号を選択しOKします。
![Trion T20環境構築33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/18565528-992d-d770-400a-53c1db3351a4.png)

この信号の立ち上がりエッジをトリガに波形を取りたいので、Value欄を「R (0-to-1 transition)」に設定します。
![Trion T20環境構築34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/936017d8-48b8-6f57-6609-8724e7de2f90.png)

次に「Capture Setup」タブに切り替えます。ここでサンプリングのどの位置でトリガをかけるかの設定をします。2048サンプリングの1024番目、つまり中間点でトリガをかける設定がデフォルトになっていますので、これをそのまま採用します。
![Trion T20環境構築35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/eb807142-930c-b102-6b37-874ca2587aed.png)

セットアップはすべて完了しましたので、画面の上の方にある「Run」ボタンを押します。
valid信号は常に変化しているので計測は一瞬で終了します。
Core Statusが「Waiting for Trigger」⇒「Post-Trigger」⇒「Full」と即座に遷移し、自動的に波形ビューワであるGTKWaveが起動します。

GTKWave起動直後はトリガのポイントを指示していないので、画面のズームと移動を使い調整していきます。トリガがかかった位置、validが0から1に遷移するポイントを探します。
![Trion T20環境構築36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948335/1cc8a483-880e-4792-a0f7-16bc3ee18f01.png)

実際のキャリブレーション作業ではこんな感じに、dinとdoutが同じタイミングで同じ値へと変化するようになるまで、タイミング関連のパラメータを追い込んでいきます。このサンプルデザインでは最初からこの評価ボードとマッチングするようパラメータ設定がされているらしく、バッチリの状態でした。

このサンプルデザインでは、デバッガの設定など諸々がお膳立てされた状態で提供されており、波形ビューワで信号のプローブができることの確認だけを軽く流した感じになります。

実際のデバッグ作業ではまず最初に Debug Wizard を使い測定する信号の選択やバッファの設定などを行う流れになるのですが、ここでは割愛しようと思います。


# 次回
前置きの部分でかなり長くなってしまいました。
ここからSoCデザインの作成に入るのですが、きりの良いところでいったん区切り、その２に続きます。