在 Verilog / SystemVerilog 中实例化处理元素网格的最佳方法?

Best way to instantiate grid of processing elements in Verilog / SystemVerilog?

我有一个 ProcessingElement.sv 模块,我想实例化一个可配置的数组,所以我想创建一个像这样的生成块:

module ProcessingArray #(parameter Y=14, X=14, W=16) (  
    input                   GlobalClk,
    input           [3:0]   OpCode,
    input           [W-1:0] DataIn,
    output logic    [W-1:0] DataOut 
    );

    

    genvar x, y;
    generate
        for (y=0; y<=Y; y++) begin 
            for (x=0; x<X; x++) begin
                ProcessingElement #(.W(16)) PE(
                    .Clk(GlobalClk),
                    .OpCode(OpCode),
                    .Input(DataIn),
                    .Output(DataOut)
                );
            end
        end
    endgenerate


endmodule

这似乎可以使用 Modelsim 进行编译,但我在寻找一种将数组元素相互连接的流畅方法时遇到了问题。通常,连接是如果 x > y,元素将水平连接;如果 y > x,垂直;如果 x == y,两者都是 AND 对角线。 这是左上角 3x3 网格如何连接的示例:

[连接数][1]

有没有办法在循环中引用(例如,通过命名实例)每个生成的实例?如果有的话,也许我可以制作另一个执行所有分配的生成语句。

本人对Verilog/SV比较陌生,如果有更好的方法,不胜感激

编辑: 这是一个展开的例子

module ProcessingArray #(parameter Y=14, X=14, W=16) (  
    input                   GlobalClk,
    input           [3:0]   OpCode,
    input           [W-1:0] DataIn,
    output logic    [W-1:0] DataOut 
    );

ProcessingElement #(.W(16)) PE_00(
    .Clk(GlobalClk),
    .OpCode(OpCode),
    .Input(DataIn),
    .Output(DataOut_00)
);

// For readability
wire wire00_01 = DataOut_00;
wire wire00_10 = DataOut_00;
wire wire00_11 = DataOut_00;

ProcessingElement #(.W(16)) PE_01(
    .Clk(GlobalClk),
    .OpCode(OpCode),
    .Input(wire00_01),
    .Output(DataOut_01)
);

wire wire01_02 = DataOut_01;

ProcessingElement #(.W(16)) PE_02(
    .Clk(GlobalClk),
    .OpCode(OpCode),
    .Input(wire01_02),
    .Output(wire02_elsewhere)
);

ProcessingElement #(.W(16)) PE_10(
    .Clk(GlobalClk),
    .OpCode(OpCode),
    .Input(wire00_10),
    .Output(DataOut_10)
);

wire wire10_20 = DataOut_10;

ProcessingElement #(.W(16)) PE_11(
    .Clk(GlobalClk),
    .OpCode(OpCode),
    .Input(wire00_11),
    .Output(DataOut_11)
);

wire wire11_12 = DataOut_11;
wire wire11_21 = DataOut_11;
wire wire11_22 = DataOut_11;

ProcessingElement #(.W(16)) PE_12(
    .Clk(GlobalClk),
    .OpCode(OpCode),
    .Input(wire11_12), 
    .Output(DataOut_12)
);

ProcessingElement #(.W(16)) PE_20(
    .Clk(GlobalClk),
    .OpCode(OpCode),
    .Input(DataIn), 
    .Output(DataOut_20)
);

ProcessingElement #(.W(16)) PE_21(
    .Clk(GlobalClk),
    .OpCode(OpCode),
    .Input(wire11_21), 
    .Output(DataOut_21)
);

ProcessingElement #(.W(16)) PE_22(
    .Clk(GlobalClk),
    .OpCode(OpCode),
    .Input(wire11_22), 
    .Output(DataOut)
);

endmodule

您可以做的是创建一个二维数组,并在生成循环内进行条件连接。完整示例如下所示:

module ProcessingArray #(parameter Y=14, X=14, W=16) (  
    input                   GlobalClk,
    input           [3:0]   OpCode,
    input           [W-1:0] DataIn,
    output logic    [W-1:0] DataOut 
    );
  // internal connections
  wire [W-1:0] ConnIn[Y][X];
  wire [W-1:0] ConnOut[Y][X];
  // entry and exit connections
  assign ConnIn[0][0] = DataIn;
  assign DataOut = ConnOut[Y-1][X-1];

  for (genvar y=0; y<Y; y++) begin : row
    for (genvar x=0; x<X; x++) begin  :col
      ProcessingElement #(.W(16)) PE(
        .Clk(GlobalClk),
        .OpCode(OpCode),
        .Input(ConnIn[y][x]),
        .Output(ConnOut[y][x])
      );
      if (y<=x && x>0) assign ConnIn[y][x] = ConnOut[y][x-1]; // horizontal 
      if (x<=y && y>0) assign ConnIn[y][x] = ConnOut[y-1][x]; // vertical 
    end
  end

endmodule

module ProcessingElement #(int W) (
  input Clk,
  input           [3:0]   OpCode,
  input           [W-1:0] Input,
  output logic    [W-1:0] Output
);
  assign Output=Input+1;  // trace connectivity
  initial #1 $display("PE %m %d",Input);
endmodule

module tb;
  logic [15:0] in,out;
  logic [3:0] op;
  
  ProcessingArray PE(clk,op,in,out);
  
  initial begin
    in = 1;
    #1 $display(out);
  end
endmodule