tranZPUter SW-700 (v1) — デベロッパーズガイド

tranZPUter SW-700 V1 デベロッパーズガイド

このガイドは tranZPUter SW-700 V1(ハードウェアリビジョン v1.2、Cyclone III FPGA)のソースコードと開発環境の詳細なウォークスルーです。V1 ハードウェアに特有の VHDL 設計、CPLD ロジック、K64F ファームウェア、TZFS Z80 ソフトウェア、ビルドツールチェーンをカバーします。V1 から現行リリースに移行する開発者は、すべての既知の非互換性を文書化した V1 vs 現行ファームウェアセクションに特に注意してください。
ハードウェアアーキテクチャとビルドシステムの詳細については tranZPUter SW-700 プロジェクトページを参照してください。現行(v1.3、Cyclone IV)デベロッパーズガイドについては 現行デベロッパーズガイドを参照してください。ユーザー向けの操作については TZFS ユーザーマニュアルを参照してください。
V1 ハードウェアに関する注意
このガイドは特に v1.2 ハードウェア(Cyclone III EP3C25E144C8 FPGA、144ピン TQFP パッケージ)を文書化しています。FPGA ソースは FPGA/SW700/v1.2/ にあります。ビデオコントローラレジスタは I/O アドレス 0xF8–0xFD にあります。このガイドに対して書かれたコードは、現行の v1.3 ハードウェア上では変更なしでは動作しません。現行ハードウェアではそれらのレジスタが 0xA8–0xAD に移動され、いくつかの新しいレジスタとサービスコマンドが追加されています。完全な移行チェックリストについては V1 vs 現行ファームウェアセクションを参照してください。

VHDL に馴染みのない開発者のための VHDL 入門

tranZPUter SW-700 FPGA ロジックは VHDL(VHSIC ハードウェア記述言語)で書かれています。ソフトウェア言語とは異なり、VHDL は並行して実行されるハードウェアを記述します — すべての process ブロックは C やアセンブリの関数のように順次実行されるのではなく、同時かつ継続的に実行されます。

エンティティとアーキテクチャ
VHDL の基本的な構成要素は外部インターフェース(ポート)を宣言する エンティティと内部動作を定義する アーキテクチャです。tranZPUter VHDL では:
  • VideoController700.vhdentity VideoController700 is — トップレベルビデオコントローラエンティティ、FPGA パッケージに接続するすべてのピンを記述する。
  • architecture rtl of VideoController700 is — ビデオコントローラロジックの RTL(レジスタ転送レベル)記述。
  • ポートは inout、または inout として宣言される。アクティブロー信号は慣例的に n で終わる(例:VZ80_RDn = Z80 /RD、アクティブロー)。

信号とプロセス
  • 信号は内部ワイヤーまたはレジスタです: signal VIDEOMODE : std_logic_vector(7 downto 0); は VIDEOMODE という名前の 8 ビット信号を宣言します。
  • 並行信号代入(任意の process の外)は常にアクティブな組み合わせロジックを記述します: CS_FB_VMn <= '0' when CS_IO_FXXn = '0' and VADDR(3 downto 0) = "1000" else '1'; — このチップセレクトはアドレスビットがポート 0xF8 を選択するたびにアサートされます。
  • プロセスブロックは同期(クロック)または非同期ロジックを記述します。process(rising_edge(CLK)) ブロックはフリップフロップ動作を記述します — 内部の代入はクロックの立ち上がりエッジで有効になります。センシティビティリスト付きの process(a, b, c) ブロックは、リストされている任意の信号が変化するたびに再評価される組み合わせロジックを記述します。
  • std_logic は 9 値型('0'、'1'、'Z' でハイインピーダンス、'X' で不明など)。std_logic_vector は std_logic ビットの配列。ほとんどのポートと信号宣言はこの 2 つの型のどちらかを使用します。

パッケージファイル
VHDL パッケージは共有定数、型、関数宣言を収集します。tranZPUter SW-700 V1 は以下を使用します:
  • VideoController700_pkg.vhd — マシンモード定数(MODE_MZ80K から MODE_MZ2000)、CPLD バージョンフラグ、ビデオコントローラとトップレベルの両方で使用される共有型定義。
  • VideoController700_Toplevel.vhd — FPGA トップレベルエンティティ、ビデオコントローラを物理デバイスピンに接続し PLL とブロック RAM をインスタンス化する。
ソースでは、共有定数を使用するすべてのファイルは use work.VideoController700_pkg.all; で始まります。

ソースツリー

パス 内容
CPLD/EPM7160/ CPLD VHDL — バス制御、Z80 トライステート、メモリ管理、クロック選択。V1 と現行で共有。
FPGA/SW700/v1.2/ V1.2 Cyclone III FPGA VHDL — 144ピン TQFP デバイス用ビデオコントローラ。
FPGA/SW700/v1.2/VideoController700.vhd メインビデオコントローラ RTL — すべてのディスプレイロジック、I/O レジスタデコード、GRAM/VRAM 制御。
FPGA/SW700/v1.2/VideoController700_pkg.vhd 共有定数と型のパッケージ。
FPGA/SW700/v1.2/VideoController700_Toplevel.vhd FPGA トップレベル — ピンアサインメント、PLL インスタンス化、BRAM 配線。
FPGA/SW700/v1.2/functions.vhd トップレベルで使用されるユーティリティ関数(log2 など)。
FPGA/SW700/v1.2/build/ Quartus プロジェクトファイルとコンパイル済み出力。SOF プログラミングファイルは build/output_files/ にある。
FPGA/SW700/v1.3/ 現行 Cyclone IV FPGA VHDL — リファレンスと移行用。
schematics/SW700/v1.2/ v1.2 ハードウェアの KiCad 回路図。PDF エクスポートも存在。
pcb/SW700/v1.2a/ v1.2a ボードリビジョンの Gerber PCB 製造ファイル。
software/TZFS/asm/ TZFS の Z80 アセンブリソース(V1 と現行で共有)。
software/TZFS/asm/include/tzfs_definitions.asm すべての I/O ポートと設定定数。
software/TZFS/asm/include/tzfs_svcstruct.asm K64F サービスコマンドと構造定義。
software/TZFS/build.sh Z80 ファームウェアのトップレベルビルドスクリプト。
software/TZFS/tools/ glass.jar(GLASS Z80 アセンブラ)を含むビルドツール。
V1 パスに関する注意
このガイドのすべての FPGA ソース参照は FPGA/SW700/v1.2/ を指します。このドキュメントと並行して現行デベロッパーズガイドを読んでいる場合、現行ガイドは FPGA/SW700/v1.3/ を参照していることに注意してください。ファイル名は同じですが内容が異なります — 特に、ポートアドレスデコード、BRAM 割り当て、マシンモードレジスタマップが異なります。

