目次

WonderKit_Z80_board

 アマチュア無線の知人から、WonderKitのZ80基板を
 貰ったので、必要な部品を実装し、動くようにして
 みました。



 パラレルインタフェースICのZ80PIOは、入手できず
 外部に8255、8251を増設してシステムが成立つよう
 にしました。

 写真で見てわかるように、Z80PIOエリアにはICが
 ありません。

 手書きの回路図があったので、メモリとI/Oのアドレス
 空間を調べると、以下。Z80ファミリICは、80hから8Fh
 まで配置されています。90hから9Fhがユーザーへ開放
 されています。



 ROM、RAMは8kバイトの手持ちがあったので
 そのまま利用しました。

 I/Oの方は、Z80CTCを利用するだけに、80からの
 4バイトを占めるようにアドレスデコーダの
 74LS138を使っています。

 50ピンのコネクタに、Z80の40ピンの信号が
 出ているので、74LS138のイネーブル信号を
 利用して8255と8251を配置しました。

 8255を2つ配置し、90hから97hまでにアサインし
 8251は、98hから9Chに接続します。

 Z80には、4MHzのデバイス指定がありましたが
 Z80Hを利用して6MHzで動かします。

 Z80CTC、8251、8255は4MHz仕様なので、I/Oアクセス
 には、ウェイトを2個入れるようにします。

 WonderKitの基板が使えるかを、アセンブリ言語で
 雪ダルマ式に増やしていきます。

 スタックポインタ設定

  擬似命令を利用して、ラベルを定義し
  スタックポインタに入れ、無限ループ
  でダイナミックストップをかけます。

STKTOP	EQU	0h

  org 0h

start:
  ld  hl,STKTOP
  ld  sp,hl

loop:
  jr  loop

	end

 8255初期化

  8255を初期化するには、I/Oの回路図が必要です。
  I/Oは、次のようにアドレスデコーダを設計して
  います。74LSシリーズでは、入力に何も接続なし
  でも、Hとされるので、入力処理を省いてます。



  I/Oのアドレスデコーダから、8255を2個使っている
  ので、一方を00hから03h、もう一方を04hから07hに
  アサインして処理します。

  P82550A	EQU	90h
  P82550B	EQU	91h
  P82550C	EQU	92h
  P82550R	EQU	93h
  P82551A	EQU	94h
  P82551B	EQU	95h
  P82551C	EQU	96h
  P82551R	EQU	97h

  8255の入出力を次のようにして、スイッチ入力
  LED出力に決めて、動作テストします。

  P82550A(input)	switches
  P82550B(output)	LEDs(echo switch state)
  P82550C(output)	LEDs(echo switch inverse state)
  P82551A(input)	switches
  P82551B(output)	LEDs(echo switch state)
  P82551C(output)	LEDs(echo switch inverse state)

  8255初期化は、ポートAのみ入力で、ポートB、Cを
  出力に設定します。

INIT_8255:
  push	bc
  push	af
  ; set control register address
  ld	c,P82550R
  ld	b,P82551R
  ; set control word
  ld	a,80h
  out	(c),a
  ; resume address #1
  ld  c,b
  ; set control word
  out	(c),a
  ;
  pop	af
  pop	bc

  ret

  ポートAの入力値をポートBには、そのまま出力し
  ポートCには反転して出力します。

main:
  ; set I/O address
  ld  c,P82550A
  ld  d,P82550B
  ld  e,P82550C
  ; get information #0 8255
  in  a,(c)
  ; echo
  ld  c,d
  out (c),a
  ; inverse
  cpl
  ; echo
  ld  c,e
  out (c),a
  ; set I/O address
  ld  c,P82551A
  ld  d,P82551B
  ld  e,P82551C
  ; get information #1 8255
  in  a,(c)
  ; echo
  ld  c,d
  out (c),a
  ; inverse
  cpl
  ; echo
  ld  c,e
  out (c),a
  ;
  jr  main

  まとめると、以下。

STKTOP	EQU	0h
P82550A	EQU	90h
P82550B	EQU	91h
P82550C	EQU	92h
P82550R	EQU	93h
P82551A	EQU	94h
P82551B	EQU	95h
P82551C	EQU	96h
P82551R	EQU	97h

  org 0h

start:
  ld  hl,STKTOP
  ld  sp,hl
  jp  main

  org 100h

main:
  ; set I/O address #0 8255
  ld  c,P82550A
  ld  d,P82550B
  ld  e,P82550C
  ; get information #0 8255
  in  a,(c)
  ; echo
  ld  c,d
  out (c),a
  ; inverse
  cpl
  ; echo
  ld  c,e
  out (c),a
  ; set I/O address #1 8255
  ld  c,P82551A
  ld  d,P82551B
  ld  e,P82551C
  ; get information #1 8255
  in  a,(c)
  ; echo
  ld  c,d
  out (c),a
  ; inverse
  cpl
  ; echo
  ld  c,e
  out (c),a
  ;
  jr  main

