標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第179回]

●AND、OR、XOR回路の説明です

7segLEDの回路ができあがって、232Cの回路まで動作したものですから、嬉しくなって、しばらくはそちらのご報告やら、思わぬトラブルの対処やらで、ここのところ、回路の説明が中断しておりました。

しばらくぶりですけれど、中断しておりました、残りの回路の説明を再開いたします。
今回はALU(arithmetic and logic unit)のうちの”logic”(論理演算命令)の回路についての説明です。
論理演算命令とは、AND、OR、XORの演算命令のことです。
8080では、Aレジスタに対してのみ演算が可能です。
Aレジスタと、汎用レジスタ、メモリ(A、B、C、D、E、H、L、M)との間で演算を行う、ANA、ORA、XRAの各命令と、Aレジスタと定数との間で演算を行う、ANI、ORI、XRIの各命令があります。
いずれの命令も演算の結果はAレジスタに格納されます。

ANDとかORとかといえば、これはもう、ロジック回路の定番、基本中の基本です。
ALU回路などというと、何かとてつもない回路のように思ってしまいそうですが、そのうちでも、この論理演算回路についていえば、ごくごく普通の、じつにありきたりのロジック回路です。
勿論CPUの命令回路ですから、データの流れをコントロールするための回路や、演算結果によって、セット、リセットされるフラグの操作などの回路が必要です(その辺はちょいと複雑ですから、それはまたタイミングチャートを使って説明をいたします)。

●AND、OR、XORロジックの中心回路です


AND、OR、XORの演算は、おなじみのゲートICを、8ビット分使っています。
ANDは74HC08を2個、ORは74HC32を2個、XORは74HC86を2個です。
演算の結果は、74HC244で内部データバス(iB0〜iB7)につながっています。ANDかORかXORかのいずれかの回路につながっている74HC244をアクティブにすれば、その結果はただちに内部データバスに出力されます。

問題はゲートの入力側です。
8ビットの入力信号が2組あります。
”A”入力と”B”入力です。
Aレジスタ、Bレジスタではありません。
名前が紛らわしいので、なんとかしようと考えたのですが、いい案を思いつきませんでした。
ここではALU回路の”A”(A0〜A7)と”B”(B0〜B7)ということにしておきます。

8080のALU演算はAレジスタの値と、もう一方の値との間で行い、その結果をAレジスタに格納します。
そこで、Aレジスタの値を”A”のラインに乗せ、もう一方の値を”B”のラインに乗せるようにします。
”A”のラインはAレジスタからの出力をそのままつなげばよいように思われますが、そうするためには、Aレジスタから内部データバスに値を出力して、その内部データバスをそのまま”A”のラインにつなぐことになります。
すると結果をAレジスタに格納するために、74HC244をアクティブにした途端に、内部データバスの値が変化して、その途端に演算結果が変わってしまいます。
演算結果をAレジスタに格納するためには、そのタイミングではAレジスタは「出力」から「入力」に変わっている必要がありますから、結局どこかに値を保持しておくラッチが必要になります。

「つくるCPU」の回路では、入力側の”A”、”B”にラッチを入れるように考えました。

●ALUのレジスタ”A”とレジスタ”B”の回路です


データのラッチには汎用レジスタのA、B、C、D、E、H、Lなどに使っているのと同じ、74HC373を使います。
汎用のレジスタと違って、ALU回路内にだけ出力されるローカルなレジスタですが、働きはれっきとした「レジスタ」ですから、ここではレジスタ”A”、レジスタ”B”としています。
レジスタ”A”は、regAWR信号をアクティブにすることで、内部データバス(iB0〜iB7)の値をそのままラッチします。
レジスタ”B”も、regBWR信号をアクティブにすることで、内部データバス(iB0〜iB7)の値をそのままラッチしますが、同時にINVselをアクティブにしておくことで、1と0を反転した値をラッチするようにもなっています。
この機能は減算命令(SUB)で利用されます。

これで、論理演算の「お膳立て」は整ったわけですが、これだけでは、「命令」としては実行されません。
このレジスタに値をセットしたり、結果を取り出して、Aレジスタに格納したりするための回路が必要です。

●ALU命令のデコード回路

順序として、まずは、命令のデコード回路から説明をすることにいたします。

ALU演算命令の、ADD、ADC、SUB、SBB、ANA、XRA、ORA、CMPは、命令コードの上位2ビットが10の命令群です。

ニーモニック 命令コード
ADD 10 000 sss
ADC 10 001 sss
SUB 10 010 sss
SBB  10 011 sss
ANA  10 100 sss
XRA 10 101 sss
ORA 10 110 sss
CMP 10 111 sss

sssはレジスタA〜L、M(メモリ)を示す、000〜111の値

そして、ADD〜CMPは、命令コードのOP5〜OP3の3ビットによって選択されます。
ADI〜CPIは、上位2ビットが11で、かつ下位3ビットが110の命令群です。

ニーモニック 命令コード
ADI 11 000 110
ACI 11 001 110
SUI 11 010 110
SBI  11 011 110
ANI  11 100 110
XRI 11 101 110
ORI 11 110 110
CPI 11 111 110

ADI〜CPIが、命令コードのOP5〜OP3の3ビットによって選択されることは、ADD〜CMPと同じです。

