始めに
Arty A7(T35)を入手して3年余り。少しずつ部品を書き溜めていますが、そろそろ付属しているDRAMへのアクセスを始めようと考えました。最終的には少しずつ機能拡張をしているRISC-V(my-riscv-rv32i)のデータRAMとしてDRAMを使うところにあります。現在データRAMとして使用しているBRAM領域はそのままキャッシュにしてDRAMのデータを読み書きできることが最終目標になります。さらにインストラクションRAMもキャッシュ化することを考えると、データ転送はバス化することが得策と考えました。いくつかのバスを検討し、AXIバスを参考にして、プロトコルをパクり、必要な機能のみをサブセットとして実装してみることにしました。このサブセットtiny_axiは、バースト長を固定した単純なリードとライトができだけに機能を絞り、これをArty A7に搭載されているSDRAM I/FであるMIGと接続してアクセスを確認するまでを行いました。実はMIGではAXIバスインターフェースが実装されており、それを使えばよいのですが、バススピードが固定され、例えばDDR3を333MHzで動作させる場合でその1/4の周波数である83.33MHzとなってしまいます。実は前記RISC-Vコアは80MHzくらいの動作で、さらにシストリックアレイ(my-systolic)を接続すると50MHz動作となるため、バスとして使えない、または各マネージャ側で非同期渡りが発生することになるため、使用をあきらめました。なので、MIGにアクセスするI/F部分でクロックを非同期渡りとして、バスは50MHzで動作させることとしました。
MIGの使用方法及び非同期FIFOを使用したクロック渡りについては、すでにACRi blogで紹介されていますが、これを改変するよりも、自分で作ってみるを目標に、このページのMIG設定方法を参考に動作環境を整えました。このページではランダム値のライト&リードで動作を確認するとなっているのですが、自分の好きな値をリードライトしたいので、my-riscv-rv32iで使用している自作のUARTモニタを改造して、DRAMへの値の書き込みとダンプをできるようにして、その間をtiny_axiで接続するという形式にしました。一応動作をしたので、これでひとまずは公開することにしました。
なお、AXI部分はAXIバスの仕様書を基に、不要な機能をごっそり取り去って作成しました。以下の仕様の章に未サポートのリストを示しますが、基本的なリードライトのみサポートと表現したほうが早そうな気がします。また、接続試験は自身のmanagerとsubordinate(まだこれらの呼び方がピンとこない)間でのみのため、ほかのモデルのAXIバスのものとの接続保障はありません。
レポジトリ
・tiny_axi AXIバスモデルおよびMIGへのI/F回路モデル
仕様
・32bit幅4バースト固定 128bitデータごとのアクセス(アドレスの下4bitは0固定)
・現在のバス部分動作周波数は130MHz程度
・Byte strobeをサポート
・基本のRead/Writeのみで、以下の特殊機能関連の信号はカット
・burst attribute はfixed固定
・user req未サポート
・Domain未サポート
・snoop未サポート
・stash未サポート
・trace未サポート
・loop back未サポート
・MMU 未サポート
・PBHA 未サポート
・Subsystem ID DRAMのみなので、0固定
・ATOP アトミックは未サポートでnon-atomic(0)固定
・MPAM 未サポート
・Uniq ID未サポート
・CMO 未サポート
・Memory encription 未サポート
使用方法
・まずはtiny_axiをgit cloneしてください。
・tiny_axiに入ってください。
・./ssimディレクトリを作成し、以下のファイルをコピーしてください。
① ./buslogics/.v
② ./mig/.v
③ ./mon/*.v
④ ./io/lchika.v
⑤ ./fpga/fpga_dram_top.v
・vivadoを立ち上げて、新規RTLプロジェクトを作り、上記ファイルをすべて登録してください。
・合成制約ファイルとして、./syn/riscv_io_pins.xdcを登録してください。
・プロジェクトが立ち上がったら、まずはクロック生成をします。
① IP Catalog ⇒ FPGA Futures and Design ⇒ Clocking ⇒ Clocking Wizardを立ち上げます。
② input clockとして100MHzを設定
③ output clockとして3ポート設定 : clk_out1 200MHz、 clock_out2 166.66667MHz、 clock_out3 50MHz
④ OKを押して完了させる
・次にMIGを生成します。手順はACRi blog MIG を使って DRAM メモリを動かそう (3)の手順で行います。詳細は割愛しますのでそちらを参照してください。前記ブログの内容から以下のパラメータを変更します。
① System Reset Polarity : ACTIVE LOW
② ピンの確認を行うファイルは./syn/Arty_C_mig.ucfを使用してください。このピンチェックで落ちる場合は、どこか設定が間違っています。
③ 最終的に許諾をすればMIGが生成されます。
・クロックとMIGを生成したら、Run Synthesis、 Run Implementation、 Generate Bitstreamの順に実行します。
・出来上がったBitstreamをArty A7に書き込みます。これでAarty A7上で本実験の論理が動作します。クロックが正常動作していれば、Lチカが動作しているはずです。(単にmclkが動作していることを確認しているだけです。)
・tera termを立ち上げます。シリアルから、Arty A7が接続されているCOM(筆者の環境ではCOM4)を選択します。
・設定⇒端末 で改行コードを 受信:AUTO 送信:CR に設定します。
・設定⇒シリアルポート でスピード:9600 データ:8bit パリティ:none ストップビット:1bit フロー制御:noneを選択します。
・これでqをタイプすると、エコーバックが戻ってくるはずです。
・書き込みはwコマンドになります。 w<address4bite> <data4byte> <data4byte> ... q
・wの後に16進数で8桁、4byte分アドレスを入れます。自動改行しますので、続けてデータを同じように4byteずつ入力します。終了はqで入力モードが終了します。qで終了時に最後が4byte分入力されていないと捨てられます。
・読み出しはrコマンドになります。 r<start address 4byte> <end address 4byte>
・rに続いて4byteずつ16進数でアドレスを入力します。途中ミスったら、qを入力すると、rコマンドモードから抜けます。
・もしアドレスで長いダンプをしてしまった場合もqコマンドで途中で抜けることができます。
以上の手順でDRAMへの読み書きが確認できると思います。
終わりに
今回は、risc-vにDRAMを実装する前段階としてDRAMおよびバスの動作確認をする実験をしました。4byteずつの書き込みですが、無事機能していることが確認できました。ACRi blogの記事は親切で図を多用してわかりやすかったのですが、必要としていたものと少し違く、改変が必要だったので、結局MIGのインターフェースから作成してみました。MIGの情報はACRi blog以外はなかなか存在しなく情報が少ないので、皆様の挑戦のための情報の足しになれば幸いです。
まずは使用方法をざっと殴り書きましたが、tiny_axiバスの詳細設計も書いていこうと思います。