CPU実験室

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

シリアルコントローラ

今回、ボード上に実装したシリアルコントローラSCN2681(DUART)は初めて使う品番ですが、フィリップス社のマニュアルが見つかったのでざっと確認しておきます。

機能は非同期調歩型シリアルコントローラが2組、ボーレートジェネレータ、タイマ/カウンタ、割込みコントローラ、入力ポート7本、出力ポート8本が集積されています

シリアル部分はuPD7201TL16C550と似たようなものだろうし後でシリアル接続デバッグの時に見ればいいだろうとほっておいて先ずはLEDチカチカにつかう汎用ポートの使い方を調べていました

マニュアルを読み進めると、この汎用出力ポートはシリアルコントローラのステータス出力と兼用になっていて制御レジスタOPCRで機能切替するとあります。パラレルデータの実体はOPRレジスタにセットしてその内容をビット反転したものが出力されるとあります。8255みたいに初期化が必要なのはこれはまぁ想定内。

ところが内蔵レジスタマップを見てみると制御ワードを入れるOPCRレジスタはあるのですが、データ本体のOPRレジスタがどうしても見つからないのです

え、OPRが直接アクセスできない?どうやってパラレルデータをセットするのか・・と一瞬悩みましたがこれはアドレス0xEにあるSet Output Port Bits Command0xFにあるReset Output Port Bits Commandを使うようです。これらのワードで「1」になっているビットが選択的にセット/リセットされ「0」のビットは変化なし、前の状態を引き継ぐとなっています。つまり8255で云うところのビットモードのようなものです(しかもこちらは全ビット同時に実行できる)

たしかにビットごとに別々の制御をさせるときは他のビットに影響を与えることなくそのビットだけON/OFFしたいわけでこの方が合理的なわけです

ただしLEDチカチカのようにビットパタンをパラレルで同時出力する場合は「1」にするところと「0」にするところをそれぞれ明示的に2度指定してやらなければなりません。

たとえばポートに0x55を出力する場合はこうなります:

 

コーディング開始

I/Oも用意できたのでいよいよ意味のあるプログラムを書いてみますが、いくつか準備があります。

 

1.2段階ジャンプ

これはトランスピュータのアーキテクチャを調べ始めた時にも検討していましたがリセットベクタがメモリ空間の最上位-2:Bootstrap(0x7FFFFFFE)の位置にあって残り2バイトなので大ジャンプするコードが書けません。そこでいったん中継点:startvect(0x7FFFFFF0)に飛んでそこから改めてROMの先頭番地:MemStart(0x7FFC0000)へ飛ばすことになります

この一連の16バイトコード:

  ”63 20 20 20 0B 00 00 00 00 00 00 00 00 00 60 00”

はROMの最終16バイトに毎回必ずセットしてやることになります。80x86のメモリ空間最上位-16の位置に置くjump far segment,offset "EA xx xx xx xx"みたいなもんです

 

2.インストラクションセット

ここが一番のポイントなんですが・・JUMP以外のメモリアクセス系のインストラクションをマニュアルで調べてます

先ず基本的にトランスピュータは内蔵の汎用レジスタが32bit長のもので3本(Areg,Breg,Creg)あり、それらはAreg→Breg→Cregとスタック構造になっています

レジスタトップ(Areg)に定数を押し込むのがLDC(load constant)命令です

Aレジスタをポップして値をメモリ空間の任意の場所に書き込むストア命令STL(store local)がありますが

これは別途用意されているレジスタWorkspacePointer(Wptr)でインデックスされたレジスタ間接アドレッシングということでしょう

最初なんでここでは簡単にレジスタ直接アドレッシングでいきます。これにはSTNL(store non-local)命令が使えそうです

Bレジスタの値をAレジスタで示されるメモリアドレスに書き込む、という動作になります。すなわちあらかじめ書込み値、メモリアドレスの順でLDC命令でスタックにプッシュしておく必要があるということです

 

3.ビット入れ替え

これは完全にポカミスによる自己都合なんですが生成されたコードをROMに焼く際に32ビット幅コードのうちD23D22を入れ替えておく必要があります。アセンブラが出力したバイナリベタコードを4つの8ビット幅ROMに焼くためにコード分割するツールを作りそのうち3個目だけ変換関数をかましておきました

 

ところでこの変換の入出力をプロットするとこんな非線形関数になります。昔、電子楽器の音源がアナログからデジタルに移行するころ、低コスト(PCMはメモリをたくさん使うので)で倍音を豊かにするためにFM音源,PD音源,LA音源とか方式が色々出ましたが、単純にカウンタとD/Aコンバータの接続をスクランブルすればいいんじゃねと個人的に実験してみました(素直につなぐとのこぎり波になる)でもあまり楽音に使える結果にはならなかったような・・・

 

I/O拡張

ROMのアクセスがうまくいってるようなので次はLEDチカチカをやりたいところなんですが、ボード上のパラレルLEDは単純にデータバスをラッチしているのではなくシリアルコントローラ(DUART)SCN2681の汎用出力ポートに接続しています

そのためこれの周辺部品も一気に実装してしまいます

 

これでボード上の実装済部品は90%に達しました

 

マシンサイクル

ボード上のトランスピュータIMST805は入力クロックClockin=4.9152MHzの4倍のProcClockOut=19.6608MHzを内部生成して各種タイミング信号を発生させます。

