Posts Issued on May 27, 2024

BSVの問題点? (2)

posted by sakurai on May 27, 2024 #805

Uartをテストベンチに組み込み動作しました。次にFIFO付Uartに改造しようとしたところ、FIFOを接続すると最初に0xAAという未定義データが受信FIFOに入ることがわかりました。

そこでverilogコードを出力し波形観測したところ、確かにリセット直後に0xAAという未定義データがUartから出力され受信FIFOに入力されています。図805.1のようにリセット直後にRDY_readがアサートされていることが判明しました。

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

UartとFIFOを接続しているverilogコードを確認すると、uart$RDY_readはreadメソッドを呼ぶとアサートされ、それによりENQされることが判明しました。

 assign rfifo$ENQ = uart$RDY_read && rfifo$FULL_N ;

最初のFIFO無しの場合に動作していたのは、ステートマシンの値がデコードされていたのでリセット直後の値は無視されていたからです。一方FIFOを接続するとリセット直後からの未定義データもFIFOに入るため、エラーが顕在化したわけです。その理由は、以下のように常にuartをreadしてenqしているためです。

 /* receiver */
 rule forever_rfeceiver_inside;
    let rdata <- uart.read;
    rfifo.enq(rdata);
 endrule

リセット直後にRDY_readが誤って出ているのではないかと言う推測をしました。ここで、readメソッドは以下のようになっており、getfsmという受信fsmの完了信号であるgetfsm.doneによりreadを開始する論理となっています(下記)。

Uart.bsv(変更前):

    method ActionValue#(Bit#(8)) read if (getfsm.done);
       getfsmDone <= False;
       return idata;
    endmethod

getfsm.doneは直接観測できないものの、これがRDY_readとなっているだろうと推測し、getfsm.doneの代わりに相当するgetfsmDone信号に入れ替えてみます(下記)。getfsmDoneを作成しているgetfsmの部分も含めて示します。

Uart.bsv:(変更後)

    Stmt getseq = seq
       await(isdata == 1'h0);
       repeat (8) action
          idata <= {isdata, (idata >> 1)[6:0]};
       endaction
       getfsmDone <= True;
    endseq;
    FSM getfsm <- mkFSM(getseq);

    method ActionValue#(Bit#(8)) read if (getfsmDone);
       getfsmDone <= False;
       return idata;
    endmethod

この修正によりリセット直後のRDY_readは出力されなくなり、FIFOを接続しても正しく動作しました。

まとめるとRDY_readがおかしいというより、初期状態でgetfsm.doneがTrueになる点がおかしいと思われます。

本件についてフォーラムに問い合わせたところ、「mkFSMのdoneメソッドは、startのRDYと等価である。startはリセット後にレディになるので、doneメソッドも trueになる。startが呼び出された後にのみTrueとなる条件が必要な場合は、自分で実装する必要がある。」、つまり初期状態でgetfsm.doneがTrueなのは仕様とのことでした。


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