Verilogでは、同一モジュールを複数インスタンスするときは以下のようにgenerate forが使える。
for (genvar i=1; i<=10; i=i+1) begin subblock u_subblock( .clk(clk), .reset_n(reset_n), .a(a[i]), .b(b[i]), .out(out[i]) ); end
これと同様に、Chiselでもfor文を用いた同一モジュールの複数インスタンス化が行える。書き方は単純だ。
class multi_module (width: Int) extends Module() { val io = IO(new Bundle { val in0 = Input(Vec(width, UInt(32.W))) val in1 = Input(Vec(width, UInt(32.W))) val out = Output(Vec(width, UInt(32.W))) }) val sub_modules = for (w <- 0 until width) yield { val d = Module (new sub_module) d } sub_modules.zipWithIndex.map { case (sub, i) => sub.io.in0 := io.in0(i) sub.io.in1 := io.in0(i) io.out(i) := sub.io.out } }
大きく分けて2種類の手法を示した。一つはfor
文を用いてモジュールそのものをインスタンス化する。ここでは、multi_module
モジュールの中でsub_module
を複数回インスタンスしている。
インスタンスする個数はパラメータwidth
に依存している。
このとき、sub_modules
がその複数のモジュールを配列の形式として格納している。
サブモジュールを操作するにあたり、同様にfor文で回しても良いのだが、それ以外にmapを使った方法が取れる。
sub_modules.zipWithIndex.map
では、sub_modules
に格納されている複数のモジュールを、zipWithIndex
で0から番号のついたペアに変換し、それぞれに対してmapを行う。
sub_modules
:{sub_modules(0), sub_modules(1), sub_modules(2), sub_modules(3), ...}
sub_modules.zipWithIndex
:{{sub_modules(0), 0}, {sub_modules(1), 1}, {sub_modules(2), 2}, {sub_modules(3), 3}, ...}
それぞれに対して、入出力ポートを接続する記述をしている。 これで、生成されるVerilogは以下のようになった。
wire [31:0] sub_modules_4_io_in1; // @[multi_module.scala 15:20:@65.4] wire [31:0] sub_modules_4_io_out; // @[multi_module.scala 15:20:@65.4] sub_module sub_modules_0 ( // @[multi_module.scala 15:20:@53.4] .io_in0(sub_modules_0_io_in0), .io_in1(sub_modules_0_io_in1), .io_out(sub_modules_0_io_out) ); sub_module sub_modules_1 ( // @[multi_module.scala 15:20:@56.4] .io_in0(sub_modules_1_io_in0), .io_in1(sub_modules_1_io_in1), .io_out(sub_modules_1_io_out) ); sub_module sub_modules_2 ( // @[multi_module.scala 15:20:@59.4] .io_in0(sub_modules_2_io_in0), .io_in1(sub_modules_2_io_in1), .io_out(sub_modules_2_io_out) ); ... assign io_out_0 = sub_modules_0_io_out; // @[multi_module.scala 22:15:@70.4] ... assign io_out_4 = sub_modules_4_io_out; // @[multi_module.scala 22:15:@82.4] assign sub_modules_0_io_in0 = io_in0_0; // @[multi_module.scala 20:16:@68.4] ... assign sub_modules_2_io_in0 = io_in0_2; // @[multi_module.scala 20:16:@74.4] assign sub_modules_2_io_in1 = io_in0_2; // @[multi_module.scala 21:16:@75.4] assign sub_modules_3_io_in0 = io_in0_3; // @[multi_module.scala 20:16:@77.4] ... assign sub_modules_4_io_in1 = io_in0_4; // @[multi_module.scala 21:16:@81.4]