5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Tang PrimerまたはArty A7で自作riscv-rv32iを動かす

Last updated at Posted at 2021-08-14

始めに

Seed FPGA board Tang Primerで、小さなCPUもどきを作っていたのですが、一つまともなものを作ってみようと思い、最小のRISC-V RV32I命令セットで作ってみることにしたのが約1年前。そこから論理は書いたものの、テストをせずに放置していたものを思い直して自作テストを作り、実装した命令を1回ずつテスト通ったので、公開してみました。今回公開したのは、RISC-VおよびUARTを使用したモニタのverilog RTL論理および動作環境です。一応Tang Primerを歌っておりますが、clock PLLのみIP使用であり、特殊な記述もないため他のFPGAへの移植も容易と思います。

始めに2(2021/9/5追記)

新たにXilinx Artix-7を使ったDigilentのArty A7で動作確認をしました。使用法をアップデートしました。

始めに3(2023/12/9追記)

外部割込みとmret命令、illegal operationのexceptionを追加しました。

2024/1/6追記

my-systolicサポート用にData RAMをパラメータ化し16Kwordに拡張しました。Arty A7でのみ動作確認しています。

2024/11/28追記

・Instruction RAMもパラメータ化しました。
・UART経由で表示ができるようにI/Oを追加いたしました。Arty A7で動作確認しました。
・またいくつかバグをつぶしてCのベアメタル動作で、libgccを使い、整数割り算と浮動小数点演算のソフトエミュレートテストを動作させてみました。動作方法を追記しました。

2024/12/21追記

・data RAMをキャッシュとしてDRAMに接続できるようにしました。レポジトリは以下。
https://github.com/yoshiki9636/my-riscv-rv32i-dc
変更点等の記事は以下です。
Arty A7で自作riscv-rv32iを動かす② DRAMでDキャッシュのみ版

参考URL

Tang Primerのページ

Tang PrimerでUARTを使ってみる2020

Tang Primer 開発環境をセッティング

RISC-V-RV32I命令セット

my-riscv-rv32i

my-riscv-rv32i-dc  Dキャッシュ版

1. Version 0.1の制約

以下の制約があります。

  • ALU周り、Load/Store、Jump系を作成。
  • fence系、csr系、ecall系、uret系などは未実装。割り込みも未実装。
  • メモリはinstructionとdataでセパレート。各々1KWordsinstruction 4Kwords, data 4 or 16 Kwordsの大きさ。
  • I/OはRGB LEDの3ピン×4。

2. 使い方

Tang Primerの合成環境のセットアップが済んでいることが前提となります。
上記URLを参考にしてください。

まずはgit cloneしてください。
https://github.com/yoshiki9636/my-riscv-rv32i

2.1 RTL simulation

Intel FPGA用に配布されている、Modelsim 10.5b で動作確認しております。
基本的なverilog記述しか使用していないので、大抵のシミュレータで動作可能と思います。

(1) ssim/ディレクトリを作成し、cpu/ fpga/ io/ mon/ sim/の内容をコピーします。

(2) asm/ディレクトリで riscv-asm1.plを使い、テスト命令列test.txtを作成。ssim/にコピーします。
  例:./risc-vasm1.pl lchika.asm > test.txt

(3) ssim/内でverilogシミュレータを動作させます。 

2.2 Tang Primer Synthesis & run

Tang Primer専用のIDEを使用して合成、FPGAへの書き込みを行います。詳しくは、SiPEEDのページを参照ください。
https://tang.sipeed.com/en/

(1) ssyn/ディレクトリを作成し、cpu/ fpga/ io/ mon/ syn/の内容をコピーします。fpga_top.v内のifdefはTANG_PRIMERを有効にしてください。

(2) IDEを立ち上げ、プロジェクトを作成、ssynをディレクトリに指定して、すべてのverilogファイルを指定します。

(3) PLLの追加が必要なので、Tools->IP Generatorを選択し、Create New IPから、PLLを選択します。名称はpll、入力24MHz、出力36MHzとして作成します。

(3.1)ssyn/uart_if.vの周波数設定が36MHz設定にします。

(4) 後は用法通りに合成、書き込みをします。

(5) USB - UART変換器を使って、FPGAとシリアル通信します。変換器のRxをB15、TxをB16、GndをGのどれかに接続します。

(6) Teratermを使ってシリアル通信をします。Teratermの新しい接続で、シリアルを選択し、COMを変換器のものにします。

(7) 設定->シリアルポートで、スピード:9600 データ:8bit パリティ:none ストップビット:1bit フロー制御:none

(8) 設定->端末で、 改行コード 受信:AUTO 送信:CR これでキーボードをたたくとエコーバックが帰ってくれば、動いております。

(9) プログラムを書き込みます。qを押して、状態をクリアしたのち、i 00000000と打ち込むと、改行されます。シミュレーションで作ったtest.txtの内容をコピペしてください。最後にqを押します。
※Teratermを使っている場合は、i 00000000と打ち込んだのち、ファイル->ファイル転送を選択してtest.txtを指定すると、ファイルをペーストしてくれます。

