ZPU Evo(lution)

English


ZPU は 32 ビットのスタックベースマイクロプロセッサーで、もともと Zylin AS の Øyvind Harboe が設計したものです。オリジナルのドキュメントは Zylin/OpenCore ウェブサイトまたは Wikipedia で確認できます。これは実行速度を犠牲にしてロジックエレメントと BRAM 使用量を最小限に抑えた、FPGA 組み込みアプリケーション向けのマイクロプロセッサーです。

Zylin はオープンソースとして公開した 2 つの設計(Small と Medium の ZPU バージョン)を作成しました。さらに、Wishbone インターフェースやパフォーマンスなどの強化を提供する Flex や ZPUino バリエーションなど、外部の開発者による追加設計も生まれました。

このドキュメントでは、パフォーマンス接続性命令セット拡張に重点を置いた ZPU Evo(Evolution)モデルと呼んでいる別の設計について説明します。これは、私が作成中のヴィンテージコンピューターのエミュレーターに CPU が必要で、メニュー、ペリフェラル、SD サービスを提供する IO プロセッサーとして機能するものが必要だったことから生まれました。

ZPU Evo のパフォーマンスは、Altera ファブリックで BRAM を使用して 100MHz で 22.2 のスコアを返す CoreMark と、Dhrystone で 13.2DMIPS で確認できます。比較は下のギャラリーのオリジナル ZPU 設計と行うことができ、現在の事実上の標準となっている CoreMark スコアに注目してください。接続性はシステムバスと Wishbone バスの両方の実装で確認できます。これにより多くのオープンソース IP デバイスとの接続が可能です。命令セット拡張は、複数の命令バイトがソースされて CPU に利用可能にされるクローズカップリング L1 キャッシュの実装で確認できます。これは最適化(例:1 サイクルで実行される最大 5 つの IM 命令)や拡張マルチバイト命令(例:LoaD Increment Repeat 命令の実装)に使用できます。スタックキャッシュ、SDRAM から L2 へのバーストモード、並列命令実行(例:and + neqbranch)などの改善の余地はまだ多くあり、私のリストに挙がっています。

CPU

ZPU Evo は ZPU Medium と Flex を引き継いでおり、例えば命令デコードなどコードの一部は類似しています。ただし、キャッシュとすべてのメモリ/IO 操作(デュアルポート命令バスが有効な場合の直接命令読み取りを除く)がルーティングされるメモリトランザクションプロセッサーの実装により、設計は異なります。オリジナルの CPU はすべてメモリ要件をその場で処理するか、ステートマシンの一部として処理していましたが、Evo はメモリ操作が必要なときはいつでも MXP にリクエストを送信します。

以下のセクションでは、オリジナルの ZPU 設計に対するいくつかの機能と変更点を示します。

バス構造

ZPU はすべてのメモリと IO デバイスがこの空間内で直接アドレス可能なリニアアドレス空間を持ちます。既存の ZPU 設計はシステムバスか Wishbone バスのどちらかを提供しますが、Evo は両方を提供します。ZPU Evo は設定に応じてアドレス空間内に最大 2 つの異なる領域を作成し、システムバスWishbone バスを提供します。

すべてのモデルにはシステムバスが実装されており、これは CPU アドレス 0 から始まり設定可能な最大アドレスビットが課す制限まで拡張されます(例:24ビットの場合 0x000000 - 0xFFFFFF)。専用のメモリマップ IO 領域がアドレス空間の上部に確保されています(他の場所にも簡単に配置できますが)(例:0xFF0000 - 0xFFFFFF)。

設定した場合、Wishbone バスをインスタンス化でき、これは最大アドレスビットを 1 つ拡張します(例:24ビットの例では 0x1000000 - 0x1FFFFFF)。これにより実質的に 2 つの同一の領域が作成され、下位はシステムバスで制御され、上位は Wishbone バスで制御されます。システムバスと同様に、Wishbone アドレス空間の上部は IO デバイス用に予約されています。

3 番目のバスを設定でき、これは命令読み取り専用です。このバスは通常メモリ領域でシステムバスをシャドウしますが、L2 キャッシュを必要とせずに命令を読み取るための高速アクセスメモリに接続されていると見なされます。これは通常、デュアルポート BRAM ブロックの 2 番目のポートで、1 番目のポートはシステムバスに接続されています。

L1 キャッシュ

