我正在编写Zynq 7010 SoC。它包含一个FPGA和2个ARM内核。板上还有ADC和DAC。我的目的是将一些电压响应f(x)采样到一个数组中并得到它的反f -1(x)。我的问题是vivado无法推断出持有反向响应的数组的Block RAM,并说:
[Synth 8-3391]无法推断'pg_inverse_reg'的块/分布式RAM,因为不支持使用的内存模式。由于位数(114688)太大,无法将存储器分解为位。使用'set_param synth.elaboration.rodinMoreOptions {rt :: set_parameter dissolveMemorySizeLimit 114688}'允许将内存分解为单个位“
我尝试使用给出的命令让它溶解成位。然而,在我运行合成一晚后,仍然没有结果。我应该改变我对问题的处理方法(例如使用ARM内核)吗?或者我的代码中是否有一个简单的更改,可能使vivado能够按照我原先的意图推断块RAM(希望加快编译时间)?由于模拟运行良好,要达到这一点需要做很多工作,我希望保留尽可能多的当前代码。
以下是有问题的代码:
module gain_measure
(
input clk_i,
input rstn_i,
input [13:0] dat_i,
output [13:0] dat_o,
// IO
input [19:0] addr,
input [31:0] wdata,
input wen
);
reg pg_measure ; // Flag, 1 = measure, 0 = don't
reg pg_direction ; // Flag, 1 = up, 0 = down
reg [ 7:0] counter ;
reg [20:0] pg_sum ;
wire [14:0] pg_up_n_down ;
wire [13:0] pg_final ;
reg pg_deviated ; // Flag, 1 = re-measure, 0 = don't
wire [14:0] pg_deviation ;
reg [13:0] process_gain[8191:0] ; // Don't initialize, unneccessary
reg [13:0] pg_inverse[8191:0] ; // Don't initialize, unneccessary
reg [13:0] pg_inv_index_up ;
reg [13:0] pg_inv_index_dn ;
reg pg_invert ; // Flag, 1 = invert gain, 0 = measuring or done
reg [13:0] pg_index ;
wire [13:0] pgm_set ;
reg [13:0] pg_dev_thr ;
always @(posedge clk_i) begin
if ( rstn_i == 1'b0 ) begin // global reset takes priority over bus
pg_measure <= 1'b0 ;
pg_direction <= 1'b0 ;
pg_invert <= 1'b0 ;
counter <= 8'b0 ;
pg_sum <= 21'b0 ;
pg_index <= 14'b0 ;
pg_inv_index_up <= 14'b0 ;
pg_inv_index_dn <= 14'b1 ;
pg_deviated <= 1'b0 ;
pg_dev_thr <= 14'h8 ;
end
else if ( ( wen == 1'b1 ) && ( addr[19:0]==16'h00 ) ) begin // get pg_measure from bus
pg_measure <= wdata[1];
pg_direction <= wdata[1];
pg_invert <= 1'b0 ;
counter <= 8'b0 ;
pg_sum <= 21'b0 ;
pg_index <= 14'b0 ;
pg_inv_index_up <= 14'b0 ;
pg_inv_index_dn <= 14'b1 ;
pg_deviated <= 1'b0 ;
pg_dev_thr <= 14'h8 ;
end
else if ( pg_deviated == 1'b1 ) begin // bus takes priority over automatic reset
pg_measure <= 1'b1 ;
pg_direction <= 1'b1 ;
pg_invert <= 1'b0 ;
counter <= 8'b0 ;
pg_sum <= 21'b0 ;
pg_index <= 14'b0 ;
pg_inv_index_up <= 14'b0 ;
pg_inv_index_dn <= 14'b1 ;
pg_deviated <= 1'b0 ;
pg_dev_thr <= 14'h8 ;
end
if ( pg_measure == 1'b1 ) begin
counter <= counter + 1 ;
if ( counter == 8'd000 )
pg_sum <= 8'b0 ;
if ( counter >= 8'd127 && counter < 8'd255 )
pg_sum <= pg_sum + dat_i ;
if ( counter == 8'd255 ) begin
if ( pg_index < 14'd8191 && pg_direction == 1'b1 ) begin // measure upwards
pg_index <= pg_index + 1 ;
process_gain[pg_index] <= pg_sum[20:7] ;
pg_inverse[pg_index] <= 14'h1FFF ;
end
else if ( pg_index == 14'd8191 && pg_direction == 1'b1 ) begin // switch directions, measure top again
pg_direction <= 1'b0 ;
process_gain[pg_index] <= pg_sum[20:7] ;
pg_inverse[pg_index] <= 14'h1FFF ;
end
else if ( pg_index > 14'd0 && pg_direction == 1'b0 ) begin // verify/measure downwards
pg_index <= pg_index - 1 ;
if ( pg_deviation > pg_dev_thr )
pg_deviated <= 1'b1 ;
process_gain[pg_index] <= pg_final ;
if ( pg_index == 14'd8191 ) begin
pg_inverse[pg_final] <= pg_index ;
pg_inv_index_up <= pg_final ;
end
else if ( pg_final < process_gain[pg_index+1] ) begin
pg_inverse[pg_final] <= pg_index ;
end
end
else begin
if ( pg_deviation > pg_dev_thr )
pg_deviated <= 1'b1 ;
process_gain[pg_index] <= pg_final ;
if ( pg_final < process_gain[pg_index+1] ) begin
pg_inverse[pg_final] <= pg_index ;
end
pg_inv_index_dn <= pg_inv_index_up ;
pg_measure <= 1'b0 ;
pg_invert <= 1'b1 ;
end
end
end
// start from value first added to pg_inv_index_up
if ( pg_invert == 1'b1 ) begin
if ( pg_inv_index_up < 14'd8191 ) begin // going up from first value set to this value
pg_inv_index_up <= pg_inv_index_up + 1;
pg_inverse[pg_inv_index_up+1] <= pg_inverse[pg_inv_index_up] ;
end
else // if pg_inv_index_up already is 8191, set it to the next lower value
pg_inverse[pg_inv_index_up] <= pg_inverse[pg_inv_index_up-1] ;
if ( pg_inv_index_dn > 14'd0 ) begin // if next pg_inverse is larger it's default or non-monotonic
pg_inv_index_dn <= pg_inv_index_dn - 1;
if ( pg_inverse[pg_inv_index_dn] < pg_inverse[pg_inv_index_dn-1] )
pg_inverse[pg_inv_index_dn-1] <= pg_inverse[pg_inv_index_dn] ;
end
end
if ( pg_inv_index_up == 14'd8191 && pg_inv_index_dn == 14'd0 )
pg_invert <= 1'b0 ;
end
assign pg_deviation = process_gain[pg_index] > pg_sum[20:7] ?
process_gain[pg_index] - pg_sum[20:7] :
pg_sum[20:7] - process_gain[pg_index] ;
assign pg_up_n_down = process_gain[pg_index] + pg_sum[20:7] ;
assign pg_final = pg_up_n_down[14:1] ;
assign pgm_set = pg_index ;
assign dat_o = pgm_set ;
endmodule