CPLD 設計(EPM7160)

CPLD(Altera EPM7160、160 マクロセル、PLCC84 パッケージ)はバス調停とメモリ管理を処理します — FPGA が内部ファブリックルーティングで確実に達成できるよりも速いグルーロジック応答時間が必要な機能。CPLD 設計は V1 と現行ハードウェアで同一です。
ソース: CPLD/EPM7160/tranZPUterSW_EPM7160.vhd(トップレベル RTL)と tranZPUterSW_pkg_EPM7160.vhd(パッケージ)。Quartus でプロジェクトファイル tranZPUterSW_EPM7160.qpf を使用してビルドする。

バスマスタリングと Z80 トライステート
CPLD は Z80 バスマスタリングを実装します:Z80 に /BUSRQ をアサートし、/BUSAK を待機し、DMA スタイルの転送のためにアドレスバスとデータバスを直接駆動します。これは K64F がモニターファームウェアを tranZPUter SRAM にロードし、Z80 に代わって SD カード I/O リクエストをサービスするために使用されます。CPLD はアドレスバスとデータバストランシーバーのバッファ方向と出力イネーブル信号を制御して Z80 をトライステート化します。

メモリ管理設定レジスタ(MMCFG、ポート 0x60)
I/O ポート 0x60 に TZMM モード値を書き込むと、tranZPUter SRAM の 8 つの 64 KB ブロック(合計 512 KB)のうち、Z80 アドレス空間に見えるのはどれかを選択します。これが TZFS バンクスイッチングメカニズムのコアです。CPLD は 0x60 I/O 書き込みをデコードしてモード値をラッチします。すべての TZFS バンクスイッチングは単一の OUT (0x60), A 命令です。

クロック選択
CPLD は 2 つのクロックソースのどちらかを Z80 にルーティングします:オリジナルの Sharp MZ-700 システムクロック(3.54 MHz)または代替の高速クロック(最大 24 MHz、K64F またはクリスタル発振器で生成)。I/O ポート:
  • SETXMHZ EQU 062H — 高速代替クロックを選択する。
  • SET2MHZ EQU 064H — システム 3.54 MHz クロックを選択する。
  • CLKSELRD EQU 066H — 現在のクロック選択を読み取る(0 = システム速度、1 = 代替)。
Z80 が Sharp MZ-700 マザーボードのペリフェラル(0xE000–0xFFFF のメモリマップド I/O)にアクセスするとき、CPLD は正しいタイミングを維持するために自動的にウェイトステートを挿入します — どのクロック速度がアクティブであっても Z80 は正しいペリフェラルタイミングを見ます。

CPLD ステータスレジスタ(ポート 0x6B)
V1 の違い — 0x6B のシステムコマンドレジスタ(tzfs_definitions.asmCPLDSTATUS EQU 06BH)は Version 2.1 CPLD の機能です。V1 CPLD 設計はこのレジスタを実装していません。V1 ハードウェアで 0x6B を読み取るコードは未定義のデータを受け取ります。ハードウェアバージョン検出に 0x6B 読み取りを使用しないでください;代わりに、既知のレジスタマップの違い(0xA8 ではなく 0xF8 のビデオレジスタ)を使用して実行時に V1 ハードウェアを検出してください。

FPGA 設計 — V1.2 Cyclone III

V1.2 FPGA は Intel(Altera)Cyclone III EP3C25E144C8 です:
  • 25,000 ロジックエレメント(LE)
  • 76 KB 埋め込みブロック RAM(BRAM)
  • 144ピン TQFP パッケージ — v1.3 デバイスの 484ピン BGA とは異なり、手はんだ可能
  • Quartus Prime 13.1(Cyclone III デバイスをサポートする最後のバージョン)でビルド
FPGA はビデオコントローラサブシステム全体を実装します:CPLD から Z80 バス信号を受け取り、ビデオレジスタ I/O をデコードし、キャラクタ RAM(VRAM)、グラフィックス RAM(GRAM)、キャラクタジェネレータ ROM(CGROM)を管理し、VGA 出力を駆動します。

BRAM 制限と 640×200 ダブルバッファ制約
76 KB BRAM は V1 の最も重要なハードウェア制約です。ビデオコントローラは BRAM を以下に使用します:
  • キャラクタ VRAM: 2 KB(テキストと属性データ)
  • キャラクタジェネレータ ROM(CGROM): 2 KB
  • グラフィックス RAM(GRAM): 各 8 KB の 3 色プレーン = 640×200 解像度で 24 KB
  • スキャンラインフレームバッファ: VGA 出力スケーラ用の追加 BRAM
