最新版 download(version1.01)
(2008/02/10更新)
crtc.v 一部の文字フォントを修正
pc.v 入力データにレジスタを追加
fz80.vをkx_z80.vに変更

以前、CPLDを使って小物ハードを作ったことはあるのですが、10万ゲート程度であればフリーのツールで、EZ-FPGAのような安価な基板で実験ができることを知り、何か作ってみたくなりました。

準備

Windowsマシン(hpのd330MT(P2.4B/256/40/W2))にXilinxのISEWebPack6.2をインストールしたところ、1分に1回くらい、「オブジェクト名は既に使用されています」という謎のアラートが出るようになってしまいました。
リストアCDでリストアしてからインストールし直してもやっぱりだめだったので、リストアCDは使わずにWindows2000だけインストールし、hpのページにあったドライバをあとからインストールしたところ、アラートは出なくなりました。BIOSはアップデートしていません。

追記(2004/9/28)
この現象は、パラレルケーブル用のドライバが重複してインストールされることによる不具合で、デバイスマネージャでJungo.WinDriverの「!」がついている方を削除すれば直るそうです。

Z80IP

とりあえず8ビットパソコン(PC-8001)でも作ってみようかな、ということでZ80コアについて調べると、有名なところでt80FPGAインフォメーションのものがありました。t80はフリーだけど回路規模が大きいです。FPGAインフォメーションのものは回路規模が小さいらしいのですがフリーではありません(条件付きでネットリストを無料で使用できる)。

「ここはひとつ、自分で書いてみようかな、HDLの勉強にもなるし」

ということで、書いてみました。既存のものと同じものを作っても面白くないので、バイナリコンパチでありながら実行クロック数を削減した、いわゆるRISCライクな感じにしてみました。ただし、パイプラインは無いのでクロックの上限は低くなります。

設計方針として、バスアクセスが無い、内部処理だけのサイクルを排除できるように構成します。その結果、最低限必要になるレジスタ群、セレクタ群、ALU、シーケンサのほかに16ビット長の演算、相対ジャンプの計算、インデックスレジスタを用いたアクセスの計算用に16ビットと8ビットの加減算をするユニット(ASU)を追加しました。あとはデータの流れを最適化すれば、内部処理だけのサイクルは皆無になります。
ただし、現状では一部の未定義フラグ変化(I/Oブロック命令のH,PVフラグ)をサポートできていませんが、使わないので気にしないことにします。
外部インターフェースは同期バスで、1マシンサイクル=1バスサイクル=1クロックになっています(ウェイトは可能)。データバスは入力と出力に分離してあります。また、リフレッシュサイクルはありませんが、Rレジスタのカウントアップは行います。
割り込みは、INTのすべてのモードとNMIに対応しています。
DMAにも対応しています。ただし、各出力がHi-Zになるわけではなく、単に内部動作が停止するだけです。

download(version0.1)

このソースを営利目的に使用することを禁止します。いないでしょうが、一応書いておきます。

ステートマシン以外は、論理合成の性能に頼らない、ゲートレベルに近い書き方になっています。そのためか、エリア優先で合成すると700スライス以下で済んでいます。これなら、10万ゲート(1200スライス)のスパルタンIIに、周辺回路も含めて余裕で入りそうです。

シミュレーションは、iverilogで、N-BASICが立ち上がるまでの10万命令をソフトウェアエミュレータのトレース結果と比較し、相違無いことを確認しています。
ただし、N-BASIC起動までには使われない以下の命令・機能については実装はしたものの未検証なので、たぶんバグがあります。

DD,FDから始まるインデックスレジスタを使う命令群
CBから始まるビット演算/シフト/ローテート命令群
割り込み

それでも、このコアでN-BASICのプロンプトまでは辿り着けそうです。
本格的なデバッグは、その後考えることにします。

EZ-FPGA

秋葉原のITプラザで、EZ-FPGAボードを買ってきました。 チップ部品のはんだ付けをしたことがないので、製作代行も頼もうかと思ったのですが、チップ部品くらい付けられなくてどーするよ、ということで、キットのまま買ってきました。
半田ごても古いのしかなかったので、ホーザンのラインペンソル(HS-11)を買いました。
製作上の注意点としては、チップコンがランドからずれないように気をつけることです。あたりまえですけど。私の場合、裏面のチップコンをいくつか付けてからVcco-GNDの導通チェックをしたら、見事にショートしてました。じっくり観察して、怪しいチップコンを剥したら直りましたが。
チップ部品のはんだ付けも、最初は力を入れすぎてどこかへ飛ばしたりしてましたが、慣れてくると力を抜きつつしっかり押さえることができるようになり、1608サイズなら楽勝になりました。

