RvCore
RV32I 多サイクルコア (docs/riscv.md「マイクロアーキテクチャ」)
1 命令を fetch → exec(→ mem)で処理する非パイプライン実装. メモリが律速(PSRAM 実効 2.25 MB/s = 約 0.56 MIPS)でパイプライン化の 利得が小さく,面積が最小で,1 命令 = 1 トランザクション境界という性質が L1 検証を単純にする.
stateDiagram-v2
[*] --> fetch
fetch --> rdreg: 命令語受領
rdreg --> exec: レジスタ読み出し確定
exec --> memacc: load / store
exec --> mdwait: 乗除算 (M 拡張)
exec --> fetch: それ以外(分岐・ジャンプ・MRET 含む)
memacc --> fetch: 完了
mdwait --> fetch: 完了
rdreg はレジスタファイルの読み出しレイテンシ(1 サイクル)を吸収する
ための待ち状態.レジスタファイルをメモリマクロへ寄せて LUT を削った
代償だが,多サイクル実行なので状態を 1 つ足すだけで済む
(パイプラインならフォワーディングの再設計が要る.docs/riscv.md).
分岐条件の比較はコア内の専用比較器で行う(ALU は分岐先アドレスの 計算に使うため).JALR の分岐先は仕様どおり最下位ビットを 0 にする.
トラップ(不正命令・ECALL・EBREAK・ロード/ストアの非整列・命令フェッチの
非整列・タイマ割り込み)は,どの状態からでも実行を打ち切って mtvec へ飛ぶ.
mepc / mcause / mtval の退避と mstatus の更新は RvCsr 側で行う.
割り込みは命令境界(フェッチ開始前)でのみ受理する.
o_illegal は不正命令例外を 1 度でも起こしたことを示す診断用の粘着フラグ.
Parameters
| ResetPc | u32 | リセット後の開始アドレス |
|---|
Ports
| i_clk | input | clock | クロック |
|---|---|---|---|
| i_rst | input | reset | リセット |
| o_mem_valid | output | logic | アクセス要求 |
| o_mem_addr | output | logic<32> | バイトアドレス |
| o_mem_write | output | logic | 1 でストア |
| o_mem_wdata | output | logic<32> | ストアデータ(整列済み) |
| o_mem_wstrb | output | logic<4> | バイトイネーブル |
| i_mem_done | input | logic | 完了 |
| i_mem_rdata | input | logic<32> | リードデータ |
| i_timer_irq | input | logic | CLINT からのタイマ割り込み |
| o_pc | output | logic<32> | 現在の PC(観測用) |
| o_trap | output | logic | トラップ受理(1 サイクル.観測用) |
| o_cause | output | logic<32> | 受理したトラップの原因(観測用) |
| o_illegal | output | logic | 不正命令例外を 1 度でも起こした(診断用) |