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

●HLT命令の説明の続きです

HLT命令はHalt(停止)命令なのですが、本当に止まってしまうのではなくて、なぜか意味も無くOPコードフェッチの部分だけを繰り返しながら、しっかり動いています。
PICなどのSLEEPとは少し考え方が違っているようです。

●なぜHLT命令なのに、動いているのでしょう?

私は8080の開発者ではないので、本当のところは、なぜだかわかりません。
だから、多分、こういうことなのではないか、という程度のことしか言えません。

何かのメッセージを出すなどして、入力を促すとか、ある操作を要求するためにスタンバイする、というような目的でしたら、HLT命令など必要はありません。
そういう目的でしたら、普通はIN命令と条件付JUMP命令を使います。

イベントドリブンのような使い方で、信号入力に即答したい場合には、INT信号による割り込みを使うことを考えますが、その場合でもHLT命令を実行させねばならない、などということはありません。
普通の命令の実行中でも、割り込み許可さえ出ていれば、割り込みは受け付けられます。

多分、HLT命令は、通常ではない、なにか別の目的のために用意されたのではないか、というように思えます。
たとえば、システムエラーなどのように、
なにか普通ではないことが発生しているぞ!
というような場合に、
なんであれ、いま実行中の処理を停止して、ひたすら緊急処理のための、割り込み入力を待つ、
という使い方のために用意されていたのではないでしょうか?

本当は、そういった場合でも、HLT〜割り込み処理、にしなければ、緊急処理ができないか、というとそんなことは無いと思いますし、要は考え方次第だと思います。
そんなことを言っていると、数多くあるマシン語命令の機能だって、全部必要か?というと、こんなもの無くったっていいのに、と思われる命令だってあるのですから、そうすると、あれもいらない、これも不要だ、などということになってしまいます。

Z80は、8080のマシン語命令コードをそのまま引き継いでいますから、Z80でもこのHLT命令は実行できます。
しかし、私はN88BASICに近い動作をする、オリジナルのBASICを作って、今も組み込み制御用に供給していますが、HLT命令は使っていません。使う必要はありませんでした。
ですから、これはまあ、使う方の好みの問題なのでしょうね。

HLT命令は、RESETと、INT(割り込み)入力によって、解除されます。

しかしもしも、HLT命令が文字通りの停止命令でフリーズしてしまうのでは、解除するにはリセットするしか方法はありません(これも回路の工夫で、なんとでもできるのですけれど)。
RESETは、問題の解決手段としては乱暴で、あくまで最後の手段です。
本来は、やはり割り込み処理によって、異常発生の原因を調べるなり記録するなり、といった処理が求められます。
ですから、HLT命令が、フリーズするのではなく、無意味なループ動作をくり返しながら割り込み入力を待つ、というようになっているのは、妥当なことだと思えます。

そうは言っても、ユーザーレベルでは、異常発生に対する対応などできようはずはないので、たいていは、リセットするか電源を落としてから、また再度電源投入するしかない、場合がほとんどだと思いますけれど。
「例外処理が発生しました」とか「ページ違反です」なんて言われたって、どうしようもありませんものね。

●MOV命令とHLT命令の競合

MOV命令の回路の説明のところで、HLT命令のマシン語コードが、01110110なので、ddd=110、sss=110になることから、MOV M,Mの動作になってしまうはずなのに、それを回避する回路がMOV命令の回路にはみあたらないのは、HLT命令の回路で対策してあるからだ、という意味の説明をしました。
どういうことかというと、MOV命令の実際の動作は、OPコードフェッチサイクルが終わったあとの、T4サイクルから開始されるので、HLT命令は、それよりも前にMclrをかけてしまうから、大丈夫なのだ、というつもりだったのです。

それが、大丈夫ではなかったのです。
実は、MOV回路のところで、MEMWRのタイミングを当初は、T5+T6にしていたのを改良し、regWRと同じ、T4に変更したところ、誤動作するようになってしまったのです。
マシンクロックごとのステップ動作ならば、正しく動作しているのに、通常の4MHz動作にすると、HLT命令でも止まってくれなくて、暴走するようになってしまいました。
どうも、HLTがおかしい。
なんだかへんなデータをメモリに書き込んでくれてしまうようだ。
ということは、出てはいけないはずの、MEMWRが出てしまっている、としか考えられません。

