メインページに戻る

インストラクションデコーダは頭脳の中の頭脳

メモリのアドレス幅やデータ幅、実装するレジスタの数などが決まると、いよいよインストラクションデコーダの設計です。コンピュータの頭脳がCPUならば、CPUの頭脳がインストラクションデコーダだと言えるでしょう。レジスタ構成やALU等の機能が全く同じCPUであっても、このインストラクションデコーダの設計次第で名機にもなれば駄機にもなるという、極めて重要な回路です。

以後、インストラクションデコーダ(instruction decorder)をIDと略記します。直訳は「命令解析器」となります。以前はコンピュータにおける「命令」をオーダーと呼び、「命令解析器」をオーダーデコーダー(order decorder)と呼んでいたのですが、調べてみますとorder decorderという言い方は現在では殆ど見受けられない様です。個人的にはODと略記したいのですが、時代には逆らえませんのでIDと略記することとします。

インストラクションデコーダ(ID)の基本原理

CPUを構成する要素の一般形式左の図は、メモリ/レジスタ/カウンタ、あるいはALU等のコンピュータを構成する個々の回路を図式化したものです。もちろん、全ての回路が図の様な4種類の信号線を有する訳ではありません。例えば今回するカウンタ74LS569の場合は、このほかに「カウントアップせよ」という信号線があります。また メモリとして使用するTC55257の場合はデータ線はINであると同時にOUTでもあります。しかしIDの設計は、まず全ての回路を左の図のように大雑把に表現することから始めました。

CPUを構成する要素のバスによる結合上記の回路を複数並べるとこうなります(注)。IN/OUTは全て共通とし、LD(Load)とOE(Output Enable)のみを個々に用意します。

こうする事により、任意の回路から任意の回路にデータを渡すのがとても簡単になります。例えば「回路n」から「回路2」へデータを渡したければ、「OE-n」と「LD-2」に信号を送れば良いのです。


どこから、どこへデータを転送するのかは、命令とクロックの組み合わせで決めます。本機の場合、命令は最大16種類で、全ての命令の実行は6クロックで行いますので、命令別のクロック数は16×6=96となります。 つまりこの96通りのタイミングのそれぞれに対し、どこからどこにデータを転送するかを決め、それに対応するLEとOEに信号を送る回路を引き終えれば、ID回路は設計完となります。

(注)チップの種類により信号線の呼称は異なります。RAMの場合、書込み信号はLDではなくWR(write)と称します。また、74LS173は書込を指示する端子名はLDですが、同時にクロック信号も与えないと書きこみは行われません。

インストラクションデコーダの原理は簡単、されど実装は超困難

命令レジスタの値をプログラムカウンタに転送すると「分岐命令」が実現できます。メモリやレジスタの値をALUに転送すると「演算命令」が実現できます。この様にコンピュータの命令とは結局は部品間のデータの転送に過ぎず、概念自体はそれほど難しくありません。もっと簡単に行うならば、縦軸を各部品の出力、横軸を各部品の入力とした表をクロック数分作成し、転送を希望する部品の所に○(丸)をつけるだけで様々な命令を作り出すことができます。

しかし実際にIDをTTLで作るとなると、話は大きく変わります。エクセルの表は簡単に作れても、その実体は「命令4のクロック3の時には部品8番から部品5番へデータを送る」と言う回路が表の升目の数だけ必要になるのです。その一つ一つをANDゲートやORゲートの配線として実現するのですから、まともに取組んでしまうと、気の遠くなるような部品数や配線数となってしまいます。さらに、実装できる命令の数(種類)には限りがありますから、どんな命令の実装を優先するかをどこかで決断しなくてはなりません。

Webを眺めますと、「コンピュータを作ろうとしたが、IDの実装で断念し、単なる演算実験器やメモリへの読み書き実験器で終わった」と思われるサイトが散見されます。

学生によるTTLコンピューターの論文40年前なら、他人の「コンピュータ作成計画」の失敗理由を知ることなど不可能でしたが、最近は学生のゼミや卒業研究をWeb上に公開する高専や大学が増えています。 サイト名の紹介するのは差し控えますが、私が見つけた中には全ての制御線(前述したLDとかOE等)に押しボタンスイッチをつけ、 人間がプログラムを解読(デコード)しながら、そのスイッチ群を操作するという「人間コンピュータ」の様な作品もありました。