JTAG

EZ-FPGAは、別売りのMINI EZ-USBを接続してUSB経由で書き込むこともできるのですが、今回は以前作ったJTAGケーブルがあるので、JTAG経由で書き込むことにします。
ezftest(EZ-FPGA用のテストツール)を走らせるために、EZ-FPGA上にクロックオシレータが必要になります。周波数は適当でいいのですが、後々NTSCエンコーダの実験をしたいので、14.318MHzを買いました。
準備ができたので、EZ-FPGAをJTAGケーブル経由でPCに接続し、ezftestを走らせたところ、エラーで止まってしまいます。
iMPACTでは、認識はするものの、
DEVICE ID=000011111111...
でエラーとなり、書き込めません。
JTAGケーブルにはXilinxの回路図にある74HC125ではなく、74HCT367を使っていました。
JTAGケーブルの電源にターゲットの3.3Vを使っているので、これを74HC367に交換したのですが、やっぱり同じです。
結局、TCKを整形するという対処法で直りました。具体的には、PCからのTCKを74HC14を2段通し、ターゲットに入力しています。

CRTC

ezftestも通り、手っ取り早く何か動いている姿を見たくなったので、PC-8001のCRTC(μPD3301)を簡略化したものを書いてみました。キャラクタジェネレータもいっしょになっていて、ブロックRAMを4つ使います。
ドットクロックが14.318MHzなので、水平は910ドットクロックでNTSCと同じですが、垂直はインターレースではないので262Hにしました(0.5H少ない)。
色のエンコードは後回しにして、とりあえず複合同期(z0)と輝度(z1)だけですが、割とあっさりと画面が出ました。
カウンタの塊で、TTLでは作る気もしなかったCRTCがこんなに簡単にできるなんて。

download(crtc.v, version0.1)

実際には、VRAMをブロックRAMに取ると6ブロックになり、XC2S100のブロックRAMを使い切ってしまうので、実機と同じようにメインメモリ上に取ることになると思います。その場合はDMAが必要になります。



CFカード

最終的にはFPGA用のコンフィグROMを搭載して、スタンドアロンで動かしたいのですが、その際、N-BASICのROM(ブートイメージ)をどこに置くかという問題があります。
専用のコンフィグROMではコンフィグデータしか入らないので(*)、I2CシリアルROMにしてコンフィグデータとブートイメージを入れるというのも考えたのですが、別途マイコンが必要なのと、読み出しが遅いのが気になります。
もうひとつ、ブートができたとしても、外部記憶に何らかのメモリーカードを使いたいというのがありました。いくらPC-8001を作るといっても、外部記憶がカセットテープでは(今だったらMDか)、実用になりません(実用を目指すのか?)。
ということで、FPGAのコンフィグは保留で、ブートイメージとsave/load用にメモリーカードを使うことにしました。
メモリーカードといってもいろいろと種類があります。USBメモリもあります。ただ、USBメモリはプロトコルアナライザがないと辛そうなので除外しました。
で、今回はCFカードを採用しました。理由は、TrueIDEモードで使ってATAデバイスの使い方が分かるようになれば、後々HDDを使ったものを作るときに役立ちそう、というのと、単に古いデジカメ用のCFカードが余っていたからです。
サンハヤトの変換基板(CK-14)とEZ-FPGAを、ベースになるユニバーサル基板に乗せ、配線しました。
このユニバーサル基板は秋月で買ったのですが、ガラエポ両面スルーホールの割には400円とお買い得です。



写真は、テスト用に使っているAVRスターターキットSTK-500につないだところで、マイコンと2本の線(クロックとデータ)でやり取りし、結果をRS-232Cで別のPCのターミナルソフトで見られるようにしてあります。
ちなみに、グランドはPC経由でつながっています。
テストは、
(1) CFカードをフォーマットしたあとブートイメージをコピーする。
(2) FPGAでAVR側からCFカードのATAレジスタにアクセスできるようにする。
(3) AVRでATAコマンド(read sectors)を発行して、読み出したデータをRS-232Cに送り出す。
(4) ターミナルソフトでログを取り、元のブートイメージと比較する。
の手順で行い、正しく動くことを確認しました。

参考文献
ATA(IDE)/ATAPIの徹底研究

