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

tranZPUter SW-700 デベロッパーズガイド(現行版)

このガイドは tranZPUter SW-700 のソースコードと開発環境の詳細なウォークスルーです。言語に馴染みのない開発者のために VHDL を紹介し、すべての主要なソースモジュールを詳説し、CPLD と FPGA の設計を解説し、メモリマッピングと CPU 切り替えアーキテクチャを説明し、ファームウェアのビルド方法、新しい Sharp MZ マシンのサポート追加方法、ハードウェア問題のデバッグ方法を示します。
ハードウェアアーキテクチャと回路図については tranZPUter SW-700 ページを参照してください。ユーザー向けの操作と TZFS コマンドについては TZFS ユーザーマニュアルを参照してください。TZFS ソースのウォークスルーについては TZFS デベロッパーズガイドを参照してください。

HDL に馴染みのないプログラマーのための VHDL 入門

tranZPUter SW-700 のデジタルロジック全体 — CPLD グルーロジックと FPGA ビデオおよびソフト CPU コア — は VHDL(VHSIC ハードウェア記述言語)で書かれています。ソフトウェアとは異なり、VHDL はプロセッサが一度に一ステップずつ実行する一連のステップを記述しません。ハードウェアを記述します:すべて同時に動作するロジックゲート、フリップフロップ、ステートマシンの集合体。VHDL ファイルのすべての process は他のすべてのプロセスと並行して実行されます;信号は各クロックエッジで一斉に値を変更します。

ENTITY と ARCHITECTURE
すべての VHDL モジュールには 2 つの部分があります:
  • ENTITY はモジュールのインターフェース — その入力ピンと出力ピン — を宣言します。ソフトウェア言語の関数シグネチャと考えてください。例えば coreMZ エンティティは CLOCK_50VZ80_ADDRVZ80_DATA、VGA 出力、その他多数のピンを inout、または inout ポートとして宣言します。
  • ARCHITECTURE は実装を含みます — 出力が入力からどのように計算されるかを記述する内部信号、コンポーネントインスタンス化、プロセス。coreMZ のアーキテクチャは rtl(レジスタ転送レベル)と名付けられています — これは合成可能な動作記述の慣例名です。
entity coreMZ is
    port (
        CLOCK_50   : in  std_logic;                      -- 50 MHz ベースクロック
        VZ80_ADDR  : inout std_logic_vector(15 downto 0); -- Z80 アドレスバス
        VGA_R      : out std_logic_vector(3 downto 0)    -- VGA 赤チャンネル
        -- ... 追加ポート ...
    );
end entity;

architecture rtl of coreMZ is
    signal PLL_LOCKED : std_logic := '0';  -- 内部信号
begin
    -- 並行ステートメントとプロセスはここに
end architecture;

SIGNAL
信号は VHDL モジュールの内部ワイヤーです — プロセス同士およびポートを接続します。信号宣言はワイヤーに名前を付け、その型を指定します。この設計で最も一般的な型は:
  • std_logic'0''1''Z'(高インピーダンス/トライステート)、またはいくつかの他のシミュレーション値になれる 1 ビット。
  • std_logic_vector(N downto 0) — N から 0(LSB)インデックスの N+1 ビットのバス。std_logic_vector(7 downto 0) は 8 ビットバス。
  • unsigned / integer — カウンタと演算に使用される数値型。
アーキテクチャで宣言された信号はその外部から見えません。ソフトウェアのローカル変数に類似していますが、信号への各代入は現在のデルタサイクルの終わりに有効になります — 単一のプロセス実行内では変更は瞬時に伝播しません。

PROCESS
process は、センシティビティリスト内の信号が変化するたびに再実行される順次的な VHDL ステートメントのブロックです。プロセスは同期ロジックの基本的な構成要素です。
クロックプロセス — この設計で最も重要なパターン — はクロックの立ち上がりエッジのみに応答します。フリップフロップ(レジスタ)をモデル化します:
process(SYS_CLK, RESETn)
begin
    if RESETn = '0' then
        -- 非同期リセット: すべてのレジスタを初期状態に駆動する。
        MY_REGISTER <= (others => '0');
    elsif rising_edge(SYS_CLK) then
        -- 同期ロジック: クロックティックごとに 1 回実行される。
        MY_REGISTER <= NEXT_VALUE;
    end if;
end process;
組み合わせプロセスはセンシティビティリストにすべての入力があり、クロックエッジのテストがありません。純粋なロジック — AND/OR/mux ツリー — をモデル化します:
process(Z80_ADDR, Z80_IORQn, Z80_M1n)
begin
    TZIO_CSn <= '1';                            -- デフォルト非アクティブ
    if Z80_IORQn = '0' and Z80_M1n = '1'
       and Z80_ADDR(7 downto 4) = "0110" then
        TZIO_CSn <= '0';                         -- I/O アドレス 0x60–0x6F 選択
    end if;
end process;

有限状態マシン(FSM)
tranZPUter SW-700 はバスマスタリング制御、CPU 切り替え、メモリモード遷移、K64F サービスリクエストハンドシェイクに FSM を広範に使用しています。VHDL の FSM は通常、各クロックエッジで state 信号(列挙型)を更新するクロックプロセスと、現在の状態をデコードして出力を生成する組み合わせプロセスの組み合わせです:
type BUS_STATE_TYPE is (IDLE, REQ_BUS, WAIT_ACK, BUS_HELD, RELEASE);
signal BUS_STATE : BUS_STATE_TYPE := IDLE;

