for 循环是您的朋友,但仅当它用于生成时,而不是在顺序代码中(always
/// )。如果您不小心,顺序 for 循环可能会导致复杂的硬件。initial
function
task
您基本上可以用与使用任何其他语言相同的方式进行编码,但(主要)问题是您无法通过模块端口传递数组。下面的工作测试示例。这在 VHDL 中会更容易和更清晰(可能还有我不使用的 SV)。如果你要做很多这样的事情而你才刚刚开始,你应该改变语言。
下面的 3x3 方阵乘法的硬件速度很快,但会消耗大量硬件。它生成 9 个 MAC 单元,每个 MAC 单元需要三个乘法器和两个加法器。您需要考虑位宽;目前的代码将 MAC 结果分配给一个 18 位值,这通常不起作用(代码正确模拟,因为 和 的值A
很小B
)。
你需要考虑资源和时间。如果你还没有 27 个乘法器和 18 个加法器,但你并不急着需要答案,那就分享一下吧。在极限情况下,您可以构建非常紧凑的串行硬件,但代价是大量的循环和复杂的控制。
module top;
wire[17:0]A[1:3][1:3]; // the matrices
wire[17:0]B[1:3][1:3];
wire[17:0]C[1:3][1:3];
wire[(9*18)-1:0] Abits; // bit-decomposed versions of the above
wire[(9*18)-1:0] Bbits;
wire[(9*18)-1:0] Cbits;
genvar i,j;
// set A and B with initial values
generate
for(i=0; i<3; i=i+1)
for(j=0; j<3; j=j+1) begin
assign A[i+1][j+1] = i*3 + j;
assign B[i+1][j+1] = i*3 + j + 1;
end
endgenerate
// decompose A and B, set C
generate
for(i=1; i<=3; i=i+1)
for(j=1; j<=3; j=j+1) begin
assign Abits[(((i-1)*3 + (j-1)) * 18)+17 -:18] = A[i][j];
assign Bbits[(((i-1)*3 + (j-1)) * 18)+17 -:18] = B[i][j];
assign C[i][j] = Cbits[(((i-1)*3 + (j-1)) * 18)+17 -:18];
end
endgenerate
initial
#1 $display("%4d %4d %4d\n%4d %4d %4d\n%4d %4d %4d\n",
C[1][1], C[1][2],C[1][3],
C[2][1], C[2][2],C[2][3],
C[3][1], C[3][2],C[3][3]);
mmult3x3 U1(Abits, Bbits, Cbits);
endmodule
module mmult3x3
(input wire[(9*18)-1:0] AI,
input wire[(9*18)-1:0] BI,
output wire[(9*18)-1:0] CO);
wire[17:0]A[1:3][1:3];
wire[17:0]B[1:3][1:3];
wire[17:0]C[1:3][1:3];
genvar i,j;
generate
for(i=1; i<=3; i=i+1)
for(j=1; j<=3; j=j+1) begin
assign A[i][j] = AI[(((i-1)*3 + (j-1)) * 18)+17 -:18];
assign B[i][j] = BI[(((i-1)*3 + (j-1)) * 18)+17 -:18];
assign CO[(((i-1)*3 + (j-1)) * 18)+17 -:18] = C[i][j];
end
endgenerate
// this is the bit that matters - everything else just works around shortcomings
// in the language:
generate
for(i=1; i<=3; i=i+1)
for(j=1; j<=3; j=j+1)
assign C[i][j] = A[i][1]*B[1][j] + A[i][2]*B[2][j] + A[i][3]*B[3][j];
endgenerate
endmodule