(10) 書き込んだプログラムをダンプするには、p 00000000 00000100と打ち込んでください。先ほどのプログラムがダンプされます。

(11) 実行は、g 00000000で実行状態になります。lchika.asmであれば、RGB LEDが色を変化させます。そのほかのテストプログラムも項目を確認後、テストパスがわかるように同じようなLチカとなります。

(12) 実行の停止もqで停止します。それ以外のコマンドは、以下の通りです。

command format
g : goto PC address ( run program until quit ) : format:  g <start addess>
q : quit from any command                      : format:  q
w : write date to memory                       : format:  w <start adderss> <data> ....<data> q
r : read data from memory                      : format:  r <start address> <end adderss>
t : trashed memory data and 0 clear            : format:  t
s : program step execution                     : format:  s
p : read instruction memory                    : format:  p <start address> <end adderss>
i : write instruction memory                   : format:  i <start adderss> <data> ....<data> q
j : print current PC value                     : format:  j

スクリーンショット 2021-08-13 150559.png

※2021/9/5追記

2.3 Arty A7 Synthesis & Run

Digilent Arty A7を使う場合の合成方法のメモです。Xilinx Vivadoを使用します。詳しくはArty A7の設計ドキュメントを探してください。

(1) ssyn/ディレクトリを作成し、cpu/ fpga/ io/ mon/ をコピーしてください。ssyn/riscv_io_pins.xdcをコピーします。fpga_top.vのifdefをARTY_A7を有効にしてください。
(2) Vivadoを立ち上げ、projectを作成、ssynの中のRTLを指定し、constraintsとして、riscv_io_pins.xdcを指定します。  

(3) MMCMの追加が必要なので、IPカタログから追加します。周波数は入力100MHz、出力90MHz85MHzで動作を確認しております。

(3.1) ssyn/uart_if.vの周波数設定を90MHz85MHzにします。
   ※uart_if.vの定数を85MHzに変更しました。アップデートをお願いいたします。
   ※定数TERMの設定は以下の式になります。HARFはTERMの1/2です。
  TERM = int( (UARTビットレートの周期[us] / クロック周期[us]) )
     = int ( (1,000,000/UARTビットレート[bps]) / (1 / クロック周波数[MHz]) )

(4) Vivadoのお作法で合成以下を行い、Arty A7に書き込みます。

(5) Arty A7はUSB接続がUARTとして使用できるので、特にUART変換器は必要ありません。あとはTang Primerの方法(7)からと同一です。

3. ベアメタルCの動作メモ(2024/11/28追記)

(1)ツールチェーンを取得、コンパイルとインストールをします。

大体ここのページの手順でOKです。
違いは、configureのところで、アーキティクチャをiのみにします。abiはilp32にします。

$ ./configure --prefix=/opt/riscv32 --with-arch=rv32i --with-abi=ilp32

インストールまで終わったら、レポジトリのctest内のファイルを以下の手順でコンパイルします。
まずstart.sをアセンブルします。

$ riscv32-unknown-linux-gnu-as -march=rv32i -mabi=ilp32 -o start.o start.s

次に以下の処理をすることで、最終的にバイナリのダンプのみのファイルを作ります。ここではprint_test.cを例にします。

$ riscv32-unknown-linux-gnu-gcc -march=rv32i -mabi=ilp32 -mstrict-align -mpreferred-stack-boundary=4 -c -o print_test.o print_test.c
$ riscv32-unknown-linux-gnu-ld -b elf32-littleriscv start.o print_test.o -T link.ld -o print_test
$ riscv32-unknown-linux-gnu-objdump -b elf32-littleriscv -D print_test > print_test.elf.dump
$ riscv32-unknown-linux-gnu-objcopy -O binary print_test print_test.bin
$ od -An -tx4 -w4 -v print_test.bin > print_test.hex

あとは、print_test.hexを.asmファイルの時と同じように読み込んで実行します。
このとき、同じイメージを命令RAM(i 00000000)とデータRAM(w 00000000)双方に書き込んでください。命令だけでないのは、一部変数の初期値がデータ領域に入っているため、データRAMにもコピーが必要なためです。
※Teratermを使っている場合は、i 00000000と打ち込んだのち、ファイル->ファイル転送を選択してtest.txtを指定すると、ファイルをペーストしてくれます。

上記print_test.cがうまく実行できれば、「Hello World!」がUartのコンソール上に表示されます。
print_test3.cは浮動小数点を表示してみています。sprintfが使えない(たぶん乗り切らない)ため、自前で少数を簡単に表示するようになっています。

最後に

これからぼちぼちとTang Primerに実装できる範囲で未実装の機能を実装していこうと思います。ただTang Primerの論理容量がネックになりつつあるので、(まだ容量ありました)そのうちにFPGAをアップグレードすることになりそうです。

2021/9/5追記

Arty A7を入手して動作速度がアップいたしました。こちらをメインで作っていこうと思います。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?