左のパワーポイントの表紙画像と本文は関係ありません

TTL間の全転送ルートと制御信号の一覧表

TTLコンピュータの作成を途中で挫折した(と思われる)学生さんの話を紹介しましたが、
私自身も、IDの設計には相当悩みました。回路はそれなりに決まっているのですが、可能な限りTTLの数を削減するために何度も回路設計からやり直したからです。下記は最終的に決めた回路概略図(ブロック図)と制御信号一覧です。
(詳細回路はフリーの回路図エディタをダウンロードして清書中 ⇒ 後日公開予定)

【全ブロック図】
8個のスイッチを入力装置、8個のLEDを出力装置として実装することにしました。
図中の演算出力レジスタは、昔の慣わしに従い以後文中ではアキュムレータ(略称はAまたはAcc)と表記します。

全ブロック図


【全制御信号】
これらの信号をクロックとプログラムに従い制御する。具体的な制御手順は次回アップ予定です。
表中の”論理”とは、機能が有効になる論理です。*が付加されているものはクロック同期式。
尚、入出力に使うTTLはまだ迷っている点が若干あるので、論理はまだ未定としています。(後日追記します)

信号名 対応する部品 論理 機能
 P-OE  プログラムカウンタ    L  出力を有効にする
 P-LD  L*  値をセットする
 P-CN  L*  値をインクリメントする
 M-OE  主メモリ  L  出力を有効にする
 M-W  L  値をセットする(クロック同期ではないことに注意)
 X-OE  命令レジスタ
(兼、汎用レジスタ) 
 L  下位12bitの出力を有効にする(上位4bitは常に有効)
 H-LD  L*  上位8bitの値をセットする
 L-LD  L*  下位8bitの値をセットする
 A-OE  演算出力レジスタ
(アキュムレータ)  
 L  出力を有効にする
 A-LD  L*  値をセットする
 IN  入力バッファ  未定  スイッチの出力を有効にする
 OT  出力レジスタ  未定  LEDに与える値をセットする
 SEL  ALU  ---  ALUに与える3bitの信号線のH/Lで演算の種類が決まる
 この3bitは命令レジスタのビット14,13,12に直結する 

クロック/命令/制御信号のマトリクス

全制御信号の洗い出しを終えたらそれを横軸にとり、縦軸はステージ(クロック)と命令の組み合わせとした表を作成します。交点の黒丸(●)は、その命令のそのステージの時、その制御信号を有効にする事を意味します。どこに黒丸を置くかによって様々な転送が可能です。それらの転送の組合わせにより、様々な命令を作ることができます。

ステ
ージ 
命令
コード 
動作 P-
OE
P-
LD
P-
CN
M-
OE
M-
W
X-
OE
H-
LD
L-
LD
A-
OE
A-
LD
IN OT
 0 共通  何もしない                        
 1 共通  M[PC]→XH  ●      ●      ●          
 2 共通  PC+1→PC      ●                  
 3 共通  M[PC]→XL  ●      ●        ●        
 4 0~7  M[X]→XL        ●    ●    ●        
 5  0  00h→A            ●        ●    
 5  1  XL-FFh-1→A            ●        ●    
 5  2  A-XL→A            ●      ●  ●    
 5  3  A+XL→A            ●      ●  ●    
 5  4  A xor XL→A            ●      ●  ●    
 5  5  A or XL→A            ●      ●  ●    
 5  6  A and XL→A            ●      ●  ●    
 5  7  FFh→ACC            ●      ●  ●    
 5  8  IN → M(nnn)          ●  ●          ●  
 5  9  XL-FFh-1→A            ●        ●    
 5  A  A-XL→A            ●    ●  ●  ●    
 5  B  OUT            ●      ●      ●
 5  C  A → M(nnn)          ●  ●      ●      
 5  D  X→PC    ●        ●            
 5  E  X→PC  X→PCと同じ但しcarry無なら何もしない      
 5  F  停止  RUN(H)/DMA(L)切替をDMAにする      
 6  共通  PC+1→PC      ●      ●      ●      