-- クロック次状態ロジック:
process(SYS_CLK, RESETn)
begin
    if RESETn = '0' then
        BUS_STATE <= IDLE;
    elsif rising_edge(SYS_CLK) then
        case BUS_STATE is
            when IDLE     => if BUSRQ_TRIGGER = '1' then BUS_STATE <= REQ_BUS; end if;
            when REQ_BUS  => BUS_STATE <= WAIT_ACK;
            when WAIT_ACK => if Z80_BUSACKn = '0' then BUS_STATE <= BUS_HELD; end if;
            when BUS_HELD => if RELEASE_REQ = '1' then BUS_STATE <= RELEASE; end if;
            when RELEASE  => BUS_STATE <= IDLE;
        end case;
    end if;
end process;

コンポーネントインスタンス化
大規模な設計はコンポーネントインスタンス化を使用してより小さなモジュールから組み立てられます — 関数を呼び出すことに相当する VHDL ですが、各インスタンス化は永続的に並行して動作する独立したハードウェアブロックを生成します。coreMZ_SoftCPU トップレベルファイルは VideoControllersoftT80softZPU モジュールをインスタンス化し、内部信号でそれらのポートを接続します:
VideoCtrl: entity work.VideoController
    port map (
        SYS_CLK    => SYS_CLK,
        VZ80_ADDR  => VZ80_ADDR,
        VZ80_DATA  => VZ80_DATA,
        VGA_R      => VGA_R,
        -- ...
    );

SoftCPU_Z80: entity work.softT80
    port map (
        SYS_RESETn => RESETn,
        SYS_CLK    => SYS_CLK,
        Z80_CLK    => VZ80_CLK,
        T80_ADDR   => T80_ADDR,
        -- ...
    );
トップレベルエンティティの仕事は完全に接続です — 自身のロジックはほとんどありません。すべてのロジックはリーフモジュールに存在します。

ソースツリー

パス 内容
CPLD/EPM7160/ CPLD VHDL: tranZPUterSW_EPM7160.vhd(メイン)、tranZPUterSW_Toplevel_EPM7160.vhdtranZPUterSW_pkg_EPM7160.vhd
CPLD/Fusion/ Fusion バリアント CPLD(代替ボードバリアント)
FPGA/SW700/v1.2/ Cyclone III FPGA VHDL(v1.2、ビデオのみボード)
FPGA/SW700/v1.3/ Cyclone IV FPGA VHDL(v1.3、現行メインストリーム — 下記参照)
FPGA/a-z80/ AZ80 オープンソース Z80 RTL(代替ソフト Z80 IP)
FPGA/nextz80/ NextZ80 代替ソフト Z80
schematics/SW700/v1.0/v1.4/ 各ボードリビジョンの KiCad 回路図
pcb/SW700/v1.2a/v1.3/v1.3a/ Gerber PCB ファイル
software/TZFS/ TZFS ファイリングシステムソフトウェア(アクティブ開発中)
software.moved.to.TZFS/zOS/MZ700/ MZ-700 用レガシー K64F zOS ソース
software.moved.to.TZFS/zOS/MZ2000/ MZ-2000 用 K64F zOS(現行リファレンス)
software.moved.to.TZFS/CPM/ CP/M BIOS
tools/ ビルドユーティリティ: build_meminitfiles.sh、Python BRAM 初期化スクリプト
build/ Quartus ビルド出力(Makefile 駆動)

FPGA/SW700/v1.3/ レイアウト(アクティブなソースツリー、MZ700/MZ2000/MZ80A/ 以下にマシンターゲット別に整理):