パフォーマンス向上のためだけでなく、特に命令最適化と拡張命令のために、レジスターを使用した L1 キャッシュが実装されています。レジスターを使用するとファブリックスペースを消費するため非常に小さくする必要がありますが、1 サイクルでランダムアクセスが可能で、これは例えば 32 ビット IM ロード(5 つの命令になる可能性がある)を 1 サイクルにコンパクト化する場合に必要です。また拡張命令の場合、最初のバイトが拡張命令を示し、続く 1〜5 バイトが命令を定義し、それが 1 サイクルで実行されます。

L2 キャッシュ

内部 BRAM(FPGA 内のオンボード Block RAM)はアクセスタイムが 1〜2 サイクルのため L2 キャッシュは必要ありません。BRAM は限られたリソースであるため、外部 RAM や SDRAM が使用されますが、これははるかに低速でキャッシュによってスループットを向上させる必要があります。L2 キャッシュはこの目的のために使用され、外部 RAM のブロックを先読みして必要に応じて L1 キャッシュにフィードします。分析によると、GCC で生成された C プログラムは通常ローカルエリア内のループと呼び出し(大規模なライブラリを使用しない限り)であるため、プログラムカウンターに対して相対的にインデックス付けされた外部 RAM と BRAM(L2 キャッシュに使用)間のシンプルなダイレクトマッピングキャッシュを実装することで、ほとんどの時間 CPU のストールを防ぐのに十分です。

命令セット

ZPU の特徴は、ハードウェアで実装されたミニマルな固定セットの命令と、追加命令の疑似マイクロコード(つまり固定セットの命令)で実装されたソフトセットを使用することです。これは領域 0x0000 - 0x0400 の 32 バイトベクターで実現され、ハードウェアに実装されていない場合、各ソフト命令はベクターに分岐します。利点は FPGA リソースの削減ですが、欠点はパフォーマンスです。

ZPU Evo はすべての命令をハードウェアで実装しますが、必要に応じて FPGA リソースを節約するためにソフト命令を使用するように設定で調整できます。これにより、リソースとパフォーマンスのバランスを取ることができます。ただし、リソースが逼迫している場合は Small/Flex ZPU モデルの使用が良い選択かもしれません。

元の命令に加えて、以下の形式のマルチバイト命令を使用して命令セットを拡張するメカニズムがあります:

Extend Instruction,<new insn[7:2]+ParamSize[1:0]>,[byte],[byte],[byte],[byte]

ParamSize の値:

  • 00 - パラメーターバイトなし
  • 01 - 8 ビットパラメーター
  • 10 - 16 ビットパラメーター
  • 11 - 32 ビットパラメーター

一部の拡張命令は開発中です(例:LDIR)。正確なオペコード値と拡張命令セットはまだ完全には定義されていません。GNU AS アセンブラーはこれらの命令で更新され、C プログラム内で呼び出せるようになります。将来的に C にとって有益であれば GCC コンパイラーに移行されます(例:ADD32/DIV32/MULT32/LDIR/LDDR)。

実装命令セット

