如果DSP块没有连接到顶级输出,我如何防止它们被合成掉?



我使用英特尔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块链在一起。它也不能扩展,但也解决了这里最初提出的问题。

最新更新