CPU実験室

誰も見向きもしない古いCPUをいじって動かしてみようというプロジェクトです

修復計画

見れば明らかなんですがROM(U16)に接続されるデータバスがD16~D23になるべきところがD22をすっ飛ばしてD23、D24になっちゃってるわけです。D24は本来つながるべきU17にも行っているので接続先が重複してしまってます。番号のカウントを先走ったか「時そば」現象か。

ボード図面でD24のラインをハイライト表示させると明白です

これをどう修復するか・・D24は正しい接続先ROM(U17)とSRAM(U4)にも接続していますが、悪いことに誤った接続先であるROM(U16)を経由しています。そのためU16に行くラインを赤丸の2か所で切断しU16をいったん孤立させてから新たにD22を導入、寸断されたD24を再建する、という手順になります

 

ヤバそうなのがU16U17を渡っているライン。基板表側を通っています

 

ラインは偶然1本独立して走っているので助かりました。これがもしすぐ上のようにピン間2本のギャップで並走していたり、そもそもPLCCソケットを密に配置していたらライン自体にアクセスできず万事休すでした。

 

メモリチェック

トランスピュータボードはパタンミスが発覚してショック大なので少し冷却期間おきます。その間に海外通販で入手したあやしいSRAMの動作確認をしてみました。

以前作成したMCS51-Rev0ボードは256kbitSRAMのスキニータイプを使うのでこれを差し替えてみます。いままでオーバースペックのHM62832UHLP-15を使っていたので差し替えで一応シルクの表記と合致しました

MCS51-Rev0ボードでは256kbitSRAMがコード空間データ空間共用の0x8000-0xFFFF領域にマップされます。メモリ交換後もモニタが起動してラージモデルのテストプログラムが動作したのでおそらくこの領域のRAMは機能しているようです。

ですが念のためSRAMの全領域をチェックしてみました。

ところで効率的なメモリチェックはどのようにやればよいでしょうか。一般的には1アドレスごとにチェッカフラグ(0x55/0xAA)やインクリメントデータを書込み、読出し、ベリファイなんでしょうがこれはビット抜けは検知できますがアドレス抜けは見逃す可能性があります。(どのメモリセルに書いて読んでるかわからないので)あやしいメモリが容量詐称してるかもしれません

そこでSRAMの全領域(0x8000-0x8FFFはプログラム自身のために確保して実際は0x9000-0xFFFFの28kbyte)に長周期の疑似乱数を書き込み、埋まってから読出しベリファイするチェックプログラムを走らせました。組込関数rand()srand()で同じrandom seedを与えれば全く同じ乱数列を発生するのでこの方法が使えます。

周期性、一様性については最初メルセンヌツイスターの生成ルーチンを入れてみたのですが結構ワークエリアを消費するので標準ライブラリ関数に差し替えました

 

random seedを変えたりして連続して動作させていますがエラーは全く発生しません。CPUはi8031のクロック12MHzなので結構速い方ですし件のSRAMは真贋はともかく動作は問題なさそうです

 

接続ミス発見

ここのところまで、起きている現象がNS32032のトラブルとそっくりです。ソフトウェアはこれ以上単純にできず間違えようがない。となるとなにか物理的に配線ミスしてるとしか思えません。

先ずはROMの制御線まわりを検図・・テレコとかはなさそうです。

次にアドレスバス、データバスがROMとRAMで相互につながっているかテスタで一本一本導通を確認したのですがデータバスの途中からどうも順番がおかしい・・

 

対応する回路図を見てみたら

 

やっぱりやらかしてました!

 

ROM入れ替え

最小ループとして得られたコード「600E」の意味を考えてみます。ぱっと見これは16ビット固定長命令にも見えますが、トランスピュータの命令体系は8ビット固定長であって実は2個の命令の組合せであることがわかります

code       mnemonic     function                 operation                           Oreg value

----------------------------------------------------------------------------------------------

0x60 :  nfix #0     ; negative prefix Oreg←BITNOT(#0)<<4;          #FFFFFFF0

0x0E :  J   #E   ; jump             Oreg←Oreg+#E; jump Oreg;  #FFFFFFFE

 

ということはnfix命令(0x60)に方が先に実行、つまりは低位のアドレスになければならないわけで、左から3番目と4番目のROMを入れ替えて挿入しました。

いやまさにこれが原因に間違いないでしょう、考えるほど確信に変わってきて勇んで電源ON!

 

・・ダメでした

バス不安定の状況変わらず、わけのわからない暴走状態です

次の手を探るしかありません

 

 

制御信号波形

最小ループはROM内の2アドレスをグルグル回るはずなのでボード上のいくつかの信号をプローブしてみてるのですがどうも制御信号の波形が安定しません。

 ch1:アドレスラッチ信号ALE(=/S0)

 ch2:ROMの/CS(=/ROMCS)

 ch3:ROMの/OE(=/MemRd)

ALEが一定間隔で出力され、メモリからのリードも行われているようですが/ROMCSはHのままでROMがセレクトされていません。ROMとは全然違うアドレスをフェッチしているようです。

不思議なのは電源をOFF/ONしたりリセットボタンを押すたびに異なる波形が観測されることです。以下は同じようにROM以外の部分を連続アクセスしていますが何故か周期が1.5倍くらいになってます

 

こんなふうに不規則なアクセスが繰り返されることもあります

 

これらはソケットにROMを挿さないで電源ONしたときと似た挙動です。つまりROM上のリセットベクタにある「j $」が全くフェッチできずにROM領域を飛び出しメモリが実装されていない領域で不定のコードを実行しつづけてるということになります

 

 

 

最小ループ

いよいよトランスピュータ上で動作するプログラムを作成してみます。いつものようにコードは一番簡単な最小ループ「j $」、リセットベクタはメモリ空間の最後の2バイトを指すので開始番地を0x7FFFFFFEにしてアセンブルします

 

アセンブルは瞬時に終わって実行可能コード”600E”が得られました。

さてこの2バイトのコードを32bitデータバスにどのように配置すればよいのでしょうか。マニュアルをみるとトランスピュータはIntel80x86と同じリトルエンディアンであるとあります

ボード上にある4個のROMソケットは左からD0-D7、D8-D15、D16-D23、D24-D31のデータバスに接続されています。リトルエンディアンならばLSBが低アドレス、すなわちソケットの最終番地は左から0x7FFFFFFC,0x7FFFFFFD,0x7FFFFFFE,0x7FFFFFFFになります

一方、最終番地に0xFF,0xFF,0x60,0x0Eの1バイトをそれぞれ書いた4個のROMを用意しました。”600E”が16ビット定数であればROMの差し込みは以下のようになります

 

これでお膳立てがすべて整ったので電源ON・・・・

 

 

 

アドレスデコーダ

とりあえずデータバス、アドレスバスはパタパタ動いているのでCPUは何かしら動作しようとしているのは判りますが外部メモリがつながっていないので、浮いているデータバスから不定のコードをフェッチしてしまい、どこにジャンプして何をしてるのかが全く分かりません。

しかもコードが確定しないので電源入り切り、リセットのたびにバスの挙動が全然違うので困ります。少なくともROMを接続できるようにはしておかなければなりません。アドレスデコーダCPLDに組み込みました。

CPLDに引き込んであるアドレスバスは最上位8ビットA24~A31のみ。これはデータとのマルチプレクスバスなのでALE信号でラッチした後、デコードしてチップセレクトを生成します。

ここではROMは7FXXXXXX、I/Oは08XXXXXX、RAMは00XXXXXXに配置しました。

コインパイル後のVHDLソース

これをRTL VIEWERで逆変換するとこんな感じです