生成具有许多嵌套案例的块

时间:2019-05-22 20:52:52

标签: verilog system-verilog

我有一个包含n x n子模块网格的模块,其中每个子模块都连接到网格中的4个邻居。每个子模块大致如下所示:

                 | up_in
                 V
           ____________
 left_in   |           |  right_out
---------> | submodule | --------->
           |___________|
                 |
                 | down_out
                 V

顶部/底部行和最左/最右列中的子模块的接线方式必须与其余子模块不同,因为它们位于边缘。像下面这样的代码可以正常工作,但是很冗长,并且重复很多:

for (genvar row = 0; row < SIZE; row++) begin
    for (genvar col = 0; col < SIZE; col++) begin
        if (col == 0) begin
            if (row == 0) begin
                submodule sub(.left_in(special), .up_in(special), .right_out(normal), .down_out(normal))
            end else if (row < SIZE - 1) begin
                submodule sub(.left_in(special), .up_in(normal), .right_out(normal), .down_out(normal))
            end else begin
                submodule sub(.left_in(special), .up_in(normal), .right_out(normal), .down_out(special))
            end
        end else if (col < SIZE - 1) begin
            if (row == 0) begin
                submodule sub(.left_in(normal), .up_in(special), .right_out(normal), .down_out(normal))
            end else if (row < SIZE - 1) begin
                submodule sub(.left_in(normal), .up_in(normal), .right_out(normal), .down_out(normal))
            end else begin
                submodule sub(.left_in(normal), .up_in(normal), .right_out(normal), .down_out(special))
            end
        end else begin
            if (row == 0) begin
                submodule sub(.left_in(normal), .up_in(special), .right_out(special), .down_out(normal))
            end else if (row < SIZE - 1) begin
                submodule sub(.left_in(normal), .up_in(normal), .right_out(special), .down_out(normal))
            end else begin
                submodule sub(.left_in(normal), .up_in(normal), .right_out(special), .down_out(special))
            end
        end
    end
end

该子模块实际上具有4个以上的端口,因此修改端口的速度很慢且容易出错。我希望能够执行以下操作:

for (genvar row = 0; row < SIZE; row++) begin
    for (genvar col = 0; col < SIZE; col++) begin
        submodule sub(
            .left_in(col == 0 ? special : normal),
            .up_in(row == 0 ? special : normal),
            .right_out(col == SIZE - 1 ? special : normal),
            .down_out(row == SIZE - 1 ? special : normal)
        );
    end
end

但是这似乎不起作用,因为我不认为在制定时就对三元进行评估-我认为它们实际上已经变成了在设计中持久存在的多路复用器。我使用的三进制错误吗?是否有一些简洁的方法来生成此n x n子模块网格?

1 个答案:

答案 0 :(得分:1)

您可以通过首先创建用于通用连接的阵列来简化。阵列必须足够大以容纳所有连接,包括输入和输出。

//    vector                row     col
wire [WIDTH-1:0] leftright [SIZE]  [SIZE+1];
wire [WIDTH-1:0] updown    [SIZE+1][SIZE];

for( genvar row=0; row<SIZE; row=row+1) begin : r
  for( genvar col=0; col<SIZE; col=col+1) begin : c
    submodule #(WIDTH) sub(
      .left_in(leftright[row][col]),
      .up_in(updown[row][col]),
      .right_out(leftright[row][col+1]),
      .down_out(updown[row+1][col])
    );
  end
end

现在您有了一个链接子模块的数组,您可以根据需要将输入和输出映射到该数组。例如:

for( genvar i=0; i<SIZE; i++ ) begin : io_mapping
  // inputs
  assign leftright[i][0] = toplevel_left_in[i*WIDTH +: WIDTH];
  assign updown[0][i]    = toplevel_up_in[  i*WIDTH +: WIDTH];
  // outputs
  assign toplevel_right_out[i*WIDTH +: WIDTH] = leftright[i][SIZE];
  assign toplevel_down_out[ i*WIDTH +: WIDTH] = updown[SIZE][i]; 
end

注意:Verilog不支持3维以上的数组; SystemVerilog可以。要使用Verilog,请更改:

//    vector                row     col
wire [WIDTH-1:0] leftright [SIZE]  [SIZE+1];
wire [WIDTH-1:0] updown    [SIZE+1][SIZE];
// ...
      .left_in(leftright[row][col]),
      .up_in(updown[row][col]),
      .right_out(leftright[row][col+1]),
      .down_out(updown[row+1][col])
// ...

收件人:

//    vector                    row     col
wire [WIDTH-1:0] leftright [0:( SIZE  *(SIZE+1)) -1];
wire [WIDTH-1:0] updown    [0:((SIZE+1)*SIZE   ) -1];
// ...
      .left_in(  leftright[    row*(SIZE+1) + col]),
      .up_in(    updown[       row*SIZE     + col]),
      .right_out(leftright[    row*(SIZE+1) + col+1]),
      .down_out( updown[   (row+1)*SIZE     + col])
// ...