Posts Tagged with "Design"

既に発行済みのブログであっても適宜修正・追加することがあります。
We may make changes and additions to blogs already published.

RISC-Vの調査(6)

posted by sakurai on June 17, 2020 #277

Bsimによるシミュレーション

QemuのシミュレーションからBsimのシミュレーションに切り替えます。ここで、Flute SoCではUARTのアドレスが異なっているため、テストプログラムのUARTアドレスを

<volatile char* UART0_ADDR = (char*)0x10000000;
>volatile char* UART0_ADDR = (char*)0xc0000000;

と変更した上でコンパイルします。

$ riscv32-unknown-elf-gcc -march=rv32i -mabi=ilp32 -nostartfiles -Tlink.lds -Wall -O2 hello.c -o hello.elf

ここで、リンカへの指示であるlink.ldsは以下のようにしています。

OUTPUT_ARCH("riscv")
ENTRY(main)

SECTIONS
{
    . = 0x80000000;
    .text.startup : { *(.text.startup) }
    .text   : {
            _start = .;
            *(.text);
            _text_end = .;
            exit = .;
         }
    .rodata : { *(.rodata) }
    .sdata   : { *(.sdata) }
    .bss    : { *.(.bss) }
    /DISCARD/ : { *(.comment);
          *(.riscv.attributes);
          *(.strtab*);
          *(.shstrtab);
        }
    . = ALIGN(8);
     = . + 0x4000;
    sp_top = .;
}

前稿で作成したelfを、Bsimによるシミュレーションが可能なhexファイルに変換します。これはFlute/Tests/elf_to_hex/elf_to_hexで行います。

$ ../Flute/Tests/elf_to_hex/elf_to_hex hello.elf Mem.hex
c_mem_load_elf: hello.elf is a 32-bit ELF file
Section .text.startup   : addr         80000000 to addr         8000006c; size 0x      6c (= 108) bytes
Section .sdata          : addr         80000068 to addr         80000070; size 0x       8 (= 8) bytes
Section .comment        : Ignored
Section .riscv.attributes: Ignored
Section .symtab         : Searching for addresses of '_start', 'exit' and 'tohost' symbols
Writing symbols to:    symbol_table.txt
    No 'exit' label found
    No 'tohost' symbol found
Section .strtab         : Ignored
Section .shstrtab       : Ignored
Min addr:                    80000000 (hex)
Max addr:                    80000073 (hex)
Writing mem hex to file 'Mem.hex'
Subtracting 0x80000000 base from addresses

作成されたhello.hexの内容は以下のようになっています。逆アセンブルリストと比較して概ね良さそうです。

@0000000    // raw_mem addr;  byte addr: 00000000
00c6802306c007130707a68300d7002306500613068006930707a703800007b7    // raw_mem addr 00000000;  byte addr 00000000
0707a70300d7002306f006930707a70300e680230707a68300e680230707a683    // raw_mem addr 00000001;  byte addr 00000020
000057b706c7a703800007b700e7802300a007130707a78300d7002302100693    // raw_mem addr 00000002;  byte addr 00000040
00000000000000000000000010000000001000000000806700f7102355578793    // raw_mem addr 00000003;  byte addr 00000060
@07fffff    // last raw_mem addr;  byte addr: 0fffffe0
000000000000000000000000000000000000000000000000000000000000000    // raw_mem addr 007fffff;      byte addr 0fffffe0

左矢前のブログ 次のブログ右矢

RISC-Vの調査(5)

posted by sakurai on June 15, 2020 #276

開発環境のインストール

開発環境のインストールを行います。最初にct-ngをインストールしようとしたのですが、RV32ではうまく行きませんでした。そこで、この記事を参考にインストールを実施しました。make中にインストールもしているので、あらかじめ/opt/riscvを作成しておき、記事中にもあるように自分が書き込み可能にしておくのが良さそうです。

qemuについてもこの記事のとおりにインストールしますが、

ERROR: glib-2.48 gthread-2.0 is required to compile QEMU

このようなエラーが出ました。私はFedora32を使用しているので、