パス 内容
MZ700/coreMZ.vhd トップレベル FPGA エンティティ — ビデオのみビルド
MZ700/coreMZ_SoftCPU.vhd トップレベル — ビデオ + ソフト CPU(T80 + ZPU)
MZ700/coreMZ_emuMZ.vhd トップレベル — ビデオ + Sharp MZ シリーズエミュレータコア
MZ700/coreMZ_pkg.vhd パッケージ: ホストモデル定数、IMPL_SOFTCPU_Z80IMPL_SOFTCPU_ZPUEVO フラグ
MZ700/functions.vhd 全モジュール間で共有されるユーティリティ関数
MZ700/VideoController/VideoController.vhd 完全なビデオパイプライン(キャラクタ、グラフィックス、OSD、パレット)
MZ700/VideoController/VideoController_pkg.vhd ビデオモード定数(MODE_MZ700MODE_MZ2000 など)
MZ700/VideoController/ChrGenRAM_DP_3208.vhd キャラクタジェネレータデュアルポート BRAM テンプレート
MZ700/VideoController/VideoRAM_DP_3216.vhd ビデオ RAM デュアルポート BRAM テンプレート
MZ700/softT80/softT80.vhd T80 ソフト Z80 ラッパーモジュール
MZ700/softT80/softT80_pkg.vhd T80 設定パッケージ
MZ700/softT80/T80/ T80 Z80 IP コアソース(T80.vhd、T80_ALU.vhd、T80_MCode.vhd など)
MZ700/softZPU/softZPU.vhd ZPU Evolution ソフト CPU ラッパー
MZ700/softZPU/softZPU_pkg.vhd ZPU 設定パッケージ
MZ700/softZPU/ZPU/ ZPU Evolution コア VHDL(zpu_core_evo_issue.vhd など)
MZ700/devices/sysbus/BRAM/ BRAM テンプレートとブート ROM
MZ700/devices/sysbus/SDRAM/ SDRAM コントローラ(W9864G6、48LC16M16 バリアント)
MZ700/devices/sysbus/uart/ UART ペリフェラル
MZ700/devices/sysbus/timer/ タイマーコントローラ
MZ700/devices/sysbus/intr/ 割り込みコントローラ
MZ700/devices/sysbus/SDMMC/ SD/MMC カードコントローラ
MZ700/devices/sysbus/RAM/ デュアルポート同期 RAM
MZ700/PLL/ Altera PLL メガファンクションインスタンス(ビデオクロック生成)
MZ700/SFL/ シリアルフラッシュローダーメガファンクション(EPCS 不揮発性ブート ROM プログラミング)
MZ700/emuMZ/ Sharp MZ シリーズ FPGA エミュレータ統合
MZ700/build/ Quartus プロジェクトファイル(デバイス/ビルドバリアントごとの .qpf.qsf

CPLD 設計

CPLD は Sharp MZ マザーボードの 5V バスと 3.3V FPGA および SRAM の間に位置します。これはすべてのバストランザクションで最初に遭遇するロジックであり、FPGA 設定レイテンシに耐えられないすべてのタイミングクリティカルなグルーを処理します。

デバイス: Altera MAX 7000A EPM7160
EPM7160 は 10 個のロジックアレイブロックに配置された 160 マクロセルを持つ 5V 耐性 CPLD です。5V 耐性により、マザーボードの TTL レベル信号を入力に直接受け入れ、FPGA への 3.3V 出力を駆動できます。これにより制御バスのインターフェースブリッジとして理想的です:別個のレベル変換チップは不要です。
CPLD ソースは 3 つのファイルで構成されます:
  • tranZPUterSW_EPM7160.vhd — メインアーキテクチャ、すべてのロジックプロセスを含む。
  • tranZPUterSW_Toplevel_EPM7160.vhd — I/O ピンアサインメント(トップレベルエンティティ)。
  • tranZPUterSW_pkg_EPM7160.vhd — パッケージ(共有定数と型定義)。
CPLD は CPLDfit フィッターツールを使用して Quartus Prime 13.0.1 でビルドされます。プログラミングは JTAG モードの標準 USB-Blaster ケーブルを使用します。

主要機能
レベル変換とバスインターフェース: CPLD はマザーボードの Z80_* 信号(5V)から VZ80_* 信号(電圧変換済み Z80 バス)を駆動します。マザーボード側のすべてのピンは 5V 耐性で動作;FPGA 側のすべてのピンは 3.3V を駆動します。
/BUSRQ ロジックとバスマスタリング: CPLD は Z80 の /BUSRQ と /BUSACK ハンドシェイクを制御する S-R ラッチと組み合わせロジックを実装します。K64F が CTL_BUSRQn をアサートすると、CPLD はこれをマザーボード Z80 への Z80_BUSRQn として転送します。Z80 が確認応答すると(Z80_BUSACKn が Low になる)、CPLD は tranZPUter ボードがバスを所有していることを示す TZ_BUSACKn をアサートします。2 つの S-R ラッチ(バスグラント用 notSRLatch1、クロック選択用 notSRLatch3)がグリッチのない遷移を確保します。
クロック周波数切り替え: 2 つの D フリップフロップがグリッチのないクロックマルチプレクサを実装します。Z80 はマザーボードの SYSCLK(オリジナルマシン速度)または CTLCLK(K64F のタイマーで生成されるプログラム可能な周波数)のどちらかで動作できます。アクティブなクロックは tranZPUter I/O ポート 0x62–0x63 への書き込みで選択されます。CPLD は両方のクロックがアイドルになるまで待機してから切り替えることで、クリーンな切り替えを確保します。
TZMM モードレジスタ(MEM_MODE_LATCH): 8 ビットメモリモードラッチは現在のtranZPUter メモリモード(TZMM)を格納します。I/O ポート 0x60 への書き込みでこのラッチをロードします。ビット 4:0 は FPGA の Z80_MEM[4:0] 出力に転送され、512KB SRAM のどの 64KB ブロックが Z80 アドレス空間にマップされるかを選択します。ビット 5 は I/O ウェイトステートジェネレータを有効化します。
I/O アドレスデコード: 組み合わせプロセスは tranZPUter I/O 範囲 0x60–0x6F への書き込みを個別のチップセレクト信号にデコードします:
-- I/O ポートデコード(addr[7:4] = 0110、すなわち 0x60–0x6F):
TZIO_CSn    -- 0x60–0x6F tranZPUter I/O ブロックアクティブ
MEM_CFGn    -- 0x60–0x61  TZMM モードレジスタを書き込む
SCK_CTLCLKn -- 0x62–0x63  CTLCLK(K64F プログラム可能周波数)に切り替える
SCK_SYSCLKn -- 0x64–0x65  SYSCLK(マザーボードクロック)に戻す
SCK_RDn     -- 0x66–0x67  現在のクロック/モード状態を読み取る
SVCREQn     -- 0x68–0x69  K64F へのサービスリクエスト
SYSREQn     -- 0x6A–0x6B  システムリクエスト
SRAM イネーブル信号: CPLD は Z80 コントロール信号と TZMM モードラッチから RAM_CSnRAM_OEnRAM_WEn を生成し、現在のモードに応じてメモリアクセスをマザーボードまたは tranZPUter SRAM にルーティングします。
I/O ウェイトステート挿入: MEM_MODE_LATCH のビット 5 が設定されると(ENIOWAIT)、CPLD はアドレス 0xE0–0xFF への I/O アクセスにウェイトステートを挿入します。これにより K64F が Z80 がレスポンスを読む前に I/O リクエストを処理するのに十分な時間を確保します。ウェイトはさらに S-R ラッチ(notSRLatch4)で実装され、K64F が CTL_BUSRQn をデアサートするまで Z80_WAITn を Low に保持します。

TZMM メモリモード
TZMM モードレジスタ(I/O ポート 0x60 に書き込み)は、Z80 アドレス空間がマザーボードメモリ対 tranZPUter SRAM ブロックにどのようにマップされるかを選択します。CPLD ソースで定義されているモードは:
モード 説明
0 デフォルト — すべてのメモリと I/O がマザーボード上(通常の Sharp MZ 動作)
1 0 と同じだが、ユーザー ROM が tranZPUter SRAM にマップされる
2–5 TZFS モード — モニタ ROM、メイン RAM、ユーザー ROM、フロッピー ROM が SRAM ブロック 0–3 内
6–7 CP/M モード — マザーボードビデオとフロッピーの例外付きで SRAM ブロック 4/5 に完全な 64KB
10–14 MZ-700 固有モード — IPL ROM、メイン RAM、D000–FFFF 領域の分割マップ
24–31 直接ブロック選択 — それぞれ SRAM ブロック 0–7 からの完全な 64KB 空間

FPGA 設計

Cyclone IV FPGA(EP4CE75F23I7、75K ロジックエレメント、2.8Mbit 埋め込み RAM)は tranZPUter SW-700 にビデオコントローラ、ソフト CPU 機能、K64F 通信インターフェースを提供します。同じ VHDL ソースツリーが、Quartus がどのトップレベルファイルを指定されるかで制御される 3 つの異なるビルド設定をサポートします:
  • coreMZ — ビデオコントローラのみ(最軽量ビルド、小型デバイスに適合)。
  • coreMZ_SoftCPU — ビデオコントローラ + T80 ソフト Z80 + ZPU Evolution(SW-700 v1.3 のメインストリームビルド)。
  • coreMZ_emuMZ — ビデオコントローラ + 完全な Sharp MZ シリーズ FPGA エミュレータコア。
すべて 3 つは devices/sysbus/ ツリーに同一のペリフェラル IP と同じ VideoController モジュールを共有します。

CPU 切り替えステートマシン
coreMZ_SoftCPU.vhd で最もアーキテクチャ的に重要なロジックは CPU 切り替え FSM です。tranZPUter SW-700 は次の 3 つの CPU で動作できます:
  1. MZ マザーボードのハード Z80 — マザーボード速度または K64F プログラム可能周波数で CPLD によってクロックされるオリジナルの Sharp CPU。
  2. FPGA 内のソフト T80 — Sharp MZ バスタイミング要件に合わせた Z80_CLK 速度でバストランザクションを提示しながら、内部パイプラインに SYS_CLK を使用し、50–100 MHz まで動作するサイクル正確な VHDL Z80 実装。
  3. FPGA 内のZPU Evolution — K64F が存在しない場合に zOS を実行するために使用される FPGA 内の 32 ビットスタック CPU。
切り替え FSM がハンドオーバーを調整します:
  1. ハード Z80 にバスをリリースするよう要求するために Z80_BUSRQn をアサートする。
  2. Z80_BUSACKn が Low になるまで待機する(Z80 がバスをトライステート化した)。
  3. 選択したソフト CPU のバスドライバを有効化する。
  4. ソフト CPU モジュールに SW_CPUEN をアサートする。
  5. ハード CPU への復帰時: ソフト CPU を無効化し、Z80_BUSRQn をデアサートし、ハード Z80 が再開するまで待機する。
MODE_CPU_SOFT 信号(I/O ポート 0x6D の CPU 設定レジスタから読み取る)がどの CPU がアクティブかを制御します。TZFS SC コマンドがこのレジスタを書き込みます。

T80 ソフト Z80 統合
T80 は確立されたオープンソース VHDL Z80 実装です。tranZPUter はそれを softT80.vhd でラップし、以下を提供します:
  • ソフトウェア制御のリセット(SW_RESET)とクロックイネーブル(SW_CLKEN)— FPGA ロジックがバス所有権の転送中に T80 をリセット状態に保持できるようにする。
  • 別個のシステムクロック(SYS_CLK、約 120 MHz 内部)と Z80 クロック(Z80_CLK)入力 — T80 は内部パイプラインに SYS_CLK を使用しながら、Sharp MZ バスタイミング要件に一致する Z80_CLK 速度でバストランザクションを提示する。
  • 完全な Z80 バス信号セット: T80_MREQnT80_IORQnT80_RDnT80_WRnT80_M1nT80_RFSHnT80_BUSACKnT80_HALTn
  • 双方向バスではなく別個のデータイン/アウトバス(T80_DATA_INT80_DATA_OUT)— トップレベルモジュールが共有 VZ80_DATA バスへのトライステートマージを処理する。
T80 コアソースファイルは softT80/T80/ に存在します: T80.vhd(トップレベル)、T80_ALU.vhd(算術/論理ユニット)、T80_MCode.vhd(マイクロコードデコーダ)、T80_Reg.vhd(レジスタファイル)、T80_Pack.vhd(パッケージ)。2 番目のバリアント T80sed.vhd はサイズ最適化版です。
T80 に加えて、softT80/ ディレクトリには開発中に評価された AZ80FPGA/a-z80/ ツリーから)と NextZ80 代替コアのスタブが含まれています。AZ80 は基本的に動作しますが、E000–E7FF 領域の Sharp I/O デバイスにアクセスする際にわずかなタイミングの不一致があります。NextZ80 はさらなる統合作業が必要です。T80 がデフォルトの本番ソフト Z80 です。