現行の v1.3 設計では、より大きな Cyclone IV BRAM バジェットにより 640×200 GRAM をダブルバッファリングできます — Z80 がもう一方のバッファに書き込んでいる間、ディスプレイは一方のバッファから読み取り、スクリーンティアリングとスノーを防ぎます。V1.2 Cyclone III は 640×200 でのダブルバッファリングには BRAM が十分ではありません。代わりにウェイトステートジェネレータが使用されます:FPGA は GRAM からディスプレイがリフレッシュされている水平ブランキング期間中に Z80 の /WAIT をアサートし、スノーを生成する同時読み書きアクセスを防ぎます。これは 640×200 グラフィックス操作が V1 では現行ハードウェアよりわずかに遅いことを意味します — Z80 は各スキャンラインのわずかな部分でストールします。これは実際には通常気にならないですが、タイミングセンシティブなグラフィックスコードを書く際には考慮すべきです。

ビデオコントローラ I/O レジスタ(V1: 0xF0–0xFD)
V1.2 FPGA は I/O アドレス範囲 0xF0–0xFF(FXX ブロック)のビデオコントローラレジスタをデコードします。Z80 ソフトウェアが使用するレジスタは:
アドレス 名前 方向 説明
0xF8 VIDEO_MODE_REG R/W ビデオモード制御。ビット [2:0] = マシンエミュレーション(000=MZ-80K、001=MZ-80C、010=MZ-1200、011=MZ-80A、100=MZ-700、101=MZ-800、110=MZ-80B)。ビット [3] = 桁幅(0=40、1=80)。ビット [4] = カラーモード(0=モノ、1=カラー)。ビット [5] = PCGRAM 有効。ビット [7:6] = VGA 出力モード。
0xF9 GRAM_MODE_REG R/W グラフィックスモード。ビット [7:6] = ピクセル演算子(00=OR、01=AND、10=NAND、11=XOR)。ビット [5] = GRAM 出力有効。ビット [4] = VRAM 出力有効。ビット [3:2] = 書き込みページ(00=赤、01=緑、10=青、11=間接)。ビット [1:0] = 読み取りページ。
0xFA GRAM_R_FILTER R/W 赤カラープレーンビットマスク(1 ビット/ピクセル、8 ピクセル/バイト)。
0xFB GRAM_G_FILTER R/W 緑カラープレーンビットマスク。
0xFC GRAM_B_FILTER R/W 青カラープレーンビットマスク。
0xFD PAGE_MODE_REG R/W グラフィックスメモリページ。ビット [0] = GRAM ページ有効(16 KB GRAM ページを 0xC000–0xFFFF にマップ)。ビット [7] = CGROM アップロード有効(CGROM を再プログラム用に 0xD000–0xDFFF にマップ)。読み取り: ビット [7] = CGROM ページ、ビット [6] = V ブランクステータス、ビット [5] = H ブランクステータス。
VideoController700.vhd の I/O デコードは FXX ブロック内の下位 4 アドレスビットを使用してレジスタを選択します:
-- VideoController700.vhd(v1.2)から:
-- CS_IO_FXXn は VADDR[7:4] = "1111"(すなわち I/O アドレス 0xF0–0xFF)のときにアサートされる。
CS_FB_VMn   <= '0' when CS_IO_FXXn = '0' and VADDR(3 downto 0) = "1000" else '1';  -- 0xF8
CS_FB_CTLn  <= '0' when CS_IO_FXXn = '0' and VADDR(3 downto 0) = "1001" else '1';  -- 0xF9
CS_FB_REDn  <= '0' when CS_IO_FXXn = '0' and VADDR(3 downto 0) = "1010" else '1';  -- 0xFA
CS_FB_GREENn<= '0' when CS_IO_FXXn = '0' and VADDR(3 downto 0) = "1011" else '1';  -- 0xFB
CS_FB_BLUEn <= '0' when CS_IO_FXXn = '0' and VADDR(3 downto 0) = "1100" else '1';  -- 0xFC
CS_FB_PAGEn <= '0' when CS_IO_FXXn = '0' and VADDR(3 downto 0) = "1101" else '1';  -- 0xFD
現行の v1.3 FPGA では、これらすべてのレジスタは AXX ブロック(0xA0–0xAF)に再配置され、VIDEO_ADDRi[7:4] = "1010"CS_IO_AXXn を使用してデコードされます。完全なアドレスマッピングについては V1 vs 現行ファームウェアを参照してください。

V1 のマシンエミュレーションモード
V1.2 ビデオコントローラは、VIDEO_MODE_REG(0xF8)のビット [2:0] で選択される以下の Sharp MZ マシンのビデオタイミングとキャラクタジェネレータのハードウェアエミュレーションをサポートします:
  • 000 = MZ-80K
  • 001 = MZ-80C
  • 010 = MZ-1200
  • 011 = MZ-80A
  • 100 = MZ-700(電源投入リセット時のデフォルト)
  • 101 = MZ-800
  • 110 = MZ-80B
V1 の制限 — モード 111(MZ-2000)は定数パッケージで定義されています(MODE_MZ2000 = 7)が、MZ-2000 ビデオタイミングパラメータとグラフィックスロジックは V1.2 VHDL では実装されていません。V1 ハードウェアで 0xF8 のビット [2:0] に 0b111 を書き込むと未定義のビデオ出力が生成されます。MZ-2000 サポートは v1.3 設計でより大きな FPGA とともに追加されました。MZ-2000 サポートを V1 にバックポートするには、MZ-2000 CRTC タイミング、そのグラフィックスカラーモード、追加ロジックが 25K LE バジェット内に収まるかどうかを確認する必要があります — 容易な作業ではありません。

