Posts Issued on August 19, 2026

BSVによるUARTの再設計 (2)

posted by sakurai on August 19, 2026 #1107

インタフェースを変えたため、呼び出し元のコードで書けば、元が

Tb.bsv

      Stmt test = seq
            uart.load(8'h55);
            uart.load(8'haa);
            uart.load(8'hc3);
            uart.load(8'h3c);
            await (uart.done());
            $finish;
      endseq;

これが

      Stmt test = seq
            uart.load(8'h55);
            uart.load(8'haa);
            uart.load(8'hc3);
            uart.load(8'h3c);
            uart.drain();
            $finish;
      endseq;

このようになります。大きなメリットは無いものの、AI曰く、

  • 第一に情報隠蔽の向きです。done 版は「完了したか」という述語をモジュールの外に公開し、それをどう使うか(待つのか、覗くだけか)は呼び側の責任で、await を書き忘れる余地があります。drain 版は待ち条件をモジュール側の呼出規約に畳み込むので、呼び側は呼ぶことしかできず、誤用の形が存在しません。
  • 第二に語彙の統一で、done 版の Tb は「呼出4回+述語待ち1回」の2語彙、drain 版は「呼出5回」の1語彙になります。
  • 第三に使い分けの指針も書けて、複数箇所から自由に覗きたい状態監視なら値メソッド(done)、シーケンスの合流点なら空アクション(drain)、という整理です。RUN_FSM マクロが await(F.done) を使っているのは前者の側で、これを後者に寄せる余地がある、という接続もできます。

呼び出し側の合成後の回路も同等で、前者が

  // rule RL_action_l17c18                                                                
  assign WILL_FIRE_RL_action_l17c18 =
             uart$done && state_mkFSMstate == 4'd4 ;

となるのに対し、後者は

  // rule RL_action_l17c17                                                                
  assign WILL_FIRE_RL_action_l17c17 =
             uart$RDY_drain && state_mkFSMstate == 4'd4 ;

となり、呼び出し側でも同一論理であることがわかります。前者はuartのdone、つまりfsmのdoneをawaitするという論理を発火論理に組み込むのに対して(awaitなどは消えている)、後者はdrainをコールするための自動バックプレッシャのRDYを発火論理に組み込むという違いとなります。


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