ZPU Evolution コア
ZPU Evolution は FPGA での組み込み使用のために設計された 32 ビットスタックベースのソフト CPU です。tranZPUter はそれを softZPU.vhd でラップし、SD カードアクセスとサービスリクエスト処理を提供する組み込みオペレーティングシステムである zOS を実行するために使用します。ZPU は Z80 の 64KB アドレス空間を避けるためにベースアドレスオフセット 0x80000 で tranZPUter 512KB SRAM にアクセスし、zOS イメージ全体が起動時に BRAM に収まります。
ZPU コアソースは softZPU/ZPU/ に存在します: zpu_core_evo_issue.vhd(インオーダーイッシュー付き)と zpu_core_evo_noissue.vhd(順次バリアント)。softZPU_pkg.vhd がバリアントを選択し、システムクロック周波数定数 SYSTEM_FREQUENCY を設定します。

ビデオコントローラ
VideoController.vhd は最大の単一ソースファイルです。Sharp MZ シリーズの完全なビデオパイプラインを実装し、オリジナルのキャラクタディスプレイハードウェアをエミュレートし、カラーグラフィックスと複数の出力モードで拡張します。
ディスプレイパイプライン:
  1. タイミング生成: PLL(PLL/Video_Clock_IV.vhd内)が 50 MHz システムクロックからピクセルクロックを導出します。水平および垂直同期カウンタが現在のピクセル位置を追跡します。サポートされているマシン/モードの組み合わせ(MZ-700 40/80 桁、MZ-2000、MZ-80B、VGA アップスケールモード)ごとに複数のタイミングパラメータセットが格納されています。
  2. キャラクタプレーン: ビデオ RAM(デュアルポート BRAM、VideoRAM_DP_3216.vhd)がキャラクタセル(40 または 80 桁 × 25 行)ごとに 1 バイトを格納します。各バイトはキャラクタジェネレータ RAM(ChrGenRAM_DP_3208.vhd)にインデックスし、8×8 ピクセルビットマップを保持します。キャラクタ ROM の内容は合成時に BRAM 初期化データからロードされます。
  3. グラフィックスプレーン: 最大 2 つのグラフィックスプレーン(GRAM I と GRAM II)がそれぞれピクセルビットマップを保持します。MZ-700 は 320×200 モノクロプレーンを使用し、MZ-2000 はキャラクタモードに関係なく 640×200 グラフィックスを使用します。各プレーンは Z80 書き込みとディスプレイ読み取りの同時アクセスを可能にするデュアルポート BRAM として実装されています。
  4. OSD プレーン: ステータスメッセージとモードインジケータ用のオンスクリーンディスプレイプレーンがオーバーレイされます。
  5. パレットとブレンド: 3 つのプレーン(キャラクタ、グラフィックス、OSD)がパレットルックアップレジスタの直前でマージされます。パレットは結合されたピクセル値を VGA コネクタとオリジナル MZ コンポジット出力用の 4 ビット R/G/B 出力にマップします。