$ sudo dnf install glib2 glib2-devel pixman-devel

と不足しているパッケージを追加したところ、configureが通ったので、makeします。

テストプログラム実行

早速、テストプログラムhello.cをコンパイルして実行してみます。Qemuを前提とするプログラムで、QemuのUartとシミュレーション停止アドレスが定義されています。

volatile char* UART0_ADDR = (char*)0x10000000;
volatile short* VIRT_TEST_ADDR = (short*)0x100000;

void _start(void) __attribute__((section(".text.startup")));

void _start(void) {
  *UART0_ADDR = 'h';
  *UART0_ADDR = 'e';
  *UART0_ADDR = 'l';
  *UART0_ADDR = 'l';
  *UART0_ADDR = 'o';
  *UART0_ADDR = '!';
  *UART0_ADDR = '\n';
  *VIRT_TEST_ADDR = 0x5555;
}

gccによりコンパイルし、qemuによりシミュレーションを行います。

$ riscv32-unknown-elf-gcc -march=rv32i -mabi=ilp32 -nostartfiles -Tlink.lds -Wall -O2 hello.c -o hello.elf
$ qemu-system-riscv32 -nographic -M virt -m 4096 -serial mon:stdio -bios none -kernel hello.elf
hello!

Qemuによりシミュレーションができました。また、逆アセンブラはobjdumpであり、以下の方法でアセンブルリストが確認できます。

$ riscv32-unknown-elf-objdump -D hello.elf

hello.elf:     ファイル形式 elf32-littleriscv

セクション .text.startup の逆アセンブル:

80000000 <_start>:
80000000:       800007b7                lui     a5,0x80000
80000004:       0707a703                lw     a4,112(a5) # 80000070 <sp_top+0xffffbff8>
80000008:       06800693                li      a3,104
8000000c:       06500613                li      a2,101
80000010:       00d70023                sb      a3,0(a4)
80000014:       06c7a683                lw      a3,108(a5)
80000018:       06c00713                li      a4,108
8000001c:       00c68023                sb      a2,0(a3)
80000020:       06c7a683                lw      a3,108(a5)
80000024:       00e68023                sb      a4,0(a3) 
:

左矢前のブログ 次のブログ右矢

RISC-Vの調査(4)

posted by sakurai on June 12, 2020 #275

シミュレーションモデルの波形を観測してみます。テストプログラムは、\$80000000から始まっていますが、シミュレーションは\$1000から始まっています。これはBootROMのようです。BootROMのブロックインが19サイクルかかっています。

図275.1はGtkwaveによるシミュレーション波形で、pcをオレンジ色で塗っています。

図%%.1
図275.1 シミュレーション波形

BootROMの処理が終わり、\$80000000にジャンプし、すぐに\$8000004cにジャンプしています。ここでpcだけを見ると、\$80000000が20サイクル、\$8000004cが24サイクルも継続しています。Linuxが動作するMMUを持つプロセッサであるためやむを得ないとはいえ、キャッシュアクセスレイテンシが大きいように思われます。
図%%.2
図275.2 シミュレーション波形(続き)

図275.2はテストプログラム実行中で、このような波形が続きますが、24サイクルのブロックインに引き続き、8命令を1サイクル実行しています。

左矢前のブログ 次のブログ右矢

RISC-Vの調査(3)

posted by sakurai on June 11, 2020 #274

前々稿の記事において、シミュレーションモデルが生成できましたが、これを実行させてみます。

テストプログラムは、add命令単体テストで、

80000000 <_start>:
80000000:       04c0006f                j       8000004c <reset_vector>
8000004c <reset_vector>:

8000004c:       f1402573                csrr    a0,mhartid
80000050:       00051063                bnez    a0,80000050 <reset_vector+0x4>
80000054:       00000297                auipc   t0,0x0
80000058:       01028293                addi    t0,t0,16 # 80000064 <reset_vector+0x18>
8000005c:       30529073                csrw    mtvec,t0
80000060:       18005073                csrwi   satp,0
:

80000100 <test_2>:
80000100:       00000093                li      ra,0
80000104:       00000113                li      sp,0
80000108:       00208f33                add     t5,ra,sp
8000010c:       00000e93                li      t4,0
80000110:       00200193                li      gp,2
80000114:       4ddf1663                bne     t5,t4,800005e0 <fail>

80000118 <test_3>:
80000118:       00100093                li      ra,1
8000011c:       00100113                li      sp,1
80000120:       00208f33                add     t5,ra,sp
80000124:       00200e93                li      t4,2
80000128:       00300193                li      gp,3
8000012c:       4bdf1a63                bne     t5,t4,800005e0 <fail>
:

のように構成されています。Bsimによるシミュレーションは、+v1で命令トレースが、+v2でパイプラインステージの内容を表示させるようになっています。+v2で実行させた結果をgrepにより計数してみると、表274.1のようになりました。パイプラインの各ステージの出力ステータスの意味は、以下のとおりです。

  • EMPTY --- 入力が来ないためアイドルとなっている
  • BUSY --- 入力があるが、処理中で出力がレディではない
  • PIPE --- 入力があり、パイプラインは正常な出力を行っている
  • NONPIPE --- 入力があり、出力は例外的な場合(トラップ等)

表274.1 ステージ毎のパイプラインの状態
状態 StageF StageD Stage1 Stage2 Stage3
BUSY 1,118 0 23 26 0
EMPTY 22 1,094 959 1,373 1,409
PIPE処理 743 789 901 484 474
合計 1,883

この表だけでもいろいろなことが推測されます。
  • 試験命令数は473命令だったので、CPI(Cycles Per Instruction)は3.98となりました。命令キャッシュミスのためにかなり大きく(悪く)なっています。
  • マシンサイクル1,883サイクルのうち、実際に処理しているのは半分くらいであり、主なパイプラインストールは命令キャッシュによるものだと考えられます。
  • StageFがBUSYの分だけStageD以降がEMPTYとなり、空いています。すなわち約1,100サイクルがパイプラインバブルとなっています。
  • Stage1に対してStage2のPIPE処理が半分なのは、ロードストア命令が半分(レジスタとロードストアが1:1)くらいだからかもしれません。
  • StageDに対してStage1のPIPE処理が増加しているのは、マルチサイクル命令のためかもしれません。

これだけ見るとかなり効率が悪そうですが、対象がテストプログラムでループが無いため、基本的にキャッシュミスが頻発します。一般のアプリケーションのようにループがあれば、ずっと効率が向上するはずです。


左矢前のブログ 次のブログ右矢

RISC-Vの調査(2)

posted by sakurai on June 10, 2020 #273

Fluteの階層構造

CPUの階層構造を図273.1に示します。5段のパイプラインは図273.1に示すように、"F"(命令Fetchステージ), "D"(命令デコードステージ), "1"(命令実行ステージ), "2"(メモリアクセス、長レインテンシステージ), "3"(ライトバックステージ)とステージ名が付けられています。なぜステージ"1”,"2",...,"5"でないかと言えば、3段パイプラインのPiccoloとステージを共用しているため書かれていました。Piccoloではパイプラインステージは”1", "2", "3"と名付けられており、Fluteでは、Piccoloの"1"を"F", ”D”, "1"に分解したようです。

図%%.1
図273.1 Flute CPU階層構造

各モジュールがmk〇〇と名付けられているのはBSVのお作法です。モジュールとそのインスタンスは一対nの関係にあり、モジュール名はいわばテンプレート名を意味するため、モジュールからインスタンスがmakeされるということを表しています。例えば上図のmkMMU_Cacheはどちらも同じモジュールですが、それぞれ命令用とデータ用に2個インスタンシエートしています。

キャッシュは上記のように、パラメタライズ可能な命令キャッシュ、データキャッシュの2つがあります。その他に、分岐予測器があります。


左矢前のブログ 次のブログ右矢

RISC-Vの調査

posted by sakurai on June 9, 2020 #272

BluespecのFluteプロセッサ

