在Xilinx FPGA上使用BRAM转换顺序数据

问题描述 投票:0回答:1

我正在编程Zynq 7010 SoC。它包含一个FPGA和2个ARM内核。板上也有ADC和DAC。我的意图是将一些电压响应f(x)采样到一个数组中,并获得其反函数f⁻¹(x)。我的问题是,vivado无法为持有反向响应的数组推断出块RAM,说:

[Synth 8-3391]无法为'pg_inverse_reg'推断出块/分布式RAM,因为不支持所使用的存储模式。由于位数(114688)太大,无法将内存分解为位数。使用'set_param synth.elaboration.rodinMoreOptions {rt :: set_parameter dissolveMemorySizeLimit 114688}'可以将内存分解为单个位。“

我尝试使用给定的命令使其分解为位。但是,我将合成运行了一个晚上之后,仍然没有结果。我是否应该改变解决问题的方法(例如使用ARM内核)?还是我的代码中有一个简单的更改,可能使vivado能够按我的原意推断出Block 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
verilog fpga xilinx vivado
1个回答
0
投票

嘿,我有同样的问题。您找到问题的答案了吗?

© www.soinside.com 2019 - 2024. All rights reserved.