標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第452回]

●計算が合いません???

前回は、
TK80のCPUクロックが2MHzだったのに、Z80版TK80ボード(ND80ZH)のCPUクロックが4MHzなので、モニタプログラムのチャタリングタイマーを補正しました。
というお話をいたしました。

CPUクロックが2MHzのボード(TK80)で、9msecのタイマープログラムを、CPUクロックが4MHzのボード(ND80ZH)でそのまま実行したら、4.5msecタイマーになってしまいます。
キー入力時のチャタリングによる誤入力を回避するためのタイマールーチンですから、それが半分の時間になってしまっては、使い物にならない可能性がありますから、クロックを4MHzにしても、約9msecになるように定数を書き換えたのです。

Z80は8080の命令をそのまま実行できますから、単純に考えたら、時間待ちのループ回数を倍にすれば計算が合う、はずでした。

念のために、ということで、オリジナルのままのタイマールーチンの各命令の実行クロック数を全部計算して、そこからD2のサブルーチンの実行時間が9msecになるように、繰り返し回数を計算で求めて、得られた値が、
アドレス02DFのMVI E,23
でした。
16進数の23は十進数では35です。

ところが。

オリジナルのTK80モニタプログラムのその部分は、
MVI E,0C
だったのです。
0Cは十進数では12です。

あれま。計算が合いませんですねえ?
2MHzのときに繰り返し回数が12回だったのですから、4MHzなら24回になるはずでしょう。
それが4MHzだと35回になってしまうのですよお。
5割近くも違うじゃありませんかあ。
なぜえ?

CPUクロック4MHzで約9msecになるように計算で求めて書き直したタイマールーチンをテストプログラムを書いて確認してみたところ、間違い無く約9msecであることは、テストプログラムを実行して得られた出力波形から明らかです(前回[第451回]のオシロの写真)。

では、TK80モニタプログラムが間違っているのか?
いや、いくらなんでも、それはないでしょうよ。

どうでもよいことかもしれませんが…。
いやあ、これはどうでもよいことでは済まされませんでしょう。
むむ。納得がいきません。
こういうことは、やっぱり納得がいくところまで、追及してみたくなってしまいますです。
一旦、気になると、そのままにしておくのが、どうにも気持ちが悪いのですよねえ。

で。
オリジナルのTK80モニタのタイマールーチンの各命令に8080のクロック数を当てはめて、実行時間を計算してみました。

すると、意外な結果になったのです。

              ;
              ;CHATTERING TIMER
              ;
                ORG $02DD
02DD 1624     D1:MVI D,24;WAIT 1/2 BIT TIME 4.5112MSEC (7)
02DF 1E0C       MVI E,0C (7)
02E1 1D         DCR E    (5)
02E2 C2E102     JNZ $-1  (10)
02E5 15         DCR D    (5)
02E6 C2DF02     JNZ $-7  (10)
02E9 C9         RET      (10)
02EA 1648     D2:MVI D,48;WAIT 1 BIT TIME 9.0176MSEC (7)
02EC C3DF02     JMP D1+2 (10)
02EF 16D8     D3:MVI D,D8;WAIT 3 BIT TIME 27.0176MSEC (7)
02F1 C3DF02     JMP D1+2 (10)
[出典]NEC日本電気鰍sK80ユーザーズ・マニアル

前回お見せしたリストの各命令にクロック数を書き加えてみました。
このクロック数をもとに、実行時間を計算してみました。

D1〜D3のルーチンは、いずれも02DF〜02E9を実行しています。
そこでまずこの部分のトータルクロック数を計算してみました。
0Cは十進の12ですから、
02DF〜02E2の部分は、7+(5+10)×12=187になります。
D2のMVI D,48の48は十進の72ですから、D2から02E9のRETまでのトータルクロック数は、
7+10+(187+5+10)×72+10=14571です。
TK80のCPUクロックは18.432MHzを9分周して得られる2.048MHzですから、1クロックは1/2.048μsecです。
ですからD2の実行時間は、14571×(1/2.048)=7114.7μsec…。

やっぱり計算が合いません…。

実はこの段階で気がついたことがあります。
それは、DCR命令のクロック数です。
8080のDCR命令のクロック数は、Z80と違っていたのです。

前回お見せした、CPUクロック4MHz用に書き直した、上と同じタイマールーチンのリストです。
このリストにコメントしてあるクロック数はZ80のクロック数です。

              ;
              ;CHATTERING TIMER
              ;
                ORG $02DD