INIT_8255:
  push	bc
  push	af
  ; set control register address
  ld	c,P82550R
  ld	b,P82551R
  ; set control word
  ld	a,80h
  out	(c),a
  ; resume address #1
  ld  c,b
  ; set control word
  out	(c),a
  ;
  pop	af
  pop	bc
  ret

  end

  8255とスイッチ、LEDの接続は、以下。



 8251初期化

  8251の初期化では、通信する前に内部レジスタに
  入っているゴミを追い出すことが必要です。

  データをパラレルからシリアルに変換するために
  クロックが必要になります。通信速度を決定する
  ために、分周回路が用意します。

  分周回路は、カウンタでよいので4040を利用します。

  通信速度の16倍のクロックを利用するので、1200bps
  から9600bpsで、周波数がどの程度になればよいかを
  計算しておきます。

  AWKを利用して計算すると、以下となりました。

  6MHzをシステムクロックにしているので
  Z80CTCをタイマーモードにし、源になる
  クロックを生成します。

  8251のピンアサインは、以下。
  (DTRとDSR、CTSとRTSを直結します。)



  シリアルインタフェースのための回路は、トランジスタ
  を利用した簡易回路で対応します。
  トランジスタは、小信号のNPNであれば、何でもよいです。



 8255と8251は、拡張基板の上に実装してありますが
 Z80CTCは、Z80を実装した基板上にあります。

 Z80CTCの動作をテストするプログラムを作成します。

 CTCは、ZC/TO0、ZC/TO1、ZC/TO2の3出力に異なる
 周波数のクロックを出力してチェックします。

 CPUが利用しているクロックが6MHzなので、分周してと
 考えましたが、4MHzのシステムクロックを利用すると
 なっているので、2分周して使います。

 2分周は、フリップフロップ74LS74で実現します。




 3MHzをZ80CTCのφに接続して、次のように設定します。

 ZC/TO0 prescaler:1/16  time constant:256 (732Hz)
 ZC/TO1 prescaler:1/256 time constant:128 (92Hz)
 ZC/TO2 prescaler:1/256 time constant:256 (45Hz)

 CTCをタイマーモードを利用します。
 CTCの制御レジスタには、次の項目を指定。

割込み    0:割込みなし     1:割込みあり
モード    0:タイマーモード   1:カウンターモード
プリスケーラ 0:1/16        1:1/256
パルスエッジ 0:falling       1:rising
起動指示   0:自動        1:トリガーパルス (タイマーモードでのみ有効)
定数     0:時間定数書込みなし 1:時間定数書込みあり
リセット   0:時間定数書込み無視 1:時間定数書込みまで待機
制御ワード  1:チャネル制御語指定

 割込みを使わなければ、各チャネルの初期化は
 次の手順を踏みます。

 制御ワードライト
 時間定数ライト

 このシーケンスをチャネル回数だけ繰り返します。
 制御ワードと時間定数を定義して、OUT命令で転送です。

 CTCのI/Oアドレスは、次のように定義。

  CTC_C0 EQU 80H
  CTC_C1 EQU 81H
  CTC_C2 EQU 82H
  CTC_C3 EQU 83H

 チャネル0から2までの制御ワードと時間定数を定義します。

  C0INI  EQU 15H ; 00010101
  C0TCNT EQU 00H ; 00000000(256)
  C1INI  EQU 35H ; 00110101
  C1TCNT EQU 80H ; 10000000(128)
  C2INI  EQU 35H ; 00110101
  C2TCNT EQU 00H ; 00000000(256)

 ここまで定義したなら、ダイナミックストップで
 Z80CTCだけが動くようにします。

SENT EQU 0E000h
STKT EQU 0000h

; CTC I/O address
CTC_C0 EQU 80H
CTC_C1 EQU 81H
CTC_C2 EQU 82H
CTC_C3 EQU 83H

; CTC control word and time constant
C0INI  EQU 15H ; 00010101
C0TCNT EQU 00H ; 00000000(256)
C1INI  EQU 35H ; 00110101
C1TCNT EQU 80H ; 10000000(128)
C2INI  EQU 35H ; 00110101
C2TCNT EQU 00H ; 00000000(256)

  org 0h
  ld  sp,STKT
  jp  start

  org 100h
start:
  call  INIT_CTC

main:
  ;
  nop
  ;
  jr    main

