この世のCPUを食べ尽くすのだ! 第3章 第5節

~あんたCPUなんか創ってどうするのよ?! Vol.3~

2018/10/8
技術書典5 け39

第3章 第5節 「加算しない」回路の追加

筆者的に不本意だったのがこの回路です。

まずは言い訳から。

本来の予定では本書Vol.3の段階で電卓を完成させる予定でした。実際に回路図も出来上がっていて、実機の制作も途中まで進んでいました。しかしRAMのタイミング制御に苦しめられた結果、計画の後退を決断せざるを得なくなりました。電卓用のCPUという新しい領域に踏み出す前に、既知のTD4に確実にRAMを搭載することを選択したのです。

その結果、本書はTD4EX3という中途半端なCPUを製作する本になりました。TD4EX3は4KBのROMと16語のRAMを搭載しているにもかかわらず、何もできないという非常に残念なCPUです。そのため筆者はTD4EX3に余計なICを搭載する気は全くありませんでした。どうせ使い物にならないからです。

ところが実際に完成したTD4EX3を動作させてみると、その時点ですでに凹んでいた筆者のガラスのハートはさらに凹む事になりました。それはTD4と共通する欠点なのですが、「常に加算を行っている」という欠点です。

TD4では命令コードの下位4ビットが加算用ICである74HC283に常に供給されています。そのためTD4は常に加算を行っており、加算したくない場合は命令コードの下位4ビットを0にする必要があります。

ところがTD4EX3ではRAMの搭載に伴い、IN命令とOUT命令の下位4ビットでアドレス指定を行うことにしました。すると「常に加算を行っている」ために、アドレスの値がデータの値に加算されてしまいます。

例えば5という値をLEDの1桁目に出力する場合、普通は以下のようにプログラムを書きます。

MOV B, 5 ;出力したい値をBレジスタに読み込む
OUT B, [0xE] ;Bレジスタの値をLED表示ポートへ出力する
MOV B, 0 ;LED番号をBレジスタに読み込む
OUT B, [0xF] ;Bレジスタの値をLED選択ポートへ出力する

ところがTD4EX3のOUT命令はアドレスの値をデータの値に加算してしましますから、2行目のOUT命令で出力されるのは5ではなく3になってしまいます。4行目も同様に0ではなくFが出力されます。

結局、正しく動作させるためには以下のように書く必要があります。

MOV B, 7 ;出力したい値(5)をBレジスタに読み込む
OUT B, [0xE] ;Bレジスタの値をLED表示ポートへ出力する
MOV B, 1 ;LED番号(0)をBレジスタに読み込む
OUT B, [0xF] ;Bレジスタの値をLED選択ポートへ出力する

これでは何をやっているのかさっぱり分かりません。

いくら最初から見えている落とし穴とは言え、OUT命令とIN命令を使うたびに穴に落ちるのではRAMを搭載した有り難味が無くなってしまいます。

そこでやむを得ず「加算しない」回路を追加することにしました。

無駄にICが増えるだけなので非常に嫌なのですが、無ければ元から地面すれすれだったTD4EX3の価値が完全に地に落ちてしまいます。そのためIN命令とOUT命令の実行時には常に0との加算を行うように、TD4EX1でも使用した74HC157をROMと74HC283の間に挿入しました。

こんな事ならTD4EX2をベースにTD4EX3を作成するのではなく、TD4EX1にRAMを追加すべきだったと思います。

ともあれ、これによりプログラムを書いたとおりに動作するCPUにする事ができました。

次ページにI/Oユニットの回路図を示します。TD4EX3の回路図については、大部分がTD4と同一であることから著作権上の懸念があり、Webへの掲載は自粛させて頂きます。