VRAM と GRAM の構成
V1 FPGA は Z80 に 2 つのメモリ領域を公開します:
  • VRAM(0xD000–0xD7FF): 2 KB のキャラクタビデオ RAM、Z80 とディスプレイスキャンロジックで共有。偶数アドレスはキャラクタコードを保持;奇数アドレスはカラー属性を保持(カラーサポートがあるマシン上)。Z80 による書き込みアクセスは CPLD を通じて FPGA にゲートされる。
  • GRAM(ページイン時 0xC000–0xFFFF): 16 KB GRAM ページは PAGE_MODE_REG(0xFD)のビット [0] を設定することで Z80 アドレス空間に切り替えられる。BRAM に 3 つの別個の 8 KB カラープレーン(赤、緑、青)が存在します — 書き込みページは GRAM_MODE_REG(0xF9)ビット [3:2] で選択される。V1 では、3 つのプレーン合計で 76 KB BRAM バジェットの 24 KB を消費する。

V1.2 FPGA ビットストリームのビルド

V1.2 FPGA プロジェクトには Quartus Prime 13.1(または Quartus II 13.1)が必要です。Altera は後の Quartus バージョンで Cyclone III デバイスサポートをドロップしました。バージョン 13.1 は Intel の FPGA ソフトウェアダウンロードアーカイブから入手できます。プロジェクトファイルは FPGA/SW700/v1.2/build/VideoController700.qpf です。

コマンドラインビルド
cd /dvlp/Projects/tranZPUter/FPGA/SW700/v1.2/build
quartus_sh --flow compile VideoController700
これは完全な Quartus コンパイルフローを実行します:解析と合成 → フィッター → アセンブラ → タイミングアナライザ。ビルドが成功すると SRAM オブジェクトファイル(output_files/VideoController700.sof)とフラッシュベースのプログラミング用 POF プログラミングファイルが生成されます。

JTAG 経由のプログラミング
quartus_pgm -m JTAG -o "P;output_files/VideoController700.sof@1"
これはコンパイルされたビットストリームを JTAG コネクタ(USB Blaster または互換品)経由で FPGA SRAM に直接プログラムします。@1 サフィックスは JTAG チェーンのデバイス 1 を選択します。SRAM プログラミングは揮発性です — FPGA は電源サイクルで設定デバイスの設定に戻ります。恒久的なストレージには Quartus プログラマ GUI を使用してシリアル設定デバイスに POF を書き込んでください。

リソース使用率
典型的な V1.2 ビルドは利用可能な 25,000 ロジックエレメントのうち約 18,000–22,000 を占有し、新しい機能のためのヘッドルームが限られています。大量の新しいロジックを追加すると LE バジェットを超えるリスクがあります。BRAM はより厳しく制約されています:3 つの GRAM カラープレーン、VRAM、CGROM が合わせて 76 KB のほとんどを占有します。追加の BRAM が必要な新機能は、何を圧縮または削除できるかを最初に特定する必要があります。
リソース圧力が重大になる場合は、代わりに v1.3(Cyclone IV、75K LE、2.5 Mb BRAM)への変更をポートすることを検討してください。

ビルド環境(Docker)