BluespecのBSVが読めるようになったところで、引き続いてFluteプロセッサの調査を行います。FluteはBluespecの開発したRISC-Vアーキテクチャの5段パイプラインRISC CPUです。それだけでなく、仮想記憶をサポートしているため、Linuxが動作します。(ページ)テーブルウォークはMMU内のハードウェアが実行します。ソースではステートベース設計のFSMで実装されていました。

Githubからダウンロード

$ git clone https://github.com/bluespec/Flute.git

としてGithubからダウンロードします。

RV32ACIMUアーキテクチャのBsimモデルの作成

アーキテクチャには各種ありますが、比較的軽いもの、例えば32bit、Floating無しのマイクロアーキテクチャを選択します。

$ cd builds/RV32ACIMU_Flute_bluesim

として、ターゲットディレクトリに移行します。

$ make all

と実行すると、

:
Simulation shared library created: exe_HW_sim.so
Simulation executable created: ./exe_HW_sim
INFO: linked bsc-compiled objects into Bluesim executable
$ 

このように、bsvで書かれたソースファイルがbscによりコンパイルされ、シミュレーションモデルであるexe_HW_simが生成されます。

RV32ACIMUアーキテクチャのBsimモデルの試験

$ make test

により、出来上がったシミュレーションモデルが、RISC-Vのテストスイートによりテストされます。

$ make test
make -C  ../../Tests/elf_to_hex
make[1]: Entering directory '/home/sakurai/src/bsv/riscv/Flute/Tests/elf_to_hex'
make[1]: 'elf_to_hex' is up to date.
make[1]: Leaving directory '/home/sakurai/src/bsv/riscv/Flute/Tests/elf_to_hex'
../../Tests/elf_to_hex/elf_to_hex  ../../Tests/isa/rv32ui-p-add  Mem.hex
c_mem_load_elf: ../../Tests/isa/rv32ui-p-add is a 32-bit ELF file
Section .text.init      : addr         80000000 to addr         80000604; size 0x     604 (= 1540) bytes
Section .tohost         : addr         80001000 to addr         80001048; size 0x      48 (= 72) bytes
Section .riscv.attributes: Ignored
Section .symtab         : Searching for addresses of '_start', 'exit' and 'tohost' symbols
Writing symbols to:    symbol_table.txt
    No 'exit' label found
Section .strtab         : Ignored
Section .shstrtab       : Ignored
Min addr:                    80000000 (hex)
Max addr:                    80001047 (hex)
 :
================================================================
Bluespec RISC-V standalone system simulation v1.2
Copyright (c) 2017-2019 Bluespec, Inc. All Rights Reserved.
================================================================
INFO: watch_tohost = 1, tohost_addr = 0x80001000
1: top.soc_top.mem0_controller_axi4_deburster::AXI4_Deburster.rl_reset
2:top.soc_top.rl_reset_start_initial ...
3: Core.rl_cpu_hart0_reset_from_soc_start
================================================================
CPU: Bluespec  RISC-V  Flute  v3.0 (RV32)
Copyright (c) 2016-2020 Bluespec, Inc. All Rights Reserved.
================================================================
6: D_MMU_Cache: cache size 8 KB, associativity 2, line size 32 bytes (= 8 XLEN words)
6: I_MMU_Cache: cache size 8 KB, associativity 2, line size 32 bytes (= 8 XLEN words)
512: top.soc_top.core.cpu.rl_reset_complete: restart at PC = 0x1000
514: Near_Mem_IO_AXI4.set_addr_map: addr_base 0x2000000 addr_lim 0x200c000
514: Core.rl_cpu_hart0_reset_complete
515: Mem_Controller.set_addr_map: addr_base 0x80000000 addr_lim 0x90000000
515:top.soc_top.rl_reset_complete_initial
instret:0  PC:0x1000  instr:0x297  priv:3
instret:1  PC:0x1004  instr:0x2028593  priv:3
instret:2  PC:0x1008  instr:0xf1402573  priv:3
:
instret:471  PC:0x80000044  instr:0xfc3f2023  priv:3
instret:472  PC:0x80000048  instr:0xff9ff06f  priv:3
instret:473  PC:0x80000040  instr:0x1f17  priv:3
2396: Mem_Controller.rl_process_wr_req: addr 0x80001000 (<tohost>) data 0x1
PASS
2397: top:.rl_terminate: soc_top status is 0x1 (= 0d1)
Simulation speed: 2396 cycles, 60915008 nsecs  = 39333 cycles/sec