名前 オペコード 説明
ADD 00000101 スタック上の 2 つの値をポップして加算し、結果をプッシュ
ADDSP 0001xxxx SP+xxxx*4 のメモリ位置の値をスタックトップの値に加算
AND 00000110 スタックから 2 つの値をポップしてビット単位 AND を行い、結果をスタックにプッシュ
ASHIFTLEFT * 00101011 算術(符号付き)左シフト
ASHIFTRIGHT * 00101100 算術(符号付き)右シフト
BREAKPOINT 00000000 デバッガーがブレークポイントを設定するためにこの値をメモリ位置に設定
CALL * 00101101 プロシージャを呼び出す
CALLPCREL * 00111111 PC 相対でプロシージャを呼び出す
DIV * 00110101 符号付き 32 ビット整数除算
EMULATE 001xxxxx PC をスタックにプッシュし PC を 0x0+xxxxx*32 に設定。オペコードのエミュレートに使用。エミュレートされたオペコードはこの表で星(*)でマーク
EQ * 00101110 等値テスト
EQBRANCH * 00110111 等値条件分岐
ESR E00000000 拡張ステータスレジスターを TOS にコピー
EXTEND 00001111 拡張命令セット
FIADD32 * 00111010 固定小数点(Q15)加算
FIDIV32 * 00111011 固定小数点(Q15)除算
FIMULT32 * 00111100 固定小数点(Q15)乗算
FLIP 00001010 スタック上の値のビット順を逆にする
IM 1xxxxxxx 7 ビット符号拡張整数をプッシュし IDIM フラグを設定
LDIR E00001yxx LoaD Increment Repeat、メモリの <n> ワードをコピー
LESSTHAN * 00100100 符号付き比較
LESSTHANOREQUAL * 00100101 符号付き比較(以下)
LOAD 00001000 スタックに格納されたアドレスをポップし、そのアドレスの値をスタックに読み込む
LOADB * 00110011 8 ビット読み込み命令
LOADH * 00100010 16 ビット読み込み命令
LOADSP 011xxxxx SP+xxxxx*4 のメモリ位置の値をスタックにプッシュ
LSHIFTRIGHT * 00101010 符号なし右シフト
MOD * 00110110 符号付き 32 ビット整数剰余
MULT * 00101001 符号付き 32 ビット乗算
NEG * 00110000 符号反転
NEQ * 00101111 不等値テスト
NEQBRANCH * 00111000 不等値条件分岐
NOP 00001011 無操作
NOT 00001001 スタック上の値のビット単位反転
OR 00000111 2 つの整数をポップし、ビット単位 OR を行い結果をプッシュ
POPPC 00000100 スタックからアドレスをポップし PC を設定
POPPCREL * 00111001 スタックポインターに対して相対的な位置からプログラムカウンターに値をポップ
POPSP 00001101 スタックトップから値をポップし SP をその値に設定
PUSHPC emulated プログラムカウンターをスタックにプッシュ
PUSHSP 00000010 スタックポインターをプッシュ
PUSHSPADD * 00111101 スタックポインターに値を加算しスタックにプッシュ
STORESP 010xxxxx スタックから値をポップし SP+xxxxx*4 のメモリ位置に格納
STORE 00001100 スタックからアドレスをポップし、次に値をポップしてアドレスのメモリ位置に格納
STOREB * 00110100 8 ビット格納命令
STOREH * 00100011 16 ビット格納命令
SUB * 00110001 符号付き 32 ビット減算
ULESSTHAN * 00100110 符号なし比較
ULESSTHANOREQUAL * 00100111 符号なし比較(以下)
XOR * 00110010 排他的論理和

E = 拡張命令、EXTEND オペコードが前置。
* = ハードウェアに実装されていない場合はエミュレートされた命令。

実装命令比較表

alt text

ハードウェア可変バイト書き込み

オリジナルの ZPU 設計では、ZPU がバイト/ハーフワード/フルワード書き込みを実行するための範囲はありましたが実装はありませんでした。CPU は常に 32 ビットワードアラインの操作を実行するか、マイクロコードで操作を実行するかのどちらかでした。

Evo では、バイトおよびハーフワード書き込みと、ハードウェアによる Read-Update-Write 操作を可能にするハードウェアが実装されました(ビルド時に選択可能)。ハードウェアによるバイト/ハーフワードロジックが有効でない場合は、32 ビットワード Read-Update-Write ロジックにフォールバックします。どちらの方法にもパフォーマンス上の利点があり、後者は 3 サイクル多くかかります。

ハードウェアデバッグシリアライザー

CPU をデバッグするため、または単に低レベルの内部動作情報を提供するために、キャッシュされた UART デバッグモジュールが実装されています。現在は出力のみですが、シミュレーション/SignalTap が利用できない場合のその場デバッグのために IOCP と連携する意図があります。

CPU RTL には、選択可能なレベルトリガーステートメントが埋め込まれており、スナップショット情報をシリアライザーに送信します。ステートメントが展開されてシリアル化され、接続されたターミナルに出力されます。

タイミング制約

これは進行中の作業です。タイミングが完全に満たされるよう、設計を徐々に更新および/または制約を追加しています。現在 100MHz でネガティブスラックがありますが、設計は完全に動作しています。将来的には TimeQuest で解析されたタイミングが満たされるよう修正される予定です。

System On a Chip

ZPU Evo を使用できる動作フレームワークを提供するため、各種デバイス(UART/SD カードなど)のインスタンス化を可能にする System On a Chip ラッパーが作成されました。

開発の一環として、ZPU Small/Medium/Flex モデルをフレームワークに組み込み、ファブリックスペースが限られている場合や CPU を比較する場合に CPU を選択できるようにしました。ただし、元の ZPU モデルでは Wishbone などの機能は利用できません。ZPUino はすでに非常に良いエコシステムを持っているため、また ZY2000 も含めませんでした。

