2021-02-09 13:32 — asano
カテゴリー:
前回メモリアクセスについて書いたので今回は本題のI/Oアクセスについてです。
最初はIN
命令です。
Op Code | Operand(s) | Object Code | Cycle | ROMC State | Timing | Status Flags | Interrupt | Function | |||
---|---|---|---|---|---|---|---|---|---|---|---|
O | Z | C | S | ||||||||
IN |
PP | 26 | L | 3 | 2 | - | - | - | - | DB ← PP | |
PP | L | 1B | 6 | 0 | 1/0 | 0 | 1/0 | A ← (I/O Port PP) | |||
S | 0 | 3S | - | - | - | - |
1サイクル目はオペランドのフェッチで詳細は前回を参照してください。CPU F3850はこの読み出された値を(おそらく)利用しません。
2サイクル目でF3850はROMC=1Bを出します。I/Oデバイスは直前のROMC=03の時のデータバスの値を控えておいてそのアドレスのポートからの値をデータバスに出力します。F3850はその値を読み取ってA
に入れ、フラグにも反映させます。
3サイクル目はお馴染み次命令のフェッチです。
続いてOUT
命令です。
Op Code | Operand(s) | Object Code | Cycle | ROMC State | Timing | Status Flags | Interrupt | Function | |||
---|---|---|---|---|---|---|---|---|---|---|---|
O | Z | C | S | ||||||||
OUT |
PP | 27 | L | 3 | 2 | - | - | - | - | DB ← PP | |
PP | L | 1A | 1 | - | - | - | - | I/O Port PP ← (A) | |||
S | 0 | 3S | - | - | - | - | x |
1サイクル目はIN
の場合と同様です。
2サイクル目でF3850はROMC=1Aと同時にA
の値をデータバスに出力してきます。I/Oデバイスは直前のROMC=03の時のデータバスの値を控えておいてそのアドレスにデータバスの値を書き込みます。
ROMC=3の時のデータバスをラッチしておき、ROMC=1A/1Bで実際の入出力動作を行なえば良さそうです。
これならROMCのデコードやタイミングの生成用にGALと、アドレスラッチ用に74LS573か74LS574あたりを載せれば一般的なバスに変換できそうということで作ってみました。
これはまだ検討始めた頃の写真、アドレスラッチはまだ実装していません。GALのRegister Mode使うのは初めてだったりするのでそのあたりの確認中です。新しいMSO1074Zが早速活躍しています。
上の部分には反対面にSBCF8へのコネクタがあります。実際に使っているピンは半分もなく、DB0~DB7, ROMC0~ROMC4, PHI, WRITE, VCC, GNDの17本です。
GALは手持ちのGAL16V8B-25QPを使いました。上下に並んでいるピンはプローブを接続したままGALを抜いて書き換えるために追加したものです。
現時点で書き込まれている論理を載せておきます。
Name f8io;
Partno GAL16V8B;
Date 2021/02/07;
Revision 2;
Designer asano;
Company Electrelic;
Assembly F8IO;
Location f8io;
Device G16V8;
/* Input */
Pin 1 = PHI;
Pin 2 = WRITE;
Pin 3 = ROMC0;
Pin 4 = ROMC1;
Pin 5 = ROMC2;
Pin 6 = ROMC3;
Pin 7 = ROMC4;
Pin 11 = !OE;
/* Output */
Pin 17 = ST0;
Pin 18 = ST1;
Pin 19 = ST2;
Pin 16 = !ALE;
Pin 15 = !IOR;
Pin 14 = !IOW;
/* */
ST0.d = !WRITE & !ST0;
ST1.d = !WRITE & ((ST1 & !ST0) # (!ST1 & ST0));
ST2.d = !WRITE & (ST2 # (ST1 & ST0));
c03 = !ROMC4 & !ROMC3 & !ROMC2 & ROMC1 & ROMC0; /* 03 */
c1a = ROMC4 & ROMC3 & !ROMC2 & ROMC1 & !ROMC0; /* 1A */
c1b = ROMC4 & ROMC3 & !ROMC2 & ROMC1 & ROMC0; /* 1B */
ALE = c03 & WRITE;
IOR = c1b & WRITE;
IOW = c1a & WRITE;
入力はピン11のOEをGNDに落としておく(これはGALの制約)以外はF3850から直結です。
ST0~ST2はタイミング調整用にクロックPHIをカウントしていたのですが、現状使っていません。
ALEは次の74ALS574にアドレスをラッチするためのもの。
IOR, IOWはいわゆる80系バスの信号です。クロック2MHzのときこれらのパルス幅は400ns~500nsもあるので十分とは思いますが、必要ならST0~ST2を使って幅を広げることにします。
GALの横にあるSN74ALS574Nはアドレスラッチ、ALSなのは手持ちの関係で使っているだけでLSなどでも問題ないはずです。
20ピンコネクタはI/Oバスとして引き出すためのもの、最初はここに8251を載せようと思っていたのですが、シンプルな回路で事前に確認したかったのと、シリアルクロックも含めて面積が不足する恐れがあったので別基板に分離することにしました。
ピン | 信号 | 備考 | ピン | 信号 | 備考 |
---|---|---|---|---|---|
1 | IOR | 2 | IOW | ||
3 | AB0 | LSB | 4 | DB0 | LSB |
5 | AB1 | 6 | DB1 | ||
7 | AB2 | 8 | DB2 | ||
9 | AB3 | 10 | DB3 | ||
11 | AB4 | 12 | DB4 | ||
13 | AB5 | 14 | DB5 | ||
15 | AB6 | 16 | DB6 | ||
17 | AB7 | MSB | 18 | DB7 | MSB |
19 | GND | 20 | VCC |
続いて裏側です。
SBCF8と接続するコネクタは下に線を通せるように少し浮かせて取り付けてあります。
(続く)
コメントを追加