テストスイートのelfを、elf_to_hexにより、asciiのメモリイメージファイルに変換しています。

これはadd命令単体のテストですが、全てのテストを行うには、以下のように実行します。

$ make isa_tests

と実行すると、

:
Worker 1: Test: rv32um-p-mul PASS [So far: total 67, executed 34, PASS 34, FAIL 0]
Worker 0 executed 33 tests, of which 33 passed
Worker 1 executed 34 tests, of which 34 passed
Total tests: 67 tests
Executed:    67 tests
PASS:        67 tests
FAIL:        0 tests
Finished running regressions; saved logs in Logs/

のように出力され、67個全てのテストが実行され、全てパスしたことが表示されます。


左矢前のブログ 次のブログ右矢

ゲームFSMとサウンドFSMの連携

posted by sakurai on June 5, 2020 #271

Ultra96においてBSVで開発

元々Verilog版では、コマンドバッファに書き込むだけで特に何もしなくても動作していました。今回BSVで再設計する際に、サウンドを4chとし、取りこぼしを避けるために考えたのがサウンドキュー(FIFO)でした。

図%%.1
図271.1 サウンドキュー

これはVivadoのFIFOジェネレータで作成したため、最小段数でもかなり深く1024段程度となっています。 実験したところ、確かに取りこぼしは無いのですが、一方、サウンドがゲームとズレて行き、まるでサウンドレコーダのような動作になってしまいました。そのため、FIFOを1段に修正しました。FIFOジェネレータでは1段のFIFOは作成できないのでVerilogで記述しました。1段のためFIFOと呼ぶのはおかしいのでコマンドバッファと呼ぶことにします。

コマンドバッファには、ゲームFSMからコマンドが来たことを示すフラグemptyを設け、書き込むと!emptyとなるようにします。サウンドFSMからは!emptyの時に新たにコマンドが来たと判断し、コマンドを読んだ後にemptyに変更します。

図%%.2
図271.2 1段バッファに変更

Artyボード移植後

Ultra96ではこれで動作していたのですが、Artyボードに移植後に自機増加音が無視されることに気づきました。サウンドFSMが取りこぼしているのだと推測し、再考すると、ゲームFSMが不必要に速いことに気づきました。DSOを接続して調べたところ、96.4%がウェイトだと判明したので、これを1MHzに落としたところ、動作するようでした。

ところが実験すると、依然として自機増加音(コマンドNo.9)が無視されるようです。そこで、ILAを接続して、

  • サウンドコマンド
  • サウンドFSMステート
  • コマンドバッファemtpy
  • サウンドFSM内部フラグ(fNO9)

を観測しました。最後の内部フラグfNO9は自機増加音がプリエンプトされないように割込みを禁止するためのフラグで、コマンドNo.9を受け付けた際にTrueになる信号です。

図%%.3
図271.3 ILA波形(NG)

図271.3はゲームFSMクロックを2MHzとして取得したものですが、フラグfNO9がTrueにならず、コマンドNo.9を無視しています。その原因は、サウンドFSMが受け取る前に次のコマンドNo.4を上書きしているためです。

従って、コマンドの書き込みの際にemptyである場合のみ書き込み、!emptyの場合は捨てる処理を行います(図271.4のマゼンタ矢印の処理を追加)。

図%%.4
図271.4 両側でemptyを確認するように修正

このように修正したところ、No.9の次のコマンドが!empty(=buffer full)のため捨てられることにより、図271.5のように受け付けられるようになりました。
図%%.5
図271.5 ILA波形(OK)

FIFOではないので、原理上取りこぼしは防げないものの、実用上これで動作するようです。