SoC は現在(ビルドツリーで)以下を実装しています:

コンポーネント オプション コメント
CPU はい ZPU Small、Medium、Flex、Evo または Evo Minimal。
Wishbone バス はい 32 ビット Wishbone バス。
(SB) BRAM はい ブートローダーとスタックとして設定可能な BRAM ブロックを実装。
命令バス BRAM はい BRAM に実装されたブートコードへの独立したバス(またはデュアルポート)を有効化。
(SB) RAM はい ブートローダー/スタック用の BRAM とは別の RAM として BRAM ブロックを実装。
(SB) SDRAM はい システムバスに SDRAM コントローラーを実装。
(WB) SDRAM はい Wishbone バス経由で SDRAM コントローラーを実装。
(WB) RAM はい Wishbone バス経由で BRAM を RAM として実装。
(WB) I2C はい Wishbone バス経由で I2C コントローラーを実装。
(SB) タイマー 0 いいえ ハードウェア 12 ビット秒、18 ビットミリ秒、24 ビットマイクロ秒ダウンカウンタータイマー。
(SB) タイマー 1 はい 選択可能な数のプリスケールされた 32 ビットダウンカウンター。
(SB) UART 0 いいえ モニター出力とコマンド入力/プログラムロードに使用するキャッシュされた UART。
(SB) UART 1 いいえ ソフトウェア(C プログラム)/ハードウェア(ZPU デバッグシリアライザー)出力に使用するキャッシュされた UART。
(SB) 割り込みコントローラー はい 優先順位付き設定可能な割り込みコントローラー。
(SB) PS2 はい PS2 キーボードとマウスコントローラー。
(SB) SPI はい 設定可能な数のシリアルペリフェラルインターフェースコントローラー。
(SB) SD はい 設定可能な数のハードウェアベース SPI SD コントローラー。
(SB) IOCTL はい MiSTer HPS-to-FPGA 通信用の IOCTL バスコントローラー。
(SB) SOCCFG はい ZPU と SoC の設定を制御プログラムに示すレジスターセット。

SDRAM

SoC は 2 つの独立したパス経由で SDRAM をサポートします:システムバス(SB)コントローラー(SOC_IMPL_SDRAM)と Wishbone バス(WB)コントローラー(SOC_IMPL_WB_SDRAM)。両方はデフォルトで無効になっており、独立して有効化できます。SDRAM タイミングパラメーター(tRCD、tRP、tRFC、tREF)とジオメトリ(行、列、バンク、データ幅)はすべて zpu_soc_pkg.vhd で設定できます。WB SDRAM コントローラーはバーストアクセスをサポートするキャッシュバリアントで、両方のバスがアクティブで外部 RAM 帯域幅が重要な場合に推奨されます。

ソフトウェア

提供されるソフトウェアには以下が含まれます:

  1. ブートローダー、I/O Control Program(IOCP)。これは単なるブートローダー以上のもので、基本形式では SD カードからアプリケーションをブートストラップできます。また、コマンドラインモニターツールとシリアルアップロード機能も含められます。
  2. アプリケーション、ZPUTA(ZPU Test Application)。これはテストスイートで、単一アプリケーションとして、またはすべての機能が SD カードに格納されているディスクオペレーティングシステムとして構成できます。ZPUTA は IOCP でブートストラップするか、ROM/BRAM 内の唯一のプログラムとしてスタンドアロンで動作できます。
  3. ディスクオペレーティングシステム、zOS(ZPU Operating System)。ZPUTA のバージョンですが、すべての機能がディスクアプリケーションとして格納されているプロダクションコードを対象としています。
  4. アプリケーションのビルドを支援する C のライブラリ関数(El. Chan の FatFS などのサードパーティライブラリを含む)。

21/04/2020: ZPU 用のソフトウェアは tranZPUter とマージされ、zSoft リポジトリで管理されています。

設定

このセクションでは、ZPU を単独で使用する場合や付属の SoC の一部として使用する場合に、ZPU と SoC を設定する方法を示します。

CPU の設定


CPU は設定ファイル ‘cpu/zpu_pkg.vhd’ を使用して設定できます。一般的にアドレスバスのサイズとどのハードウェア機能を有効にするかを指定します。以下の表は設定可能なオプションを示しています。