(*)追記(2004/9/28)
アプリケーションノートXAPP694によると、コンフィグROMにユーザーデータを入れることもできるようです。

RAM

ブートイメージが読み出せるようになったので、次はメインメモリです。今回は、DIPパッケージの単純なSRAMで、1個で済むように1MビットのTC551001CPにしました。1Mビットだと128kバイトになるので、半分をZ80にそのままマップします。
RAMは、配線がしやすいようにEZ-FPGAの下のスペースに置きました。
次にテストプログラムです。
Z80のテストがまだなので、Z80コアは使わずにATAのread sectorsコマンドを発行し、ブートイメージをRAMに転送します(boot.v)。
その後、RAM上のイメージをマイコンから読み出し、RS-232Cに送り出してチェックします。
ここで、不具合が発生しました。ATAのLBAがうまく設定できず、正しいデータを読み出せないという症状です。CFカードだけでテストしたときは大丈夫だったのに……
しかも、この不具合はエリア優先で合成したときだけ出現し、スピード優先で合成すると正しく動くのです。
最終的に、スピード優先ではZ80コアを含めて全体が入りそうにないので、エリア優先で動くことが必須です。というか、そんな不安定な状態では後々困ります。

原因は、ATAのタイミング規格を守っていなかったことでした。ライトはOKなのですが、リード時にDIORネゲートからのCS・アドレスホールドタイムをちゃんと取っていませんでした。
RTLでは0ですが、実際は合成オプションにより若干+-となり、不具合となって現れたのでしょう。
読み出したデータをラッチしさえすれば、あとは適当でいいと思ったのが甘かったです。ATAステータスレジスタの読み出しでタイミング違反をしたのがいけなかったようです。
タイミングを修正した結果、エリア優先でもスピード優先でも動くようになり、読み出したデータも正常でした。

download(boot.v, version0.1)

ICE

ブートイメージがRAMに置けるようになったので、いよいよZ80コアのテストをします。
そのために、Z80コアにICE機能をつけました。1命令ずつバスサイクルが有効のままウェイトし、マイコンがレジスタ、バス、アクセス種別を読み取ったら次の命令に進むようにしました。
テストは、CFカードからブートイメージを読み出してRAMに転送したあとCPUのリセットを解除し、1命令ずつ実行します。例によって読み出したデータをRS-232Cに送り、ターミナルソフトでログを取ります。それを、iverilogでシミュレーションした結果と比較します。
結果は、実行した10万命令で全て同一となりました。これでN-BASICのプロンプトまでたどり着いているはずです。
実は、RTLで大丈夫なのに実装したらダメだったらどうしようと思っていたのですが、あっけないくらいまともに動いてしまいました。FPGAってけっこう扱いやすいかも。

Ok

ここまで来たらプロンプトが見たい。ということで、CRTCをDMA対応に書き換えて組み込みました。
実機と同じようにVRAM自体はメインメモリ上に取り、CRTC側にはブロックRAMを1つ使って1行分のバッファ(120バイト)を用意します。テキスト・アトリビュート兼用です。
キャラクタを1行表示し終わった水平帰線の間にDMAで次の1行分を転送します。時間的には270ドットクロックあります。DMA中はRAMの~CE=~OE=0に保ち、2ドットクロック/バイトで転送すれば間に合います。
なお、CPUのクロックもドットクロックと同じ14.318MHzなので、RAMアクセスのために常に1ウェイト入れています。
結果は以下の写真のとおり。N-BASICのプロンプトが出ました!



download(version0.2)

ところで、実機ではDMAのせいでだいぶ遅くなっていたのが不評でしたが、この実装では
1画面分の時間:910ドットクロック/Hで262Hなので
910*262=238420ドットクロック
DMAにかかる時間:2ドットクロック/バイトで120バイト、DMA開始・終了時のロスが2ドットクロック、これが25行分なので
((2*120)+2)*25=6050ドットクロック
以上から、DMAによりCPUが止められる時間は3%未満になります。
実機のDMAってすごく遅かったんですね。

キーボード

画面が出たので、次はキーボードです。PS/2キーボードが簡単そうですが、今回はUSBキーボードに挑戦です。
いしかわさんのページの情報を元に、AVRマイコンにUSBキーボードをつないで実験した結果、set addressとset configurationさえすれば、インタラプト転送が可能になり、キーの状態が変化したときに以下のようなデータを返してくることが分かりました。

