8080マイコンをつくろう!(TK−80完全復活!)
なんと8080です!
もちろん、BASICからCP/Mまで、できます!
36年の時を経ていまよみがえる8080CPUマイコン組立キット!
なんたってはるか昔の生産中止品を集めて作る組立キットです。
生産前から堂々予告です。
入手できなくなったら即生産終了!売り切れ御免!
[第12回]
●TK−80は遅かった!
ND8080のシステムROMにはTK−80モニタプログラムのほかにND80ZモニタとZB3BASICシステムが含まれています。
TK−80モニタ以外の部分はND80Z3.5(ND80ZV)のシステムプログラムがもとになっています。
ND80Z3.5(ND80ZV)のCPUはZ80ですから、そのシステムプログラムもZ80のためのプログラムとして作成したものです。
その中には8080にはない命令やレジスタを使ったものがかなり含まれていますから、もとのプログラムを8080で実行できるように書き直して、ND8080用のシステムプログラムを作成しました。
もっともそのかなりの部分はMYCPU80用に作成したプログラムを流用しています。
そのあたりのところがかなりややこしいことになっていて、最後の詰めのところで苦戦しています。
なにしろプログラムによってはND80Z3.5用とMYCPU80用が入り混じってしまっていて整理するのも一苦労です。
そんな作業をしているなかでちょっと気になったことがありました。
それはTK−80モニタプログラムの中で使われているチャタリングタイマーです。
これは命令の実行クロックを利用して、指定した回数を繰り返し実行することで、目的のタイマーを作り出しているものです。
とうぜんCPUクロックに依存します。
またZ80と8080では同じ命令でもクロック数が異なるものもあります。
ND80Z3.5(ND80ZV)はTK−80互換ということで、TK−80と同じモニタプログラムを実装しているのですが、TK−80のCPUクロックは約2MHzだったのに対してND80Z3.5(ND80ZV)は6MHzですから、同じプログラムのままではチャタリングタイマーとしては時間が短すぎます。
そこでND80Z3.5(ND80ZV)ではそこの部分だけを補正してあります。
今回のND8080はTK−80と同じ18.432MHzのクリスタルを実装していて、それを8224で1/9分周して2.048MHzをCPUクロックにしています。
そこまでしなくても18MHzのクリスタルを使えばちょうど2MHzのCPUクロックになってそのほうがよいとも思ったのですが、ここはやっぱりオリジナルに敬意を表して同じ18.432MHzクリスタルを使いました。
そういうことなのでチャタリングタイマーについてはTK−80のモニタプログラムを手直ししなくても全く同しタイマーになるはずだったのですが。
念のために命令のクロック数をもとにしてプログラムの実行時間を計算してみたところ、意外な結果になってしまいました。
下はND80Z3.5(ND80ZV)のTK−80モニタプログラムのチャタリングタイマーです。
; ;CHATTERING TIMER ; ORG $02DD 02DD 1624 D1:MVI D,24;=36 ck=7 124.83*36+(7+10)/6=4496.71microsec 02DF 1E34 D1_2:MVI E,34;=52 ck=7 7+14*52+14=749 749/6=124.83microsec 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 124.83*72+(7+10+10)/6=8992.26microsec 02EC C3DF02 JMP D1_2 02EF 16D8 D3:MVI D,D8;=216 124.83*216+27/6=26967.78microsec 02F1 C3DF02 JMP D1_2 |
TK−80のチャタリングタイマーとだいたい同じ時間になるようにループ回数を調整してあります。
そしてこちらがND8080のモニタプログラムのチャタリングタイマーなのですが…。
; ;CHATTERING TIMER ; ;D1=4.5112ms ;D2=9.0176ms ;D3=27.0176ms ORG $02DD 02DD 1624 D1:MVI D,24;=36 ck=7 (7+202*36+10)/2.048=7289/2.048=3559.082microsec 02DF 1E0C D1_2:MVI E,0C;=12 ck=7 7+15*12+15=202 02E1 1D D1_3:DCR E; ck=5 02E2 C2E102 JNZ D1_3; ck=10 02E5 15 DCR D; ck=5 02E6 C2DF02 JNZ D1_2; ck=10 02E9 C9 RET; ck=10 02EA 1648 D2:MVI D,48;=72 (7+10+202*72+10)/2.048=14571/2.048=7114.746microsec 02EC C3DF02 JMP D1_2 02EF 16D8 D3:MVI D,D8;=216 (7+10+202*216+10)/2.048=43659/2.048=21317.871microsec 02F1 C3DF02 JMP D1_2 |
プログラムの先頭部分のコメント文のところに書いてあるのがTK−80のチャタリングタイマーの数値です。
そしてその下のプログラムはTK−80モニタプログラムとそっくりそのままの同じプログラムです。
各命令のクロック数はck=のところに記しました。
その横に繰り返し回数から算出した総クロック数を記して、それに1クロックあたりの時間(1/2.048μs)を掛けて実行時間を算出しています。
そうしましたら、そこにありますように、全然計算が合いません。
計算で求めた実行時間は本来のTK−80の実行時間よりも2割ほど短くなってしまいました。
そんなばかな。
計算間違いではないかと思いました。
あるいは命令のクロック数を間違えているのではないか、とも思いました。
しっかりと確かめてみましたけれど、どこにも間違いはありません。
まさかNECの技術者が計算間違いをするわけはなし…。
この計算結果に間違いはないとすると、TK−80は2MHzよりも遅いクロックで動いていたことになります。
ここでもういちど。
そんなばかな。
そこで、TK−80ユーザーマニュアルをしっかり読んでみましたら。
謎が解けました。
そういうことだったのか。
TK−80の時代にはROMもRAMも高価でしかもアクセスタイムも遅かったのです。
実際メモリによってはCPUクロックが2MHzでもアクセスタイムが遅くて間に合わないものもありました。
そこでTK−80はメモリをアクセスするときに1クロックのウェイトをかけていたのです。
下はND8080のCPU回路の一部です。
CPU回路の全体の回路図は[第7回]にあります。
8080のREADY端子は8224のREADYに接続してあります。
これが普通の配線です。
ところがTK−80の回路図を見ますと、READYとWAITが下のように接続されています。
このように接続すると、8080がメモリをアクセス(READ、WRITE)するときに1クロックが余分に挿入されて、遅いメモリでも間に合う設計になっています。
これでやっと謎が解けました。
そこでメモリアクセスのたびに1クロック余計にかかることを考慮して各命令のクロック数を補正したうえで、もう一度計算してみました。
; ;CHATTERING TIMER ; ;D1=4.5112ms ;D2=9.0176ms ;D3=27.0176ms ORG $02DD 02DD 1624 D1:MVI D,24;=36 ck=7+2 (9+256*36+13)/2.048=9238/2.048=4510.742microsec 02DF 1E0C D1_2:MVI E,0C;=12 ck=7+2 9+19*12+19=256 02E1 1D D1_3:DCR E; ck=5+1 02E2 C2E102 JNZ D1_3; ck=10+3 02E5 15 DCR D; ck=5+1 02E6 C2DF02 JNZ D1_2; ck=10+3 02E9 C9 RET; ck=10+3 02EA 1648 D2:MVI D,48;=72 (9+13+256*72+13)/2.048=18467/2.048=9017.09microsec 02EC C3DF02 JMP D1_2 02EF 16D8 D3:MVI D,D8;=216 (9+13+256*216+13)/2.048=55331/2.048=27017.09microsec 02F1 C3DF02 JMP D1_2 |
おお。
今度は計算が合いました。
あっと。
惜しい。
ほんの少しだけ違っています。
どのくらい違っているかと言いますと、
4511.2−4510.74=0.46μs
9017.6−9017.09=0.51μs
27017.6−27017.09=0.51μs
約0.5μsの差です。
これはCPUクロックの丸めによる誤差ではなさそうです。
約0.5μsといえばCPUクロックが2MHzのときの1クロックの時間です。
ということは上のプログラムの中で、繰り返さなくて1回しか実行されない命令のクロック数が、TK−80では本来のクロック数よりも1クロック多くなっている、と考えられます。
このプログラムの中で1回しか実行されない命令は…。
RETです。
RETは8080のdatasheetでは10クロック(ウェイトをかけたときは13クロック)です。
ただしRZなどの条件付リターンは11クロックになっています。
むむむむむ。
ひょっとすると、NECの技術者がRETのクロック数を間違えて11にしてしまったのか、それともNECはIntelの8080ではなくて、自社で開発したNECオリジナルの「8080」を作って使っていたらしいので、NEC製の8080ではRETが11クロックだったのか、そのどちらかのように思えます。
ともあれこれで疑問は解決しました。
そして、TK−80が本来の実行クロック(2MHz)よりも約2割ほど遅いクロックで動作していた、という意外なことがわかりました。
ND8080の実行速度がTK−80よりも2割も速いなんて、これではせっかくTK−80と同じ18.432MHzクリスタルを使った意味がないじゃありませんか。
そうかといって、TK−80と同じようにREADYとWAITを接続して、クロックを2割ほどダウンさせるっていうのは、いやいくらなんでも、それはないでしょうよ。
ここは素直にCPUクロックはウェイトをかけない2.048MHzのままでいくことにします。
チャタリングタイマーについてはND80Z3.5(ND80ZV)と同じようにTK−80のチャタリングタイマーと同じぐらいの値になるように調整することにします。
8080マイコンをつくろう![第12回]
2016.3.31upload
前へ
次へ
ホームページトップへ戻る