Posts Issued on September 16, 2026

posted by sakurai on September 16, 2026 #1121

接続法 1、EN/RDY を mkConnection でつなぐ

BSV流のEN/RDYによる接続を図1121.1に示します。

図1121.1
図1121.1 EN/RDY の接続

送り手 mkProducer は FIFO からの取り出しを Get で、受け手 mkConsumer は FIFO への書き込みを Put で公開し、最上位 mkTop が mkConnection でつなぎます。

package EnRdy;

import GetPut :: *;
import FIFOF  :: *;
import Connectable :: *;

// 送り手 : FIFO から取り出す Get
(* synthesize *)
module mkProducer (Get #(Bit #(8)));
   FIFOF #(Bit #(8)) q <- mkFIFOF;
   Reg #(Bit #(8)) cnt <- mkReg (0);

   rule fill;
      q.enq (cnt);
      cnt <= cnt + 1;
   endrule

   method ActionValue #(Bit #(8)) get;
      q.deq;
      return q.first;
   endmethod
endmodule

// 受け手 : FIFO に入れる Put
(* synthesize *)
module mkConsumer (Put #(Bit #(8)));
   FIFOF #(Bit #(8)) q <- mkFIFOF;

   rule drain;
      q.deq;
   endrule

   method Action put (Bit #(8) x);
      q.enq (x);
   endmethod
endmodule

// 最上位 : mkConnection でつなぐ
(* synthesize *)
module mkTop (Empty);
   Get #(Bit #(8)) p <- mkProducer;
   Put #(Bit #(8)) c <- mkConsumer;
   mkConnection (p, c);
endmodule

endpackage

bsc が生成した mkTop.v のモジュール本体です。

module mkTop(CLK,
	     RST_N);
  input  CLK;
  input  RST_N;

  // ports of submodule c
  wire [7 : 0] c$put;
  wire c$EN_put, c$RDY_put;

  // ports of submodule p
  wire [7 : 0] p$get;
  wire p$EN_get, p$RDY_get;

  // submodule c
  mkConsumer c(.CLK(CLK),
	       .RST_N(RST_N),
	       .put(c$put),
	       .EN_put(c$EN_put),
	       .RDY_put(c$RDY_put));

  // submodule p
  mkProducer p(.CLK(CLK),
	       .RST_N(RST_N),
	       .EN_get(p$EN_get),
	       .get(p$get),
	       .RDY_get(p$RDY_get));

  // submodule c
  assign c$put = p$get ;
  assign c$EN_put = p$RDY_get && c$RDY_put ;

  // submodule p
  assign p$EN_get = p$RDY_get && c$RDY_put ;
endmodule  // mkTop

mkConnection は Connectable 型クラスのメソッドで、インタフェースの組ごとにインスタンスが定義されています。Get と Put の組のインスタンスは、本質的に次のルール一つです。

instance Connectable #(Get #(a), Put #(a));
   module mkConnection #(Get #(a) g, Put #(a) p) (Empty);
      rule connect;
         let x <- g.get;
         p.put (x);
      endrule
   endmodule
endinstance

ルールの発火条件は、呼んでいるメソッド全部の RDY の AND です。get と put は RDY を持つ普通のメソッドなので、この接続ルールは mkTop の中の AND ゲート一つになりました。両端の RDY を集めて AND を取り、その結果を EN として両端に返しています。両端の中では、RDY は FIFO の状態そのもので、EN はそのまま FIFO の制御になります。mkProducer.v と mkConsumer.v の該当行です。

  // mkProducer.v
  assign get = q$D_OUT ;
  assign RDY_get = q$EMPTY_N ;
  assign q$DEQ = EN_get ;

  // mkConsumer.v
  assign RDY_put = q$FULL_N ;
  assign q$D_IN = put ;
  assign q$ENQ = EN_put ;

両端の判断は外の EN に委ねられ、EN で「今回は転送」と言われて動きます。


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