第1バイト SYNC
第2バイト DATA0/DATA1
第3バイト モディファイア
第4バイト 0
第5バイト キーコード1
第6バイト キーコード2
第7バイト キーコード3
第8バイト キーコード4

モディファイアのビット構成は、

ビット0 左Ctrl
ビット1 左Shift
ビット2 左Alt
ビット3 左Windows
ビット4 右Ctrl
ビット5 右Shift
ビット6 右Alt
ビット7 右Windows

です。キーコードはHID Usage Tablesのkeyboard/Keypad Pageに定義されているUsage IDです。キーが押されていなければ全て0、何か押されていればそのキーコードが入りますが、キーボードの回路構成上、3つ以上のキーを同時に押すとどのキーが押されているか分からなくなることがあり、このようなときは全てのキーコードが1になります。

UKP

上記を元にステートマシンを書いてみたのですが、回路が大きくなりそうだったので途中で止めて、専用のショボいプロセッサを作ることにしました。名づけてUKP(USB Keyboard Processer)。
プロセッサにしようと思ったのは、どのみちset configurationなどのパケット用にROMが必要になるので、そこに簡易なコードも置いて、小さなプロセッサで処理すれば回路が減らせそうだと考えたからです。
UKPは、オシレータの14.318MHzからEZ-FPGAに実装されているPLLで作る12MHzで駆動します。
UKPのレジスタなどは以下のとおり。

PC プログラムカウンタ10ビット
Wレジスタ 回数を数える8ビットのレジスタ
Cフラグ 接続状態かどうかを示す1ビットのレジスタ
Tカウンタ USBのタイミングを取るための3ビットのカウンタ
タイマー 1mSを作る14ビットのカウンタ

命令セットは、以下のようにしました。

NOP ノーオペレーション
LDI cc Wレジスタに8ビット定数をロード
START D-が0になるまで待ち、Tカウンタをクリアする
OUT0 Tカウンタが0になるまで待ち、D+,D-共に0を出力する
OUT1 Tカウンタが0になるまで待ち、D+に1を、D-に0を出力する
OUT2 Tカウンタが0になるまで待ち、D+に0を、D-に1を出力する
HIZ Tカウンタが0になるまで待ち、D+,D-をHi-Zにする
BZ aa D-が0ならジャンプ
DJNZ aa Wレジスタをデクリメントし、0でなければジャンプ
BNAK aa 直前のレスポンスがNAK/STALLならジャンプ
BC aa Cフラグが1ならジャンプ
TOGGLE Cフラグをトグル
WAIT 1mSのタイミングまで待つ
IN Tカウンタがサンプリングタイミングになるまで待つ。D+,D-共に0なら次の命令へ。
そうでなければ、Wレジスタをデクリメントして0なら次の命令へ。

オペコードは4ビット(=1ワード)、オペランドは(もしあれば)8ビットです。
ジャンプ命令は、PCが10ビットなので、4ワード単位のジャンプになります。

以上のアーキテクチャで、キーボードを制御するコードを書きました(ukp.s)。これを、専用のショボいアセンブラ(asukp)でアセンブルし、ukprom.vを作成します。
と書くと簡単そうですが、実際は正しく転送できるようになるまでukp.sをけっこう書き直しました。ちょっと間違えるとキーボードが無反応になるのです。こんなとき、HDLより修正が容易なアセンブラだと助かります。

さて、キーボードの状態が変化したときにデータを受け取るところまでできたので、このデータをキーマップに基づいて変換し、どのキーが押されているかを10バイトのレジスタ(ポートレジスタ)に保存します。
CPUからは、ポートレジスタが入力ポートの0〜9番地に見えるようにすれば、N-BASICでキーボードを扱えるようになります。
ここで、ポートレジスタの操作にちょっと工夫が要ります。
キーボードが送ってくるのは押されているキーのコードだけで、放されたキーは分かりません。したがってポートレジスタの操作は、一旦全クリアし、押されているキーに相当するビットを立てていくという処理になります。
インタラプト転送でキーボードがデータを返し始めてから全クリアを始めても間に合わず、かといってCPUからいつ読まれるか分からないのに前もってクリアしておくわけにもいかないので、ポートレジスタをダブルバッファにしました。
これにより、CPUに見せていないほうは常に回っているタイマーの下位ビットをアドレスに入れて常時クリアするようにしておき、キーボードからデータが来たら必要なビットを立てて表と裏を入れ替えるようにしました。
テストは、例によってAVRマイコンを使い、USBキーボードのキーを押したり放したりしながら、ポートレジスタを読み出し、正しく動くことを確認しました。

