標準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
前へ
次へ
ホームページトップへ戻る