;*****************************
INIT_CTC:
  push  af
  push  bc
  ; CTC channel 0
  ld    a,C0INI
  ld    c,CTC_C0
  out   (c),a
  ld    a,C0TCNT
  out   (c),a
  ; CTC channel 1
  ld    a,C1INI
  ld    c,CTC_C1
  out   (c),a
  ld    a,C1TCNT
  out   (c),a
  ; CTC channel 2
  ld    a,C2INI
  ld    c,CTC_C2
  out   (c),a
  ld    a,C2TCNT
  out   (c),a
  ;
  pop   bc
  pop   af
  ret

  end

 手持ちのROMは、27128がありました。



 アクセスタイムを見ると250nsです。

 6MHzで動いているZ80CPUでは、命令を取出すときの
 タイミングが間に合いません。
 nWAITを利用して、2回ウェイトを入れます。



 M1信号で命令を取出すフェーズになるので、この
 信号を利用して、シフトレジスタでシーケンサを
 作っておきます。

 シーケンサは、M1が'L'になったなら、状態値を00→01と
 変化させ、01→11→10→00とクロックごとに状態変化し
 00で停止します。00となったときには、M1が'H'になって
 いるので、'L'になるまで待機します。

 タイミングチャートでみると、次のようになります。



 外付けシーケンサは、M1信号だけで反応するので、通常の
 リードサイクルには、影響しません。

 シーケンサは、デジタル回路でマイコンのような確定した
 動作をさせるために使います。

 WAIT回路は、シーケンサがとる4状態(00、01、11、10)を
 00→01→11→10と動かすときに、00で止めておいてM1信号
 をトリガーにして00→01と状態遷移させます。01へと状態
 遷移してしまうとクロックが入る度に、01→11→10→00と
 状態を変えます。00に戻ると、M1信号がディセーブルに
 なっているので、そこでストップモーションを繰返す仕様
 にしました。M1信号が入らないと、00を保持しています。

 リードサイクルでは、次のタイミングチャートになります。



 6MHzでZ80CPUが動作すると、1周期は167nsになります。
 アクセスタイムが250nsで問題がないかを計算してみます。

 T1のfalling_edgeで、nMREQ、nRD信号がイネーブルになり
 T2のrising_edgeまで83nsほど時間があります。
 アドレスデコーダで83nsの半分の時間を使うとして40ns。
 T3のrising_edgeまでには、167ns+40ns=207nsに。
 T3のfalling_edgeまでには、207ns+83ns=283nsとなり
 アクセスタイムが250nsでも30nsの余裕があります。

 この計算は、ワーストケースなので30nsより大きい50ns
 程度の余裕があり、充分データをROMから取出せます。

 T3のfalling_edgeの30ns前にデータは確定しているので
 セットアップタイムを確保できます。

 この処理のために外付け回路を半田付けした後
 手書きの回路図を見ると、Z80CTCからタイマー
 割込みをかけるようになっていました。

 Z80CTC、Z80PIOのIEI、IEOを接続してディジー
 チェインで、割込みの優先順位をZ80CTC→Z80PIO
 #1→Z80PIO#2→Z80PIO#3となっていました。

 Z80CTCのZC/TO、CLK/TKの接続は、以下。



 外部のCMOS4040で、64分周しています。

 4040の出力クロックを利用し、チャネル
 1、2、3では、カウンタモードで分周
 していけます。チャネル3で割込み処理
 ができるように設計されています。

 チャネル0は、カウンタモードで動作させ
 ZC/TO_0からクロックを出力できます。
 4040で64分周するので、チャネル1に入る
 クロックは、次式で計算できます。

 φを、プリスケーラで1/16か1/256。
 カウンタでの分周は、2から256。
  φx1/16x(1/2から1/256)
  φx1/256x(1/2から1/256)

 φは4MHzで設計されていたので、プリスケーラ1/16とし
 250分周すると、1kHzを生成できます。

 チャネル1から3は、カウンタモードで動作させるので
 分周比を2から256までの値から選んで組み合わせると
 相当細かい精度をもったタイマー割込みを発生させられ
 ます。

 φを3MHzとして、プリスケーラを1/16に選び
 75分周すると、ZC/TO_0からは2500Hzを出力
 できます。

 WonderKit基板に50ピンのコネクタを半田付けし
 外部基板と接続できるようにし、この基板上に
 WAIT回路を入れることにします。
 50ピンの信号は、以下となっています。

50 A11   49 A10
48 A12   47  A9
46 A13   45  A8
44 A14   43  A7
42 A15   41  A6
40 φ    39  A5
38  D4   37  A4
36  D3   35  A3
34  D5   33  A2
32  D6   31  A1
30 Vcc   29  A0
28  D2   27 GND
26  D7   25 nRFSH
24  D0   23 nM1
22  D1   21 nRESET
20 nINT  19 nBUSRQ
18 nNMI  17 nWAIT
16 nHALT 15 nBUSAK
14 nMREQ 13 nWR
12 nIORQ 11 nRD
10 GND    9
 8 GND    7 nSYSTEM_RESET
 6 (nY7)  5 (nY6)
 4 (nY5)  3 (nY4)
 2 Vcc    1 Vcc

 11から50に、Z80の信号をそのまま接続
 してあります。In Circuit Emulatorを
 接続するには、適した配置でしょう。

 3から6のnY4からnY7は、I/Oのアドレス
 デコーダのnCS信号をジャンパー線で接続
 しました。

 nY4からnY7を利用すると、4つのI/Oを確保
 できることになります。
 8255、8251を接続するには最適です。

 8255、8251のリセットは、正論理なので
 nRESETをトランジスタで反転しRESETに
 します。

 インバータなら、74LS04や74LS14で充分
 ですが、14ピンのICをひとつの反転処理
 に利用すると、5ゲートが余ってしまう
 ので、不経済です。こういう場合、安価
 に入手できるNPNトランジスタを使います。


目次

inserted by FC2 system