02DD 1624     D1:MVI D,24;=36 ck=7 127.75*36+(7+10)*0.25=4603.25microsec
02DF 1E23     D1_2:MVI E,23;=35 ck=7  7+14*35+14=511 0.25*511=127.75microsec
02E1 1D       D1_3:DCR E;       ck=4
02E2 C2E102     JNZ D1_3; ck=10
02E5 15         DCR D;    ck=4    
02E6 C2DF02     JNZ D1_2; ck=10
02E9 C9         RET;      ck=10
02EA 1648     D2:MVI D,48;=72  127.75*72+(7+10+10)*0.25=9204.75microsec
02EC C3DF02     JMP D1_2
02EF 16D8     D3:MVI D,D8;=216 127.75*216+27*0.25=27600.75microsec
02F1 C3DF02     JMP D1_2

Z80ではDCR命令のクロック数が4であるのに、8080では5になっています。
8080は1クロック余計にかかっているのです。

しかし、そのことと、8080の命令クロック数をあてはめて計算した結果、D2の実行時間がオリジナルのモニタプログラムのリストに書かれている9.0176msecにならない、ということとは、別の問題です。
これは一体どういうことなのでしょうか?

●TK80はメモリアクセスに1ウェイトを加えていた

あらためて、TK80のユーザーズマニアルを読んでみて、そうだったのか!と合点がいきました。
昔はメモリのアクセスタイムが遅かったのです。
特にROMは遅かったことを、思い出しました。
CPUクロックが2MHzでも、ROMをアクセスするのには速すぎたので、TK80はメモリをアクセスする度に1クロックを追加していたのです。
すると、DCRは1バイト命令ですから、そのクロック数は5+1=6になりますが、MVIは2バイト命令なので(メモリを2回アクセスするので)、クロック数は7+2=9になり、JMPは3バイト命令なので、クロック数は10+3=13になります。

むむむ。
やっと読めてきました。
もう一度、計算のやり直しです。

02DD 1624     D1:MVI D,24;WAIT 1/2 BIT TIME 4.5112MSEC (9)
02DF 1E0C       MVI E,0C (9)
02E1 1D         DCR E    (6)
02E2 C2E102     JNZ $-1  (13)
02E5 15         DCR D    (6)
02E6 C2DF02     JNZ $-7  (13)
02E9 C9         RET      (13)
02EA 1648     D2:MVI D,48;WAIT 1 BIT TIME 9.0176MSEC (9)
02EC C3DF02     JMP D1+2 (13)
02EF 16D8     D3:MVI D,D8;WAIT 3 BIT TIME 27.0176MSEC (9)
02F1 C3DF02     JMP D1+2 (13)

02DF〜02E2の部分は、9+(6+13)×12=237になります。
D2から02E9のRETまでのトータルクロック数は、
9+13+(237+6+13)×72+13=18467です。
D2の実行時間は、18467×(1/2.048)=9017.1μsec!
おお!合いました。

ところで、上の計算の237+6+13は、256になります。ここに1/2.048を掛けると、256×(1/2.048)=125μsecになります(端数なし、ちょうどです)。
その昔、TK80の回路図をはじめて見たとき、なんでこんな半端な周波数を使っているのだろう、と疑問に思ったのですが、その後にこのクリスタル(18.432MHz)がRS232C回路で使われていることを知りました。
2のn乗を扱うバイナリ回路と相性がいい周波数だったのですねえ。

余談ですが、TK80のユーザーズマニアルによりますと、8080はREADY(23pin)とWAIT(24pin)を結線すると、メモリアクセス時に1ウェイト(1クロック)が追加される、のだそうです。
ということは、Z80を使って、実行時間の上でもTK80との互換性を維持するのは、事実上無理、とまでは言いませんけれど、そこまでやるか、ということですから、CPUクロックについての互換性は、前回にも書きましたように、考慮しないことにしましょう、というのが正解のようです。

●ND80の回路図がでてきました

チャタリングタイマーの問題で、あれこれ調べようとして、昔の資料をあさっていましたら、なんととっくの昔に処分してしまったと思っていた、初代ND80の回路図(原本)が出てきました。
昔はCADなどありませんでしたから、方眼紙にエンピツで手書きをしています。
むむむ。
懐かしいですねえ。


消費電流を押さえるために、速度が気にならない部分にはCMOSゲートを使っています。
ROMは1KBの2708、RAMは1K×4ビットの2114を使っています。
メカニカルキーが高かったので(今でも結構高いですけれど)、メカニカルキーの代わりにCMOSゲートを利用したタッチキー回路になっています。
右上にはトランスとブリッジ整流回路、3端子による整流回路も見えます。
当時高かったマルチ電源も基板上に乗せてしまいました。

スキャナにかけようとしましたら、裏に日付が書いてありました。

昭和54年ですから、え…と、1979年ですねえ。
おお、31年前です。

CPU部分を拡大してみました。
うう。こちらもちゃんと、READYとWAITが結線してありました。



2010.3.9upload

前へ
次へ
ホームページトップへ戻る