<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 用Xilinx Vivado HLS實(shí)現(xiàn)浮點(diǎn)復(fù)數(shù)QRD矩陣分解

          用Xilinx Vivado HLS實(shí)現(xiàn)浮點(diǎn)復(fù)數(shù)QRD矩陣分解

          作者:Xilinx公司王宏強(qiáng),徐堅(jiān),等 時(shí)間:2015-04-23 來(lái)源:電子產(chǎn)品世界 收藏

                  在數(shù)字信號(hào)處理領(lǐng)域,如自適應(yīng)濾波、DPD系數(shù)計(jì)算、MIMO Decoder 等,常常需要矩陣解方程運(yùn)算以獲得其系數(shù),因此需對(duì)矩陣進(jìn)行求逆運(yùn)算。然而,由于直接對(duì)矩陣求逆會(huì)導(dǎo)致龐大的運(yùn)算量,所以在實(shí)際工程中往往需要先將矩陣分解成幾個(gè)特殊矩陣(正規(guī)正交矩陣或上、下三角矩陣以求其逆矩陣需要更小的運(yùn)算量)的乘積。目前,QRD矩陣分解法是求一般矩陣全部特征值的最有效且廣泛應(yīng)用的方法之一。它是將矩陣分解成一個(gè)正規(guī)正交矩陣Q與上三角形矩陣R,稱為QRD矩陣分解。

          本文引用地址:http://www.ex-cimer.com/article/273080.htm

            由于浮點(diǎn)具有更大的數(shù)據(jù)動(dòng)態(tài)范圍,所以在眾多多算法中具有只需要一種數(shù)據(jù)類型的優(yōu)勢(shì),所以很多QRD矩陣分解是基于浮點(diǎn)數(shù)據(jù)類型的。不過(guò)在通信應(yīng)用中,更多的場(chǎng)景還是復(fù)數(shù)類型。因此,隨著通信技術(shù)的日益發(fā)展,算法的復(fù)雜度越來(lái)越高,QRD矩陣的維度也越來(lái)越大。如果是用傳統(tǒng)的手寫(xiě)RTL,浮點(diǎn)復(fù)數(shù)超大維度QRD矩陣分解的FPGA實(shí)現(xiàn)將變得非常復(fù)雜,需要很長(zhǎng)的時(shí)間來(lái)編寫(xiě)RTL代碼、仿真和進(jìn)行驗(yàn)證等工作,使得開(kāi)發(fā)效率不是很高。

            本文將介紹如何使用 HLS(高層次綜合)工具實(shí)現(xiàn)浮點(diǎn)復(fù)數(shù)QRD矩陣分解并提升開(kāi)發(fā)效率。使用HLS可以快速、高效地基于FPGA實(shí)現(xiàn)各種矩陣分解算法,降低開(kāi)發(fā)者對(duì)算法FPGA的實(shí)現(xiàn)難度。其中包括:

          •    使用Vivado HLS開(kāi)發(fā)效率比手寫(xiě)RTL實(shí)現(xiàn)快5-10倍,而實(shí)現(xiàn)的FPGA資源效率與手寫(xiě)RTL接近
          •    由于C/C++仿真驗(yàn)證比傳統(tǒng)FPGA RTL要快100倍,Vivado HLS實(shí)現(xiàn)可以大大縮短用戶的代碼開(kāi)發(fā)時(shí)間和仿真驗(yàn)證時(shí)間,從而大幅提高生產(chǎn)效率。

            1. Vivado HLS工具介紹

            Vivado HLS 是公司2010 年收購(gòu) AutoESL 以后重新打造的高層次綜合工具,它可以讓用戶通過(guò)添加適當(dāng)?shù)膁irectives(制導(dǎo)語(yǔ)句) 和 constrains(約束), 將其C/C++/System C代碼直接轉(zhuǎn)換成 FPGA RTL( Verilog, VHDL, System C )代碼。讓用戶可以在算法開(kāi)發(fā)環(huán)境而非通常的硬件開(kāi)發(fā)環(huán)境中只需專注于算法規(guī)格和算法的 C 實(shí)現(xiàn),Vivado HLS 工具會(huì)自動(dòng)考慮 FPGA 微觀實(shí)現(xiàn)架構(gòu),并可生成可綜合的FPGA RTL代碼。如圖1所示。

            圖1 Vivado HLS設(shè)計(jì)介紹

            Vivado HLS FPGA設(shè)計(jì)流程:

          •   首先用 C/C++/System C 將算法實(shí)現(xiàn),并編寫(xiě) C testbench 驗(yàn)證 C 的功能,確保其功能正確;
          •    然后就可以通過(guò) Vivado HLS 工具進(jìn)行 C 綜合,將 C 轉(zhuǎn)換成 RTL;
          •    接著做 C/RTL 的協(xié)同仿真(Co-simulation),以保證生成的RTL代碼功能與C的功能完全一致。
          •    最后 Vivado HLS 生成的 RTL 代碼可直接用于 設(shè)計(jì)開(kāi)發(fā)環(huán)境下做系統(tǒng)集成、仿真和生成bit文件。

            圖2 Vivado HLS設(shè)計(jì)流程

            2. QRD矩陣分解算法

            QRD矩陣分解是將一個(gè)矩陣A分解成Q與R相乘,

            其中R是個(gè)上三角矩陣, Q是個(gè)正交矩陣,

            Q = 1

            是Q的轉(zhuǎn)置共軛矩陣

            3. QRD矩陣分解 Vivado HLS 實(shí)現(xiàn)C++代碼構(gòu)架

            QRD矩陣分解C++實(shí)現(xiàn)代碼的頂層模塊是qrd_engine.cpp, 它調(diào)用cal_core.cpp(核心計(jì)算函數(shù)), coef_cal.cpp(系數(shù)計(jì)算函數(shù)),以及浮點(diǎn)加、減、乘、除法等子函數(shù)來(lái)實(shí)現(xiàn)。

            struct cf_t {

            float re;

            float im;

            };

            void qrd_engine

            (

            cf_t in_u[(R_DIM+Y_DIM)/DIV_NUM][DIV_NUM],

            cf_t pd_err_in,

            float lamda,

            float lamda_sqrt,

            float diag[R_DIM],

            cf_t r[R_DIM][X_DIM],

            cf_t p[R_DIM]

            )

            {

            #pragma HLS ARRAY_PARTITION variable=in_u complete dim=2

            #pragma HLS ARRAY_PARTITION variable=r complete dim=2

            //注:這里對(duì)數(shù)組加入完全分割directive,目的是提高數(shù)據(jù)的并行帶寬,從而獲得并行計(jì)算。

            #pragma HLS RESOURCE variable=in_u core=RAM3S

            //注:這里對(duì)數(shù)組加入RAM3S directive,目的是控制生成的BRAM的延遲。

            for (i=0;i

            {

            #pragma HLS PIPELINE II =124

            #pragma HLS latency max = 123

            //注:這里加入II(interval是指下一個(gè)新的可以輸入QRD模塊的數(shù)據(jù)與前一個(gè)數(shù)據(jù)之間所間隔的時(shí)鐘周期數(shù))及l(fā)atency directives (延遲制導(dǎo)語(yǔ)句),目的是控制這個(gè)模塊在指定的延遲節(jié)拍范圍內(nèi)完成所有的計(jì)算。

            coef_calc(lamda_sqrt,lamda,diag[i],pre_in_u,pd_err_in,&s_o,&s_conj_o,&lamda_sqrtxs_o,&c_o,&lamda_sqrtxc_o,&diag_out,&p_o,&pd_err);

            cal_core(u_tmp, r_tmp, s_n, i, j, k, c_o, lamda_sqrtxc_o, lamda_sqrtxs_o, s_conj_o, &in_u_w2, &r[i][r_addr]);

            }

            }

            void coef_calc

            (

            float lamda_sqrt,

            float lamda,

            float r_diag,

            cf_t u_diag,

            cf_t pd_err_in,

            cf_t *s,

            cf_t *s_conj,

            cf_t *lamda_sqrtxs,

            float *c,

            float *lamda_sqrtxc,

            float *diag,

            cf_t *p_o,

            cf_t *pd_err

            )

            void calc_core

            (

            cf_t in_u,

            cf_t r,

            int s_n,

            int i,

            unsigned char j,

            unsigned char k,

            float c_o,

            float lamda_sqrtxc_o,

            cf_t lamda_sqrtxs_o,

            cf_t s_conj_o,

            cf_t* u_ret,

            cf_t* r_ret

            )

            4. QRD矩陣分解的Vivado HLS設(shè)計(jì)實(shí)現(xiàn)與優(yōu)化

            4.1 C模塊劃分

            Vivado HLS生成的RTL代碼在默認(rèn)情況下保留原有c代碼的層次結(jié)構(gòu)。在構(gòu)建c代碼層次時(shí),可以采用由上至下、自下而上相結(jié)合的模塊劃分方式。

            將單精度浮點(diǎn)基本運(yùn)算如加、減、乘、除、平方根等寫(xiě)成最底層的子函數(shù),以便添加directives來(lái)指導(dǎo)工具優(yōu)化方向。

            float hfmult

            (

            float in1,

            float in2

            )

            {

            #pragma HLS PIPELINE

            // 注:將hfmult函數(shù)流水化設(shè)計(jì),以獲得更好的時(shí)序性能

            #pragma HLS RESOURCE variable=return core=FMul_fulldsp latency=9

            // 注:制定hfmult的延遲為9個(gè)時(shí)鐘周期,以便hfmult內(nèi)部實(shí)現(xiàn)有充分的時(shí)鐘節(jié)拍流水,特別是有足夠的時(shí)鐘節(jié)拍分配給DSP48內(nèi)部做流水處理

            float out;

            out = in1 * in2;

            }

            類似的設(shè)計(jì)方法及思路也同樣適用于浮點(diǎn)加,減等運(yùn)算。

            4.2 提高C轉(zhuǎn)換成FPGA RTL 實(shí)現(xiàn)的并行度

            由于計(jì)算時(shí)間、速度的要求,往往需要提高運(yùn)算的并行度,需要對(duì)qrd_engine中in_u及r數(shù)組(HLS綜合成FPGA的BRAM或分布式RAM)加數(shù)組分割directive,這樣數(shù)據(jù)才可以并行進(jìn)入后面的并行處理單元。

            #pragma HLS ARRAY_PARTITION variable=in_u complete dim=2

            #pragma HLS ARRAY_PARTITION variable=r complete dim=2

            4.3 對(duì)數(shù)組memory地址讀寫(xiě)設(shè)計(jì)優(yōu)化

            C語(yǔ)言中的數(shù)組通常會(huì)被綜合成FPGA的存儲(chǔ)memory,這樣就會(huì)有地址的讀寫(xiě)。但為了達(dá)到更好的時(shí)序性能,可以盡量減少對(duì)memory的讀寫(xiě),從而簡(jiǎn)化所生成RTL代碼中的mux。

            寫(xiě)法1,定義成,in_u[i/DIV_UNM][i%DIV_NUM],對(duì)下面的運(yùn)算,將產(chǎn)生兩次memory讀寫(xiě)。

            calc_coef(lamda_sqrt, in_u[i/DIV_UNM][i%DIV_NUM], …);

            for(j=0; j

            for(k=0; k

            {

            in_u_read = in_u[u_addr][k];

            }

            寫(xiě)法2,定義成變量in_u_pre, 通過(guò) if(u_addr == (i+1)/DIV_NUM && k==(i+1)%DIV_NUM)判斷來(lái)實(shí)現(xiàn)同樣的功能,這樣只需要一次memory讀寫(xiě),從而獲得更好的II性能,當(dāng)然也提升了時(shí)序性能。

            calc_coef(lamda_sqrt, in_u_pre, …);

            for(j=0; j

            for(k=0; 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;

            }

            有時(shí)為了使in_u綜合出的RAM時(shí)序更好,也可以對(duì)in_u綜合的RAM加resource directive來(lái)控制其stage, 比如為3 stage,這樣生成的RAM, 在輸入,輸出都會(huì)打一拍register。

            #pragma HLS RESOURCE variable=in_u core=RAM3S

            4.4 浮點(diǎn)運(yùn)算加法級(jí)聯(lián)與加法樹(shù)

            由于浮點(diǎn)運(yùn)算的精度與其運(yùn)算的先后順序有直接關(guān)系,在Vivado HLS中,為了保證生成的RTL代碼與C中的精度一樣, Viado-HLS一般不會(huì)改變代碼中中浮點(diǎn)運(yùn)算的順序。有時(shí)為降低浮點(diǎn)運(yùn)算的latency,使用并行加法樹(shù)將比串行級(jí)聯(lián)加法來(lái)獲得更有效。

            浮點(diǎn)串行加法級(jí)聯(lián),這樣寫(xiě)法是有嚴(yán)格先后順序的,Vivado HLS將其生成串行實(shí)現(xiàn)的RTL代碼,其latency為35個(gè)時(shí)鐘周期。

            void fp_adder_cascade (float *r, float a, float b, float c, float d)

            {

            #pragma HLS PIPELINE

            *r = a + b + c + d;

            }

            如果用戶確定上面的浮點(diǎn)加順序調(diào)整對(duì)精度的影響在誤差范圍內(nèi), 那么可以采用并行加法樹(shù),這樣 Vivado HLS 將其生成并行加法RTL代碼實(shí)現(xiàn),其latency為降為23個(gè)時(shí)鐘周期。

            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;

            }

            4.5 對(duì)浮點(diǎn)乘法使用的DSP48的優(yōu)化

            同樣我們也可以通過(guò)設(shè)置充足的latency directive給DSP48,這樣有足夠的時(shí)鐘節(jié)拍給到DSP48內(nèi)部打拍register。

            如果對(duì)上述的單精度浮點(diǎn)乘法hfmult latency設(shè)置為3,這樣分配到每個(gè)DSP48 內(nèi)部只有2級(jí)latency, 那么綜合總合出來(lái)代碼DSP48內(nèi)部的A_reg 或 P_reg不會(huì)打一拍, 這樣將會(huì)大大降低時(shí)序性能。

            derive_core fmul_der -base FMul_maxdsp -latency 3 -fixed

            set_directive_resource -core fmul_der hfmult out

            或者:

            為了達(dá)到較好的時(shí)序性能,對(duì)上述的單精度浮點(diǎn)乘法hfmult latency至少設(shè)置為4,這樣分配到每個(gè)DSP48 內(nèi)部只有3級(jí)latency, 那么綜合總合出來(lái)代碼DSP48內(nèi)部的A_reg 或 P_reg都會(huì)各打一拍。

            derive_core fmul_der -base FMul_maxdsp -latency 4 -fixed

            set_directive_resource -core fmul_der hfmult out

            4.6 對(duì)Shifter Register的優(yōu)化

            利用Vivado HLS 2014.4的Shift Register RTL Attribute,有5種類型SRL來(lái)控制不同的shifter register組合:srl, srl_reg, reg_srl, reg_srl_reg。

            比如在Vivado HLS生成的RTL代碼中加(* srl_style “reg_srl_reg” *),將綜合成在SRL之前、之后分別用一個(gè)register來(lái)實(shí)現(xiàn)。如圖所示:

            5. Vivado HLS QRD矩陣分解設(shè)計(jì)結(jié)果

            本文中QRD矩陣分解的大小是128x128的單精度復(fù)數(shù)浮點(diǎn),我們使用Xilinx

            Vivado HLS 2014.4版本,將其生成的RTL在Xilinx Virtex-7 FPGA上實(shí)現(xiàn)。

            5.1 延遲(latency)性能

            本文所述的設(shè)計(jì),在Xilinx Vivado HLS 2014.4中達(dá)到的延遲15237個(gè)時(shí)鐘周期。

            5.2 Interval(吞吐率的倒數(shù))性能

            在Xilinx Vivado HLS中,interval是指下一個(gè)新的可以輸入QRD模塊的數(shù)據(jù)與前一個(gè)數(shù)據(jù)之間所間隔的時(shí)鐘周期數(shù),也可以理解為吞吐率的倒數(shù)。這里Interval的單位是時(shí)鐘周期。

            本文所述的設(shè)計(jì),在Xilinx Vivado HLS 2014.4 中達(dá)到的Interval是15238個(gè)時(shí)鐘周期。

            5.3 時(shí)序(timing)性能

            使用Xilinx Vivado HLS 2014.4在Xilinx Virtex-7器件中實(shí)現(xiàn)單個(gè)128x128單精度浮點(diǎn)復(fù)數(shù)QRD分解模塊,時(shí)鐘頻率達(dá)到了350 MHz (2.85ns)。

            5.4 處理時(shí)間性能

            QRD矩陣分解的處理時(shí)間就是所用的延遲x時(shí)鐘周期,所以是:15237 x 2.85 = 43.4 uS。

            5.5 FPGA資源

            將Xilinx Vivado HLS 2014.4生成的RTL代碼,在Vivado 2014.4中綜合,實(shí)現(xiàn),使用的資源如下表。這個(gè)資源使用率只占Xilinx Virtex-7 7V485T的4%,使用Vivado HLS 2014.4高效地實(shí)現(xiàn)了QRD矩陣分解。

            6. 總結(jié)

            使用Xilinx Vivado HLS工具,可以讓算法工程師、FPGA工程師及軟件工程師快速基于FPGA實(shí)現(xiàn)典型的數(shù)字信號(hào)處理算法。本文以浮點(diǎn)復(fù)數(shù)QRD矩陣分解為例,介紹了如何使用 Vivado HLS 快速、高效地基于FPGA實(shí)現(xiàn),并降低開(kāi)發(fā)者對(duì)算法的FPGA實(shí)現(xiàn)難度。

            Vivado HLS可以幫助設(shè)計(jì)者大幅提升生產(chǎn)力。 使用 Vivado HLS 開(kāi)發(fā)效率比手寫(xiě)RTL實(shí)現(xiàn)快5-10倍,其FPGA資源效率與手寫(xiě)RTL接近,且C/C++仿真驗(yàn)證比傳統(tǒng)FPGA RTL要快100倍。

           

          Xilinx公司資深DSP專家王宏強(qiáng)

            Xilinx公司高級(jí)FAE 徐堅(jiān)鄧濤

            Xilinx公司工具與方法學(xué)高級(jí)專家徐天容

          c語(yǔ)言相關(guān)文章:c語(yǔ)言教程


          c++相關(guān)文章:c++教程




          關(guān)鍵詞: Xilinx Vivado

          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();