在 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
我有一个 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