マニュアルのメモリアクセス関連の説明を読んでみました。

まずProcClockOutの半周期ごとにマシンサイクルT1~T6に遷移しそれに同期してステータス出力/MemS0~/MemS4を発生します

これらのマシンステートT1~T6を何クロック分にするかは自由にプログラムできます。それによりステータス出力/MemS0~/MemS4の開始位置、幅も変えることができるのでこれらをメモリ制御信号(ALE、/CE、/CAS、/RAS、カラムとロウアドレスの切替え・・)に利用することで様々なメモリ(速度、SRAM/DRAM)を使うことができるとされています。

プログラムの方法はMemConfigピンをアドレスピンにつないでおくだけでリセット解除後の初期シーケンスでプリセットされたセッティングが読み込まれます

 

このボードではAD8AD9をジャンパポストで選択できるようにしてあります(Internal configuration)ちなみにVDDに接続するとデフォルト(AD31接続と同じ)となりマシンサイクルは最長、低速のROMも読めます。逆にGNDに接続するとプリセットに無い自由なユーザセッティングをROMの特定番地から読取ります(External configuration

このように結構高度なメモリコントローラが内蔵されているということです。アドレスラッチやデマルチプレクサだけは外付けで必要ですがタイミング生成のためのグルーロジックは全く要らないと言っていいでしょう

 

これを踏まえてもう一度最小ループ時の波形を見てみます

ch1:ProcClockOut、ch2:ALE(=/MemS0)、ch3:/MemRD(プローブのGND処理が適当だったので波形が暴れてますが)、1マシンサイクルTm=1/19.6608MHz/2=25.4nsとすると

まずAD9にジャンパした時:(7マシンサイクル×2命令)×Tm=356ns 

で周期=2.81MHz

 

AD8にジャンパした時:(6マシンサイクル×2命令)×Tm=305ns 

で周期=3.27MHz

たしかに計算通りです。最小マシンサイクルでも正常動作するようなのでジャンパピンはAD8接続で決まりです

動作クロック

CPUの動作クロック周波数についてちょっと勘違いしてました。外部から与えるクロックClockinはCPU内部で5逓倍されると思い込んでましたがデータシートをよく見てみるとこれはオーダー時の速度サフィックス指定によるものでIMST805-G25Sならば倍率PLLx5.0である、ということのようです

今回入手したものはIMST805-G20Sなんでカタログ落ちしてますが倍率PLLx4.0、内部動作20MHzということなんでしょう。

CPUから出力されるProcClockOutは逓倍後のCPU内部動作クロック、マイクロコードの1ステートと合致しているということなのでCPLDにも取り込んでいるこの信号をプローブしてみました


すると確かに入力クロックClockin=4.9152MHzの4倍、19.66MHzProcClockOut端子に観測されました

速度サフィックスが外部入力クロック(FSB)の上限ではなく、逓倍後の内部動作周波数を示すのはIntel80486DX2からPentium,Celeronあたりでもそうでしたがちょっと混乱します

 

最小ループ再び

パタンの修正ができたので、信号線をプローブして電源ON!

・・とその前に。

今回ROM(U16)へのデータバスの引き込みを修正しました

 修正前:D24 D23 D21 D20 D19 D18 D17 D16

 修正後:D22 D23 D21 D20 D19 D18 D17 D16

つまりD23は元々つながっていましたがD22D23の順番が入違ってしまってます。これも本来の位置に直すとするとパタン修正が倍になるのでこのままで諦め。そのためROM単体でのデータバス配置もD6 D7 D5 D4 D3 D2 D1 D0となるので書込みデータの変換が必要になります。U16に書かれているデータは現状「60」の1byteですがこれのD7/D6を入れ替えて「A0」に焼き直しておきます。プログラムが大きくなったら簡単な変換ツールを通せばよいでしょう。

これがアドレスバスの入れ違いだと連続したコードがぐちゃぐちゃの順番になり面倒なことになるところでした。

で、ROMを交換して改めて電源ON!

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

 ch2:ROMの/CS(=/ROMCS)

 ch3:ROMの/OE(=/MemRd)

 

お・・今度はうまくいきました。ROMから連続して読出しが行われています。電源入り切り、リセットボタン押下でも百発百中この波形になるので「j  $」が連続して実行されているとみてよいでしょう。

ただ周期がなにか微妙。約2.8MHzと読み取れます。CPUに与えているクロックは4.9152MHzですがCPU内蔵のPLLで5逓倍されるようなので内部動作クロックは24.6MHzのようです。これから1周期のクロックサイクルを計算すると8~9クロックということになり、きれいに割り切れませんが合ってるかどうかはあとで調べてみます

パタン補修

まずPLCCソケット間のラインから。隙間は約2.5mmしかありませんがルータにハイスビットを装着して切削できました

       切断前                  切断後

 

もう一か所の切断箇所は基板の裏面なのとパタン密度が低いのでこちらは簡単

        切断前                  切断後

それよりハンダ付けした時の飛沫なのかハンダボールが結構飛び散ってるのに気付きました。細いラインは幅6mil=0.15mmなので直径0.2mmくらいありそうです。あとで掃除しておいた方がよさそうです

 

パタン切断ができたのでUEWで2本ジャンパを飛ばして補修完了しました