ADD〜CMPは、OP7=1、OP6=0でセレクトしたあと、OP5〜OP3とともに、74HC238によってデコードされて、各命令を選択する信号になります。
ADI〜CPIは、その他の多くの命令のデコード回路で、11xxx110によって選択された信号を、同じ74HC238に入力します。

ALU命令回路は、最初にAレジスタの値を、ALUレジスタ”A”に入れ、もう一方のレジスタ、メモリ(A〜L、M)の値か定数値をALUレジスタ”B”に入れることと、演算結果をAレジスタに書き込むことは、共通な作業なので、その部分は個々の命令回路ではなくて、このデコード回路の部分でやってしまいます。

そのところは、タイミングチャートを見た方がわかりやすいですね。

●ANA、ORA、XRA、ANI、ORI、XRI命令のタイミングチャートです

レジスタ(A〜L)に対する、ANA、ORA、XRAと、メモリ(M)に対するANA、ORA、XRAでは、レジスタ”B”にレジスタの値を入れるか、メモリの値をいれるか、のところだけが違っていますが、そのほかは全く同じです。
また、Aレジスタと定数値との間で演算を行う、ANI、ORI、XRIは、メモリ(M)に対するANA、ORA、XRAとほぼ同じ動作です。

ALU命令のデコード回路図の右の方で、M2でregRDを出力しています。この期間にはs3〜s0は出力されていませんから、s3〜s0=1111でAレジスタが選択され、その値が内部データバスに出力されます。
そしてT4でreg”A”WRを出力していますから、内部データバスに出力されたAレジスタの値が、ALUのレジスタ”A”に書き込まれます。

同じ回路図の左の方で、M3でもregRDを出力していますが、このときには、OP2〜OP0の値をそのままs2〜s0に出力します。
それによって、レジスタA〜Lかメモリ(M)が選択され、その値が内部データバスに読み込まれます。
この値は、回路図の右の方、T6でreg”B”WRが出力されることによって、ALUのレジスタ”B”に書き込まれます。

ADI〜CPI命令のときは、M3のタイミングで命令コードの次のメモリアドレスから、そのメモリの値を読み込みます。そのためM3でPCselがアクティブになって、PC(プログラムカウンタ)の値が、外部アドレスバスに出力されると同時にMEMRD信号が出され、内部データバスにはメモリの値が読み込まれます(PCsel信号がアクティブになると、MEMRD出力からデータの読み込みまでが同時に行われます)。
この場合には、命令の最後のサイクル(T9)で、PC(プログラムカウンタ)を+1するために、PCclkが出力されます。

演算の結果は、ALUのレジスタ”A”とレジスタ”B”に値が書き込まれた直後から確定します。
その結果は、内部データバスが開放されるM4の期間に内部データバスに送り出されます。この部分は各命令によって、アクティブにする74HC244が異なりますから、個別の命令回路での制御になります。
そのようにして内部データバスに送り出された演算結果は、Aレジスタに書き込まれます。ここはCMP命令以外は共通なのですが、回路の都合で、その部分も個別の命令回路に置いてあります。

●論理演算のコントロール回路

これが、その個別の論理演算回路です。

M4のタイミングでANA(およびANI)命令はAndRDをアクティブにします。
XRA(XRI)命令はXorRDをアクティブにします。
ORA(ORI)命令はOrRDをアクティブにします。
そして、そのいずれの命令の場合でも、T8でregWRをアクティブにします。このとき、d3〜d0は出力されないので、d3〜d0=1111でAレジスタが選択され、内部データバスの値が書き込まれます。
同じT8で、HF(ハーフキャリーフラグ)とCF(キャリーフラグ)がリセット(クリア)されます。
またZF(Zeroフラグ)とSF(signフラグ)は、このときの内部データバスの値によって、セット、リセットされます。
ZFenblとSFenblの回路は、INR(DCR)レジスタ回路([第58回])にあります。

ここではもうひとつ、PF(パリティフラグ)のセット、リセットをします。
パリティとは、ビットの1の数が偶数個あるか奇数個かを示す値です。
偶数個のときにパリティフラグがセットされ、奇数個のときにリセットされます。
この回路でも74HC86を使っています。
74HC86はXORゲートです。
2つの入力が、1、1か0、0でともに同じときに、出力が0になり、2つの入力が1、0か0、1の場合には、出力は1になります。
上の回路図のように74HC86を組み合わせた、最終段の74HC86ゲートの出力は、内部データバスの値の1のビットの個数が偶数の場合に0になり、奇数個の場合に1になります。
その結果によって、PFset(パリティフラグセット)、PFres(パリティフラグリセット)信号が出力されます。

●全命令のデコード回路

全命令のデコード回路は[第61回]にあります。
ところが、このときにはまだ全ての回路ができていなくて、そこにある回路図では、命令のいくつかはデコードされていませんでした。
今回のADI〜CPI命令は、その回路図にはありません。
そこで、あらためて、最終的な命令デコード回路をお見せすることにいたします。

ADI〜CPIは、回路図の中ほどの左側、74HC238(3)の9pinから出力されています。
2009.3.9upload

前へ
次へ
ホームページトップへ戻る