こういうときは、オシロの出番です。
ソニーテクトロの高ーいヤツだったんですけれど、さすがに今は年代物になってしまいました。
うまくストレージで、とらえてくれればよいのですけれど…。


100MHzのオシロなのですけれど、ストレージモードは、このレンジが精一杯のところです。
点にしか見えませんが、T3からT4へのタイミングで、しっかり、パルスが出てしまっているようです。
上はMEMWR、下は74HC161のQb出力です。

HLT命令の回路は、T4でMclrを出力します。
マシンクロックを出力しているバイナリカウンタ74HC161は、MclrによってリセットされてただちにT0に戻るのですが、わずかな遅れによって、多分数十nsecの間、T4が出てしまいます([第53回]●HLT命令のタイミングチャートです)。
そうすると、op7とop6が01でMOV回路が選択されて、ddd=110なので、わずかなT4の期間ですが、MEMWRがアクティブになってしまいます。

いまどきのメモリは高速なので、数十nsecのWRパルスでも、データを書きかえるのには十分です。
当初はMOV命令の、MEMWR信号の出力タイミングはT5になってからだったので問題は無かったのですが、regWRと同じタイミング(T4)にしてしまったので、こんなところでトラブルが発生するようになってしまいました。
さりとてもうもとには戻れないし…。ということで、HLT命令のMclrをT3で出力するように変更したのですが…。

なんとなく気持ちが落ち着かないのですねー。
他の命令は、全部偶数クロックで終了するのに、HLTだけ奇数クロックだなんて…。
べつにそれでいけないことは無いのですけれど、なんとなく嫌な感じです。
それで、HLT命令の説明を始めるにあたって、どうにも気持ちが悪いので、またもとのT4でMclrを出力するように戻してしまいました。

それじゃあ、また、MEMWRが出てしまうじゃあないの?
そうなんです。
そこで、結局、HLT命令のときには、MOV命令回路が働かないように、ANDゲートを追加いたしました。

●ANDを追加した、MOV命令の回路図です



追加したANDゲート74HC08(3)のpin10に入っているHLTAは、HLT命令が実行されていることを外部に知らせる信号で、T2サイクルで出されます(負論理、アクティブL)。
HLTAは、RSフリップフロップからの出力信号です([第53回]HLT命令の回路図です)。
T2でアクティブになると、それ以後はHLTが解除されるまで(resetかINTが入力されるまで)ずっと出っ放しになります。
MEMWRをアクティブにする、regWRは、T4にならないと出力されませんから、これでHLT命令の実行時にわずかに発生していたT4期間のMEMWR出力は完全に押さえられました。

●ついうっかりしてしまった、74HC126の回路

前回、プログラムカウンタの回路図(カウントアップを禁止している部分の回路)の説明をしたときに、 近くに空いているオープンコレクタゲートがなかったので、たまたま近くで空いていた74HC126を代わりに使ったが、それがあとでトラブルの原因になってしまった、と書きました。
もう一度、その部分の回路図をお見せします。



最初は74HC126の出力についているダイオードは、つけてありませんでした。
HLTのときにはPCCKDE2はLになる([第53回]HLT命令の回路図です)ので、74HC126はハイインピーダンスになります。
だから、OR回路は成立する。
って、これは、とんだ勘違いでした。

どうもプログラムカウンタの動きがおかしい。
オシロであちこち調べていたら、PCclkが浮き上がっている。2Vくらい。
こういうときは、間違い無く、出力がショートしています。

やっと、間違いに気がつきました。
74HC126はオープンコレクタじゃなかった。3ステートバッファでした。
pin13がLのときはオープンコレクタゲートと同じようにハイインピーダンスになるものだから、ついうっかり勘違いしてしまいました。
図のように、ダイオードを入れて、やっと、一件落着、になりました。
2008.9.1upload

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