自作CPU #14 スタックが動いた!


前回の記事でかいた通り、自作CPUでスタックへPUSH命令が実行できませんでした。

そこでロジックアナライザーを使って解析したら原因が判明しました。

波形

f:id:Hamakita:20180117143712j:plain

CLK:クロック

SPC:SPへのクロック

WE:スタックを構成するRAMへの書き込みパルス

SP-D/U:SPのカウント方向を制御

AD0:PCの最下位ビット

00番地にpush命令、01番地に00番地へジャンプという命令を書き込みクロック1MHzでテストしてみました。AD0はプログラムカウンタの最下位ビットです。クロックの立ち上がりでアドレスが切り替わりメモリから読み出し、制御バスの値が切り替わるのですが、そのうちの一つで今回の命令で関係あるのがsp-D/Uです。これはスタックポインタのカウント方向を制御するビットで0の時カウントアップ、1の時カウントダウンとなります。

PUSH命令はカウントダウンする必要があるので00番地の命令が読み出されると1になるはずです。

普通クロックの立ち上がりで命令をロードした後、次のクロックの立ち上がりの時に実行完了するのですが、つまり00番地がカウント命令なら次の01番地の命令をリードするクロックの立ち上がりでカウントする。しかしPUSH命令のときは少し特殊でスタックポインタは常にデータが入っている先頭をさしますので次のクロックの立ち上がりまでに

SPの値を-1

スタックを構成するRAMへデータ書き込み

を行う必要がありました。そこで

命令が読み出されるクロックの立ち上がりをトリガーにしてマルチバイブレータでパルスを生成、その後クロックの立下りをトリガーにしてRAMへの書き込みパルスを生成

という仕組みをつくりました。

しかしサンプリングされた波形をみてみると

00番地の命令をロードした後、SPCにマルチバイブレータにより 生成されるべきクロックが確認できません。これの原因は明白でSP-D/Uのロードに時間がかかっているせいです。SPCはマルチプレクサを通して、クロックとマルチバイブレータとで切り替えています。この切り替えもSP-D/Uが行っているので、ロードに時間がかかるとSPCにパルスが出てこなかったのだろうと思います。

そこでクロックの立ち上がりをトリガーにするのではなくSP-D/Uをトリガーにするように変更してみました。SP-D/Uが立ち上がるのはPUSH命令の時だけで他の命令では常に0ですので期待通りの動作が実現できると思います。

パターンを切ってつなぎ変えました。

 

f:id:Hamakita:20180118013625j:plain

修正後動作確認しましたら無事PUSH命令を実行できました。

修正後の波形 SPCに短いパルスが確認できる

f:id:Hamakita:20180118013158j:plain

スタックは今回のCPU作りで最も気合をいれて設計したうちの一つなので無事動かせて一安心です。