表中の略語

PC:プログラムカウンタ
X:命令レジスタ下位12bit
XH:命令レジスタ上位8bit
XL:命令レジスタ下位8bit
M[PC]:メモリのPC番地
M[X]:メモリのX番地
A:アキュムレータ
00h:16進の0(ゼロ)
FFh:16進値(10進の255)

全ての命令コードは16bitです。
表中の「命令コード」は、その上位4bitを16表記しています。

例えば、命令コードが"1nnn"の場合の各ステージの動作を抽出するとこうなります。

ステージ  命令  動作 動作の詳細解説OE
 0 共通  何もしない  
 1 共通  M[PC]→XH  プログラムカウンタで示されるアドレスから
命令を2バイト取出し、Xレジスタにセットする
 2 共通  PC+1→PC
 3 共通  M[PC]→XL
 4 0~7  M[nnn]→XL  nnnで示されるメモリ内容をXLにセットする
 5  1  XL-FF-1→A  XLからFF(TTLはHi-ZはH)を引き、さらにcarryを引いてAに格納する。
結果256を引くことになり、命令のオペランドで示されるメモリの内容がAに転送されるロード命令となる
 6  共通  PC+1→PC  次の命令のためにプログラムカウンタを+1する

同様に、他の命令も各ステージ毎に行われる処理を重ね合わせると、その命令が何を行うのかがわかります。


TTLコンピュータの命令一覧

下記が本機の命令一覧です。本機の命令デコードはかなりの冗長性(要するにムダ)があるので、デコードをもっと丁寧にすれば、条件分岐命令の条件を増やしたり、シフト命令を追加することも比較的容易です。しかし、命令の実装は欲張るとキリがないので下記に抑えています。

命令  ニモニック 動作 動作の詳細解説OE
 0xxx  CLR  0 → Acc  Accの全ビットを0にする
 1nnn  LD nnn  M[nnn] → Acc  nnn番地の内容をAccにロードする
 2nnn  SUB nnn  Acc - M[nnn] →Acc  Accからnnn番地の値を引く
 3nnn  ADD nnn  Acc + M[nnn] →Acc  Accにnnn番地の値を加える
 4nnn  XOR nnn  Acc ^ M[nnn] →Acc  Accにnnn番地とのEXOR処理をする
 5nnn  OR nnn  Acc | M[nnn] →Acc  Accにnnn番地とのOR処理をする
 6nnn  AND nnn  Acc & M[nnn] →Acc  Accにnnn番地とのAND処理をする
 7xxx  SET  FF → Acc  Accの全ビットを1にする
 8xxx  IN nnn  DATA SW → M[nnn]  DataSWの状態をnnn番地に格納する
 9xnn  LDI nn  nn → Acc  値nnをAccにセットする
 Axnn  SBI nn  Acc - nn →Acc  値nnをAccから引く
 Bnnn  STA nnn  Acc → M[nnn]  Accの値をnnn番地にストアする
 Cnnn  OUT nnn  A →LED , nnn→LED  Accの値と値nnnをLEDに表示する
 Dnnn  JMP nnn  nnn → PC  nnn番地に分岐する
 Ennn  JNC nnn  If no carry nnn →PC  carryがなければnnn番地に分岐する
 Fxxx  HLT  プログラム実行を停止し、DMAモードに移行する


・xはデコードされないビットであり値は任意

・動作の演算子表記はC言語に準拠

・M[nnn]はメモリのnnn番地の内容を意味する


シフト命令もありませんし、条件分岐命令も1種類だけです。大規模プログラムの作成には必須と言えるサブルーチンコールを行う命令もありません。しかし私は上記の限られた命令を組み合わせることにより、インテルの礎を築いた名機8080の持つ命令と同等の処理はできるのではないかと思っています。

インテルの8080の命令を全てエミュレート可能か否かは、いずれ「ソフトウエア編」で改めて検証結果を報告予定です。しばらくはハードウェアの設計と製造に注力したく思います。(2011/4/21)


メインページに戻る