出力モード: ビデオコントローラはオリジナルの Sharp モニター用のネイティブコンポジット出力(COLR_OUT、CSYNC_OUTn)と、現代のディスプレイ用の複数の VGA 出力モード(ネイティブ解像度からアップスケールされた 640×480、800×600)をサポートします。アクティブなモードはビデオモード I/O レジスタへの書き込みで選択されます。
VideoController_pkg.vhd のマシンモード定数:
constant MODE_MZ80K   : integer := 0;   -- MZ-80K
constant MODE_MZ80C   : integer := 1;   -- MZ-80C
constant MODE_MZ1200  : integer := 2;   -- MZ-1200
constant MODE_MZ80A   : integer := 3;   -- MZ-80A
constant MODE_MZ700   : integer := 4;   -- MZ-700(主要ターゲット)
constant MODE_MZ800   : integer := 5;   -- MZ-800
constant MODE_MZ80B   : integer := 7;   -- MZ-80B
constant MODE_MZ2000  : integer := 8;   -- MZ-2000(現行拡張ターゲット)

メモリコントローラ
FPGA のメモリコントローラは TZMM モード値(CPLD から Z80_MEM[4:0] 経由で受信)を SRAM バンク選択信号に変換します。tranZPUter ボードは 8 つの 64KB バンク(ブロック 0–7)として整理された 512KB の高速 SRAM を搭載しています。Z80 アクセス用に、FPGA は選択されたブロックへの 64KB ウィンドウを提示します。ZPU アクセス用には、完全な 512KB が直接アドレス可能です。
メモリコントローラは上位アドレスビット VZ80_A16VZ80_A21 を介して FPGA 内部リソース(ビデオ RAM、グラフィックス RAM、キャラクタジェネレータ RAM)の直接アドレス指定も処理します。これらの上位ビットが FPGA リソースを選択すると、バスサイクルは外部 SRAM の代わりに適切な内部 BRAM に誘導されます。これにより、ソフト CPU が Sharp MZ のレジスタ選択された 8KB ウィンドウメカニズムを使用せずにビデオメモリにアクセスできます。

K64F 通信インターフェース
K64F Kinetis ARM Cortex-M4 マイクロコントローラは zOS を実行し、tranZPUter の I/O プロセッサとして機能します。Z80 ソフトウェアと 2 つのメカニズムで通信します:
サービスリクエストプロトコル: Z80 ソフトウェアが I/O ポート 0x68(SVCREQ ポート)に書き込むと、CPLD が SVCREQn をアサートします。FPGA はこの信号を監視し、K64F に見える割り込みまたはフラグを発生させます。Z80 は K64F がリクエストされたサービスを完了して CTL_BUSRQn をデアサートするまで CPLD の ENIOWAIT メカニズム経由でウェイトステートを挿入します。
共有 SRAM ブロック: サービスリクエストパラメータとレスポンスデータは Z80 アドレス空間(SRAM ブロック 0 内)の 0xED80 にある専用 128 バイト領域を通じて交換されます。Z80 はサービスリクエストをアサートする前にこのアドレスにコマンドバイトとパラメータを書き込みます;K64F がそれらを読み取り、操作(通常 SD カードアクセスまたは BIOS ロード)を実行し、結果を書き込み、完了を通知します。
このプロトコルにおける FPGA の役割は受動的です — Z80 バスと K64F のメモリマップインターフェースが共有ブロックに同時にアクセスできるよう SRAM デュアルポートアクセスを提供します。FPGA は SVCREQn も監視し、ポーリングを必要とせず直接 K64F への割り込み信号を生成できます。