Z80 アセンブリファームウェアと K64F C/C++ ファームウェアは、ホスト OS に関係なく一貫したツールチェーンバージョンを提供する Docker コンテナ内でビルドできます。コンテナイメージには以下が含まれます:
  • Java ランタイム(GLASS Z80 アセンブラ用、tools/glass.jar
  • ARM GCC クロスコンパイラ(K64F ファームウェア用)
  • Python 3 と Perl(ROM イメージ生成スクリプト用)
  • 標準ビルドユーティリティ(make、bash、coreutils)
FPGA コンパイル(Quartus 13.1)はコンテナ化されていません — Quartus はプログラミング用の JTAG USB ハードウェアへの直接アクセスが必要なため、ネイティブにインストールする必要があります。

ビルドの実行
# Z80 ファームウェア(TZFS)をビルド — Docker コンテナ内で自動的に実行:
cd /dvlp/Projects/tranZPUter/software/TZFS
./build.sh


# ビルドスクリプトはすべての TZFS バンク、モニターパッチ済みイメージをアセンブルし、

# roms/ 出力ディレクトリにバイナリ ROM イメージを生成する。

K64F ファームウェア

Freescale Kinetis K64F(ARM Cortex-M4、120 MHz、256 KB SRAM、1 MB フラッシュ)は SD カードアクセス、モニターファームウェアロード、バスマスタリング操作を管理します。Z80 と FPGA と並行して動作し、共有メモリ API を通じて Z80 から開始されたサービスリクエストに応答します。

K64F サービス API
Z80 は TZSVCMEM(0xED80) の共有メモリブロックと SVCREQ(0x68) への単一 I/O ポート書き込みを通じて K64F と通信します。サービス API 構造は software/TZFS/asm/include/tzfs_svcstruct.asm で定義されています。Z80 コードからの呼び出しシーケンスは:
; ステップ 1 — サービスブロックにコマンドバイトを設定する。
LD   A, TZSVC_CMD_LOADFILE
LD   (TZSVCCMD), A              ; 共有メモリにコマンドを書き込む

; ステップ 2 — K64F にリクエストを通知する。
LD   A, TZSVC_STATUS_REQUEST
LD   (TZSVCRESULT), A           ; 結果フィールドを「保留中」としてマーク
OUT  (SVCREQ), A                ; K64F 割り込みをトリガー

; ステップ 3 — K64F が完了するまでポーリングする。
WAIT:
    LD   A, (TZSVCRESULT)
    CP   TZSVC_STATUS_REQUEST
    JR   Z, WAIT

; ステップ 4 — 結果を確認する(0x00 = 成功、非ゼロ = エラーコード)。
LD   A, (TZSVCRESULT)
OR   A
JR   NZ, ERROR

主要なサービスコマンド
TZSVC_CMD_LOADFILE      EQU 01H  ; SD カードから Z80 RAM に名前付きファイルをロード
TZSVC_CMD_SAVEFILE      EQU 02H  ; Z80 RAM 領域を SD カードの名前付きファイルとして保存
TZSVC_CMD_DIR           EQU 03H  ; SD カードディレクトリ一覧を読み取る
TZSVC_CMD_SD_RDPAGE     EQU 04H  ; 生 SD セクターを読み取る
TZSVC_CMD_SD_WRPAGE     EQU 05H  ; 生 SD セクターを書き込む
TZSVC_CMD_EMU_SETMZ80K  EQU 10H  ; ハードウェアエミュレーションを MZ-80K モードに切り替える
TZSVC_CMD_EMU_SETMZ80A  EQU 13H  ; ハードウェアエミュレーションを MZ-80A モードに切り替える
TZSVC_CMD_EMU_SETMZ700  EQU 14H  ; ハードウェアエミュレーションを MZ-700 モードに切り替える
TZSVC_CMD_EMU_SETMZ800  EQU 15H  ; ハードウェアエミュレーションを MZ-800 モードに切り替える
TZSVC_CMD_EMU_SETMZ80B  EQU 16H  ; ハードウェアエミュレーションを MZ-80B モードに切り替える
TZSVC_CMD_CPU_SETZ80    EQU 20H  ; アクティブ CPU をハードウェア Z80 に設定
TZSVC_CMD_CPU_SETT80    EQU 21H  ; FPGA の T80 ソフトコア Z80 を有効化
TZSVC_CMD_CPU_SETZPUEVO EQU 22H  ; FPGA の ZPU Evolution ソフト CPU を有効化
TZSVC_CMD_SET_VIDMODE   EQU 23H  ; ビデオ出力モードを設定
TZSVC_CMD_SET_VGAMODE   EQU 24H  ; VGA 出力モードを設定
TZSVC_CMD_SET_VBORDER   EQU 25H  ; ビデオボーダーカラーを設定
V1 の違い — サービスコマンド TZSVC_CMD_LOAD2000IPL(0x26) は K64F に MZ-2000 IPL ファームウェアのロードをリクエストします。このコマンドは現行ファームウェアと tzfs_svcstruct.asm に存在しますが、V1 FPGA は MZ-2000 ビデオモードを実装していないため V1 ハードウェアでは意味がありません。V1 で 0x26 を発行すると K64F レベルでは成功する場合があります(ファイルはロードされます)が、FPGA は MZ-2000 互換のビデオを表示しません。同様に、MZ-2000 エミュレーションモードを設定する任意の K64F サービスコマンドは V1 で未定義の FPGA 動作を生成します。

モニターファームウェアロード
コールドスタート時、TZFS は K64F サービスリクエストを発行して適切なモニタ ROM イメージを 0x0000 の tranZPUter SRAM にロードします。K64F は CPLD 経由のバスマスタリングを使用して、Z80 が /BUSRQ で保持されている間に SD カードから SRAM にファームウェアイメージを DMA します。利用可能なモニタイメージには SA-1510(MZ-80A)、1Z-013A(MZ-700)、それぞれのパッチ済み 80 桁バリアントが含まれます。モニタイメージは TZFS で設定されたマシンエミュレーションモードに基づいて選択されます。

TZFS Z80 ソフトウェア

TZFS(tranZPUter ファイリングシステム)はユーザー向けコマンドインターフェースを提供する Z80 アセンブリ言語ファームウェアです。V1 と現行ハードウェアで共有されています — software/TZFS/asm/ の同じソースツリーがハードウェア固有の機能用の条件付きアセンブリガードを使用して両方のためにビルドされます。V1 では、0xA8 範囲のレジスタまたは V1 に存在しないサービスコマンドに依存する機能は単純に実行されません;ソースは V1 ハードウェアで同様にコンパイルおよび動作します。

TZMM バンクスイッチング
TZFS はメモリ管理設定レジスタ(MMCFG、ポート 0x60)を使用して 4 つの 64 KB SRAM バンクを切り替えます:
TZMM モード 0xE800–0xEFFF 0xF000–0xFFFF 目的
TZMM_TZFS 0x22 TZFS コア(バンク 0) TZFS コア コマンドディスパッチ、ジャンプテーブル
TZMM_TZFS2 0x23 TZFS コア(バンク 0) tzfs_bank2 メッセージ、ヘルプ、印刷ルーチン
TZMM_TZFS3 0x24 TZFS コア(バンク 0) tzfs_bank3 メモリユーティリティ、I/O、エミュレーション制御
TZMM_TZFS4 0x25 tzfs_bank4 完全な Z80 アセンブラ/ディスアセンブラ(52 KB)
単一の OUT (0x60), A 命令がバンクスイッチを実行します。TZFS コア(バンク 0)は TZMM_TZFS、TZMM_TZFS2、TZMM_TZFS3 モードで常に 0xE800–0xEFFF に見えており、ジャンプテーブルとバンク間スタブが常に到達可能であることを確保します。TZFS ソースモジュールの完全なウォークスルーについては TZFS デベロッパーズガイドを参照してください。

V1 のビデオ制御コマンド
ユーザーがビデオモードコマンド(例:MZ-80A エミュレーションに切り替えるための VMODE 3)を入力すると、TZFS は適切な TZSVC_CMD_SET_VIDMODE または TZSVC_CMD_EMU_SET* コマンドで K64F サービス API を呼び出します。K64F はバスマスタリング経由で V1 FPGA ビデオレジスタ 0xF8 に新しいモード値を書き込むか、その専用インターフェースを通じて FPGA に通知します。Z80 の観点からは、ビデオコマンドフローは V1 と現行ハードウェアで同一です — 違いは K64F が書き込む内容とどのレジスタアドレスにあるかだけです。
K64F サービス API をバイパスしてビデオレジスタに直接書き込む Z80 コードを書く場合は、V1 ハードウェアでは 0xF8–0xFD に書き込む必要があります。標準 TZFS フローはすべてのビデオ操作を K64F サービス経由でルーティングするため、TZFS 定義ファイルは V1 レジスタアドレスの名前付き定数を公開しません。直接アクセスには、リテラルポートアドレスを使用し、V1 依存性を明確に文書化してください。
; V1 のみ — 直接ビデオモードレジスタ書き込み。
; このコードは現行(v1.3)ハードウェアでは動作しません。
; 現行ハードウェアでは代わりに TZSVC_CMD_SET_VIDMODE を使用するか 0xA8 に書き込む。
LD  A, 04H          ; MZ-700 モード(ビット[2:0]=100)、40桁(ビット3=0)、カラー(ビット4=0)
OUT (0F8H), A       ; V1: ビデオモードレジスタは 0xF8 にある

V1 vs 現行ファームウェア — 移行ガイド

このセクションは V1(v1.2、Cyclone III)と現行(v1.3、Cyclone IV)のハードウェアとファームウェアの間のすべての既知の非互換性を文書化します。V1 から現行にコードを移行する開発者、または両方で動作するように意図した新しいコードを書く開発者は、ここに列挙されているすべての項目を考慮する必要があります。

1. ビデオレジスタアドレスブロックの再配置
これは最も重要な非互換性です。 すべての 6 つのビデオコントローラレジスタが FXX I/O ブロック(0xF0–0xFF)から現行ファームウェアの AXX ブロック(0xA0–0xAF)に移動しました。
レジスタ V1 アドレス 現行アドレス 説明
ビデオモード 0xF8 0xA8(VMCTRL) マシンエミュレーション、桁幅、カラーモード
グラフィックスモード 0xF9 0xA9(VMGRMODE) GRAM 演算子、ページ、出力有効
赤マスク 0xFA 0xAA(VMREDMASK) 赤カラープレーンビットマスク
緑マスク 0xFB 0xAB(VMGREENMASK) 緑カラープレーンビットマスク
青マスク 0xFC 0xAC(VMBLUEMASK) 青カラープレーンビットマスク
ページ/CGROM 0xFD 0xAD(VMPAGE) GRAM ページ有効、CGROM アップロード
移行アクション: OUT(0F8H)OUT(0F9H)OUT(0FAH)OUT(0FBH)OUT(0FCH)、または OUT(0FDH)(または対応する IN 命令)を含むコードはすべて現行アドレスを使用するよう更新する必要があります。TZFS 定義ファイルでは、リテラル16進アドレスではなく名前付き定数(VMCTRLVMGRMODEVMREDMASKVMGREENMASKVMBLUEMASKVMPAGE)を使用することで、定義ファイルへの単一の変更が条件付きアセンブリ経由で両方のターゲットを処理できます。

2. V1 にはシステムコマンドレジスタ(0x6B)がない
I/O ポート 0x6B(CPLDSTATUS EQU 06BH)の CPLD システムコマンドレジスタは現行ハードウェアにのみ存在する Version 2.1 CPLD の機能です。V1 では、0x6B からの読み取りはバスから不定値のデータ(通常はプルアップがアサートされた 0xFF)を返します。現行ハードウェアでのハードウェアバージョン検出、機能クエリ、CPLD 設定にこのレジスタを使用するコードは V1 では正しく機能しません。
移行アクション: V1 では 0x6B 読み取りを使用しないでください。実行時に V1 ハードウェアを検出するには、0xF8 に既知の値を書き込んで読み返す;値が反映されない場合(現行ハードウェアの FPGA が V1 の位置で 0xF8 をデコードしないため)、ハードウェアは現行です。あるいは、実行時検出ではなくビルド時フラグに依存してください。

3. V1 に MZ-2000 エミュレーションがない
MZ-2000 ビデオタイミング、グラフィックスカラーモード、キャラクタジェネレータは V1.2 FPGA には実装されていません。VIDEO_MODE_REG(0xF8)のビット [2:0] にマシンモード値 7(バイナリ 111)を書き込むと V1 ハードウェアで未定義のビデオ出力が生成されます。
移行アクション: V1 ハードウェアでは VMODE 7 / MZ-2000 モードを使用しないでください。V1 と現行の両方をサポートする必要があるコードを書く場合は、すべての MZ-2000 コードパスを V1 検出チェックまたはビルド時フラグでガードしてください。

4. V1 に MZ-2000 K64F サービスコマンドがない
以下の K64F サービスコマンドは現行ファームウェアには存在しますが、V1 ハードウェアは MZ-2000 FPGA サポートを欠くため V1 ハードウェアでは意味がありません:
  • TZSVC_CMD_LOAD2000IPL(0x26) — SD カードから MZ-2000 初期プログラムローダーをロードする
  • TZSVC_CMD_EMU_SETMZ2000 — ハードウェアエミュレーションを MZ-2000 モードに切り替える
V1 でこれらのコマンドを発行すると K64F エラーは発生しないかもしれません(K64F がファイルをロードに成功する場合があります)が、FPGA は MZ-2000 互換の出力を表示しません。
移行アクション: すべての MZ-2000 サービスコールを V1 検出でガードしてください。

5. V1 に 640×200 ダブルバッファがない
V1 Cyclone III FPGA は 640×200 グラフィックスモードのダブルバッファリングには BRAM が不足しています。代わりにウェイトステートジェネレータが Z80 をディスプレイリフレッシュ中にストールさせます。影響:
  • 大きな GRAM 領域を埋めるグラフィックス集中コードは、ウェイト挿入のため V1 ではわずかに遅く実行されます — 通常数パーセントですが、サイクルカウンタで測定可能です。
  • 最悪の場合、持続的なバックツーバックの GRAM 書き込みを実行するプログラムは、ウェイトジェネレータがフィールド境界で特にすべてのリフレッシュ競合をカバーできない場合、V1 で目に見えるスノーを経験する可能性があります。これは現行ハードウェアでは発生しません。
移行アクション: グラフィックスデモを現行から V1 にポートするときにスノーアーティファクトが現れる場合は、大きな GRAM フィル前に水平ブランキングチェックを追加してください。PAGE_MODE_REG(0xFD)ビット [5] と [6] から H ブランクステータスを読み取ることで、ソフトウェアが脆弱な間隔中の書き込みを避けることができます。

6. FPGA ソースパスが異なる
すべての FPGA VHDL ソース参照が V1 と現行で変わります:
項目 V1 パス 現行パス
ビデオコントローラ VHDL FPGA/SW700/v1.2/VideoController700.vhd FPGA/SW700/v1.3/VideoController700.vhd
パッケージファイル FPGA/SW700/v1.2/VideoController700_pkg.vhd FPGA/SW700/v1.3/VideoController700_pkg.vhd
Quartus プロジェクト FPGA/SW700/v1.2/build/VideoController700.qpf FPGA/SW700/v1.3/build/VideoController700.qpf
Quartus バージョン 13.1(Cyclone III サポート) 18.1 以降(Cyclone IV サポート)
FPGA デバイス EP3C25E144C8(25K LE、144 TQFP) EP4CE75F484C8 / EP4CE115(75K/115K LE、484 BGA)
移行アクション: 現行のソースツリーに対して開発された VHDL パッチや新機能を V1 に適用する場合は、ロジックが V1 リソースバジェット(25K LE、76 KB BRAM)内に収まることを確認してからコミットしてください。レジスタマップまたは BRAM 割り当てへの変更が不要な V1 用に開発された機能は、現行は V1 のスーパーセットであるため、通常は変更なしで現行にバックポートできます。

移行チェックリストのまとめ
# 違い V1 現行 必要なアクション
1 ビデオモードレジスタ 0xF8 0xA8(VMCTRL) すべての OUT/IN アドレスを更新
2 グラフィックスモードレジスタ 0xF9 0xA9(VMGRMODE) すべての OUT/IN アドレスを更新
3 赤マスクレジスタ 0xFA 0xAA(VMREDMASK) すべての OUT/IN アドレスを更新
4 緑マスクレジスタ 0xFB 0xAB(VMGREENMASK) すべての OUT/IN アドレスを更新
5 青マスクレジスタ 0xFC 0xAC(VMBLUEMASK) すべての OUT/IN アドレスを更新
6 ページ/CGROM レジスタ 0xFD 0xAD(VMPAGE) すべての OUT/IN アドレスを更新
7 CPLD ステータスレジスタ 存在しない 0x6B(CPLDSTATUS) V1 検出でガード
8 MZ-2000 ビデオモード 実装されていない 実装済み V1 検出でガード
9 TZSVC_CMD_LOAD2000IPL 機能しない 0x26 V1 検出でガード
10 640×200 ダブルバッファ ウェイトステートのみ ダブルバッファ 必要に応じて V1 のスノーを処理
11 FPGA ソースディレクトリ v1.2/ v1.3/ パッチ適用時は正しいパスを使用
12 Quartus バージョン 13.1 18.1+ 正しいツールチェーンバージョンを使用

V1 へのマシンエミュレーションサポートの追加

ビデオコントローラは、VIDEO_MODE_REG(0xF8)ビット [2:0] に書き込まれる値で新しいマシンエミュレーションモードを識別します。V1 に新しいモードを追加するには 3 つの場所で変更が必要です:
  1. VideoController700_pkg.vhd に定数を追加する: まだ存在しない場合は、マシンタイプの新しい MODE_* 定数を定義する。既存の定数ファイルにはすでに MZ-2000(モード 7)を含むすべての 8 つの Sharp MZ バリアントのエントリが含まれているが、MZ-2000 CRTC ロジックは v1.2 VideoController700.vhd に存在しない。
  2. VideoController700.vhd の CRTC タイミングを実装する: CTRLREGISTERS プロセスは CS_FB_VMn(0xF8)への書き込みをデコードする。適切なタイミング信号を設定する case 文に新しいブランチを追加する:MODE_VIDEO_* フラグ、水平および垂直同期パラメータ、キャラクタセル寸法、カラー属性フォーマット。MZ-2000 では、320×200 または 640×200 ピクセルアドレス可能カラーモードと関連する GRAM バンキングの実装が必要。完成した実装については FPGA/SW700/v1.3/ の v1.3 ソースを参照する。
  3. BRAM バジェットを確認する: 追加のスクリーンバッファ RAM が必要な新しいマシンモードは、残りの BRAM ヘッドルーム内に収まる必要がある。新しいモードが別の VRAM または追加の GRAM プレーンを必要とする場合は、進める前に必要な BRAM ブロック(Cyclone III の M9K ブロック、各 9 Kbits = 1,152 バイト)を計算する。
  4. K64F サービスコマンドを追加する: 新しいマシンがモードを切り替える前に K64F がモニタ ROM イメージをロードする必要がある場合は、tzfs_svcstruct.asm に新しい TZSVC_CMD_EMU_SET* 定数を追加し、ARM 側にハンドラを実装する。
  5. TZFS コマンドを追加する: ユーザーが入力したコマンドを適切なサービスコールにマップする tzfs.asm の CMDTABLE にエントリを追加する。K64F サービスブロックを設定して ?SVCREQ を呼び出すハンドラを tzfs_bank3.asm に追加する。ヘルプテキストを tzfs_bank2.asm に追加する。

デバッグのヒント

RIO/WIO を使用してレジスタアドレスを確認する: TZFS プロンプトで WIO F8,04 を使用して V1 ハードウェアのポート 0xF8 に 0x04(MZ-700 モード)を直接書き込む。ディスプレイが MZ-700 タイミングに切り替わる場合、V1 FPGA が存在して正しく応答しています。現行ハードウェアでは代わりに 0xA8 に書き込む — 現行ハードウェアで 0xF8 に書き込むと別のレジスタ(そこにデコードされているものがある場合)にヒットし、予期しない結果を生む場合があります。
ブランキングステータスのためにページレジスタを読み取る: RIO FD でポート 0xFD を読み取る。V1 では、返された値のビット [6] と [5] がそれぞれ V ブランクと H ブランクステータスを反映します。ビット [7:6] がセットされた 0xFF の返却値は通常、V ブランクがアクティブで CGROM ページモードがオフであることを示します — これは垂直帰線消去期間中の正常な動作です。
FPGA がプログラムされていることを確認する: 電源投入後にビデオ出力がない場合やランダムピクセルが表示される場合、FPGA 設定フラッシュに問題がある可能性があります。新しい SOF を使用して JTAG 経由で再プログラムしてください。SOF が誤った Quartus デバイスターゲット(例:EP3C25 の代わりに EP4CE75)でビルドされた場合、ビットストリームは静かに拒否され FPGA は設定されません — ビルド前に Quartus プロジェクトファイルのデバイス設定を確認してください。
K64F サービスブロックを検査する: TZFS プロンプトで D ED80 と入力して K64F サービス通信領域を16進ダンプする。最初のバイトはコマンド;2 番目は結果ステータス。結果が 0x01 の場合、K64F はまだリクエストを処理中;非ゼロの非 0x01 結果はエラーを示す。tzfs_svcstruct.asmTZSVC_STATUS_* 定数と照合する。
TZFS デバッグ出力を有効化する: ビルド前に tzfs_definitions.asmENADEBUG EQU 1 を設定して TZFS を再ビルドする。これによりコールドスタート時、バンクスイッチ中、K64F サービスコール中に診断出力が追加されます。V1 では、コールドスタート出力が TZMM モードレジスタ(0x60)が書き込みを受け付けていること、K64F サービスハンドシェイクが期待されるポールタイムアウト内に完了していることを確認します。
GRAM スノーの調査: 640×200 グラフィックス操作が V1 でスノーアーティファクトを生成する場合、各 GRAM 書き込みバーストの前に H ブランクを待つポーリングループを追加する。タイトなループでポート 0xFD を読み取り、ビット [5](H ブランク)がセットされるまでスピンし、その後次のアクティブ期間が始まる前に書き込みバーストを実行する。
Quartus タイミング解析: 変更された V1.2 ビットストリームをビルドした後、build/output_files/VideoController700.sta.rpt の Quartus TimeQuest タイミングレポートを確認する。クリティカルパスの負のセットアップスラック(タイミング違反)はビットストリームをハードウェアで使用する前に解決する必要があります — タイミング違反を持つ FPGA の動作は予測できません。一般的な原因は VRAM mux または GRAM ページロジックを通る長い組み合わせパスです。
DASM を使用してインタラクティブにアセンブルされたコードを確認する: TZFS ASM コマンドを使用してスクラッチアドレスにテストルーチンを入力した後、すぐに DASM addr,endaddr と入力して結果を逆アセンブルする。コードを実行する前に命令エンコーディングが正しいことを確認する。特に I/O 命令(IN A,(0F8H)OUT(0F8H),A)ではエンコーディングの誤りが静かな誤ったポートアクセスを生成できる。

参考サイト

リソース リンク
tranZPUter SW-700 V1 プロジェクトページ /sharpmz-700-upgrades-tranzputer-sw/
tranZPUter SW-700 現行(v1.3)プロジェクトページ /sharpmz-700-upgrades-tranzputer-sw-current/
tranZPUter SW-700 現行デベロッパーズガイド /tranzputer-sw-700-current-developersguide/
TZFS デベロッパーズガイド /sharpmz-upgrades-tzfs-developersguide/
TZFS ユーザーマニュアル /sharpmz-upgrades-tzfs-usermanual/
RFS デベロッパーズガイド /sharpmz-upgrades-rfs-developersguide/
tranZPUter プロジェクトページ /transzputer/
GLASS Z80 アセンブラ software/TZFS/tools/glass.jar としてバンドル済み
Intel Quartus Prime 13.1 Intel FPGA ソフトウェアダウンロードセンター(Cyclone III サポート)
Cyclone III デバイスハンドブック Intel FPGA ドキュメント — LE アーキテクチャ、BRAM M9K ブロック、PLL
Altera EPM7160 データシート MAX 7000 ファミリー — マクロセルアーキテクチャ、ピンアサインメント
Zilog Z80 CPU ユーザーマニュアル 標準データシート — バスタイミング、I/O サイクルタイミング、命令セット