設定変数 モデル 説明
EVO_USE_INSN_BUS Evo true/false BRAM メモリへの接続に独立した命令バスを使用。他のすべてのメモリと I/O 操作は通常のバスを経由します。このオプションは主にデュアルポート BRAM で使用され、命令バス側で、もう一方が標準バスに接続されていると、実行コードがこのメモリにある場合に大幅なパフォーマンス向上が得られます。
EVO_USE_HW_BYTE_WRITE Evo true/false バイトのハードウェア書き込みを実装。読み取りは常に 32 ビットでアラインされています。
EVO_USE_HW_WORD_WRITE Evo true/false 16 ビットワードのハードウェア書き込みを実装。
EVO_USE_WB_BUS Evo true/false システムバスに加えて Wishbone インターフェースを実装。
DEBUG_CPU すべて true/false CPU デバッグ出力を有効化。
DEBUG_LEVEL すべて 0 〜 5 デバッグ出力のレベル。0 = 基本(ブレークポイントなど)、1 = 実行命令を含む、…
DEBUG_MAX_TX_FIFO_BITS すべて 2 〜 ~16 デバッグ出力用 UART TX FIFO のサイズ。
DEBUG_MAX_FIFO_BITS すべて 2 〜 ~16 デバッグ出力データレコード FIFO のサイズ。
DEBUG_TX_BAUD_RATE すべて 任意のボーレート整数値 デバッグシリアライザー送信機の出力ボーレート。例:115200
maxAddrBit すべて <16..31n> + WB_ACTIVE アドレスバスの幅を設定。

ZPU Evo には、ハードウェア命令とキャッシュを有効/無効にするためのオプションが多数あります:

設定変数 説明
IMPL_OPTIMIZE_IM true/false 命令キャッシュが有効な場合、Im 命令を最適化して速度を向上。
IMPL_ASHIFTLEFT true/false 算術左シフト。
IMPL_ASHIFTRIGHT true/false 算術右シフト。
IMPL_CALL true/false 直接アドレスへの呼び出し。
IMPL_CALLPCREL true/false 間接アドレスへの呼び出し(プログラムカウンターにオフセットを加算)。
IMPL_DIV true/false 32 ビット符号付き除算。
IMPL_EQ true/false 等値テスト。
IMPL_EXTENDED_INSN true/false 拡張マルチバイト命令セット。
IMPL_FIADD32 true/false 固定小数点 Q17.15 加算。
IMPL_FIDIV32 true/false 固定小数点 Q17.15 除算。
IMPL_FIMULT32 true/false 固定小数点 Q17.15 乗算。
IMPL_LOADB true/false メモリから 1 バイトを読み込む。
IMPL_LOADH true/false メモリからハーフワード(16 ビット)を読み込む。
IMPL_LSHIFTRIGHT true/false 論理右シフト。
IMPL_MOD true/false 32 ビット剰余(除算後の余り)。
IMPL_MULT true/false 32 ビット符号付き乗算。
IMPL_NEG true/false TOS の値を符号反転。
IMPL_NEQ true/false 不等値テスト。
IMPL_POPPCREL true/false スタックポインターに対して相対的な位置からプログラムカウンターに値をポップ。
IMPL_PUSHSPADD true/false スタックポインターに値を加算しスタックにプッシュ。
IMPL_STOREB true/false メモリ/IO に 1 バイトを格納/書き込む。
IMPL_STOREH true/false メモリ/IO にハーフワード(16 ビット)を格納/書き込む。
IMPL_SUB true/false 32 ビット符号付き減算。
IMPL_XOR true/false TOS の値の排他的論理和。
RESET_ADDR_CPU <n> リセット後の実行開始アドレス。通常 ROM/BRAM 内のファームウェアの先頭。
START_ADDR_MEM <n> プログラムメモリの開始位置。
STACK_ADDR <n> スタック開始アドレス。
CLK_FREQ <n> CPU クロック周波数(Hz)。

SoC の設定


System on a Chip は設定ファイル ‘zpu_soc_pkg.vhd’ を使用して設定できます。

使用する CPU を選択するオプション(警告:1 つのみ有効にできます):

設定変数 説明
ZPU_SMALL <0 または 1> SoC で SMALL CPU を選択。Wishbone インターフェースは利用不可。
ZPU_MEDIUM <0 または 1> SoC で MEDIUM CPU を選択。Wishbone インターフェースは利用不可。
ZPU_FLEX <0 または 1> SoC で FLEX CPU を選択。Wishbone インターフェースは利用不可。
ZPU_EVO <0 または 1> SoC で EVOLUTION CPU を選択。
ZPU_EVO_MINIMAL <0 または 1> SoC で Minimalist EVOLUTION CPU を選択。

