# CPU (MIPS-I compatible) ## 概要 Jelly とは、FPGA向けの MIPS-I ライクな命令セットのコアを有したソフトコア プロセッシングシステムです。 ## CPUコアの概要 Jelly の備える CPU コアは命令セットとしては、 MIPS-I ライクな命令セットを 備えており、gcc などによる開発が可能です。 ただし、lwl, lwr, swl, swr 命令は備えていないので注意が必要です。 割込みなどの命令セット以外の機能は基本的に独自仕様なのであくまで コンパイラが流用できるという以外はMIPSシステムと互換性はありません。 ## jelly_cpu_top モジュール ### パラメータ ``` CPU_USE_DBUGGER デバッガを有効にするかどうかを指定します。 0: 無効 1:有効 (デフォルト) CPU_USE_EXC_SYSCALL syscall 命令を有効にするかどうかを指定します。 0: 無効 1:有効 (デフォルト) CPU_USE_EXC_BREAK break 命令を有効にするかどうかを指定します。 0: 無効 1:有効 (デフォルト) CPU_USE_EXC_RI 予約命令例外(Reserve Instruction)を発生させるかどうかを指定します。 0: 無効 1:有効 (デフォルト) CPU_USE_HW_BP ハードウェアブレークを利用するかどうかを指定します。 0: 無効 1:有効 (デフォルト) CPU_GPR_TYPE 汎用レジスタの実装タイプを指定します。 0: デュアルポートRAMを倍速クロックで利用 (デフォルト) 1: デュアルポートRAMを2個利用 2: フリップフロップ記述(合成依存) CPU_MUL_CYCLE 乗算命令のパイプライン段数を指定します。 デフォルトは0です。 数を増やすと実行効率は落ちますが高周波でのタイミング制約が 満たしやすくなります。 33以上に指定すると加算器の繰り返しに切り替わり、ハードウェア乗算器 資源が節約できます。 CPU_DBBP_NUM ハードウェアブレークポイントの個数を1〜4で指定します。 デフォルトは 4 です。 TCM_ENABLE = 0, 密結合メモリ(TCM:Tightly Coupled Memory)を有効/無効を指定します。 0: 無効(デフォルト) 1:有効 TCM_ADDR_WIDTH TCMを有効にする場合、TCMの32bitでのメモリビット幅を指定します。 デフォルトは8で、32bit で 2^8 = 256 word (1024 byte) です。 TCM_MEM_SIZE TCMを有効にする場合、TCMの32bitでのメモリサイズを指定します。 デフォルトで (1 << TCM_ADDR_WIDTH) となります。 TCM_READMEMH TCMを有効にする場合、初期値の読み込みを $memreadh 命令で行うか どうかを指定します。 0: 無効(デフォルト) 1:有効 Xilinx のISE付属のXSTで合成する場合、$memreadh でメモリの初期化が可能です。 TCM_READMEM_FIlE TCMを有効にする場合、$memreadh 命令読み込むファイルを指定します。 32bitワードで16進数のファイルをメモリサイズ分準備してください。 CACHE_ENABLE キャッシュメモリを有効にするかどうかを指定します。 0: 無効(デフォルト) 1:有効 CACHE_LINE_SIZE キャッシュ1ラインのワード数を2のべき乗で指定します。 0:1words, 1:2words, 2:4words, ... というように指定します。 デフォルトは 1 で、2^1 = 2 word です。 キャッシュミス時、1ライン分のデータが読み込まれます。 CACHE_ARRAY_SIZE キャッシュアレイのサイズを2のべき乗で指定します。 1:2lines, 2:4lines, 3:8lines, ... というように指定します。 CACHE_LINE_SIZEとこの値でキャッシュの総サイズが決定されます。 CACHE_BRIDGE キャッシュ対象ポートのI/Fにブリッジ回路を挿入するかどうかを 指定します。 0: 無効(デフォルト) 1:有効 ブリッジを挟むとアクセスサイクルが1サイクル伸びますが、 高周波でのタイミング制約が満たしやすくなります。 THROUGH_BRIDGE 非キャッシュ対象ポートのI/Fにブリッジ回路を挿入するかどうかを 指定します。 0: 無効(デフォルト) 1:有効 ブリッジを挟むとアクセスサイクルが1サイクル伸びますが、 高周波でのタイミング制約が満たしやすくなります。 WB_CACHE_ADR_WIDTH キャッシュ対象ポートのアドレスバスの幅を指定します。 4Gのメモリ空間をすべてキャッシュ対象とする場合を除き、必要量の アドレスバス数に減らすことで、キャッシュのタグRAMを節約できます。 WB_CACHE_DAT_SIZE キャッシュ対象ポートデータバスの幅を2のべき乗で指定します。 0:8bit, 1:16bit, 3:32bit, ... というように指定します。 32bit より大きいバスを使うことで、キャッシュラインを一気に 充填できます。デフォルトでキャッシュラインの幅となります。 WB_THROUGH_ADR_WIDTH 非 キャッシュ対象ポートのアドレスビット数を指定します。 デフォルトは 30 です。 WB_THROUGH_ADR_WIDTH 非 キャッシュ対象ポートのバスの幅を2のべき乗で指定します。 0:8bit, 1:16bit, 3:32bit, ... というように指定します。 デフォルトは 2 (32bit) です。 SIMULATION シミュレーション実行を指定します。 0:合成時(デフォルト) 1:シュミレーション PCトレースをファイルに落とすなどのシュミレーション時固有機能が有効になります。 ``` ### ポート信号 ``` reset (input) リセット信号を指定します。1でリセットが有効です。 同期リセットですので、リセット有効状態で最低1サイクルのクロックを入れて 初期化する必要があります。 リセット解除は clk の立ち上がりに同期して行ってください。 clk (input) 基本クロックです。 clk_x2 (input) 倍速クロックです。clkと位相のそろった倍速クロックを入れてください。 汎用レジスタに倍速クロックを指定した場合にのみ必要です。 endian (input) エンディアンを指定します。 0:リトルエンディアン 1: ビッグエンディアン 動作途中での切り替えは行わないでください。 vect_reset[31:0] (input) リセットベクタのアドレスを指定します。 リセット解除後、PCはこの値になります。 下位2bitは必ず0にしてください。 vect_interrupt[31:0] (input) 割込みベクタのアドレスを指定します。 割込み受付時、PCはこの値に分岐します。 下位2bitは必ず0にしてください。 vect_exception[31:0] (input) 例外ベクタのアドレスを指定します。 例外発生時、PCはこの値に分岐します。 下位2bitは必ず0にしてください。 interrupt_req (input) 割込み要求信号です。1で割り込みを要求します。 interrupt_req (output) 割込みを受け付けたタイミングで1を出力します。 必要なければ特に監視する必要はありません。 pause (input) 外部から強制的にCPUをインターロックさせます。 1で停止し、0で動作を再開します。 利用しない場合は常時 0 としてください。 tcm_addr_mask[31:0] (input) tcm_addr_value[31:0] (input) TCMに割り当てるアドレスを指定します。 バイトアドレスなのでご注意ください。下位2bitは必ず0にしてください。 (address & tcm_addr_mask) == tcm_addr_value となるアドレスが、TCM領域として割り当てられます。 動作中の変更は行わないでください。 cache_addr_mask[31:0] (input) cache_addr_value[31:0] (input) キャッシュ対象とするアドレスを指定します。 バイトアドレスなのでご注意ください。下位2bitは必ず0にしてください。 (address & cache_addr_mask) == cache_addr_value となるアドレスが、キャッシュ対象となります。 動作中の変更は行わないでください。 wb_cache_adr_o (output) wb_cache_dat_i (input) wb_cache_dat_o (output) wb_cache_we_o (output) wb_cache_sel_o (output) wb_cache_stb_o (output) wb_cache_ack_i (input) キャッシュ対象ポートのWISHBONEバスです。 キャッシュ領域への書き込みや、キャッシュミスがこのポートから アクセスされます。 アドレスはバイトアドレスではなく、指定したデータバスのサイズが 単位となります。 wb_through_adr_o (output) wb_through_dat_i (input) wb_through_dat_o (output) wb_through_we_o (output) wb_through_sel_o (output) wb_through_stb_o (output) wb_through_ack_i (input) 非キャッシュ対象ポートのWISHBONEバスです。 TCMでもキャッシュでもないアドレスにロード/ストアを行うとこのポートから アクセスされます。 アドレスはバイトアドレスではなく、指定したデータバスのサイズが 単位となります。 wb_dbg_adr_i[5:2] (input) wb_dbg_dat_i[31:0] (input) wb_dbg_dat_o[31:0] (output) wb_dbg_we_i (input) wb_dbg_sel_i[3:0] (input) wb_dbg_stb_i (input) wb_dbg_ack_o (output) 外部からCPU内のデバッグユニットにアクセスするためのポートです。 WISHBONEバス仕様です。 ``` ## CPUデバッグポート デバッグポートから下記のアドレスにアクセスできます。 ### レジスタ仕様 ``` DBG_CTL アドレス: 0x0 (バイトアドレス 0x00) デバッグ制御レジスタです。 bit0 [Read Only] : ブレーク状態 (ブレークが受け付けられ停止すると1になる) bit1 [Read/Write] : ブレーク要求 (1でCPUに停止を要求 ) DBG_ADDR アドレス: 0x2 (バイトアドレス 0x08) bit0〜bit31 [Read/Write] デバッグアクセスを行うアドレスを指定します。 REG_DATA アドレス: 0x4 (バイトアドレス 0x10) bit0〜bit31 [Read/Write] DBG_ADDRで示されるアドレスにある、CPUの内部レジスタがこの アドレス経由で読み書きできます。 DBUS_DATA アドレス: 0x6 (バイトアドレス 0x18) bit0〜bit31 [Read/Write] DBG_ADDRで示されるメモリアドレスにこのアドレス経由で 読み書きできます。 アクセスはデータバス経由で行われます。 IBUS_DATA アドレス: 0x7 (バイトアドレス 0x1c) [オプション] bit0〜bit31 [Read/Write] DBG_ADDRで示されるメモリアドレスにこのアドレス経由で 読み書きできます。 アクセスは命令バス経由で行われます。 将来のハーバードアーキテクチャに対する予備的機能です。 ``` ## UART経由デバッグ制御 Jelly では、上記のCPUデバッグポートを UART 経由で制御する モジュールを用意しています。 UARTプロトコルは以下のとおり。 ``` 接続確認(nop) 要求パケット 0x00 応答パケット 0x80 単純に応答のみ行います 状態確認(statu) 要求パケット 0x01 応答パケット 0x81 status 0x81 に続いて、status 1バイトが返されます。 status の 0bit目に、エンディアンが返されます。 他のビットは現在予約bitです デバッガライト(dbg_write) CPUデバッグポートの指定アドレスにシングルライトを行う 要求パケット 0x02 sel+adr dat0 dat1 dat2 dat3 応答パケット 0x82 (注:アドレス4bitと、レーンセレクト4bit で1バイト) デバッガリード(dbg_read) 要求パケット 0x03 sel+adr 応答パケット 0x83 dat0 dat1 dat2 dat3 (注:アドレス4bitと、レーンセレクト4bit で1バイト) メモリライト(mem_write) 要求パケット 0x04 size adr0 adr1 adr2 adr3 dat0 dat1 dat2 dat3 .... 応答パケット 0x84 サイズ、アドレスの後にデータを送ります。 1パケットで最大で256バイトまで送ることが出来ます。 すべての送信が終わると応答パケットが返ります メモリリード(mem_read) 要求パケット 0x05 size adr0 adr1 adr2 adr3 応答パケット 0x85 dat0 dat1 dat2 dat3 .... サイズ、アドレスを送ると応答パケットが来ます。 1パケットで最大で256バイトまで送ることが出来ます。 ``` ## WISHBONEバス Jellyでは OpenCores(http://www.opencores.org/) の定めるWISBONEバスを 利用しています。 WISHBONEバス規格は多岐にわたっていますが、Jellyではシングルアクセスに 必要な最小限の信号のみ利用しています。 以下に利用している信号のみ簡単に説明します。 ``` adr_o アクセスするアドレスを指定します。 バイト単位ではなくデータバスの単位となります。 したがって、32bitデータバスの場合、アドレスバス幅は30bit幅で4Gbyteのメモリ空間を カバーします。 dat_o dat_i データの入出力を行う信号です。ライト/リードの信号が流れます。 we_o リード/ライトの指定を行う信号です。 0:read 1:write となります。 sel_o リード/ライト時のデータバスの有効なレーンを示します。 Jellyの場合、レーンサイズは8bit固定です。 32bitバスの場合、4bit幅の信号となります。 stb_o マスター側がアクセスを要求していることを示します。 アクセスが完了するまで 1 をキープします。 ack_i スレーブ側がアクセスを完了させたことを示します。 組合せ回路に stb_o を含むことができ、アクセス要求と同じサイクルで アクノリッジを返すことが可能です。 ``` ## Jelly bus WISHBONEバスはサイクル内でトランザクションが完結するため多くの場合 便利ですが、FPGAの内蔵SRAMの様にREAD結果の取得が次サイクルとなり、 メモリにCPUコアを直結する場合に相性が悪いです。 そこで下記のような独自バスを jbus として定義しています。 ``` en [master] バスのイネーブル 組合わせ回路に ready を含んでもよい addr [master] アドレス値 クロックの立ち上がりで en & valid & ready が 1 のとき受け付けられる master は en または ready が 0 のサイクルで値を変化させてはならない we [master] 1で書き込みを示す クロックの立ち上がりで en & valid & ready が 1 のとき受け付けられる master は en または ready が 0 のサイクルで値を変化させてはならない sel [master] バイトセレクト。1で有効バイト クロックの立ち上がりで en & valid & ready が 1 のとき受け付けられる master は en または ready が 0 のサイクルで値を変化させてはならない wdata [master] 書き込みデータ クロックの立ち上がりで en & valid & ready が 1 のとき受け付けられる master は en または ready が 0 のサイクルで値を変化させてはならない rdata [slave] 読み出しデータ クロックの立ち上がりで en & valid & ready が 1 のとき受け付けられる 読み出し要求が受け付けられた後、en & ready の時データが出力される slave は en が 0 のサイクルで値を変化させてはならない valid [master] アクセス要求 master は en または ready が 0 のサイクルで値を変化させてはならない 組合わせ回路に ready を含んではならない ready [slave] アクセス許可 組合わせ回路に valid を含んでもよいが、en を含んではならない ``` ## 命令セット等 こちらに置いておきます。 ```eval_rst :download:`files/jelly_cpu.ods` ```