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

復活!CP/M ワンボードマイコンでCP/Mを!
CP/MがTK−80互換のワンボードマイコンの上で復活します
ND80ZVとMYCPU80の上でCP/Mが走ります

[第290回]


●まだ誤動作のタネは残っています

何回かにわたって長々と説明をしてきました、Z80で追加された命令が原因で発生する誤動作につきましては、前回の回路にて見事にクリアできたのでありますが。
まだ誤動作のタネは残っておりました。

今回はZ80に起因する誤動作ではありません。
もともとのIMSAI8080でも発生したはずの誤動作についてです。
あ。
私はIMSAI8080をさわったことはありませんから、もちろんそれは単なる推測です。
しかしIMSAI8080の回路図を見る限り、そしてその回路動作を基本的にそのまま踏襲しておりますE−80(仮称)ミニコンの試作回路での実証によりまして、IMSAI8080でもおそらく同じ誤動作が発生したであろうことは、ほとんど確実と言ってもよいと思っています。

どういうことかといいますと。
すでに何回も説明しておりますように、E−80(仮称)ミニコンのフロントパネルのREAD(アドレスセット&リード)やREAD NEXT(アドレスインクリメント&リード)の操作は、WAIT信号によってCPUを一時停止させておいて、データバスにJP命令コード(C3H)またはNOP命令コード(00H)を強制的に挿入して、それを実行させることで実現しています。
そのためにはWAIT信号でCPUを停止させるときに必ずM1(OPコードフェッチサイクル)で停止させておく必要があります。
さらにZ80ではそれでも十分ではなくて、2バイトの命令コードの場合には1番目のOPコードフェッチサイクルで停止させなければなりません。

前回までの回路において、そのように対策したはずなのでありますが。
まだ、M1サイクル以外で停止して、そこでREAD、READ NEXTなどのスイッチ操作が行われてしまう場合があるのです。
それは、STEP操作の後で発生します。

●STEP操作の後で発生する誤動作

STEP操作につきましては[第284回]で説明をいたしました。
そのときの回路図を再掲いたします。


STEP回路もREAD、READ NEXTなどの回路と同じように、STOPスイッチの入力後に操作可能になります。
当然そのときはM1(OPコードフェッチサイクル)でCPUが停止しているのですが。
しかし、STEP回路は一旦動作すると、M1サイクル(OPコードフェッチサイクル)とは無関係に機能します。

回路図を見ていただきますと分かりますように、STEP回路はMREQやM1に束縛されない形で独立してWAIT信号をコントロールしています。
STEP回路のWAIT信号の出力タイミングはRD信号とWR信号によって決められています。
STEPスイッチを押すとWAIT信号が解除されて、その結果待たされていたマシンサイクルが実行されます。
マシンサイクルが完了すると必ずRDもWRもアクティブでない期間が現れます(マシンサイクルとマシンサイクルの間にはRDもWRもない期間が存在します)。
すると再びWAIT信号がアクティブになって、CPUは次のマシンサイクルで停止します。

上の説明ではマシンサイクルを強調するために文字を着色して示しました。
STEP動作ではCPUはマシンサイクルごとに停止します。
具体的な例としてアドレス0123にD3、アドレス0124にFFという命令コードが書いてあって、それをSTEPスイッチによって1ステップずつ動作させてみる場合を考えてみます。

D3FF は OUT (FF),A のマシン語コードです。
最初にアドレスLEDに0123が表示されていて、データLEDにD3が表示されているところから操作を開始します。
これはSTOPスイッチを押してCPUを停止させ、パネルスイッチを0123にセットして、READスイッチによって、その状態にしたあとと考えてください。
当然このときにはMEMRDとM1を示すLEDが点灯しています。
CPUがM1(OPコードフェッチサイクル)であることを示しています。

ここでSTEPスイッチを押すと、アドレスLEDは0124になり、データLEDはFFになります。
MEMRDを示すLEDは点灯したままですが、M1を示すLEDは消灯します。
CPUはメモリからデータ(この場合はI/Oアドレス値)を読むマシンサイクルであることを示しています。

ここでもう一度STEPスイッチを押すと、アドレスLEDの下位8ビットにはFFが表示され、データLEDにはAレジスタの値が表示されます。
このときIOWRを示すLEDが点灯します。
I/Oアドレスにデータを出力するI/O WRITEマシンサイクルであることを示しています。

さてこの状態のときに、READスイッチを操作して、新しいメモリアドレスを設定しようとしたら、どのようなことがおきるでしょうか?
READスイッチを押すと、データバスにはJP命令のコード C3 が強制的に挿入されます。
しかしそのときCPUはI/OアドレスFFにデータを出力するマシンサイクルで停止していたはずです。
その結果、データバスはCPUから出力されるAレジスタの値とREAD回路から出力されたC3Hがぶつかった状態となり、その値がI/OアドレスFFに出力され、続いてパネルスイッチの下位8ビットと上位8ビットがその順番でCPUに読み込まれ、命令コードとして解読されて実行されてしまいます。
この場合、READ回路によってデータバスに挿入されたC3Hは命令コードとしてではなくて、I/O出力データとして処理されてしまいます。