左矢前のブログ 次のブログ右矢

posted by sakurai on June 4, 2020 #270

QSPIフラッシュへの書き込み

通常ではVivadoからPROGRAM AND DEBUG⇒Open Hardware Manager⇒Open Target⇒Auto Connectとし、Program DeviceによりJTAG経由でFPGAにビットストリームを焼きこみます。しかしながらこれだと電源断によりFPGAのSRAM内容が消えてしまいます。また、FPGAプログラミング用のPCが常に必要です。オンボードFlashにデータを焼きこめばPCを持ち運ぶ必要がなく、電源onでアプリケーションが立ち上がるため、Flashのプログラミングを行います。

binファイルの作成

最初にFlashへ書き込むデータファイルであるbinファイルを用意します。これは、Tools⇒Setting(歯車マーク)⇒Project Settings⇒Implementation画面で行います。この画面を開くと、Write Bitstream(write_bitstream)という選択枝が現れ、その下に複数のチェックボックスが表示されます。その中の、-bin_file*のチェックボックスにチェックします。

図%%.1
図270.1 bin_fileにチェック

これを行ってから、通常どおりPROGRAM AND DEBUG⇒Generate Bitstreamを実施するとWrite Bitstreamが完了しますが、同時にbinファイルが生成されています。場所はbitファイルと同じところで'プロジェクト/プロジェクト.runs/impl_1/'です。

binファイルの焼きこみ

binファイルができたら、Add Configuration Memoryにより、Add Configuration Memory Device画面が開きます。Flashデバイスの選択が可能なので、この中で"s25fl128sxxxxx0"を選択します。Search窓にs25fl128を入力すれば、候補が3つ現れますがその真ん中です。

図%%.2
図270.2 FLASHデバイスの選択

選択したらOKをクリックします。するとプログラミングが始まり、30秒程でプログラミングが完了します。

実行

リファレンスマニュアルにはJP1でプログラミングモードが決まるとあります。JP1の位置がどちらでもJTAGからは書き込めるとのことです。初期状態はJP1はショートで、SPI-FLASHのモードとなっており、そのまま電源のOFF⇒ONでSpace Invadersが立ち上がりました。

図%%.3
図270.3 JTAG接続なしにSpace Invadersが動作


左矢前のブログ 次のブログ右矢

posted by sakurai on June 3, 2020 #269

Arty A7-35ボードの購入

DigilentからArty A7-35ボード(魚拓)を購入しました。このボードはUltra96と比べて本体が約半額と安いだけでなく、(弊社開発の)PMOD変換ボードも不要なので、最も安くSpace Invadersを動かすことができます。

必要な周辺

Space Invadersを動作させるには、Artyボードの他に必要なものは以下のとおりです。

Arty A7-35ボードへの移植

除算器を引き算に変換

FPGAの世代や遅延、容量は違うものの、基本的には同様に動作するはずです。ところが、一部動作がおかしかったので修正しました。まず、除算器にバグがあるようなので引き算方式に修正しました。スコアを表示する箇所において、各桁表示のため1000、100、10で割る場合がありますが、1000で割った商を誤ることがあるようです。除算をやめ、引けなくなるまで1000、100、10を引く方式に変更したところ、回路規模も小さくなり正常に動作するようになりました。

FSM clockを1/10に変更

ゲームFSMクロックを10MHzで設計し、96.4%がウェイトだと判明したので、FSMクロックを1MHzに落としました。自機増加音が無視されることがあるので、クロックを落としたのですが、原因は異なっていました(後述)。

60Hzクロックの生成

この修正により、FSMの待ち時間が影響を受けます。1tick=60HzのタイミングをとるのにFSMクロック数を数えていましたが、FSMクロックの周波数が変わるため、外部から60Hzを入力するように修正します。60Hzクロックは、上記FSMクロックである1MHzクロックをバイナリカウンタで\$411B回カウントすることで生成します。さらにFSM内での60Hzクロックとの同期は以下のように行います。countはtick(=16.67msec)の何倍待たせるかを示す引数です。

     repeat(pack(extend(count))) seq
        await(tick == 0);
        await(tick == 1);
     endseq