各ボードの周波数設定:

設定変数 説明
SYSCLK_E115_FREQ 75000000(デフォルト) E115 FPGA ボードの周波数を設定。
SYSCLK_QMV_FREQ 75000000(デフォルト) QMTECH Cyclone V FPGA ボードの周波数を設定。
SYSCLK_DE0_FREQ 100000000(デフォルト) DE0-Nano FPGA ボードの周波数を設定。
SYSCLK_DE10_FREQ 100000000(デフォルト) DE10-Nano FPGA ボードの周波数を設定。
SYSCLK_CYC1000_FREQ 100000000(デフォルト) Trenz CYC1000 FPGA ボードの周波数を設定。
SYSTEM_FREQUENCY 75000000 上記でオーバーライドされない場合のデフォルトシステムクロック周波数。

ZPU モデルの ID(フォーマット:2 バイト、MSB=<モデル>、LSB=<リビジョン>):

設定変数 説明
ZPU_ID_SMALL 16#0101# ZPU Small の ID を設定。
ZPU_ID_MEDIUM 16#0201# ZPU Medium の ID を設定。
ZPU_ID_FLEX 16#0301# ZPU Flex の ID を設定。
ZPU_ID_EVO 16#0401# ZPU Evo の ID を設定。
ZPU_ID_EVO_MINIMAL 16#0501# ZPU Evo Minimal の ID を設定。

EVO CPU キャッシュ固有の設定:

設定変数 説明
MAX_EVO_L1CACHE_BITS <3..n>(例:5) Evo の Level 0 命令キャッシュの最大サイズ(命令数)をビット数で設定。
MAX_EVO_L2CACHE_BITS <8..n>(例:14) Evo の Level 2 命令キャッシュの最大サイズ(バイト数)をビット数で設定。
MAX_EVO_MXCACHE_BITS <3..n>(例:3) Evo のメモリトランザクションキャッシュの最大サイズをビット数で設定。
MAX_EVO_MIN_L1CACHE_BITS <3..n>(例:3) Minimal Evo の Level 0 命令キャッシュの最大サイズをビット数で設定。
MAX_EVO_MIN_L2CACHE_BITS <8..n>(例:12) Minimal Evo の Level 2 命令キャッシュの最大サイズをビット数で設定。
MAX_EVO_MIN_MXCACHE_BITS <3..n>(例:3) Minimal Evo のメモリトランザクションキャッシュの最大サイズをビット数で設定。

各種 IO デバイスの設定:

設定変数 説明
MAX_RX_FIFO_BITS <4..n>(例:4) UART RX FIFO のサイズ。
MAX_TX_FIFO_BITS <4..n>(例:10) UART TX FIFO のサイズ。
MAX_UART_DIVISOR_BITS <1..n>(例:16) UART クロックレートジェネレーター除数の最大ビット数。
INTR_MAX <1..n>(例:16) 最大割り込み入力数。

SoC 固有のオプション:

設定変数 説明
SOC_IMPL_TIMER1 true/false タイマー 1(プリスケールされたダウンカウンターの配列)を実装。
SOC_TIMER1_COUNTERS <0..n>(例:0) タイマー 1 のダウンカウンター数。値は 2^ の配列なので 0 = 1 カウンター。
SOC_IMPL_SD true/false SD カードインターフェースを実装。
SOC_SD_DEVICES <0..n> 実装する SD カードチャンネル数。
SOC_IMPL_INTRCTL true/false 優先順位付き割り込みコントローラーを実装。
SOC_IMPL_TCPU true/false Z80 バスを制御する TCPU コントローラーを実装。
SOC_IMPL_SOCCFG true/false SoC 設定情報レジスターを実装。

メイン起動 BRAM(sysbus 上、起動ファームウェアを含む):

設定変数 説明
SOC_IMPL_BRAM true/false BIOS と初期スタック用の BRAM を実装。
SOC_IMPL_INSN_BRAM true/false EVO CPU 用の専用命令 BRAM を実装。
SOC_MAX_ADDR_BRAM_BIT <n>(例:15) システム BRAM ROM/スタックの最大アドレスビット(バイト)。例:15 = 32KB または 8K 32 ビットワード。
SOC_ADDR_BRAM_START <n>(例:0) BRAM の開始アドレス。