FPGA のビルド

FPGA ビルドは Quartus Prime(古い Cyclone IV デバイスサポートとの互換性のためのバージョン 13.0.1、または .qsf プロジェクトファイルで確認されている 17.1 Lite)を使用します。Quartus プロジェクトファイルは FPGA/SW700/v1.3/MZ700/build/coreMZ.qpf です;個別のビルド設定は Quartus を対応する .qsf ファイルに向けることで選択します:
QSF ファイル ビルド デバイス
coreMZ_E75.qsf ビデオのみ、EP4CE75 EP4CE75F23I7
coreMZ_E75_SoftCPU.qsf ビデオ + T80 + ZPU、EP4CE75 EP4CE75F23I7
coreMZ_E75_emuMZ.qsf ビデオ + エミュレータ、EP4CE75 EP4CE75F23I7
coreMZ_E115.qsf ビデオのみ、EP4CE115 EP4CE115F23I7
coreMZ_E115_SoftCPU.qsf ビデオ + ソフト CPU、EP4CE115 EP4CE115F23I7
coreMZ_E115_emuMZ.qsf ビデオ + エミュレータ、EP4CE115 EP4CE115F23I7
# 完全コンパイル(コマンドライン):
cd /dvlp/Projects/tranZPUter/FPGA/SW700/v1.3/MZ700/build
quartus_sh --flow compile coreMZ --rev coreMZ_E75_SoftCPU


# JTAG 経由で FPGA をプログラム(揮発性 — 電源サイクルで失われる):
quartus_pgm -m JTAG -o "P;output_files/coreMZ_E75_SoftCPU.sof@1"


# 永続的な NV ブート ROM をプログラム(設計の SFL メガファンクション経由):
quartus_pgm -m JTAG -o "P;output_files/coreMZ_E75_SoftCPU.jic@1"
NV プログラミングに関する注意: FPGA は EPCS64 シリアル設定デバイスから起動します。設計には Serial Flash Loader(SFL)メガファンクション(SFL/SFL_IV.vhd)が含まれており、coreMZ_pkg.vhdIMPL_SFL = true の場合、FPGA を通じて EPCS64 への JTAG インターフェースを公開します。これにより、別個の SPI プログラマなしに同じ USB-Blaster 接続で FPGA を永続的にプログラムできます。

CPLD のビルド
# CPLD をコンパイルおよびフィット:
cd /dvlp/Projects/tranZPUter/CPLD/EPM7160
quartus_sh --flow compile "tranZPUterSW EPM7160"


# USB-Blaster を使用して JTAG 経由でプログラム:
quartus_pgm -m JTAG -o "P;output_files/tranZPUterSW_EPM7160.pof"
CPLD プロジェクトファイルは tranZPUterSW_EPM7160.qpf です。フィッターツール(CPLDfit)は Quartus フローによって自動的に起動されます。プログラミングは CPLD の内部 EEPROM に書き込まれる .pof(プログラマオブジェクトファイル)を生成します — 電源サイクルをまたいで永続的です。

Docker ビルド環境

正しい Cyclone IV デバイスサポートを含む Quartus を含む Docker イメージが、ホストに Quartus をインストールすることなく再現可能なビルド環境を提供します。イメージはビデオモジュールや他の tranZPUter サブプロジェクトと同じパターンで使用されます:
# Quartus コンテナを起動(GUI のためにディスプレイを転送し、プログラマのために USB を渡す):
docker run --rm -it \
  -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix \
  -v /dvlp/Projects/tranZPUter:/project \
  --device /dev/bus/usb quartus:13.1 bash


# コンテナ内 — EP4CE75 の SoftCPU ビルドをコンパイル:
cd /project/FPGA/SW700/v1.3/MZ700/build
quartus_sh --flow compile coreMZ --rev coreMZ_E75_SoftCPU


# JTAG 経由でプログラム(USB-Blaster が --device 経由で転送される):
quartus_pgm -m JTAG -o "P;output_files/coreMZ_E75_SoftCPU.sof@1"
--device /dev/bus/usb フラグはコンテナに USB サブシステムへのアクセスを与え、USB-Blaster ケーブルがホスト上と同様にコンテナ内に現れるようにします。一部の Linux ホストでは --privileged を追加するか、USB-Blaster デバイス(Altera/Intel USB-Blaster VID:PID 09fb:6001)の udev ルールを設定する必要がある場合もあります。

K64F ファームウェア(zOS)

tranZPUter SW-700 の K64F Kinetis マイクロコントローラは zOS を実行します — SD カード初期化とファイル I/O、サービスリクエスト処理、システム起動シーケンシングを提供する小さな組み込みオペレーティングシステムです。K64F ソースは software.moved.to.TZFS/zOS/ にあります;MZ-700 ファームウェアは zOS/MZ700/、MZ-2000 ファームウェア(現行リファレンスビルド)は zOS/MZ2000/ にあります。
ファームウェアは C(startup/ に一部の ARM アセンブリスタートアップコードあり)で書かれており、ARM GCC ツールチェーンでビルドされます。ビルドシステムは Make ベースです;トップレベルのビルドスクリプトがすべてのコンポーネントを組み立てます:
# TZFS ツリーからすべての K64F ファームウェアをビルド:
cd /dvlp/Projects/tranZPUter/software/TZFS
./buildhost.sh


