この記事はのちのちかなり書き変えることになるかもしれません.
前回のあらすじ
- FPGA上に自作PCを作ろう!
- まずはRAMを作ったよ! (動かしてない)
基本構成
本当は効率的な方法とか考えて賢く作りたいんですが,そんな実力はないのでまずはそういうの無視して分かりやすい形で作ろうと思います.
機械語32ビット,イミディエイトデータ32ビットの計64ビットを一つの単位とします.
私は以前,RISC-VのISA(RV32I)をFPGA上に実装したことがあるのですが,即値が32ビットの中に入っていてよく分からなかったのでここでは分けることにします.
TD4でも分けていますしね.
よく考えたら,ISAを作るということはコンパイラも作らなければならないのでは…しんどいですね.
CPU内のレジスタについては,RISC-Vに倣って,32ビットが31個あることにします.
レジスタ内のアドレスは6ビットで指定し,プログラムカウンタは固定でアドレス6'h1f
へ置くことにします.
レジスタとプログラムカウンタ合わせて32個って感じですね.
また,PYNQ Z2にはIOがたくさんありますので,これもCPU直結で動かせるようにしたいと思います.
レジスタのアドレスは6'h00
~6'h1f
の6ビットで表現しますが,IOは最上位ビットに1
を指定することにします.つまり6'h20
スタートのアドレスになります.
具体的なアドレスと割り当ては以下の通り.
アドレス | 割り当て |
---|---|
6'h20 |
タクトスイッチ.上位4ビットは0固定.書き込み禁止. |
6'h21 |
DIPスイッチ.上位6ビットは0固定.書き込み禁止. |
6'h22 |
LED.上位4ビットは0固定. |
6'h23 |
RGB LED.上位2ビットは0固定. |
6'h24 |
Pmod A. |
6'h25 |
Pmod B. |
6'h26 |
AR8~AR13.上位2ビットは0固定. |
6'h27 |
A,AR_SDA,AR_SCL.上位5ビットは0固定. |
6'h28 |
AR0~AR7. |
6'h29 |
AR_RST.上位7ビットは0固定.書き込み禁止. |
6'h2A |
AR_MISO,AR_SCK,AR_MOSI,AR_SS.上位4ビットは0固定. |
6'h2B |
アナログピンはいったんオミット |
6'h2C |
XADCもいったんオミット |
6'h2C |
XADCもいったんオミット |
6'h2D |
GPIO0~GPIO7. |
6'h2E |
GPIO8~GPIO15. |
6'h2F |
GPIO16~GPIO23. |
6'h30 |
GPIO24~GPI27.上位4ビットは0固定. |
ちなみに私は,RISC-V RV32IとTD4しかCPUを知らないので,基本的にこの二つを真似る形で作ろうと思ってます.
よくある質問
Q. RAXレジスタとかはどうするんですか?
A. どうしよう…考えてない…
ISA
RISC-Vの真似で,「~~系」と名付けていくことにします.
また,以下の用語を使うことにします.
- type 何系のコマンドか
- func 機械語の種類
- mask マスク
- rs1 演算に使用するレジスタのアドレスひとつめ
- rs2 演算に使用するレジスタのアドレスふたつめ
- rd 演算結果を出力するレジスタのアドレス
- imm 即値を使用するか.
使用する場合はrs1またはrs2を無視し,即値のみまたはrs1と即値で演算を行う
31 29 28 23 22 19 18 13 12 7 6 1 0
| type | func | mask | rs1 | rs2 | rd |imm|
演算系
ProcessingでP系.type
は3'h0
.
指定された処理と同時に,pc
をインクリメントします.
maskは使用しないため4'h0
固定.
以下,func
は5'h00
からスタートして1ずつインクリメントするとします.
- AND 論理積
- OR 論理和
- XOR 排他的論理和
- NOT 反転.なお,rs2は無視する
- NAND 否定論理積
- ADD 算術和
- SUB 算術差
- ADDI 算術和.符号を考慮する
- SUBI 算術差.符号を考慮する
シフト系
ShiftでS系.type
は3'h1
.
指定された処理と同時に,pc
をインクリメントします.
rs1で指定された番地の数値をrs2またはイミディエイトデータの数値分だけシフトしrdに格納します.
risc-vには算術左シフト命令はないようですが,ここでは実装することにします.
参考
また,maskは使用せず4'h0
固定とします.
- SLL 左シフト命令
- SRL 右シフト命令
- SLA 算術左シフト命令
- SRA 算術右シフト命令
代入系
AssignmnetでA系.type
は3'h2
.
指定された処理と同時に,pc
をインクリメントします.
rs1で指定された番地の数値または指定されたイミディエイトデータをrdに格納します.
rs1
は使用しないため6'h00
固定です.
- MOV イミディエイトデータをrdに格納する
分岐系
ForkでF系.type
は3'h3
.
rs1とrs2の数字を比較し,その結果がtrueならpc
にイミディエイトデータを足し,falseならインクリメントします.
maskとrdは使用しないため0
固定とします.また,必ずイミディエイトデータを使用するため,imm
は1'b1
固定です.
- EQ 等しいか比較
- NE 等しくないか比較
- LT 小なりか rs1 < rs2
- GT 大なりか rs1 > rs2
- ELT 以下か rs <= rs2
- EGT 以上か rs >= rs2
ジャンプ系
JumpでJ系.type
は3'h4
.
maskとrs2とrdは使用しないため0
固定とします.
- JUMP rs1またはイミディエイトデータへジャンプ
メモリ系
MemoryでM系.type
は3'h5
.
指定された処理と同時に,pc
をインクリメントします.
メモリ書き込み・読み込みの命令.
- RM rs1またはイミディエイトデータで指定された番地のデータをrdへ読み込み
- WM rs1またはイミディエイトデータで指定された番地へ,rs2のデータを書き込み
次回の目標
早速これに従うCPUを作ろう!
と言いたいところですが,アセンブラとかコンパイラとか作ったらこのあたり作り直しになりそうな気がするのでまずアセンブラを作りましょう.