標準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追記

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