コンピュータの動作原理（６）8ビットプロセッサP08：前編

8ビットプロセッサP08
====

今回から２回にわけて、Logisimで動作する8ビットCPU P08 の解説をしていきます。名前は単に8ビットプロセッサだからです、捻ってません。まずP08のCPUとしての概要について、それから各ユニットの解説です。

シミュレータ上で動作を確認しながらの方が解りやすいと思います。出来れば[P08.circ](http://qv80.cocolog-nifty.com/blog/files/P08.circ)をお手元にご用意ください。右クリ…

## 特徴
ちっさい命令セットコンピュータ(Minimal Instruction Set Computer)。
命令（インストラクション）：13種類、各12Bit
アドレス：8Bit
データ：8Bit
レジスタ：アキュムレータ、コードポインタの２つ

いわゆるMinimal Instruction Set Computerです。プログラムから意識するレジスタはアキュムレータとコードポインタのみですが、他にオペコードレジスタという内部で使う専用のレジスタがあります。
命令は12ビットで、データとはビット数が違います。

・アキュムレータ
8Bitです。メモリからデータを読む、メモリにデータを書き込む時はこのレジスタを使います。また算術・論理演算はこのアキュムレータとメモリの内容との間で行われ、結果はアキュムレータに保存します。そういう回路にしてありますし、命令もそういうモノだけにしました。P08では、いわゆる汎用レジスタはコレだけです。

・コードポインタ
8Bitです。これから実行しようとしている命令のアドレスが入ってます。プログラムカウンタとかインストラクションポインタとか言います。どっちの味方でもないので、今まで見たこと無いですが「コードポインタ」と呼ぶことにしました。


## P08

### インストラクションセット
「コンピュータの動作原理（１）概要」の図の一番上に書いてあるマシンコードについて、P08のマシンコード体系について説明します。
プロセッサが直接実行出来るコードをマシンコードと言います、あるコードがどういう働きをするのかの説明の時は、命令とかインストラクションという言い方が多いです。他にバイナリーとかバイナリーコードとか言う事もありますが、これは主にテキストと区別する時の言い方です。
そのプロセッサがどんな命令体系なのかについて一通り説明する時は、「インストラクションセット」と表現します。

P08の命令は13種類。データ移動命令が4、算術・論理演算が4、分岐命令が3、IOが2種類です。
命令は12ビット長で、上位4ビットが命令の種類、下位8ビットが主にアドレスです。

LDとかSTとかは、ニーモニックという表記方法です。マシンコードの動作が想像しやすいように名前をつけたものです。このニーモニックで書かれたテキストをマシンコードに変換するのが、アセンブラと呼ばれている物の主な役割です。
Opeodeの覧に、具体的なマシンコードのフォーマットが示してあります。
CarryとZeroはそれぞれ1ビットのフラグでxは演算結果によってセット/リセットされる場合、0にリセットされる場合は0と表記してあります。空欄は変化なしです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/136856/01237493-612c-a351-bc26-abb112576e0a.png)

	LD：アキュムレータ（以下Acc）にオペコードの下位8ビットで示すアドレス（以下MEMと表記）の内容を転送する。
	ST：MEMへAccの内容を転送する。
	LDA：Accにオペコードの下位8ビットとAccを加算した値で示すアドレスの内容を転送する。
	MOV：Accにオペコードの下位8ビットを転送する。
	ADD：AccにMEMの内容を加算する。桁あふれしたらCarry Flag(以下CF)=1、結果が0だったらZero Flag(以下ZF)=1。
	SUB：AccからMEMの内容を減算する。最上位より上からの借りが発生したらCF=1、結果が0だったらZF=1
	AND：AccにAccとMEMのANDをセットする。結果が0だったらZF=1
	NOR：AccにAccとMEMのNORをセットする。結果が0だったらZF=1
	JC：CFが1ならオペコードの下位8ビットをコードポインタに転送する。
	JZ：ZFが1ならオペコードの下位8ビットをコードポインタに転送する。
	JMP：オペコードの下位8ビットをコードポインタに転送する。
	IN：I/Oポートから8ビットデータをAccに転送する。
	OUT：I/OポートへAccの内容を出力する。


### 全体図