download

NTSC

次は、画面に色をつけます。テレビのコンポーネント入力はまだ一般的ではないので、S端子出力を作ります。そのために、色情報をNTSCエンコードします。
さとうさんのページの情報によると、RGBをYUVに変換し、14.318MHzでV,U,-V,-Uと順番に出力すれば色がつくらしい。
ということで、RGBからYUVへの変換式

Y = 0.299R + 0.587G + 0.114B
U = -0.168R - 0.332G + 0.500B
V = 0.500R - 0.419G - 0.081B

において、UとVに着目すると、デジタルRGBであるPC-8001では以下のような値になります。

色番号 U V
0 0.000 0.000
1 0.500 -0.081
2 -0.168 0.5000
3 0.332 0.419
4 -0.332 -0.419
5 0.168 -0.500
6 -0.500 0.081
7 0.000 0.000

これを12倍すると、以下のようになり、四捨五入したときの誤差が3%以内に収まることが分かりました。

色番号 U V
0 0.000 0.000
1 6.000 -0.972
2 -2.016 6.000
3 3.984 5.028
4 -3.984 -5.028
5 2.016 -6.000
6 -6.000 0.972
7 0.000 0.000

つまり、色信号は4ビットのDACで生成できることになります。
あとは、バックポーチにカラーバーストを乗せます。カラーバーストは、ラスタごとに位相を反転させます。

輝度信号は今までのまま、とりあえず試したのが下の写真です。
回路的には、4ビットDACはR2RラダーDACです(1k/2k)。フルスケール0.3Vにしました。また、インピーダンスを下げるためにビデオアンプNJM2267を追加しています。



N-BASICのダイレクトモードで色を変更しているので、色番号と実際の色は1つずれています。
これを見ると、なんか変です。PC-8001の場合、キャラクタ単位でしか色をつけられないので、ドットがない部分も色を出力しているのですが、黒い部分に色がついてしまっています。輝度信号がペデスタルレベルなら色信号があっても黒くなると思っていたのですが、違うんですね。
そこで、ドットがない部分は色信号もなくしたところ、以下のようになりました。



やっぱり変です。写真ではちょっと分かりにくいですが、色番号が小さいほど白っぽくなっています。輝度信号もRGBに従って変えてやらないとダメみたいです。ということで、輝度信号も4ビットDACにしました。フルスケール1.0Vです。輝度は4ビットでは誤差が大きいのですが、気にしないことにします。



これでまともになりました。
width40で1ドットだと色信号は半波長分しかないのに、ちゃんと色がつくんですね。アナログ回路の不思議です。
カラー版CRTCと、UKPを組み込んだのが以下のソースです。

download(version0.3)

RTC

ふとprint time$をしてみたら固まってしまいました。ということで、RTC(μPC1990)を実装しなければいけません。
PC-8001のRTCはバッテリバックアップがないので、単なるカウンタの塊です。さくっと作りました。

download(rtc.v)

BEEP:MOTOR

次は音です。BEEP用に圧電スピーカを買いました。また、MOTOR用にリレーを買いました。リレーに関しては、接点には何もつながず、動作音だけのために使います。ONのとき「チッ」、OFFのとき「トッ」って感じが本物っぽいです。3つ買って試したんですが、一番いい動作音がした左手前のリレーを実装しました。カバーが透明なのもいい感じです。


コンフィグROM

なひたふさんのところのコンフィグROMを買って、実装しました。
EZ-FPGAの裏面のM0〜M2をGNDに落として、あとはROMをつなぐだけです。
さあ、iMPACTで書き込もうと思ったのですが、書き込み方が分かりません。
ちょっと調べるとiMPACTではめんどくさいみたいなので、同じくなひたふさんのMITOUJTAGで書き込みます。これなら簡単です。
これでスタンドアロンで起動できるようになり、ハードウェア的にはほぼ完成です。



1階部分



2階部分を取り付けたところ

save/load

