16ビットマイコンボードの製作
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
いつか使ってみるつもりで入手してそのまま置いてあった16ビットCPUのことを思い出しました。
AMD社のAM188です。
その名の通り、CPUコアは80188互換の16ビットCPUです。
そのAM188を使った16ビットマイコンボードの製作記事です。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第54回]
●AM188EMのCLOCK(4)
前回からの続きです。
カメレオンロジアナは「TTLでCPUをつくろう」[第374回]で紹介いたしました。
なかなかに便利な優れものです。
右下に見えるのがカメレオンロジアナです。
前回までのテストで、どうもAM188の命令とクロックの間になにやら不適切な関係がありそうな疑いが濃厚になってきました。
そこでカメレオンロジアナでチェックし易いように、うんとシンプルなプログラムを実行させてみることにしました。
下がそのリストです。
2018/7/11 7:226 86cktst8.LST [00001] ;;; clock test for am188 [00002] ; [00003] ORG=8000 [00004] ; [00005] 8000 FEC0 LOOP:INC AL;3 [00006] 8002 EBFC90 JMP LOOP;14 <8000> [00007] ; [00008] ;END LOOP =8000 |
もうこれ以上簡単なプログラムは無い、というくらいシンプルなプログラムです。
なおJMP LOOPのマシン語コードは
EBFC90
になっていますが、これは自作8086アセンブラの手抜きで、
JMP LOOPのマシン語コードは
EBFC
です。
そのうしろの90はNOPです。
アセンブラの都合でこういうマシン語になりますが、実用上問題はありません。
このプログラムを実行して、それをカメレオンロジアナで観測しました。
画面では一部が隠れていますがPROBE00〜07がデータバスD0〜D7、PROBE08〜15がアドレスバスA0〜A7です。
PROBE16がCLKOUTA(10MHzクロック)、PROBE17はRAMRDです。
ちょうど600nsの近辺でアドレス8000の読み込みが行なわれています。
そのあと800ns(8001)、1000ns(8002)、1200ns(8003)、1400ns(8004)とRAMからの読み込みが行なわれ、少し間が空いて1700ns近辺で再び8000の読み込みに戻っています。
一巡するのに1100nsかかっています。
ところでこのループは上のリストに記載したクロック数で計算すると17クロックですから、17×0.05=0.85μs(850ns)のはずです。
おかしいじゃありませんか。
250nsもオーバーしています。
どこかがおかしい?
?????
!
あっ!
そういうことか!
なんてこったい。
この何日間もの間、貴重な時間を費やして、それがこんなことだったとは。
ううむ。
なんと愚かなことを。
もっと早く気が付くべきでありました。
やっぱりZ80や8080の頭でつい考えてしまっていました。
8086は16ビットである以上に、8080やZ80とはそのアーキテクチャが全く異なっていたのでした。
Z80や8080は命令をメモリから読み込んでそれを解読し実行し、そしてまた次の命令をメモリから読み込んで、という流れで処理を進めます。
当然命令にかかる実行時間はメモリから読み込む時間とそれを解読して実行する時間の合計です。
ところが8086は(当然AM188も)そこのところが全く異なっていたのでした。
8086は命令をメモリから読み込む部分と、命令を解読して実行する部分を分離して独立させました。
メモリから読み込む機構は、命令の実行とは関係なく(実際は無関係にはできないのですが)メモリから命令をアドレス順に読み込んでバッファに蓄えていきます。
それを実行する機構はバッファから順次命令を読み出して解読し実行していきます。
AM188のデータシートにあった命令の実行クロック数は、この内部的に解読し実行するのにかかるクロック数で、それと「無関係に」並行して行なわれるメモリからの読み込み時間は、命令の実行クロック数には含まれていなかったのでした。
それで疑問が解けました。
AM188がメモリからコードを読み取るのには4クロックかかります。
前回のメモリREADのWaveformを参照してください。
ところが上のリストにありますようにINC ALのクロック数は3クロックです。
メモリから1バイトを読むのに4クロックかかるのに、実行時間が3クロックというのはおかしいじゃありませんか。
それはメモリから読み込むのにかかる時間を除外した内部だけの実行クロック数だったのでした。
そういうことだったのです。
仮にスタートした直後でバッファには何もまだ読み込まれていないとすると、CPUは結局バッファに命令が読み込まれるまで待っているしかありません。
そして4クロック後にやっとINC ALが読み込まれて、それをCPUが3クロックで実行してしまったとしても、またバッファは空ですから、やっぱりもう1クロックは待つしかありません。
そこに計算よりも余計にかかるクロック数の存在が認められます。
そしてJMP命令とかCALL命令にはもうひとつ困難な問題があります。
それが上のロジアナのチャートに表われています。
8ビットの概念でメモリから読み込まれるときのアドレスを追跡すると、下のようになります。
8000→8001→8002→8003→8000
ところが上のロジアナのチャートでは
8000→8001→8002→8003→8004→8000
のようになっていました。
AM188CPUの内部の実行の様子は見ることはできません。
ロジアナのチャートからわかるのは、メモリから読み込む機構の読み込み動作だけです。
アドレス8004は本来は読み込む必要はないものなのですが、メモリからの読み込みは命令の解読実行とは一応無関係に行なわれるので、読み込まれてしまいます。
その直後にJMP命令が解読実行され、そこで8000番地の命令を読め、というコマンドが内部的に出されて、すると読み込まれていたバッファの内容はそこで破棄されて、新たに8000から読み直すという動作が行なわれます。
おそらくこの間のロスタイムが上の計算で出てきた、余分にかかった250ns(5クロック)だったと考えられます。
このような流れの変更によるバッファのクリアおよび別のアドレスからの再読み込みはJMP命令だけではなくて、JNZなどの条件ジャンプ命令やCAL、RETでも発生するはずです。
また流れは変わりませんが、メモリへのデータの書き出しや、IN、OUT命令の実行の間、メモリからの連続読み込みは一時中断されます。
ここまで書いてきて、突然ですが、もうひとつ疑問に思ってきたことの意味がわかりました。
データシートに記載されている命令の実行クロックが8086と8088で同じになっている命令が多くあるのはなぜか、という疑問です。
8086のデータバス幅は16ビットですからメモリから一度に2バイトを読み込みます。
8088のデータバス幅は8ビットですから一度に1バイトしか読めません。
それならその分だけ8088は8086よりも実行クロック数が余計にかかるはずではないか?
という疑問だったのですが、おそらく8086と8088のCPUコアは同じはずで、だから内部の命令解読実行クロック数は8086と8088で同じであっても何の不思議もなかったのでした。
当然メモリから命令データを読み込むのにかかる時間は、8088は8086の倍を要します。
命令の実行クロック数に関係なく8088は8086よりも実行時間は遅くなるはずです。
さてそういうことになると。
そもそもことの発端でありました、DS1307との通信のために必要な5μsのウェイトタイマーは作れないじゃないか、というお話になります。
その通りです。
8080やZ80ならばクリスタル発振の精度に合う程度の正確さでソフトウェアによる遅延タイマーを実現することができます。
しかし8086では、今まで説明してきました理由から、おそらくそのような正確なソフトウェアタイマーを作ることはできません。
5μsが7μsになってしまう程度のアバウトさは認容するしかありませんでしょう。
16ビットCPUがそんないい加減なことでよいのか?
然り。
そこは8ビットの頭を16ビット対応に切り換えるべきでありましょう。
おそらく16ビットの世界では正確なタイマーは外部ペリフェラルに求めるべき、というのが常識なのではありますまいか。
16ビットマイコンボードの製作[第54回]
2018.7.12upload
前へ
次へ
ホームページトップへ戻る