P08.circを開くと左側にCircuitの一覧があります。開いた時にデフォルトで回路全体を表示するようにしてあります。Processorと書かれた枠内がプロセッサ本体で、メモリやI/Oとは分けてあります。
プロセッサ本体の中には命令デコーダ、CodePointer、Accumulator、OPECodeレジスタ、ALU、JUMP制御部などの各種ユニットがあります。
![WSS_20171223_270.jpg](https://qiita-image-store.s3.amazonaws.com/0/136856/6089f6f4-5fa0-d56e-0df0-18e4a6f8c536.jpeg)

	ナイト2000をあらかじめ書き込んであります。Simulate→Simulation Enableで動作が確認できます。
	Simulate→Tick Frequencyを1KHzくらいにするといいでしょう。

たくさん出てくる![MUX.jpg](https://qiita-image-store.s3.amazonaws.com/0/136856/b8c2e387-38cb-16d7-8582-466c6db01710.jpeg)はマルチプレクサです。
前回解説したセレクタですね。マルチプレクサの下に生えている入力が選択信号で、P08では選択信号が1ビットのモノと2ビットのモノを使っています。

それから![WSS_20171222_258.jpg](https://qiita-image-store.s3.amazonaws.com/0/136856/5ff1f274-0bed-8e97-2a95-9833186a89b1.jpeg)がレジスタの例、これはアキュムレータですね。
Dが入力、Qが出力です。enと書かれている左側につながっているのが取り込みEnableです。これが1なら、△の下に生えている信号が0→1になったタイミングでDを取り込み、Qに出力します。

　※クロック、メモリ、IOはコアの外にありますが、これは必ずしも物理的に別のパッケージ[^1]になっているとは限りません。製品によって（I/O部のLED以外は）全部1つのパッケージに入っている場合もあります。マイクロコントローラと呼ばれるモノです。


[^1]: たとえば[こんなの](http://www.toppan.co.jp/electronics/semicon/package/)がパッケージです。


## ユニット構成

### CLOCK
クロックは制御信号のうち同期信号として使われるものです。Logisimでは部品として用意されているものがあるので、これを使います[^2]。

全体図左下CLKがクロックの供給源です。P08は二層クロックを採用しています。
二層クロックは下のチャートのQ、Eで示す2つの信号で、オーバーラップしながら0と1を繰り返します。Qが0→1になったあとEが0→1、そのあとQが1→0、Eが1→0の順で変化します。こうすると、一回り（1サイクル）の間にタイミングの取れる所が4箇所になります。QとEは前回の順序回路に出てきた制御信号の役割を果たします。
下のチャートには、プロセッサの各部分がどのタイミングで入力を取り込むかについて書いてあります。
<img src="https://qiita-image-store.s3.amazonaws.com/0/136856/d3a8cca2-ef00-21f4-ef46-e8e8164dec63.png" width="80%">

[^2]: 実物は水晶振動子（クオーツ）と呼ばれる一定の周波数で振動する素子で、これから取り出した信号を使います。

### Stage
Processorの右下「Stage 0:Fetch 1:Decode & Execute」と書いてあるDFFがステージコントロールです。Eが1→0になったタイミングで0→1→0→1→0と変化します。

Stageが0の時はメモリから命令を1つOPCodeレジスタに読み込みます。その後Stageが1になったら読み込んだ命令のビットパターンに従って制御信号を出します。このそれぞれをFetch Stage、Decode&Execute Stage と呼んでいます。

プロセッサの仕組みを調べると、フェッチ、デコード、実行、書き戻し（ライトバック）の４ステージで解説してあるものが多いですが、P08は命令体系がシンプルなので、ステージは2つでじゅうぶんですよわかってくださいよ。

Stageが0、つまりFetch Stageの時のQが0から1になるタイミング[^3]（以降「↑」）で、AddressBufferがCPの内容を取り込みます。これでアドレスがプロセッサ本体の外に出ますから、少し待って、そのあとのE↑のタイミングで命令をOPECodeレジスタに取り込みます。OPECodeレジスタの上位4ビットはALUの演算の種類選択や、JUMP制御部などにつながっています。

OPECodeレジスタの下位8ビットは、
・実行しようとしている命令が分岐命令だったらCPに転送できるようにCPへ、
・データ移動命令や演算の、メモリへアドレスとして出力する必要のある命令だった時のためにAddressBufferへ、
・アキュムレータに転送する命令だった時のためにアキュムレータへ
それぞれへつなげてあります。あとはデコーダから出る制御信号が実際に必要なユニットの取り込みEnableを1にするので、Enableを1にされたユニットが決まったタイミングで取り込みます。

また、だいたいこのあたりのタイミングでコードポインタを1つ進めます。プロセッサの中央「CP++」と書かれたユニットが、入力に1を加算するユニットです。
その後E↓でStageの0と1が切り替わります。
次はDecode & Execute Stageです。

[^3]: 信号が0から1になる瞬間を、立ち上がりとかライジングエッジとか言います。「Q↑」はQが0から1になる時、Qの立ち上がりを表します。

### DecoderROM
Processorの中央下にあるROMがデコーダROMで、このあたりが「命令デコーダ」です。
Decode & Execute Stageの時にこのROMの内容がそのまま制御信号としてプロセッサ本体の各ユニットへと出て行きます。
P08の場合、制御信号の半分はここから出て行きます。DecoderROMに入力するアドレスは、OPECodeレジスタに取り込んだ命令の上位4ビットで、出力は7ビットです。マシンコードはここで制御信号に変換されます。ここから出て行く信号は上位から順に
・アキュムレータにデータを取り込むかどうか：1ビット
・メモリに出すアドレスを3種類のうちどれにするか（又はどれでもないか）：2ビット
・アキュムレータの内容をデータバスに出すかどうか：1ビット
・I/Oかメモリアクセスか：1ビット
・メモリへの書き込みかどうか：1ビット
・メモリからの読み出しかどうか：1ビット
です。

長くなったので、次回はDecoderROMの信号を１つづつ追っていきましょう。

　※制御信号はフェッチステージの時は定数0x21を出力します。DecoderROMのすぐ右にありますね。

----

　※以上の回路は[P08.circ](http://qv80.cocolog-nifty.com/blog/files/P08.circ)（以下略）

----