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

时间:2015-03-17 11:17:53

标签: verilog fpga xilinx vivado

我正在编写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

0 个答案:

没有答案