CPU 初期化オプション:

設定変数 説明
SOC_RESET_ADDR_CPU <n> リセット後の実行開始アドレス。通常 SOC_ADDR_BRAM_START。
SOC_START_ADDR_MEM <n> プログラムメモリ(BRAM/ROM/RAM)の開始位置。
SOC_STACK_ADDR <n> スタック開始アドレス(BRAM/RAM)。通常 SOC_ADDR_BRAM_END - 8。
SOC_ADDR_IO_START <n> Evo システムバス IO 領域の開始アドレス。
SOC_ADDR_IO_END <n> Evo システムバス IO 領域の終了アドレス。
SOC_WB_IO_START <n>(例:32505856) Wishbone バス IO 範囲の開始アドレス。
SOC_WB_IO_END <n>(例:33554431) Wishbone バス IO 範囲の終了アドレス。

ビルド

このセクションでは基本的なビルドの方法を示します。対象の開発ボードは QMTECH Cyclone V ボードを前提としています。

ソフトウェアのビルド

Jenkins でビルドを自動化できますが、シンプルな起動コンパイルには build.sh と階層的な Makefile システムを以下の基本手順に従って使用します。

  1. ZPU GCC ToolChain をダウンロードしてインストールします。/opt などの共通の場所にインストールします。
  2. 環境変数のパスを設定します。
     export PATH=$PATH:/opt/zpu/bin
    
  3. ZPU Evo リポジトリをクローンします。
  4. <zpu evo dir>/software/zputa/zputa.h ファイルを編集して、zputa コアイメージにどの機能をビルドするかを選択します(デフォルトではすべての機能がアプレットとしてビルドされますが、zputa コアイメージにビルドインされている場合は無視されます)。BUILTIN_<utility> を ‘1’ に設定すると機能が選択されます。
  5. どのメモリマップを使用するか、また ZPUTA がアプリケーションかブートローダーかを決定し(独自のアプリケーション向けには同様の選択になります)、以下のようにビルドコマンドを発行します。
     cd <zpu evo dir>/software
     # この例では Tiny IOCP ブートローダーを選択し、ZPUTA をアプリケーションとしてビルドします。
     # ZPUTA ベースアドレスは 0x1000、アプレットが読み込まれて実行されるアドレスは 0xC000 です。
     ./build.sh -I 3 -O zputa -o 2 -B 0x1000 -A 0xC000
     # ビルドコマンドは IOCP ブートローダーをインストールした VHDL BRAM イメージを自動的に作成します。
     # 新しいブートローダーを有効にするには ZPU Evo SOF ビットストリームをビルドして FPGA にアップロードする必要があります。
    
  6. システムに SD カードを挿入して FAT32 フォーマットでフォーマットし、ファイルをコピーします。
     cd build/SD
     cp -r * <abs path to SD card, ie. /media/psmart/ZPU>
     # SD カードを取り出して FPGA 開発ボードの SD カードリーダーに取り付けます。
    

RTL ビットストリームのビルド

FPGA ビットストリームをビルドするには(HDL を FPGA の設定マップに変換する)、2 つの方法があります:

  1. Intel Quartus Prime 17.1 以降をインストールします(または以下の Docker イメージをビルドします)。
  2. Quartus Prime を開いてプロジェクトを読み込み(File -> Open Project)、<zpu evo dir>/build/QMV_zpu.qpf を選択します。
  3. コンパイルします(Processing -> Start)。

または代替方法として

  1. Intel Quartus Prime 17.1 以降をインストールします。
  2. Makefile ビルドシステムを使用してコマンドを発行します。
     cd <zpu evo dir>/build
     make QMV_EVO
    

ZPU Small ビルド

ZPU Small CPU は以下のように設定を変更してビルドできます:

cd <repository>
zpu_soc_pkg.vhd を編集:

1. 希望の CPU に変更:
    constant ZPU_SMALL                :     integer    := 1;
    constant ZPU_MEDIUM               :     integer    := 0;
    constant ZPU_FLEX                 :     integer    := 0;
    constant ZPU_EVO                  :     integer    := 0;
    constant ZPU_EVO_MINIMAL          :     integer    := 0;

