標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第245回]
●割込みのテスト回路です
8080の割込みは、割込み信号(INT)を受付けた直後に外部データバスに乗せられたRST命令を読み込むことで行われます。
通常はデータバスには何ものせなくても、INT信号さえ入力すれば、割込みが実行される、RST7割込みが最もよく使われます。
この「つくるCPU」でも、ですからINT信号を受け付けて、RST7を実行するような回路さえつくっておけば、まあ、それでよいのではないか、十分でしょう、とも考えたのですが、やっぱりできるだけ8080に近い動作を実現したいというこだわりから、RST7だけではなくて、データバスに乗せられたRST0〜RST6を読み込んで、割込み処理を行うという、「本物志向」の回路を作ってしまいました。
作ったからには動作テストをしなければなりません。
RST7割込みは、INT信号を入れるだけですから、簡単です。
しかし、その他の、RST0〜RST6は、INT信号を入れるだけではだめで、データバスにRST0〜RST6のOPコードを乗せなければなりません。
でも、それはそれほど難しいことではなくて、図のようにして簡単にテストすることができました。
ここでのポイントは真中にある74HC126です。
左にあるのは、当社のBASIC制御ボードZB25Kです。
操作が簡単なので、今回のテストに利用しました。
ZB25K上のI/Oポート82C55からINT信号を「つくるCPU」基板に出力します。
それに先だって、RST命令の3ビットのベクトルを出力します。
この3ビットの出力は、「つくるCPU」がINT信号を受け付けたあとに出される、INTRD信号の期間中にデータバスに乗せる必要があります。
そこで図のように74HC126を使います。こうすることで、外部では特別のタイミングなどを考慮しなくても、ただ3ビットを出力しておくだけで済みますから非常に簡単です。
●テストを行うためにBASICボードと接続している様子です
左側にあるのがBASICボードZB25Kです。
写真ではフラットケーブルに隠れてしまって見えませんが、小さいジャノ目基板に74HC126を乗せて、ZB25K、ジャノ目基板、「つくるCPU」の間をフラットケーブルで接続しています。
●割込みのテストプログラムです
2009/6/8 20:47 INTTEST.TXT
END=0060
;;; MYCPU80 INT TEST(RST1-RST6) 09/06/08
;;;
ORG $0000
0000 C34000 JMP START
;RST1
ORG $0008
0008 F5 PUSH PSW
0009 04 INR B
000A F1 POP PSW
000B FB EI
000C C9 RET
;RST2
ORG $0010
0010 F5 PUSH PSW
0011 0C INR C
0012 F1 POP PSW
0013 FB EI
0014 C9 RET
;RST3
ORG $0018
0018 F5 PUSH PSW
0019 14 INR D
001A F1 POP PSW
001B FB EI
001C C9 RET
;RST4
ORG $0020
0020 F5 PUSH PSW
0021 1C INR E
0022 F1 POP PSW
0023 FB EI
0024 C9 RET
;RST5
ORG $0028
0028 F5 PUSH PSW
0029 24 INR H
002A F1 POP PSW
002B FB EI
002C C9 RET
;RST6
ORG $0030
0030 F5 PUSH PSW
0031 2C INR L
0032 F1 POP PSW
0033 FB EI
0034 C9 RET
;
ORG $0040
0040 310080 START:LXI SP,$8000
0043 AF XRA A
0044 47 MOV B,A
0045 4F MOV C,A
0046 57 MOV D,A
0047 5F MOV E,A
0048 67 MOV H,A
0049 6F MOV L,A
004A FB EI
004B 3C LOOP1:INR A
004C F24B00 JP LOOP1
004F 3E07 MVI A,07
0051 D398 OUT 98
0053 3E80 MVI A,80
0055 3C LOOP2:INR A
0056 FA5500 JM LOOP2
0059 3E17 MVI A,17
005B D398 OUT 98
005D AF XRA A
005E C34B00 JMP LOOP1
;
LOOP1 =004B LOOP2 =0055 START =0040
アドレス0000のRST0はリセットと同じで、今回のテストには向きませんから、除外します。
また0038のRST7も、INT信号を入力するだけで済みますから、これも今回のテストからは除外します。
今回はRST0とRST7を除いた、RST1〜RST6をテストすることにしました。
0000番地からスタートするメインプログラムはAレジスタをインクリメント(+1)しながら、128回カウントアップするごとに、I/O出力(アドレス98のビット4)から1と0を交互に出力します。
アドレス0008〜0030から始まるRST1〜RST6プログラムは、今回はテストですから、簡単なプログラムになっています。
普通は8バイトやそこらではおさまりませんから、そこからJMPして、その先に割り込みのプログラムを書きます。
今回はレジスタを+1するだけですから、8バイトにおさまってしまいます。
PUSH PSW、POP PSWは、割込みプログラムの中のINR命令の実行によって、フラグが変化してしまうのを防ぐために使われます。
各レジスタの値も割込みプログラムの実行によって変化しますが、メインプログラムではAレジスタ以外は使っていませんから、各レジスタを退避させる必要はありません。
●割込み信号を発生させるBASICプログラムです
これは「つくるCPU」のプログラムではありません。
上で説明しましたように、割込みテストのために利用した、当社のBASIC制御ボードZB25Kのプログラムです。
10 'MYCPU80 INT TEST 09/06/08
20 OUT $83,$80
30 OUT $80,$FF
40 FOR A%=1 TO 6
50 OT%=$08+A%
60 FOR A=0 TO 1000:NEXT A
70 OUT $80,OT%
80 OUT $80,A%
90 OUT $80,OT%
100 NEXT A%
110 GOTO 40
BASICを使うと、簡単に出力信号を作ることができます。
ただ、BASICはマシン語のプログラムに比べて実行速度が遅いのが欠点です。
●INT信号とINTRD信号です
上(CH1)がINT信号で、下(CH2)はINT信号を受け付けたときに「つくるCPU」側から出力されるINTRD信号です。
INT信号の幅が長いために、割込みが複数回受け付けられてしまいます。
なおこれは「割込み処理中」に重ねて割込みが受け付けられているのではなくて、「割込みが終了した直後」に次の割込みが受け付けられているので、異常な動作ではありません。
でも、今回のテストの本来のねらいとしては、1回のINT信号で1回の割込みが受け付けられる、ということにありますから、これは、ちょっと、なんとかしたいところです。
●INT信号のところだけ、マシン語サブルーチンを使いました
10 'MYCPU80 INT TEST 09/06/08
20 OUT $83,$80
30 OUT $80,$FF
40 FOR A%=1 TO 6
60 FOR A=0 TO 200:NEXT A
70 USR($4010)
100 NEXT A%
110 GOTO 40
4010 3A40F4 LD A,($F440)
4013 D380 OUT (80),A
4015 0610 LD B,10
4017 05 DEC B
4018 C21740 JP NZ,$4017
401B F608 OR 08
401D D380 OUT (80),A
401F C9 RET
上はBASICプログラムで、下はBASICプログラムでCALLしているマシン語プログラムです。
こちらはZ80CPUなので、ザイログニーモニックを使っています。
INT信号の幅が短くなったため、1回のINT信号で1回だけの割込み処理が行われるようになりました。
●テスト中の各レジスタのLED表示です
右端のAレジスタだけは高速でインクリメントしていますから、全点灯しているように見えます。
その他の、D、E、B、C、H、Lの各レジスタはINT信号が入力されるたびに、RST1〜RST6のいずれかが実行され、そのときに該当するレジスタが+1されます。
●INT信号の信号幅について
上のテストで見たようにINT信号の幅が余り長いと、複数回、割込みが発生してしまいます。
逆に余り短いと、無視されてしまって、割込みが受け付けられません。
どの位の幅があるとよいのでしょうか?
その最大幅は、割込みを利用するシステムによって異なってきます。
最小幅のほうは、少なくとも最長の命令の実行時間以上である必要があります。
「つくるCPU」では、最長の命令は、SHLD命令、LHLD命令([第104回])の20クロックです。1クロックは0.5μsecですから、その20倍は10μsecになります。
したがって、最低でも10μsec以上の間はINT信号をアクティブにしておく必要があります。
まあ20〜30μsecぐらいの信号幅が妥当なところなのではないでしょうか。
●メインルーチンの処理中に割込みが入っている様子です
(この項は09.6.10に追加しました)
せっかくメインルーチンでI/O回路からパルスを出力するようにプログラムしたのですから、その様子もお見せすることに致しました。
上(CH1)がINT信号です。左の方にポツンとかすかに見えています。
パルス幅が20μsecほどですから、このレンジではこの程度にしか見えません。
下(CH2)はI/O(アドレス98のビット4)からの出力パルスです。
今回の割込み処理プログラムはレジスタをインクリメントしてリターンするだけの、非常に短いルーチンですから、メインプログラムの実行にはほとんど影響を与えません。
2009.6.9upload
2009.6.10追記
前へ
次へ
ホームページトップへ戻る