# または MZ-700 zOS ファームウェアのみをビルド:
cd /dvlp/Projects/tranZPUter/software.moved.to.TZFS/zOS/MZ700
./build.sh
K64F へのフラッシュ: Kinetis K64F はサブマイクロコントローラに OpenSDA ブートローダーを含んでいます。K64F ボードがリセットボタンを押した状態で USB 経由で接続されると、USB マスストレージデバイス(仮想ドライブ)として列挙されます。コンパイルされた .bin ファイルをこのドライブのルートにコピーすると、OpenSDA ブートローダーが K64F のフラッシュをプログラムし、自動的にリセットします。ボード上の LED が完了を示します。
OpenSDA デバッグ: 同じ USB 接続は、ボードが通常モードで動作しているとき(ブートローダーモードでなく)GDB-over-OpenSDA をサポートします。OpenOCD と Kinetis ターゲット設定で接続し、zOS のフルソースレベルデバッグのために localhost:3333 の OpenOCD サーバーに GDB をアタッチします。

TZFS ソフトウェア

TZFS(tranZPUter ファイリングシステム)は Sharp MZ ホスト CPU で動作し、コマンドモニタ、SD カードファイリングシステム、CP/M ブートローダー、マシンエミュレーションコマンドを提供する Z80 ソフトウェアスタックです。TZFS ソースは software/TZFS/ にあります(/dvlp/Projects/TZFS/ にシンボリックリンクあり)。
TZFS は RFS(ROM ディスクファイリングシステム)と同じルーツを持ちますが、tranZPUter の大きな 512KB SRAM、K64F I/O プロセッサ、マルチマシンターゲットサポートに適応されています。主要なソースファイル:
ソースファイル 内容
asm/tzfs.asm メイン TZFS バンク 0 — コマンドディスパッチャ、バンクスイッチスタブ
asm/tzfs_bank2.asm SD カードコントローラ
asm/tzfs_bank3.asm メモリユーティリティ(16 進ダンプ、メモリ編集、テープ↔SD)
asm/tzfs_bank4.asm CMT(テープ)コントローラ
asm/include/tzfs_definitions.asm 中央設定: BUILD_MZ700BUILD_MZ2000ENADEBUG、アドレス定数
asm/include/tzfs_svcstruct.asm サービスリクエスト構造定義(0xED80 の共有メモリ)
asm/cbios.asm CP/M CBIOS エントリーポイントとディスクパラメータテーブル
asm/cbiosII.asm CBIOS II — tranZPUter ハードウェア用拡張 CBIOS
asm/monitor_sa1510.asm パッチ済み SA-1510 モニタ ROM
asm/mz2000_ipl.asm MZ-2000 IPL ROM
# TZFS とすべての ROM イメージをアセンブル:
cd /dvlp/Projects/tranZPUter/software/TZFS
./buildhost.sh


# TZFS のみをアセンブル(開発中のより高速なビルド):
tools/assemble_tzfs.sh


# アセンブルされたイメージをマウントされた SD カードにコピー:
tools/copytosd.sh -D/dvlp/Projects/tranZPUter -M/media/sdcard -tMZ-700
buildhost.sh スクリプトは 4 つのサブスクリプトを順番に呼び出します:assemble_tzfs.shassemble_roms.shassemble_cpm.shmake_cpmdisks.sh。各スクリプトは次のスクリプトが実行される前に成功する必要があります。buildhost.sh へのオプションの -m フラグは追加で processMZFfiles.sh を実行し、変更された MZF プログラムファイルを再セクタします — これは低速で、ソフトウェアライブラリが変更されたときのみ必要です。
完全な TZFS ソースウォークスルーについては TZFS デベロッパーズガイドを参照してください。

新しい Sharp MZ マシンのサポート追加

tranZPUter SW-700 はマルチマシンサポート用に設計されています。新しい Sharp MZ ターゲットの追加には、CPLD VHDL、FPGA VHDL、K64F ファームウェア、TZFS ソフトウェア全体での調整された変更が必要です。以下の手順では仮想的な新しいマシン「MZ-XXXX」を例として使用します。
  1. CPLD: CPLD/EPM7160/tranZPUterSW_EPM7160.vhd に TZMM モード定数を追加する。 新しいマシンのメモリマップ用の新しいモード値(5 ビット MEM_MODE_LATCH デコードを拡張)を定義する — どのアドレス範囲がマザーボード上にあり、どの SRAM ブロックにあるか。既存のモードテーブルの横のコメントブロックに新しいモード番号を文書化する。
  2. FPGA: FPGA/SW700/v1.3/MZ700/coreMZ_pkg.vhd にホストハードウェアモデル定数を追加する。 既存のパターンに従って HOST_HW_MZXXXX 定数を追加する(例:constant HOST_HW_MZXXXX : integer := 8;)。VideoController/VideoController_pkg.vhd に対応するビデオモード定数を追加する(MODE_MZXXXX : integer := N)。
  3. FPGA: VideoController/VideoController.vhd にビデオタイミングパラメータを追加する。 ビデオタイミングテーブルはマシンモードでインデックスされる配列です。新しいマシンの水平/垂直ピクセル数、同期極性、フロント/バックポーチ幅、キャラクタセル寸法を含む新しい行を追加する。マシンが非標準のピクセルクロック周波数を使用する場合、PLL/ に新しい PLL 設定が必要になる場合がある。
  4. K64F: software.moved.to.TZFS/zOS/MZ2000/ にサービスコマンドを追加する。 新しいマシンのモニタ/IPL ROM を SD カードから指定の SRAM ブロックにロードする LOAD_MZXXXXBIOS サービスコマンドハンドラを追加する。既存の LOAD_MZ700BIOSLOAD_MZ2000BIOS コマンドハンドラをテンプレートとして使用する。
  5. TZFS: software/TZFS/asm/include/tzfs_definitions.asm にマシンモデルコードを追加する。 BUILD_MZXXXX EQU 0 フラグを追加する。マシン固有の I/O ポートアドレス、画面寸法、メモリレイアウトが異なる場所に新しい条件付きアセンブリブロックを追加する(既存の IF BUILD_MZ2000 パターンに従う)。
  6. TZFS: tzfs.asm/関連バンクファイルに BIOS ロードとマシン切り替えコマンドを追加する。 MZ XXXX モニタコマンドを実装する:(a)適切な TZMM モードを設定し、(b)K64F に LOAD_MZXXXXBIOS サービスリクエストを発行し、(c)FPGA ビデオモードレジスタを MODE_MZXXXX に設定する。
  7. テスト: TZFS モニタから MZ XXXX(または適切なコマンド文字列)と入力する。FPGA がビデオモードを切り替え、K64F が ROM をロードし、マシンが正しく起動することを確認する。RIO 0x6D で CPU Info レジスタを読み取り、RIO 0x60 でアクティブな TZMM モードを確認する。

