我使用英特尔Stratix 10 FPGA和Quartus Prime Pro 21.4来开发一个电源测试项目。
我不知道如何阻止Quartus优化我的DSP块。
我想在FPGA中使用所有3000个DSP块,以便我可以看到DSP块的最大电流绘制。当然,我们可以使用功率估计器,但我们需要实际的物理测试。
我实际上不需要DSP块的输出。我只关心他们正在运行和使用FPGA资源。
我已经将英特尔固定DSP核心IP实例化为乘数:
https://www.intel.com/content/www/us/en/docs/programmable/683450/current/native -固定-点- dsp -英特尔stratix - 51840. - html
我使用generate for
环路来生成3000个这些DSP IP块。我的问题是,除非我将每个DSP块的输出直接连接到顶级输出,否则DSP块会被合成掉。我只有~1000个输出可用,所以这是不可能的。
我想我可以用寄存器数组连接每个输出来捕获输出。但似乎如果我不实际使用输出值或将其直接连接到顶级输出引脚,那么Quartus认为我们不需要它并将其优化掉。
我尝试的第二个解决方案是使用组合逻辑:
top_output = DSP_out[0] || DSP_out[1] || DSP_out[2] || DSP_out[3]
这个解决方案将生成4个DSP块,即使生成循环运行3000次。我试着在一个循环中这样做,但它没有工作。是否有一种方法可以欺骗系统合成所有DSP块,即使我不将块连接到顶级输出?
我似乎能够访问DSP块的输出而没有问题。例如,我能够根据我输入到单个乘法器中的数字打开或关闭LED。
下面是完整的代码:
`timescale 1ps/1ps
`default_nettype none
module power_test_design (
input wire clk_i,
output reg [0:0] outputa,
output reg [0:0] outputb
);
localparam NUM_DSP_BLOCKS = 3000;
genvar i;
wire reset;
integer k;
//input stimulus signals for the DSP
reg [17:0] ay_r;
reg [17:0] by_r;
reg [17:0] ax_r;
reg [17:0] bx_r;
//create wires and registers to hold outputs from multiplier
(* keep = "true" *) wire [36:0] resulta [NUM_DSP_BLOCKS-1:0];
(* keep = "true" *) reg [36:0] resulta_r [NUM_DSP_BLOCKS-1:0];
(* keep = "true" *) wire [36:0] resultb [NUM_DSP_BLOCKS-1:0];
(* keep = "true" *) reg [36:0] resultb_r [NUM_DSP_BLOCKS-1:0];
reg [2:0] ena_r;
// Stratix10 system reset
reset_release U_RESET (
.ninit_done (reset ) // output, width = 1, ninit_done.ninit_done
);
// DSP stimulus
always @(posedge clk_i) begin : DSP_SET_FF
if (reset)
begin
ay_r <= {18{1'b0}};
by_r <= {18{1'b0}};
ax_r <= {18{1'b0}};
bx_r <= {18{1'b0}};
ena_r <= {3{1'b0}};
end else
begin
ena_r <= 3'b001;
ay_r <= $unsigned(ay_r) + 1;
by_r <= $unsigned(by_r) + 1;
ax_r <= $unsigned(ax_r) + 2;
bx_r <= $unsigned(bx_r) + 3;
end
end
generate
for (i=0; i<NUM_DSP_BLOCKS; i=i+1) begin : GEN_DSPS
dsp_fixed U_DSP (
.ay (ay_r), // input, width = 18, ay.ay
.by (by_r), // input, width = 18, by.by
.ax (ax_r), // input, width = 18, ax.ax
.bx (bx_r), // input, width = 18, bx.bx
.resulta (resulta[i]), // output, width = 37, resulta.resulta
.resultb (resultb[i]), // output, width = 37, resultb.resultb
.clk0 (clk_i), // input, width = 1, clk0.clk
.clk1 (), // input, width = 1, clk1.clk
.clk2 (), // input, width = 1, clk2.clk
.ena (ena_r) // input, width = 3, ena.ena
);
//bring result to a register to assign output logic
assign resulta_r[i] = resulta[i];
assign resultb_r[i] = resultb[i];
end
endgenerate
//output logic -this code generates 6 DSP blocks....I need to generate all 3000
always @(posedge clk_i) begin : outputLogic
for (k=1; k<50; k=k+1)
begin
outputa = resulta_r[k] || resulta_r[k+1] || resulta_r[k+2];
outputb = resultb_r[k+3] || resultb_r[k+4] || resultb_r[k+5];
end
end
endmodule
`resetall
到目前为止,我尝试了几种方法来分配这个输出。第一:always @(resulta_r[0], resulta_r[1], resulta_r[2], resulta_r[3]) begin
if (resulta_r[0] == 4)
begin
outputa = 1;
end
else if (resulta_r[1] == 6)
begin
outputa = 1;
end
else if (resulta_r[2] == 6)
begin
outputa = 1;
end
else if (resulta_r[3] == 6)
begin
outputa = 1;
end
else
begin
outputa = 0;
end
end
使用此代码,为每个if
语句生成DSP块。下一个想法是
always @(posedge clk_i) begin : outputLogic
for (k=1; k<50; k=k+1)
begin
outputa = resulta_r[k] || resulta_r[k+1] || resulta_r[k+2];
outputb = resultb_r[k+3] || resultb_r[k+4] || resultb_r[k+5];
end
end
的工作原理类似。我得到了为组合语句中的每个result[k]
生成的DSP块。但是这在合成时总共只产生6个DSP块。它只根据这个组合语句中有多少DSP块输出来生成块。
我在quartus中使用Virtual pins解决了这个问题。我可以分配每个输出引脚只有一个虚拟引脚,而不是一个实际的引脚。有了这个设置,我可以有尽可能多的输出引脚,因为我需要,而不是真正连接到任何东西。
Quartus Virtual Pins
由于某些原因,设计仍然不能扩展到3000,但我已经联系了英特尔。解决了优化DSP块的原始问题,除非它们连接到输出。
解决这个问题的另一个解决方案是将这些DSP块链在一起。它也不能扩展,但也解决了这里最初提出的问题。