微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > FPGA和CPLD > 用Xilinx Vivado HLS实现浮点复数QRD矩阵分解

用Xilinx Vivado HLS实现浮点复数QRD矩阵分解

时间:04-27 来源:互联网 点击:

  • QRD矩阵分解的Vivado HLS设计实现与优化


    C模块划分

    Vivado HLS生成的RTL代码在默认情况下保留原有c代码的层次结构。在构建c代码层次时,可以采用由上至下、自下而上相结合的模块划分方式。

    将单精度浮点基本运算如加、减、乘、除、平方根等写成最底层的子函数,以便添加directives来指导工具优化方向。
    float hfmult
    (
            float in1,
            float in2
    )
    {
    #pragma HLS PIPELINE
    // 注:将hfmult函数流水化设计,以获得更好的时序性能
    #pragma HLS RESOURCE variable=return core=FMul_fulldsp latency=9
    // 注:制定hfmult的延迟为9个时钟周期,以便hfmult内部实现有充分的时钟节拍流水,特别是有足够的时钟节拍分配给DSP48内部做流水处理
        float out;
        out = in1 * in2;
    }

    类似的设计方法及思路也同样适用于浮点加,减等运算。

    提高C转换成FPGA RTL 实现的并行度

    由于计算时间、速度的要求,往往需要提高运算的并行度,需要对qrd_engine中in_u及r数组(HLS综合成FPGA的BRAM或分布式RAM)加数组分割directive,这样数据才可以并行进入后面的并行处理单元。
    #pragma HLS ARRAY_PARTITION variable=in_u complete dim=2
    #pragma HLS ARRAY_PARTITION variable=r complete dim=2

    对数组memory地址读写设计优化

    C语言中的数组通常会被综合成FPGA的存储memory,这样就会有地址的读写。但为了达到更好的时序性能,可以尽量减少对memory的读写,从而简化所生成RTL代码中的mux。

    写法1,定义成,in_u[i/div_UNM][i%div_NUM],对下面的运算,将产生两次memory读写。
    calc_coef(lamda_sqrt, in_u[i/div_UNM][i%div_NUM], …);
           for(j=0; j<N_DIM; j++)
                 for(k=0; k<div_NUM; k++)
                 {
                         in_u_read  = in_u[u_addr][k];
                 }

    写法2,定义成变量in_u_pre, 通过 if(u_addr == (i+1)/div_NUM && k==(i+1)%div_NUM)判断来实现同样的功能,这样只需要一次memory读写,从而获得更好的II性能,当然也提升了时序性能。

    calc_coef(lamda_sqrt, in_u_pre, …);
           for(j=0; j<N_DIM; j++)
                 for(k=0; k<div_NUM; k++)
                 {
                         in_u_read  = in_u[u_addr][k];
                         if(u_addr == (i+1)/div_NUM && ==(i+1)%div_NUM)
                         in_u_pre = in_u_read;
                 }

    有时为了使in_u综合出的RAM时序更好,也可以对in_u综合的RAM加resource directive来控制其stage, 比如为3 stage,这样生成的RAM, 在输入,输出都会打一拍register。

    #pragma HLS RESOURCE variable=in_u core=RAM3S

    浮点运算加法级联与加法树

    由于浮点运算的精度与其运算的先后顺序有直接关系,在Vivado HLS中,为了保证生成的RTL代码与C中的精度一样, Viado-HLS一般不会改变代码中中浮点运算的顺序。有时为降低浮点运算的latency,使用并行加法树将比串行级联加法来获得更有效。

    浮点串行加法级联,这样写法是有严格先后顺序的,Vivado HLS将其生成串行实现的RTL代码,其latency为35个时钟周期。

    void fp_adder_cascade (float *r, float a, float b, float c, float d)
    {
    #pragma HLS PIPELINE
    *r = a + b + c + d;
    }

    如果用户确定上面的浮点加顺序调整对精度的影响在误差范围内, 那么可以采用并行加法树,这样 Vivado HLS 将其生成并行加法RTL代码实现,其latency为降为23个时钟周期。

    void fp_adder_tree (float *r, float a, float b, float c, float d)
    {
    #pragma HLS PIPELINE
    float e, f;
    e = a + b;
    f = c + d;
    *r = e + f;
    }

    对浮点乘法使用的DSP48的优化

    同样我们也可以通过设置充足的latency directive给DSP48,这样有足够的时钟节拍给到DSP48内部打拍register。

    如果对上述的单精度浮点乘法hfmult latency设置为3,这样分配到每个DSP48 内部只有2级latency,  那么综合总合出来代码DSP48内部的A_reg 或 P_reg不会打一拍, 这样将会大大降低时序性能。
    derive_core fmul_der -base FMul_maxdsp -latency 3 -fixed
    set_directive_resource -core fmul_der hfmult out



    或者:



    为了达到较好的时序性能,对上述的单精度浮点乘法hfmult latency至少设置为4,这样分配到每个DSP48 内部只有3级latency,  那么综合总合出来代码DSP48内部的A_reg 或 P_reg都会各打一拍。
    derive_core fmul_der -base FMul_maxdsp -latency 4 -fixed
    set_directive_resource -core fmul_der hfmult out



    对Shifter Register的优化

    利用Vivado HLS 2014.4的Shift Register RTL Attribute,有5种类型SRL来控制不同的shifter register组合:srl, srl_reg, reg_srl, reg_srl_reg。

    比如在Vivado HLS生成的RTL代码中加(* srl_style “reg_srl_reg” *),将综合成在SRL之前、之后分别用一个register来实现。如图所示:



    Vivado HLS QRD矩阵分解设计结果

    本文中QRD矩阵分解的大小是128x128的单精度复数浮点,我们使用Xilinx

    Vivado HLS 2014.4版本,将其生成的RTL在Xilinx Virtex-7 FPGA上实现。

    延迟(latency)性能

    本文所述的设计,在Xilinx Vivado HLS 2014.4中达到的延迟15237个时钟周期。

    Interval(吞吐率的倒数)性能

    在Xilinx Vivado HLS中,interval是指下一个新的可以输入QRD模块的数据与前一个数据之间所间隔的时钟周期数,也可以理解为吞吐率的倒数。这里Interval的单位是时钟周期。
    本文所述的设计,在Xilinx Vivado HLS 2014.4 中达到的Interval是15238个时钟周期。

    时序(timing)性能

    使用Xilinx Vivado HLS 2014.4在Xilinx Virtex-7器件中实现单个128x128单精度浮点复数QRD分解模块,时钟频率达到了350 MHz (2.85ns)。

    处理时间性能

    QRD矩阵分解的处理时间就是所用的延迟x时钟周期,所以是:15237 x 2.85 = 43.4 uS。

    FPGA资源

    将Xilinx Vivado HLS 2014.4生成的RTL代码,在Vivado 2014.4中综合,实现,使用的资源如下表。这个资源使用率只占Xilinx Virtex-7 7V485T的4%,使用Vivado HLS 2014.4高效地实现了QRD矩阵分解。

    Slice    4048
    LUT    11882
    FF    12495
    DSP    109
    BRAM    0
    SRL    314

    总结

    使用Xilinx Vivado HLS工具,可以让算法工程师、FPGA工程师及软件工程师快速基于FPGA实现典型的数字信号处理算法。本文以浮点复数QRD矩阵分解为例,介绍了如何使用 Vivado HLS 快速、高效地基于FPGA实现,并降低开发者对算法的FPGA实现难度。

    Vivado HLS可以帮助设计者大幅提升生产力。 使用 Vivado HLS 开发效率比手写RTL实现快5-10倍,其FPGA资源效率与手写RTL接近,且C/C++仿真验证比传统FPGA RTL要快100倍。。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top