あとはソフトウェアです。CFカードにプログラムをsave/loadできるようにします。
そのためにまず、CPUからCFカードのATAレジスタにアクセスできるようにboot.vを書き換えました。
CS0の方をI/Oの0e0h〜0e7hに割り当てます。CS1の方は使いません。
次に、BASICのコマンドでsave/loadできるようにZ80のコードを書きます。
アセンブラは、どこからダウンロードしたか忘れてしまったのですが、インストールしてあったものがあったのでそれを使います。
開発の仕方ですが、アセンブルしてできたバイナリをブートイメージといっしょにCFカードに入れてブートすればいいのですが、この方法だと、いちいちカードを抜いてPCカードアダプタに入れてWindowsノートのスロットに入れてファイルをコピーしなければなりません。
代わりに、アセンブルしてできたバイナリをtestrom.vに変換し、N-BASICで拡張エリアになっている6000h〜にマップする方法にしました。この方法だと、論理合成する間2〜3分待たないといけないのですが、待っているだけのほうが楽なのでこれでいいことにします。

あと、デバッグ用にICE機能を改良します。
N-BASIC起動までのトレースはスタート直後からでよかったのですが、走っている状態でのデバッグは、ある特定の開始条件が成立した時点からトレースできなければいけません。
そこで、出力ポートの0efh番地のLSBをトレースイネーブルフラグとし、ここに1を出力したサイクルからトレースが有効になるようにしました。
トレースの仕方は、前述のICEのところと同じです。この機能により、デバッグが楽になりました。

いよいよZ80のコードを書きます。
本来はCFカードの容量に応じてFAT12/FAT16やさまざまなクラスタサイズに対応すべきですが、とりあえず版ということで、今テストに使っている8Mバイトのカード専用に作りました。8Mバイトの場合、FAT12でクラスタサイズは4kバイトです。また、ディレクトリ階層は扱わず、ルートディレクトリのみとしました。
BASICコマンドとして、以下の4つを実装しました。

files ファイル一覧
load ファイルをロード
save ファイルをセーブ
kill ファイルを消去

ファイルフォーマットは拙作Mac8001と同じで、BASICとマシン語を1つのファイルで扱えるようにしたものです。

ファイル全体の構成
ヘッダ 16バイト
BASIC Nbバイト
マシン語 Nmバイト

ヘッダの構成
実行アドレス 2バイト(ビッグエンディアン)
BASICの長さ(Nb) 2バイト(〃)
マシン語の先頭番地 2バイト(〃)
マシン語の長さ(Nm) 2バイト(〃)
パッド 8バイト

それにしても、久々にZ80のコードを書いたのですが、ものすごく書きにくく感じました。
最近慣れているアセンブラがARMとAVRなもので。

download(version0.4)

fz80

ロードができるようになったので、CFカードにいろいろなゲームを入れて走らせてみます。
オールBASICのものは、ちゃんと動きます。しかし、マシン語を使ったものは動作がおかしいものがあります。
N-BASICは、DD/FDから始まるインデックスレジスタを使う命令、CBから始まるビット操作/シフト/ローテート命令を全く使っていません。そのような命令の動作が正しくないようです。
そこで、ICE機能を使ってトレースするのですが、動作がおかしくなる直前からトレースしたいので、その場所を見つけます。
オールマシン語のゲームでは難しいので、BASICも併用したものでBASIC上で場所が見つけやすいものを優先的に調べます。
場所が見つかったら、その場所で出力ポート0efhに1を出力します(トレースイネーブル)。
あと、ゲームプログラムではRレジスタを簡易乱数に使っていることが多いので、あとでエミュレータのトレース結果と比較するために同時に初期化する必要があります。
まとめると、トレースを開始するところに以下のようなコードを挿入します。

3E 01 D3 EF ED 4F

これで得られたトレース結果と、エミュレータから得られるトレース結果を比較し、fz80をデバッグしていきました。
また、割り込みのデバッグに関してはさとうさんにご協力いただきました。

download(version0.5)

END

今日は2004年9月28日。PC-8001が発売された日からちょうど25年になります。
fz80のデバッグも終了し、様々なプログラムが正常に走るようになりました。
このプロジェクトを開始した頃とは違って、スパルタン3スターターキットなど、より大容量のFPGAボードも安価に手に入るようになりました。
このようなボードを使えばt80を使っても入るので、なにも自分でZ80コアを作る必要はありませんでした。
しかし、ある程度の規模のロジックを全て自分で書いたことでとても勉強になり、それがFPGA上で走っているのを見ると、感慨もひとしおです。

ここに、最終バージョンを置いておきます。
このソースは、非営利目的に限り自由に使用できます。
ただし、いっさいの保証やサポートはありません。

download(version1.0)

最後に、スクリーンショットを載せて、「FPGAでPC-8001を作る計画」を終了します。