デバッグのヒント

SignalTap II ロジックアナライザ: Quartus Prime には SignalTap II が含まれており、回路のタイミングを変更せずにライブ FPGA で信号遷移をキャプチャするインシステムロジックアナライザです。SignalTap プローブを追加するには:Quartus プロジェクトの SignalTap II ファイルを開き、対象信号(例:BUS_STATEVZ80_ADDRMEM_MODE_LATCH)を追加し、トリガー条件を設定し、再コンパイルします。アナライザは JTAG ケーブル経由でキャプチャされたデータをストリームします。これはバスタイミングと FSM シーケンシングの問題を診断するための主要なツールです。
K64F OpenSDA デバッグ: K64F には組み込み OpenSDA サポートがあります。USB 経由で接続し、Kinetis K64 ターゲット設定で OpenOCD を起動し、zOS サービスリクエストハンドラと SD カード初期化コードのソースレベルデバッグのために localhost:3333 に GDB をアタッチします。
TZFS レジスタ I/O コマンド: TZFS モニタから、RIO(I/O 読み取り)コマンドで FPGA/CPLD レジスタから直接読み取ります:
  • RIO 0x6D — CPU Info レジスタ: 有効なソフト CPU 機能(T80、ZPU など)を返す。
  • RIO 0x6F — System Info レジスタ: FPGA ビルドバリアントと機能フラグを返す。
  • RIO 0x60 — モードラッチが読み取り可能なビルドで現在の TZMM モードを読み取る。
TZMM モード確認: メモリマップを変更するマシン切り替えまたは TZFS コマンドの後、RIO 0x60 を使用し、CPLD ソースのモードテーブルと照合して、期待されるブロックマッピングがアクティブであることを確認します。
ENADEBUG の有効化: ビルド前に software/TZFS/asm/include/tzfs_definitions.asmENADEBUG EQU 1 を設定します。これにより SD カード初期化(CMD0/CMD8/ACMD41 レスポンス、セクター読み取りステータス)とサービスリクエストディスパッチ中に詳細出力が有効になります。SD カード互換性の問題と K64F 通信の問題を診断するのに役立ちます。
ソフト CPU クロックレート: T80 が物理ハードウェアアクセス(例:Sharp I/O 領域 E000–E7FF のキーストロークの見逃しや間違ったデータ)で誤った結果を生成する場合、softT80.vhdSW_CLKEN タイミングを調整して効果的な T80 クロックレートを下げます。AZ80 コアはこの領域でマージナルなタイミングの問題があることが知られています;本番には T80 を使用してください。
ビデオタイミングの問題: VGA モードの切り替えが再び切り替えるまで続くフリッカーを引き起こす場合、そのモードの PLL がロックしていません。これは一部のビルドで別の PLL インスタンスを使用するモード(一部のビルドの VGA モード 1 と 2)での既知の問題です。影響を受けるモードから離れてまた戻ると、PLL が再ロックを強制します。
BRAM 初期化: キャラクタジェネレータ BRAM の内容は合成時に ChrGenRAM_DP_3208.vhd の VHDL 配列定数として埋め込まれます。ビルド後にキャラクタディスプレイがゴミを表示する場合、BRAM 初期化データがターゲットマシンのキャラクタセットと一致していることを確認してください。ソースキャラクタ ROM バイナリから BRAM 初期化ファイルを再生成するために tools/build_meminitfiles.sh を使用し、再ビルドしてください。

参考サイト

リソース リンク
tranZPUter SW-700 プロジェクトページ /sharpmz-700-upgrades-tranzputer-sw/
tranZPUter SW-700 現行 README /sharpmz-700-upgrades-tranzputer-sw-current/
TZFS ユーザーマニュアル /tzfs-usermanual/
TZFS デベロッパーズガイド /tzfs-developersguide/
Sharp MZ シリーズ FPGA エミュレータ /sharpmz-emulator/
tranZPUter Gitea リポジトリ git.eaw.app/eaw/tranZPUter
Altera MAX 7000A データシート EPM7160 デバイスファミリー — マクロセルアーキテクチャ、タイミング仕様
Altera Cyclone IV データシート EP4CE75 / EP4CE115 — ロジックエレメント数、BRAM、PLL 仕様
Quartus Prime 13.0.1 Intel(Altera)— CPLD/FPGA 合成、CPLDfit、SignalTap II
T80 Z80 コア OpenCores — サイクル正確な VHDL Z80 実装
ZPU Evolution OpenCores — FPGA 組み込み用 32 ビットスタック CPU
Zilog Z80 CPU ユーザーマニュアル 標準データシート — バスタイミング、命令セットリファレンス