Verilog 如何展开嵌套的 for 循环?
How does Verilog unroll nested for loops?
我正在尝试使用一系列嵌套的 for 循环求和,但没有成功。我想我需要更好地了解 Verilog 如何展开 for 循环,然后才能真正想象如何解决我的问题。
基本上我有一系列 tap 输出(tap_output_i 和 tap_output_q),它们是 3D 数组(src、dst、tap)。我想对每个时钟到达特定目的地的所有源和抽头求和。
这是我有的东西不起作用(out_sig 每次都是 0):
//NODES = 2
wire signed [DAC_BUS_WIDTH-1:0] out_sig_i [NODES-1:0];
wire signed [DAC_BUS_WIDTH-1:0] out_sig_q [NODES-1:0];
reg signed [DAC_BUS_WIDTH-1:0] out_sig_i_reg[NODES-1:0];
reg signed [DAC_BUS_WIDTH-1:0] out_sig_q_reg[NODES-1:0];
integer dstVal,srcVal, tapVal;
//generate
always @(posedge clk) begin: AlwaysSummingForLoop
for (dstVal=0; dstVal<2; dstVal=dstVal+1) begin:SummingForLoop
out_sig_i_reg[dstVal] <= 0;
out_sig_q_reg[dstVal] <= 0;
for (srcVal=0; srcVal<2; srcVal=srcVal+1) begin:SrcForLoop
if(srcVal != dstVal) begin:innerIf
for (tapVal=0; tapVal<8; tapVal=tapVal+1) begin:tapSum
out_sig_i_reg[dstVal] <= out_sig_i_reg[dstVal] + tap_output_i[srcVal][dstVal][tapVal];
out_sig_q_reg[dstVal] <= out_sig_q_reg[dstVal] + tap_output_q[srcVal][dstVal][tapVal];
end
end
end
end
end
//endgenerate
assign out_sig_i[0] = out_sig_i_reg[0];
assign out_sig_q[0] = out_sig_q_reg[0];
assign out_sig_i[1] = out_sig_i_reg[1];
assign out_sig_q[1] = out_sig_q_reg[1];
我 运行 遇到的问题是重置每次计数的累计(out_sig_i_reg
和 out_sig_q_reg
)总和...
<=
是一个非阻塞赋值。也就是说,它使右侧的临时副本在程序上(非阻塞)执行此时间步长的代码,然后将临时变量赋值给左侧。它用于模拟触发器行为的模拟。
触发器每个时钟周期只能更改一次值。
你有(简码):
out_sig_q_reg[dstVal] <= 0;
for (i=0; i<2; i=i+1) begin
for (j=0; j<8; j=j+1) begin
out_sig_q_reg[dstVal] <= out_sig_q_reg[dstVal] + tap_output_q[i][dstVal][j];
end
end
在上面的代码中,out_sig_q_reg[dstVal] <= 0;
永远不会生效,它总是被下一条语句覆盖; out_sig_q_reg[dstVal] <= out_sig_q_reg[dstVal] ...
您的 for 循环重复使用相同的左侧,但只有最后一次赋值会获胜。对于给定的寄存器,每个时钟周期只有一个 <=
有效。有效的 for 循环需要更改内部最左侧的寄存器。
您可以创建一个组合块,它使用 =
描述迭代,然后在最后通过一个触发器。
always @* begin
//..
out_sig_q[dstVal] = 0;
for (i=0; i<2; i=i+1) begin
for (j=0; j<8; j=j+1) begin
out_sig_q[dstVal] = out_sig_q[dstVal] + tap_output_q[i][dstVal][j];
end
end
//..
end
always (@posedge clk) begin
for ...
out_sig_q_reg[dstVal] <= out_sig_q[dstVal];
我正在尝试使用一系列嵌套的 for 循环求和,但没有成功。我想我需要更好地了解 Verilog 如何展开 for 循环,然后才能真正想象如何解决我的问题。
基本上我有一系列 tap 输出(tap_output_i 和 tap_output_q),它们是 3D 数组(src、dst、tap)。我想对每个时钟到达特定目的地的所有源和抽头求和。
这是我有的东西不起作用(out_sig 每次都是 0):
//NODES = 2
wire signed [DAC_BUS_WIDTH-1:0] out_sig_i [NODES-1:0];
wire signed [DAC_BUS_WIDTH-1:0] out_sig_q [NODES-1:0];
reg signed [DAC_BUS_WIDTH-1:0] out_sig_i_reg[NODES-1:0];
reg signed [DAC_BUS_WIDTH-1:0] out_sig_q_reg[NODES-1:0];
integer dstVal,srcVal, tapVal;
//generate
always @(posedge clk) begin: AlwaysSummingForLoop
for (dstVal=0; dstVal<2; dstVal=dstVal+1) begin:SummingForLoop
out_sig_i_reg[dstVal] <= 0;
out_sig_q_reg[dstVal] <= 0;
for (srcVal=0; srcVal<2; srcVal=srcVal+1) begin:SrcForLoop
if(srcVal != dstVal) begin:innerIf
for (tapVal=0; tapVal<8; tapVal=tapVal+1) begin:tapSum
out_sig_i_reg[dstVal] <= out_sig_i_reg[dstVal] + tap_output_i[srcVal][dstVal][tapVal];
out_sig_q_reg[dstVal] <= out_sig_q_reg[dstVal] + tap_output_q[srcVal][dstVal][tapVal];
end
end
end
end
end
//endgenerate
assign out_sig_i[0] = out_sig_i_reg[0];
assign out_sig_q[0] = out_sig_q_reg[0];
assign out_sig_i[1] = out_sig_i_reg[1];
assign out_sig_q[1] = out_sig_q_reg[1];
我 运行 遇到的问题是重置每次计数的累计(out_sig_i_reg
和 out_sig_q_reg
)总和...
<=
是一个非阻塞赋值。也就是说,它使右侧的临时副本在程序上(非阻塞)执行此时间步长的代码,然后将临时变量赋值给左侧。它用于模拟触发器行为的模拟。
触发器每个时钟周期只能更改一次值。
你有(简码):
out_sig_q_reg[dstVal] <= 0;
for (i=0; i<2; i=i+1) begin
for (j=0; j<8; j=j+1) begin
out_sig_q_reg[dstVal] <= out_sig_q_reg[dstVal] + tap_output_q[i][dstVal][j];
end
end
在上面的代码中,out_sig_q_reg[dstVal] <= 0;
永远不会生效,它总是被下一条语句覆盖; out_sig_q_reg[dstVal] <= out_sig_q_reg[dstVal] ...
您的 for 循环重复使用相同的左侧,但只有最后一次赋值会获胜。对于给定的寄存器,每个时钟周期只有一个 <=
有效。有效的 for 循环需要更改内部最左侧的寄存器。
您可以创建一个组合块,它使用 =
描述迭代,然后在最后通过一个触发器。
always @* begin
//..
out_sig_q[dstVal] = 0;
for (i=0; i<2; i=i+1) begin
for (j=0; j<8; j=j+1) begin
out_sig_q[dstVal] = out_sig_q[dstVal] + tap_output_q[i][dstVal][j];
end
end
//..
end
always (@posedge clk) begin
for ...
out_sig_q_reg[dstVal] <= out_sig_q[dstVal];