60Hzクロックの"L"を待ち、もし"L"であれば次に"H"を待つようにします。これにより60Hzの立ち上がりに同期して動作することになります。

このように変更した結果、FSMの処理時間は10倍の約5msecに増加し、60Hzの周期16.67msecの約30%になりました。図269.2の黄線が60Hzクロック、青線がそれによる実行(Hでウエイト中、Lで実行中)を示します。

図%%.8
図269.8 青線が"H"でウェイト中


左矢前のブログ 次のブログ右矢

FM-7 Z80カードの調査(3)

posted by sakurai on June 2, 2020 #268

引き続き、Z80コネクタへの信号を解説します。また、Z80CPUの高速化に伴い、Z80⇒6809切り替え時にDRAMのRASプリチャージタイム不足が判明したため、その対策も取っています。

EB

EBはZ80のMREQに相当する信号のため、前稿でのライト信号(=$\text{R/}\overline{\text{W}}$, M5 5pin)とCPUの$\overline{\text{RD}}$の負論理ORを取り、EBとしています。

QB

QBは立ち上がりはアドレス有効を示す信号です。また、6809の場合はQBの立下りでデータ確定しますが、Z80は$\overline{\text{WR}}$の立ち下がりでデータ確定します。そのため$\overline{\text{WR}}$の反転をQBとして使用する場合、その考慮が本体DRAM側で必要となります。その理由からFM-7メインボードのDRAMの回路図では、Z80と6809でQBの論理を反転させています。

RWB

RWBは、前述のライト信号を後縁を広げてRWBとしています。またデータバスバッファのDIRも後縁を広げて制御しています。この理由は図268.3でも示されているように、ライトサイクル時にZ80からのデータの切れが悪く、MREQがネゲートされていてもまだ出ているように見えるためです。

DRAM RASプリチャージタイム不足

基本的には上記の回路で動作しますが、一点、Z80から6809に戻る時に問題があります。それはZ80のEBにより\$FD05に0をライトすると$\text{G/}\overline{\text{H}}$が1となり、すぐに6809からQが出力されます。そのため、RASのプリチャージタイム$\text{t}_\text{RP}$が不足となり、結果としてDRAM化けが起こります。これを解決するために、Z80から\$FD05にライトする場合には、D0を0とし、EB、QBを出力せずに、6809側のEでライトし、CPUを切り替えるようにしています。

本来であれば、このようなトリッキーなことをせずZ80カードがやっているように、6809側で切り替え信号を遅延させてバスアクセスを行えば良いはずですが、時期的に本体側の回路変更ができなかったのかもしれません。

I/O掲載のZ80カード

アーカイブサイトに1985年9月号の月刊I/Oが保存されていました。その中に「FM-7/New7/77 IC9個でできる! Z80カードの製作」という記事がありました。IC9個は簡易回路とのことで、動作が不安定のようです。一方、コンパチ回路は基本的に富士通純正回路のコピーであり、ゲートを組み替えているだけに見受けられます。従って回路は正しく動作するはずですが、記事中に2点誤りがあります。

  • Z80Wが負論理となっている⇒Z80Wは正論理です。記事中では負論理のバーがついていますが、Z80Wは正論理の”Z80 wait”の意味であり、正論理の6809動作中を示す信号です。つまり$\text{6809/}\overline{\text{Z80}}$を表します。筆者はこの$\overline{\text{Z80}}$を$\overline{\text{Z80W}}$と誤認したのかもしれません。ただしこれは表記上の問題であり、回路への実害はありません。
  • Z80カード側ではCPU(6809)のHALTと誤認する恐れがある⇒BA/BSだけで判断するとDMA(リフレッシュ)の場合と誤認するため、6809が動作中でないことを表すZ80Wとの論理をとっており、誤認しません。そもそも6809がHALT中にはDMAはかかりません。これも回路解釈の誤りで、回路への実害はありません。

左矢前のブログ 次のブログ右矢


ページ: