見出し画像

A2PDP11 (8) コンソール ODT への入力

前回、コンソール ODT の出力ができるようになりましたが、ALE にノイズがのる現象が出ていました。ブレッドボードから、ワイヤーラッピングに変更したり、ダンピング抵抗を入れてみたりしましたが、改善せず。一旦諦めて、ソフト的な対処でしのぎます。
下図に、ノイズ発生時のキャプチャを示します。オレンジマーカーのタイミングで、ALE が一瞬 HIGH になっています。特に、17777566 (XBUF) アクセス時に、頻発します。

ALE のノイズ

top.sv を修正します。ALE がアサートしてからのクロック数をカウントし、0 のときだけ DAL をラッチするようにしました。

logic [7:0] count;
always_ff@(posedge clk) begin
    if (!ale_n) begin
        count <= count + 1'b1;
    end else begin
        count <= 0;
    end
end

logic [21:0] mdal;
logic [3:0] maio;
logic [1:0] mbs;
always_ff@(negedge ale_n) begin
    if (count == 0) begin
        mdal <= {dal_hi, dal_lo};
        maio <= aio;
        mbs <= bs;
    end
end

Tang Nano 9K および Arduino との接続を変更します。
ODT の送受信データは、レベル変換 IC を介して、Arduino と繋いでいます。
レベル変換は、SN74LVC245AN を使いました。3.3V 電源でも、5V 入力が可能です。

Tang Nano 9K および Arduino 接続図

Arduino のスケッチを修正します。
D2-D9 は、ODT 入出力データです。
DIR は、SN74LVC245AN のデータ方向切り替えで、Arduino と Tang Nano 9K 間のデータ送受信方向を示します。
 LOW の時、Tang Nano 9K から Arduino(ODT 出力データ)
 HIGH の時、Arduino から Tang Nano 9K(ODT 入力データ)
OE は、SN74LVC245AN の出力イネーブル信号(負論理)です。
RRDY(Read Ready)は、Arduino がデータを受信可能なとき HIGH になります。
RSTB(Read Strobe)は、Tang Nano 9K からの出力があるとき HIGH になります。
WRDY(Write Ready)は、Arduino から送信データがある時 HIGH になります。
WSTB(Write Strobe)は、Tang Nano 9K が Arduino からのデータ受信待ちの時 HIGH になります。

// ODT serial console interface
// TEST 5: 2024.08.10 Read ODT console out, nanja.info
// TEST 6: 2024.08.25 Read/Write ODT console, nanja.info

#define d0_pin 2
#define d1_pin 3
#define d2_pin 4
#define d3_pin 5
#define d4_pin 6
#define d5_pin 7
#define d6_pin 8
#define d7_pin 9
#define dir_pin 10    // LOW = Read from DCJ11, HIGH : Write to DCJ11
#define oe_n_pin 11   // ODT data enable
#define rrdy_pin 12   // Ready to read from DCJ11's ODT data
#define rstb_pin 13   // Strobe for read from DCJ11's ODT data
#define wrdy_pin 14   // Ready to write to DCJ11's ODT data
#define wstb_pin 15   // Strobe for write to DCJ11's ODT data

void setup() {
  Serial.begin(9600);
  pinMode(d0_pin, INPUT);
  pinMode(d1_pin, INPUT);
  pinMode(d2_pin, INPUT);
  pinMode(d3_pin, INPUT);
  pinMode(d4_pin, INPUT);
  pinMode(d5_pin, INPUT);
  pinMode(d6_pin, INPUT);
  pinMode(d7_pin, INPUT);
  pinMode(rrdy_pin, OUTPUT);
  pinMode(rstb_pin, INPUT);
  pinMode(wrdy_pin, OUTPUT);
  pinMode(wstb_pin, INPUT);
  pinMode(dir_pin, OUTPUT);
  pinMode(oe_n_pin, OUTPUT);
  digitalWrite(rrdy_pin, HIGH);
  digitalWrite(wrdy_pin, LOW);
  digitalWrite(dir_pin, LOW);
  digitalWrite(oe_n_pin, HIGH);
  Serial.println("Serial Start");
}

void loop() {
  static byte rdata;  // read from DCJ11's ODT data
  static byte wdata;  // write to DCJ11's ODT data
  if (digitalRead(rstb_pin)) {
    digitalWrite(dir_pin, LOW);
    pinMode(d0_pin, INPUT);
    pinMode(d1_pin, INPUT);
    pinMode(d2_pin, INPUT);
    pinMode(d3_pin, INPUT);
    pinMode(d4_pin, INPUT);
    pinMode(d5_pin, INPUT);
    pinMode(d6_pin, INPUT);
    pinMode(d7_pin, INPUT);
    digitalWrite(oe_n_pin, LOW);
    bitWrite(rdata, 0, digitalRead(d0_pin));
    bitWrite(rdata, 1, digitalRead(d1_pin));
    bitWrite(rdata, 2, digitalRead(d2_pin));
    bitWrite(rdata, 3, digitalRead(d3_pin));
    bitWrite(rdata, 4, digitalRead(d4_pin));
    bitWrite(rdata, 5, digitalRead(d5_pin));
    bitWrite(rdata, 6, digitalRead(d6_pin));
    bitWrite(rdata, 7, digitalRead(d7_pin));
    digitalWrite(oe_n_pin, HIGH);
    digitalWrite(rrdy_pin, LOW);
    Serial.write(rdata);
    digitalWrite(rrdy_pin, HIGH);
  } else if (digitalRead(wstb_pin)) {
    digitalWrite(dir_pin, HIGH);
    pinMode(d0_pin, OUTPUT);
    pinMode(d1_pin, OUTPUT);
    pinMode(d2_pin, OUTPUT);
    pinMode(d3_pin, OUTPUT);
    pinMode(d4_pin, OUTPUT);
    pinMode(d5_pin, OUTPUT);
    pinMode(d6_pin, OUTPUT);
    pinMode(d7_pin, OUTPUT);
    digitalWrite(d0_pin, bitRead(wdata, 0));
    digitalWrite(d1_pin, bitRead(wdata, 1));
    digitalWrite(d2_pin, bitRead(wdata, 2));
    digitalWrite(d3_pin, bitRead(wdata, 3));
    digitalWrite(d4_pin, bitRead(wdata, 4));
    digitalWrite(d5_pin, bitRead(wdata, 5));
    digitalWrite(d6_pin, bitRead(wdata, 6));
    digitalWrite(d7_pin, bitRead(wdata, 7));
    digitalWrite(oe_n_pin, LOW);
    digitalWrite(wrdy_pin, LOW);
  } else {
    if (Serial.available() > 0) {
      wdata = Serial.read();
      digitalWrite(wrdy_pin, HIGH);
    }
    digitalWrite(oe_n_pin, HIGH);
  }
}

top.sv の ODT の出力(XBUF)を Arduino に転送する部分を修正します。
rxrdy は DCJ11 の XCSR の done フラグで、HIGH の時、ODT の出力を処理できることを示します。
rrdy1 は、CLK に同期した、RRDY 信号です。
rstb は、Tang Nano 9K から Arduino への転送待ちを示します。
rdata は、ODT の出力データです。
ad は、Arduino との入出力データ接続ラインです。

ODT の出力(XBUF への書き込み)を rdata にラッチし、RSTB を HIGH します。同時に、rxrdy を LOW にして、ODT の次の出力を抑制します。
Arduino が受信すると RRDY が LOW になるので、RSTB を LOW にします。
受信が完了したら、rxrdy を HIGH にし、ODT の次の出力を受け付けるようにします。
バスリセット(GP CODE = 014)時に、rxrdy と RSTB をリセットするようにしました。 

logic rxrdy;
logic rrdy1;
logic rrdy0;
logic [7:0] rdata;
always_ff@(negedge clk) begin
    rrdy0 <= rrdy;
    rrdy1 <= rrdy0;
end

always_ff@(negedge clk) begin
    if ((sctl_n == 0) && (mdal == XBUF)) begin
        rstb <= 1'b1;
        rxrdy <= 1'b0;
        rdata <= dal_lo[7:0];
    end else if (!rrdy1) begin
        rstb <= 1'b0;
    end else if (!rstb) begin
        rxrdy <= 1'b1;
    end
    if (gp_code == 8'o014) begin
        rxrdy <= 1'b1;
        rstb <= 1'b0;
    end
end

assign ad = rstb ? rdata : 8'bz;

Arduino から、Tang Nano 9K へのデータ転送部を実装します。
wxrdy は、RCSR の done フラグで、HIGH の時、ODT への入力データがあることを示します。
wrdy1 は、CLK に同期した、WRDY 信号です。HIGH の時、Arduino から送信するデータがあることを示します。
wstb は、Tang Nano 9K から Arduino へのデータ転送待ちを示します。
wdata は、ODT への入力データです。

Arduino から出力データがある時(wrdy1  = HIGH)、WSTB を HIGH にし、データ転送待ち状態にします。
ad から wdata にデータをコピーし、WSTB を LOW にします。同時に、wxrdy を HIGH にして、DCJ11 に、ODT 入力があることを伝えます。
RBUF の読み取りを確認し(mdal == RBUF)、wxrdy を LOW にします。
バスリセット(GP CODE = 014)時に、wxrdy と WSTB をリセットします。

logic wxrdy;
logic wrdy1;
logic wrdy0;
logic [7:0] wdata;
always_ff@(negedge clk) begin
    wrdy0 <= wrdy;
    wrdy1 <= wrdy0;
end

always_ff@(negedge clk) begin
    if (wrdy1) begin
        wstb <= 1'b1;
    end else if (wstb) begin
        wdata <= ad;
        wstb <= 1'b0;
        wxrdy <= 1'b1;
    end else if (mdal == RBUF) begin
        wxrdy <= 1'b0;
    end
    if (gp_code == 8'o014) begin
        wxrdy <= 1'b0;
        wstb <= 1'b0;
    end
end

BUFCTL のアサート(LOW)時の、ODT インターフェースへの応答を修正します。
受信制御・状態レジスタ RCSR(17777560)の読み出しに対し、wrdy を返します。
送信制御・状態レジスタ XCSR(17777564)の読み出しに対し、rxrdy を返します。
受信バッファレジスタ RBUF(177777562)の読み出しに対し、wdata を返します。
それ以外の読み出し時は、odt_out をハイインピーダンスにし、dal_out を返します。

logic [15:0] dal_out;
logic [15:0] odt_out;
assign dal_lo = bufctl_n ? 16'bz : dal_out | odt_out;

always_ff@(negedge bufctl_n) begin
    if ((maio == DATA_READ) && (mbs == BS_EXT)) begin
        if (mdal == RCSR) begin 
            odt_out <= {8'b0, wxrdy, 7'b0};
        end
        if (mdal == XCSR) begin
            odt_out <= {8'b0, rxrdy, 7'b0};
        end
        if (mdal == RBUF) begin
            odt_out <= wdata;
        end
    end else begin
        odt_out <= 16'bz;
    end
end

コンソール ODT の動作を確認します。
下図は、<CR><LF>出力時の様子です。オレンジマーカー部で、XBUF に 015 <CR> が書き込まれます。赤マーカー部で、RRDY が LOW になり、Arduino がデータを受信したことがわかります。白マーカー部で RRDY が HIGH になり、Arduino のシリアル出力が完了し、次のデータ受信が可能になったことがわかります。

ODT 出力時の信号

数は、'0' を入力した時の様子です。
赤マーカー部で、WRDY が立ち上がり、Arduino から送信データがあることがわかります。オレンジマーカー部で、ad に '0'(060)が出力され、黄色マーカー部で、WRDY が LOW になり、データが wdata に取り込まれます。白マーカー部は、エコーバック出力を示します。

ODT 入力時の信号

コンソール ODT の入出力ができるようになりました。
数は、R0 レジスタに 123456 を書き込む様子です。

コンソール ODT

次はメモリを実装します。

参考文献

DCJ11 Microprocessor User's Guide, 5.3 CONSOLE ODT, 1983

この記事が気に入ったらサポートをしてみませんか?