概要
Z80とROMでLチカしてみました。
基本的にLEDはZ80のアドレスバスに接続し、アドレスバスの出力を可視化します。加えて、動作の理解のため、M1のピンと、リフレッシュのピンにも接続します(役割は後述します)。
まず、動作させた動画を掲載します。クロックは1Hzとしているので、命令サイクルごとの動きがよく分かると思います。本記事では、これらの回路の設計、プログラム、CPUの動作原理をまとめて紹介します。
注釈を追加。 pic.twitter.com/THBwh7SGiK
— くれ:|| (@kure) 2025年7月13日
使用した部品一覧
- Z80(SHARP Z80 CPU Z80A-CPU-D LH0080A)
- ROM(SST39SF040-70-4C-PHE)
- ROMライター(XGecu T48)
- クロック回路(この記事で作ったもの)
- その他小物(赤色LEDたくさん、抵抗、ジャンパワイヤ)
回路図
実物の回路は以下です。LEDはアドレスバスとM1ピンとリフレッシュピンに接続しています。LEDは下の方から下位のビットに接続してます。(例:一番下だけ点灯したら1)
回路図は以下の通りです。Z80とROMだけを接続したシンプルな回路です。ROMを使っていますが、CPU的にはメモリの役割として使っています。
Z80とROMが接続されているのは、以下です。メモリとして使っているため、MREQとRDをROMに接続します。
Z80の動作原理
実際に回路を動かす前にZ80の動作原理を確認します。下部に掲載の図はトランジスタ技術 SPECIAL No.49から抜粋です。サンプルはLD A (1234h) 命令の様子です。(メモリの1234h番地からAレジスタに値を読み込む)
- 前提として、メモリの0番地~2番地に
LD A (1234h)
命令が格納されており、メモリの1234hに読み取らせたいデータが格納されているということです。つまり- メモリ0番地: LD
- メモリ1番地: 34h
- メモリ2番地: 12h
- まず電源を入れてZ80をリセットすると、プログラムカウンタが0になり、0番地から命令を読み込んでいきます。
- 0なので、アドレスバスはすべてLOW
- 命令(オペコード)を読み込みます(例:
LD
) - オペコード分、プログラムカウンタを進めます(
LD
の場合は1Byte)
- プログラムカウンタが1になり、1番地からオペランドを読み込んでいきます。LDの場合は、オペランドが1Byte * 2 の2Byteなので、1Byteを2回読み取っていきます。
- 1なので、アドレスバスの最下位のピンをHIGHにします
- オペランドの下位バイト(アドレス1)の値をデータピン経由で読み取ります(34h)
- プログラムカウンタが2になり、2番地からオペランドを読み取ります
- 命令
LD A (1234h)
が読み取れたので、命令を実行します。命令はアドレス 1234h からAレジスタに読み込むということなので、アドレスバスに 1234h を出力します。 - 無事に命令を実行できました。次の命令に移るため、プログラムカウンタを1増やして、アドレスバスに3を出力して命令(オペコード)をフェッチします。
- オペコードフェッチ時はM1サイクルと呼ばれるので、M1ピンがLOWになります
- オペコード読み取り後は通常「リフレッシュアドレス」というものを出力するようです。これはDRAMの際に、必要な処理らしいのですが、今回は関係ないので深堀りしていません。
- この際、リフレッシュピンがLOWになります
以上がZ80が命令を読み込んで、実行するまでのサイクルになります。これをプログラムカウンタを増やしながら順次進めていきます。
かいつまむと、
オペコードをフェッチする→オペランドをフェッチする→実行する
をプログラムカウンタを増やしながら繰り返す、ということです。
その他メモ
- Z80のアドレスピンは16個=2Byte分あります
- 2Byteということは、10進数で65536通りの値を表現できます
- データピンは8個=1Byteです。ということは、1Byte * 65536 = 64KB までのメモリを扱えるということです。すなわち、アドレス空間が64KB。
ROMプログラムの準備
さて、大体の動作原理がわかったところで、いよいよプログラムを動かしていきます。
最初にROMにプログラムを書き込みます。 ※ROMの使い方は以前、この記事で紹介していますので、省略します。
今回は、CPUの動作原理を確認するのが目的なので、意味のないプログラムですが、以下のように先程の動作原理の解説でも用いた命令 LD A, (0x01)
を連続で実行していきます。
START: LD A, (0x01) LD A, (0x01) LD A, (0x01) LD A, (0x01) LD A, (0x01) JP START
Z80を動作させる
それでは、Z80に電源を入れて、リセットします。リセットすることで、PCが0から、Z80がメモリから命令を順番に読み込んで行きます。リセットは、リセットピンをLOW→HIGHにすることで可能です。
最初の動画を再掲します。いかがでしょうか。動作原理に解説したとおり、アドレスバスに想定どおりの出力がされながら、実行が進んでいく様子が分かるのではないでしょうか。
注釈を追加。 pic.twitter.com/THBwh7SGiK
— くれ:|| (@kure) 2025年7月13日
おわりに
雑誌片手にZ80の動作原理を学習しつつ、Lチカさせることで、実際の動作を確認していきました。 理屈と動作が辻褄があっているので、おそらく記載した内容も間違っていないとは思うのですが、不正確な部分等あればご指摘いただけますと幸いです。
次は、IOデバイスも加えて、もう少しコンピューターらしくしていきたいと思います。
その他参考記事
データシート