SSブログ
English Version

Z80GALの構想(その2)GALの設計 [Z80]

 前回の記事ではシリアル通信用のタイマー割込みを発生させるためのGAL22V10による分周器の実験について書き、GALで実現するには不適切なので8ピンのPICで対応予定であることを書きました。

 今回はシリアル通信用のタイマー以外の周辺機能(ROM/RAM切替え、SD Card用のSPI、調歩同期シリアル通信)のインターフェース部分をGALに実装すべく、GALの設計を行いましたのでメモを残しておきます。

 GALはPALにレジスタ(D-FF)が追加になったりしていますが、1個でSPIと調歩同期シリアルのシリパラ変換を実現できるほどパワフルではありません。今回はそれぞれのインターフェースに必要なビット単位でのインターフェースをGALで実現しました。

 現時点でのソースは下記になります。
 メモリ切替え用の23ピンに配置した「RAM」は外部に出す必要が無いのですが前回の記事に書いたようにNODE宣言してピンにアサシンしないようにすることができないようなのでもったいないですが外部ピンにアサインしています。

Z80ワンボードマイコン(Z80GAL)用GALソース
Name Z80GAL; Partno SA0001; Date 2020/10/22; Revision 001; Designer skyriver; Company Piclabo; Assembly None; Location None; Device G22V10; /*****************************************************************/ /* */ /* Memory select,Serial and SD-Card interface for Z-80 one borad */ /* by skyriver */ /*****************************************************************/ /* GAL22V10 +--- ---+ clock 1| |24 +5V /RESET 2| |23 RAM REG /MREQ 3| |22 /ROMRD /IORQ 4| |21 /RAMRD /RD 5| |20 SDCK REG /WR 6| |19 SDO REG A7 7| |18 SDI A6 8| |17 /SDCS REG A5 9| |16 DAT1 A4 10| |15 DAT0 A3 11| |14 TX REG GND 12| |13 RX +-------+ */ /** Inputs **/ PIN 1 = clock; /* Register Clock */ PIN 2 = !RESET; /* reset */ PIN 3 = !MREQ; /* memory request */ PIN 4 = !IORQ; /* I/O request */ PIN 5 = !RD; /* read */ PIN 6 = !WR; /* write */ PIN [7..11] = [A7..3]; /* address */ PIN 13 = RX; /* serial in */ PIN 18 = SDI; /* SPI data in */ /** Outputs **/ PIN 23 = RAM; /* select RAM 0:ROM 1:RAM */ PIN 22 = !RAMRD; /* RAM read */ PIN 21 = !ROMRD; /* ROM read */ PIN 20 = SDCK; /* SPI clock */ PIN 19 = SDO; /* SPI data out */ PIN 17 = !SDCS; /* SD chip select */ PIN 16 = DAT1; /* read pnly */ PIN 15 = DAT0; /* LSB of data : I/O */ PIN 14 = TX; /* serial out */ /* can't use NODE NODE N_ROM; NODE N_SDCK; */ field adr = [A7..3]; field baseadr = [A7..5]; field register = [RAM,SDCK,SDO,SDCS,TX]; /** address definition **/ $DEFINE AdBase 'h'e0 /* Base of I/O Address */ $DEFINE AdSetRAM 'h'f8 /* DAT0: 0:ROM, 1:RAM */ $DEFINE AdSdCs 'h'f0 /* SDCS DAT0: 1:act 0:disable,can write & read */ $DEFINE AdSdOut 'h'e8 /* SD clock, SDO */ $DEFINE AdSdIn 'h'e8 /* SD SDI */ $DEFINE AdSeri 'h'e0 /* serial in/out use dat0 */ /** logic definition **/ register.ar = RESET; register.sp = 'b'0; append RAM.d = DAT0 & IORQ & WR & adr:AdSetRAM; append RAM.d = RAM & !(IORQ & WR & adr:AdSetRAM); append RAM.oe = 'b'1; append RAMRD = RAM & MREQ & !IORQ & RD; append RAMRD.oe = 'b'1; append ROMRD = !RAM & MREQ & !IORQ & RD; append ROMRD.oe = 'b'1; append SDCK.d = DAT1 & IORQ & WR & adr:AdSdOut; append SDCK.d = SDCK & !(IORQ & WR & adr:AdSdOut); append SDCK.oe = 'b'1; append SDO.d = DAT0 & IORQ & WR & adr:AdSdOut; append SDO.d = SDO & !(IORQ & WR & adr:AdSdOut); append SDO.oe = 'b'1; append SDCS.d = DAT0 & IORQ & WR & adr:AdSdCs; append SDCS.d = SDCS & !(IORQ & WR & adr:AdSdCs); append SDCS.oe = 'b'1; append TX.d = DAT0 & IORQ & WR & adr:AdSeri; append TX.d = TX & !(IORQ & WR & adr:AdSeri); append TX.oe = 'b'1; append DAT0.oe = IORQ & RD & baseadr:AdBase; append DAT0 = SDI & IORQ & RD & adr:AdSdIn; append DAT0 = RX & IORQ & RD & adr:AdSeri; append DAT0 = SDCS & IORQ & RD & adr:AdSdCs; append DAT0 = RAM & IORQ & RD & adr:AdSetRAM; append DAT1.oe = IORQ & RD & adr:AdSdIn; append DAT1 = SDCS & IORQ & RD & adr:AdSdIn;


 WinCuplもだいぶ慣れてきたのでソース作成はあまり問題がないのですが、シミュレータを動かす度にSIファイルにヘッダ情報が無かったり、エラーが発生したりである程度複数なパターンをシミュレーションして確認するのは苦労します(一つのファイルで全て試験すればいいのかも)

 今回行ったそれぞれの機能についてのシミュレーション結果をメモとして残しておきます。

  1. ROM/RAM切替機能
     リセット後のメモリリードはROM側が選択されていて、メモリ切替え用I/Oアドレスに書き込むことでDAT0(LSB)が1の場合はRAM、0の場合はROMが選択されます。
     下図のシミュレーションは以下の動作のシミュレーションです。
    1. ROM選択状態でのメモリリード
    2. RAM選択操作(RAMが1になる)
    3. RAM選択状態でのメモリリード
    4. メモリ選択状態のリード(DAT0にRAMの状態が出力される
    5. ROM選択操作(RAMが0になる)

    ROM/RAM切替機能のシミュレーション結果

  2. SPIインターフェース
     GALに実装しているのはSPI用のクロックと選択信号(SDCS)の出力とSDI/SDOそれぞれの入出力機能です。実装するのはビット単位でのインターフェースだけでシリパラ変換等はZ80上のソフトで実現する予定です。
     下図のシミュレーションは以下の操作を確認しています。
    1. SDCS(選択信号)をactive(0)に設定
    2. クロックとSDOを1に設定
    3. クロックを0に変更
    4. クロックを1、SDOを0に設定
    5. SDI(1)とSDCS(1)の読込み
    6. SDI(0)とSDCS(1)の読込み

    SPIインターフェース機能のシミュレーション結果

  3. 調歩同期シリアル通信インターフェース
     シリアル通信に関してはGALに実装するのは送受用の2ビットのインターフェースのみです。
     下図のシミュレーションは以下の操作を確認しています。
    1. TXを1に設定
    2. TXを0に設定
    3. RX(1)の読込み
    4. RX(0)の読込み
    5. 0xE8のI/Oアドレス(SPI関連の読込み)の読込み(SDIを設定していなかったのでLSBは不定になっている)

    調歩同期シリアル通信インターフェース機能のシミュレーション結果


 シミュレーション時にSIファイルのヘッダ情報が空になるエラーが高い頻度で発生し手動で設定し直してもすぐになくなることもあり、回避方法がまだつかめていません。
 プロジェクトのファイル構成ツリーを見ると複数パターンのシミュレーションを管理できるように見えますがやり方が判っていません。
 まぁ、GALにはあまり複雑な機能は実装できないのでシミュレーターでの確認がなんとかできました。


★追記 2020/10/23 {
 WinCuplでコンパイルして生成されたJEDACファイルをTL866II Plusに読込む際に「format error」が表示される場合があります。
 ネットで探すと「GALを使ってみる.1」にもWinCuplで作ったJEDACファイルは読み込みエラーが発生するようなことが書いてあります。

 エラーが発生したJEDACファイルを調べてみると
  • JEDECファイルの末尾のチェックサムでエラーが発生しているのか確かめるためにエラーが発生しないJEDECファイルの末尾の^C前後のチェックコードを変更してからTL866で読込んでもエラーは発生しなかった
  • *Lの行を1行削除するとエラーは発生しなくなった
  • 読込みでエラーが発生してもTL866で読込んだ内容をファイルに書き出し、元のJEDECファイルと内容を比較すると違いは無かった
  • エラーが発生した場合(当然コンパイルは通るもの)でもPLDファイル内の論理式などを変更してJEDACファイルの行数が変わるとエラーが発生しなくなった

 以上のことからTL866で読込み時にエラーが表示されてもJEDECファイルの内容は読込まれているようです。
 エラーの表示は行数に依存する(ように見える)のでTL866側の問題の可能性が高いと思います。
 TL866II Plusのソフトを最新(App:Ver10.41,Firm:Ver04.2.122)にしても状況は同じでした。

 尚、JEDECファイルのフォーマットに関してはChaNさんの「PLDフューズファイルについて」を参考にさせて頂きました。
}
★追記 2020/10/24
 TL866で発生する「file format error」の画面キャプチャ追加

TL866II PlusでWinCuplで生成したJEDECファイル読込み時のエラー



★追記 2020/10/23 {
 今後も変更する可能性がありますが最新版を貼っておきます。
 ・メモリ後半のアクセスは必ずRAMになるように変更
 ・余分なIORQチェックを削除

★更新 2020/10/25 Ver0.02
 ・PICからのタイマー割込み信号を疑似的なopen drain出力にし、PullUp抵抗を追加
 ・タイマー割込み要求をGAL経由で読み込み可能とした
 ・これに伴いI/Oアドレスディコード用のアドレス線を一本削減

Z80ワンボードマイコン(Z80GAL)用GALソース(最新版)
Name Z80Gal; Partno SA0001; Date 2020/10/25; Revision 002; Designer skyriver; Company Piclabo; Assembly None; Location None; Device G22V10; /*****************************************************************/ /* */ /* Memory select,Serial and SD-Card interface for Z-80 one borad */ /* by skyriver */ /*****************************************************************/ /* GAL22V10 +--- ---+ clock 1| |24 +5V /RESET 2| |23 RAM REG /MREQ 3| |22 /ROMRD /IORQ 4| |21 /RAMRD /RD 5| |20 SDCK REG /WR 6| |19 SDO REG A7 7| |18 SDI A6 8| |17 /SDCS REG A5 9| |16 DAT1 TINT 10| |15 DAT0 A15 11| |14 TX REG GND 12| |13 RX +-------+ */ /** Inputs **/ PIN 1 = clock; /* Register Clock */ PIN 2 = !RESET; /* reset */ PIN 3 = !MREQ; /* memory request */ PIN 4 = !IORQ; /* I/O request */ PIN 5 = !RD; /* read */ PIN 6 = !WR; /* write */ PIN [7..9] = [A7..5]; /* address */ PIN 10 = TINT; /* Timer interrupt 1:active */ PIN 11 = A15; /* MSB of address */ PIN 13 = RX; /* serial in */ PIN 18 = SDI; /* SPI data in */ /** Outputs **/ PIN 23 = RAM; /* select RAM 0:ROM 1:RAM */ PIN 22 = !RAMRD; /* RAM read */ PIN 21 = !ROMRD; /* ROM read */ PIN 20 = SDCK; /* SPI clock */ PIN 19 = SDO; /* SPI data out */ PIN 17 = !SDCS; /* SD chip select */ PIN 16 = DAT1; /* data-bus(I/O) */ PIN 15 = DAT0; /* LSB of data-bus(I/O) */ PIN 14 = TX; /* serial out */ /* can't use NODE NODE N_ROM; NODE N_SDCK; */ field adr = [A7..5]; field baseadr = A7; field register = [RAM,SDCK,SDO,SDCS,TX]; /** address definition **/ $DEFINE AdBase 'h'80 /* Base of I/O Address */ $DEFINE AdSetRAM 'h'e0 /* DAT0: 0:ROM, 1:RAM */ $DEFINE AdSdCs 'h'c0 /* SDCS DAT0: 1:act 0:disable,can write & read */ $DEFINE AdSdOut 'h'a0 /* SD clock, SDO */ $DEFINE AdSdIn 'h'a0 /* SD SDI(=above) */ $DEFINE AdSeri 'h'80 /* serial in/out use dat0 */ /** logic definition **/ register.ar = RESET; register.sp = 'b'0; append RAM.oe = 'b'1; append RAM.d = DAT0 & IORQ & WR & adr:AdSetRAM; append RAM.d = RAM & !(IORQ & WR & adr:AdSetRAM); append RAMRD.oe = 'b'1; append RAMRD = RAM & MREQ & RD; append RAMRD = A15 & MREQ & RD; append ROMRD.oe = 'b'1; append ROMRD = !RAM & !A15 & MREQ & RD; append SDCK.oe = 'b'1; append SDCK.d = DAT1 & IORQ & WR & adr:AdSdOut; append SDCK.d = SDCK & !(IORQ & WR & adr:AdSdOut); append SDO.oe = 'b'1; append SDO.d = DAT0 & IORQ & WR & adr:AdSdOut; append SDO.d = SDO & !(IORQ & WR & adr:AdSdOut); append SDCS.oe = 'b'1; append SDCS.d = DAT0 & IORQ & WR & adr:AdSdCs; append SDCS.d = SDCS & !(IORQ & WR & adr:AdSdCs); append TX.oe = 'b'1; append TX.d = DAT0 & IORQ & WR & adr:AdSeri; append TX.d = TX & !(IORQ & WR & adr:AdSeri); append DAT0.oe = IORQ & RD & baseadr:AdBase; append DAT0 = SDI & IORQ & RD & adr:AdSdIn; append DAT0 = RX & IORQ & RD & adr:AdSeri; append DAT0 = SDCS & IORQ & RD & adr:AdSdCs; append DAT0 = RAM & IORQ & RD & adr:AdSetRAM; append DAT1.oe = IORQ & RD & (adr:AdSdIn # adr:AdSeri); append DAT1 = SDCS & IORQ & RD & adr:AdSdIn; append DAT1 = TINT & IORQ & RD & adr:AdSeri;

}


[TOP] [ 前へ ] 連載記事 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。