2. ZPU Small は Wishbone インターフェースをサポートしないため、Wishbone デバイスを無効化:
    constant SOC_IMPL_WB_I2C          :     boolean    := false;
    constant SOC_IMPL_WB_SDRAM        :     boolean    := false;

Makefile ビルドシステムを使用する場合の例(QMV ボード向け Small CPU のビルド):

    cd <zpu evo dir>/build
    make QMV_SMALL

ZPU Medium ビルド

ZPU Medium CPU は以下のように設定を変更してビルドできます:

cd <repository>
zpu_soc_pkg.vhd を編集:

1. 希望の CPU に変更:
    constant ZPU_SMALL                :     integer    := 0;
    constant ZPU_MEDIUM               :     integer    := 1;
    constant ZPU_FLEX                 :     integer    := 0;
    constant ZPU_EVO                  :     integer    := 0;
    constant ZPU_EVO_MINIMAL          :     integer    := 0;

2. ZPU Medium は Wishbone インターフェースをサポートしないため、Wishbone デバイスを無効化:
    constant SOC_IMPL_WB_I2C          :     boolean    := false;
    constant SOC_IMPL_WB_SDRAM        :     boolean    := false;

Makefile ビルドシステムを使用する場合の例(QMV ボード向け Medium CPU のビルド):

    cd <zpu evo dir>/build
    make QMV_MEDIUM

ソフトウェアは同じで、メモリが少ない場合以外はソフトウェアビルドへの変更は不要です。


ZPU Flex ビルド

ZPU Flex CPU は以下のように設定を変更してビルドできます:

cd <repository>
zpu_soc_pkg.vhd を編集:

1. 希望の CPU に変更:
    constant ZPU_SMALL                :     integer    := 0;
    constant ZPU_MEDIUM               :     integer    := 0;
    constant ZPU_FLEX                 :     integer    := 1;
    constant ZPU_EVO                  :     integer    := 0;
    constant ZPU_EVO_MINIMAL          :     integer    := 0;

2. ZPU Flex は Wishbone インターフェースをサポートしないため、Wishbone デバイスを無効化:
    constant SOC_IMPL_WB_I2C          :     boolean    := false;
    constant SOC_IMPL_WB_SDRAM        :     boolean    := false;

Makefile ビルドシステムを使用する場合の例(QMV ボード向け Flex CPU のビルド):

    cd <zpu evo dir>/build
    make QMV_FLEX

ソフトウェアは同じで、メモリが少ない場合以外はソフトウェアビルドへの変更は不要です。


ZPU Evo ビルド

ZPU Evo には 2 つの事前定義バージョンがあり、同じ CPU で異なる設定を使用します。EVO と ‘EVO MINIMAL’ です。後者は ZPU Small のようにほとんどの命令をマイクロコードで実装します。

WishBone インターフェースなしで EVO をビルドする場合:

zpu_soc_pkg.vhd を編集:
    constant ZPU_SMALL                :     integer    := 0;
    constant ZPU_MEDIUM               :     integer    := 0;
    constant ZPU_FLEX                 :     integer    := 0;
    constant ZPU_EVO                  :     integer    := 1;
    constant ZPU_EVO_MINIMAL          :     integer    := 0;

Makefile を使用して QMV ボード向けに Evo CPU をビルドする例:

    cd <zpu evo dir>/build
    make QMV_EVO

新しい開発ボードのセットアップに関する注意事項

独自の FPGA ボードを使用している場合(テストして Quartus 設定ファイルを作成したリストにないもの)は、以下の必要なファイルを作成してください:

build/<your board name>.qpf
build/<your board name>.qsf
build/<your board name>_Toplevel.vhd

既存の設定をコピーしてカスタマイズするのが最善です。例えば、Cyclone IV を使用しているボードなら E115_zpu* ファイルをコピーして変更します:

cp build/E115_zpu.qpf build/NEW_zpu.qpf
cp build/E115_zpu.qsf build/NEW_zpu.qsf
cp build/E115_zpu_Toplevel.vhd build/NEW_zpu_Toplevel.vhd

build/NEW_zpu.qpf ファイルでボード名に合わせて PROJECT 名を変更します:

PROJECT_REVISION = "NEW_zpu"

build/NEW_zpu.qsf ファイルでピン割り当てをボードで使用可能なものに変更します。UART、SD カード、CLOCK の最低限の変更を行ってください。

また、PLL 割り当ても確認・変更する必要があります。事前定義の設定の 1 つを使用するか、独自のものを作成してください。