これより1つ前のステップ、CPUがI/OアドレスFFを読んでいるときのマシンサイクルでREADスイッチを押したときも同様のことが起こります。
その場合には、READ回路によってデータバスに挿入されたC3Hは命令コードとしてではなくて、I/OアドレスとしてCPUに読み込まれます。
いずれの場合でもC3HはJP命令として解読されないために、期待されるREADの動作にはなりません。

そのもう1つ前のステップ、CPUがD3Hを読み込んでいるとき、つまりM1(OPコードフェッチサイクル)で停止しているときにREADスイッチを押せば、期待した通りのREADの動作になります。
また OUT (FF),A の次のステップに進んで、次の命令のM1(OPコードフェッチサイクル)になったときにREADスイッチを押した場合にも、期待した通りにREADの動作が行われます。

今までに説明をしてきましたような誤動作を避けるために、STOP回路は第一OPコードフェッチサイクル以外では停止しない仕組みにしたのですが、STEP回路はその仕組みの外で動作するために、OPコードフェッチサイクル以外のマシンサイクルで停止することも出来、そのときにREAD、READ NEXTなどの操作を行えば、依然として誤動作してしまうことになるのです。

最初に書きましたように、このことはZ80の問題ではなくてCPUが8080であっても、全く同じことになったはずです。
IMSAI8080でも同じことが起きたはずなのですが、それについてはどのように対処されていたのでしょうか?
IMSAI8080のUSER MANUALをざっと読んでみた限りでは、そのことに関しての注意書きなどは無いようでした(私の読み方が悪いのかもしれません。どこかに書いてあるのかも)。
ただ一般的なプログラムの書き込みやメモリ読み出し(もっぱら書き込みが正しく行なわれたかを確認するためとして説明されています)はアドレス0000Hから、となっていて、その場合にはRESETしてから始める、というように説明されています。
すでに説明をしておりますように、READ、READ NEXTなどの操作に先立ってRESETするようにすれば、今まで説明をしてきましたような誤動作は発生しません。

しかし本当にいつもRESETしてから、そのような操作が行なわれるのでしょうか?
たとえば。
入力したプログラムが期待した通りに動作しなかった場合には、STEP操作によって1ステップずつ実行しながら、どこで動作が食い違っているのか、などを確認することになります(実際にSTEP機能はそのためにあります)。
あるところまでSTEPを進めてきた結果、どこを直せばよいかがわかったとします。
すると、CPUが今どのマシンサイクルで停止しているのかということは考慮されることなく、いきなり書き換えるべきアドレスをパネルスイッチに設定し、READスイッチでそのメモリアドレスを呼び出し、続いてWRITEの操作をする…、というような操作が行なわれるのではないでしょうか。

ええ。
私の場合にはついそのように操作してしまい、
「あれ、アドレスが設定されない?」
で、やっと「ああ、そうか」と気づいて、そこでRESETしてから、READの操作を行なう、ということを何度も経験してしまいました。
これは、まあ、「慣れる」ということもありますから、RESETすることがクセになってしまえば、すべてOKよ、ということなのかもしれません。
どうもIMSAI8080の場合には、そのように慣れておしまいなさいよ、ということだったようであります。

しかし、すべてのユーザーがそのように慣れておしまいになるかどうかはなんとも保証の限りではありません。
私のように性懲りも無く何回もついそのように操作してしまうユーザー様もいらっしゃいますでありましょう。

問題はそのたびにデータバスで衝突が起きるということです。
今回のケースでは、STEP操作で、CPUが OUT (FF),A のI/O WRITEマシンサイクルで停止しているときにREADまたはREAD NEXTの操作(WRITE、WRITE NEXTでも同じ)を行なうと、CPUから出力されたAレジスタの値と、回路から出力されたC3Hまたは00Hがデータバス上で衝突します。
I/O WRITE以外は衝突しないかといいますと、そういうことではありません。
[第286回]で説明しましたように、READ(アドレスセット&READ)の場合には、READ回路から出力されるパネルスイッチの値と、CPUがスタックに保存しようとして出力するアドレス値とが2サイクルにわたって衝突します。

その衝突している時間はCPUクロックに依存しますがクロック2MHzでもたかだか数マイクロ秒です。
しかしワーストのケースはCPUがFFHを出力しているときに、回路からNOP(00H)が出力されるときで、このときはCPUとHCMOSゲートの出力がD0〜D7の全ビットでショートします。
それはかなりこわいことなので、試して確かめてみようなどとはとてもとても思いもよらぬことです。

実際、たとえ数マイクロ秒とはいえ、これは相当にコワいです。
こんなことを繰り返しておりますと、そのうちにCPUかCMOSゲートのどちらかが、あるいはその両方が突然プッツンしてお亡くなりになってしまわれるかもしれません。
それを考えると怖くて夜もおちおち寝てなどおられませぬ。

そういうことになりますと、これはやっぱりなんとか対策しないことにはいきませぬでしょう。
本日は時間がなくなってしまいましたので、この続きは次回にすることにいたします。

ワンボードマイコンでCP/Mを![第290回]
2013.1.11upload

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