第二章 FPGA改善面積方法

? 通常哭尝,我們使用正確的拓?fù)浣Y(jié)構(gòu)來減少面積哥攘,簡(jiǎn)而言之,將邏輯資源盡可能的復(fù)用,當(dāng)然這會(huì)帶來速度或者吞吐率的下降逝淹。因此常常用在需要迭代遞歸的運(yùn)算中耕姊,這些運(yùn)算的輸出往往需要反饋回到輸入端。

? 以下策略經(jīng)常被用于改善FPGA設(shè)計(jì)的面積:

  1. 卷起流水線

    “卷起流水線”這個(gè)名字聽起來較難理解栅葡,實(shí)際上這是一種跟我們常用的插入流水線相反的操作茉兰,即將一些并行流水線的邏輯通過更簡(jiǎn)單的串行結(jié)構(gòu)來實(shí)現(xiàn),具體需結(jié)合實(shí)際用例更好理解欣簇。

    module mult8(
        output [7:0] product,
        input [7:0] A,
        input [7:0] B,
        input clk);
        
        reg [15:0] prod16;
        
        assign product = prod16[15:8];
        
        always @(posedge clk)
         prod16 <= A * B;
    endmodule
    

    優(yōu)化后為:

    module mult8(
        output done,
        output reg [7:0] product,
        input [7:0] A,
        input [7:0] B,
        input clk,
        input start);
        
        reg [4:0] multcounter;   // counter for number of shift/adds
        reg [7:0] shiftB;        // shift register for B
        reg [7:0] shiftA;        // shift register for A
        
        wire adden;          // enable addition
        
        assign adden = shiftB[7] & !done;
        assign done = multcounter[3];
        
        always @(posedge clk) begin
            // increment multiply counter for shift/add ops
            if(start) 
             multcounter <= 0;
            else if(!done) 
             multcounter <= multcounter + 1;
            // shift register for B
            if(start) 
             shiftB <= B;
            else 
             shiftB[7:0] <= {shiftB[6:0], 1’b0};
            // shift register for A
            if(start) 
             shiftA <= A;
            else 
             shiftA[7:0] <= {shiftA[7], shiftA[7:1]};
            // calculate multiplication
            if(start) 
             product <= 0;
            else if(adden) 
             product <= product + shiftA;
        end
    endmodule
    

    對(duì)應(yīng)RTL圖為:


    image.png

    在之前的乘法器中规脸,數(shù)據(jù)可以流水線的形式每拍輸出一個(gè)結(jié)果,而將流水線卷起后熊咽,使用移位寄存器和加法來實(shí)現(xiàn)乘法運(yùn)算莫鸭,降低了邏輯資源,但這樣需要8個(gè)clk才能夠完成一次運(yùn)算横殴。

  1. 通過額外控制來復(fù)用邏輯

    復(fù)用邏輯資源通常需要加入額外的控制來決定資源被誰使用被因,實(shí)際上在第1小節(jié)的例子中,便使用了循環(huán)移位寄存器(shiftB)的比特來控制累加器是否計(jì)算衫仑,而在其他應(yīng)用中梨与,控制的邏輯往往會(huì)更加復(fù)雜。因此文狱,在復(fù)用的邏輯比控制邏輯資源更大時(shí)我們可以增加額外的控制來指定計(jì)算邏輯的復(fù)用粥鞋,而控制邏輯我們慣用狀態(tài)機(jī)來實(shí)現(xiàn)。

    下面以一個(gè)數(shù)字低通FIR濾波器為例

    Y = coeffA*X[0] + coeffB*X[1] + coeffC*X[2]
    

    優(yōu)化得到:

    module lowpassfir(
        output reg [7:0] filtout,
        output reg done,
        input clk,
        input [7:0] datain, // X[0]
        input datavalid, // X[0] is valid
        input [7:0] coeffA, coeffB; coeffC); // coeffs for low pass filter
        
        // define input/output samples
        reg [7:0] X0, X1, X2;
        reg multdonedelay;
        reg multstart;           // signal to multiplier to begin computation
        reg [7:0] multdat;
        reg [7:0] multcoeff;     // the registers that are multiplied together
        reg [2:0] state;         // holds state for sequencing through mults
        reg [7:0] accum;         // accumulates multiplier products
        reg clearaccum;      // sets accum to zero
        reg [7:0] accumsum;
        wire multdone;           // multiplier has completed
        wire [7:0] multout;  // multiplier product
        
        // shift-add multiplier for sample-coeff mults
        mult8x8 mult8x8(
        .clk(clk), 
        .dat1(multdat),
        .dat2(multcoeff), 
        .start(multstart),
        .done(multdone), 
        .multout(multout)
        );
        
        always @(posedge clk) begin
            multdonedelay <= multdone;
            // accumulates sample-coeff products
            accumsum <= accum + multout[7:0];
            
            // clearing and loading accumulator
            if(clearaccum) 
             accum <= 0;
            else if(multdonedelay) 
             accum <= accumsum;
             
            // do not process state machine if multiply is not done
            case(state)
            0: begin
                // idle state
                if(datavalid) begin
                    // if a new sample has arrived
                    // shift samples
                    X0 <= datain;
                    X1 <= X0;
                    X2 <= X1;
                    multdat <= datain; // load mult
                    multcoeff <= coeffA;
                    multstart <= 1;
                    clearaccum <= 1; // clear accum
                    state <= 1;
             end
                else begin
                    multstart <= 0;
                    clearaccum <= 0;
                    done <= 0;
                end
            end
            1: begin
                if(multdonedelay) begin
                    // A*X[0] is done, load B*X[1]
                    multdat <= X1;
                    multcoeff <= coeffB;
                    multstart <= 1;
                    state <= 2;
                end
                else begin
                    multstart <= 0;
                    clearaccum <= 0;
                    done <= 0;
                end
            end
            2: begin
                if(multdonedelay) begin
                    // B*X[1] is done, load C*X[2]
                    multdat <= X2;
                    multcoeff <= coeffC;
                    multstart <= 1;
                    state <= 3;
                end
                else begin
                    multstart <= 0;
                    clearaccum <= 0;
                    done <= 0;
                end
            end
            3: begin
                if(multdonedelay) begin
                    // C*X[2] is done, load output
                    filtout <= accumsum;
                    done <= 1;
                    state <= 0;
                end
                else begin
                    multstart <= 0;
                    clearaccum <= 0;
                    done <= 0;
                end
            end
            default
             state <= 0;
            endcase
        end
    endmodule
    

    其對(duì)應(yīng)RTL圖為


    image.png
  1. 在不同功能的操作中共享邏輯資源

    在這里所說的資源共享并不是指FPGA布局布線工具對(duì)底層的優(yōu)化如贷,而是指在頂層架構(gòu)級(jí)別的資源塊可以被兩個(gè)不同的功能模塊共享。

    下面以一個(gè)在FPGA設(shè)計(jì)中最常用到的計(jì)數(shù)器為例


    image.png

    在模塊A和模塊B中到踏,分別使用了8比特和11比特的計(jì)數(shù)器杠袱,將計(jì)數(shù)器資源放到更高層級(jí),讓A和B模塊共享使用窝稿,如下:


    image.png
  1. 復(fù)位對(duì)面積優(yōu)化的影響

    在我們進(jìn)行FPGA設(shè)計(jì)時(shí)楣富,一個(gè)很大的誤區(qū)就是復(fù)位只在全局層面進(jìn)行實(shí)現(xiàn)而對(duì)設(shè)計(jì)的大小影響極小伴榔;其實(shí)纹蝴,在考慮設(shè)計(jì)面積的時(shí)候,對(duì)大量信號(hào)都進(jìn)行復(fù)位是會(huì)帶來很大的時(shí)序和布線壓力的踪少。

    聽起來為每一個(gè)觸發(fā)器都設(shè)置復(fù)位是一個(gè)比較好的設(shè)計(jì)習(xí)慣塘安,但這樣的代價(jià)是工程會(huì)變得更大也更慢,同時(shí)會(huì)抑制工具對(duì)區(qū)域的優(yōu)化援奢,而這是不必要的兼犯。

    接下來會(huì)在具體場(chǎng)景中說明復(fù)位操作給設(shè)計(jì)的速度和面積帶來的影響,以及怎么進(jìn)行優(yōu)化。

4.1 無復(fù)位接口的資源

對(duì)于某些FPGA資源來說切黔,它們并不存在復(fù)位接口砸脊,例如簡(jiǎn)單的循環(huán)移位寄存器:

always @(posedge iClk)
 if(!iReset) 
     sr <= 0;
 else 
     sr <= {sr[14:0], iDat};

always @(posedge iClk)
 sr <= {sr[14:0], iDat};

這兩種描述看似差別很細(xì)微,僅僅是前者在復(fù)位時(shí)將寄存器中的值置零而已纬霞,然而對(duì)于FPGA來說凌埂,第一種描述將會(huì)使用觸發(fā)器實(shí)現(xiàn),第二種描述可以使用FPGA內(nèi)置的循環(huán)移位寄存器SRL16來實(shí)現(xiàn)诗芜,下面給出兩種設(shè)計(jì)對(duì)應(yīng)RTL圖:


image.png


image.png

而這兩者實(shí)現(xiàn)時(shí)所消耗資源也會(huì)有所差異


image.png

4.2 無置位接口的資源

與4.1相似的瞳抓,F(xiàn)PGA中有些資源是沒有置位接口的,比如一個(gè)8*8的乘法器

module mult8(
    output reg [15:0] oDat,
    input iReset, iClk,
    input [7:0] iDat1, iDat2,
    );
    
    always @(posedge iClk)
     if(!iReset) 
            oDat <= 16’hffff;
     else 
            oDat <= iDat1 * iDat2;
endmodule

其對(duì)應(yīng)RTL圖為


image.png

由于乘法器中只有復(fù)位接口而無置位接口绢陌,因此在代碼中如果我們使用置位操作挨下,那么復(fù)位端口被閑置的同時(shí)將會(huì)引入額外的邏輯完成置位操作。

4.3 沒有異步復(fù)位的資源

同樣的脐湾,F(xiàn)PGA中也有一些資源是不支持異步復(fù)位的臭笆,比如內(nèi)置DSP核:

module dspckt(
    output reg [15:0] oDat,
    input iReset, iClk,
    input [7:0] iDat1, iDat2);
    
    reg [15:0] multfactor;
    
    always @(posedge iClk or negedge iReset)
        if(!iReset) begin
            multfactor <= 0;
            oDat <= 0;
        end
        else begin
            multfactor <= (iDat1 * iDat2);
            oDat <= multfactor + oDat;
        end
    
endmodule

由于在上述代碼中使用了異步復(fù)位,因此會(huì)在dsp核對(duì)外圍引入額外的邏輯


image.png

額外邏輯資源消耗情況如下


image.png

4.4 同步復(fù)位RAM

在很多FPGA內(nèi)置的RAM資源一般是支持同步復(fù)位秤掌,如果我們?cè)谟迷Z設(shè)計(jì)時(shí)采用了異步復(fù)位模式愁铺,可能會(huì)導(dǎo)致最后綜合出不同結(jié)構(gòu)的RAM

module resetckt(
    output reg [15:0] oDat,
    input iReset, iClk, iWrEn,
    input [7:0] iAddr, oAddr,
    input [15:0] iDat);
    
    reg [15:0] memdat [0:255];
    
    always @(posedge iClk or negedge iReset)
        if(!iReset)
         oDat <= 0;
        else begin
         if(iWrEn)
             memdat[iAddr] <= iDat;
             oDat <= memdat[oAddr];
         end
    
endmodule

如果使用同步復(fù)位,將會(huì)綜合出一個(gè)BRAM


image.png

而使用異步復(fù)位闻鉴,將會(huì)綜合處一個(gè)distributed RAM茵乱,并增加額外解碼邏輯


image.png

這兩者的資源消耗情況為


image.png

如果使用了錯(cuò)誤的RAM復(fù)位方式,可能對(duì)綜合結(jié)果產(chǎn)生極大的影響孟岛。

筆者注:在當(dāng)前使用調(diào)用IP核的方式實(shí)現(xiàn)RAM時(shí)瓶竭,同步復(fù)位和異步復(fù)位的影響不會(huì)如上述情況。

4.5 利用觸發(fā)器的復(fù)位/置位功能實(shí)現(xiàn)某些邏輯

FPGA的觸發(fā)器往往是支持復(fù)位或者置位功能的渠羞,因此在進(jìn)行設(shè)計(jì)時(shí)斤贰,我們可以利用這一點(diǎn)將一些邏輯從組合邏輯中轉(zhuǎn)移出來,例如次询,使用置位端實(shí)現(xiàn)或門:


image.png

或是利用復(fù)位端實(shí)現(xiàn)與門


image.png

在下面的設(shè)計(jì)中荧恍,我們可以通過移除異步復(fù)位信號(hào)并利用復(fù)位端實(shí)現(xiàn)對(duì)應(yīng)邏輯

module setreset(
    output reg oDat,
    input iReset, iClk,
    input iDat1, iDat2);
    
    always @(posedge iClk or negedge iReset)
        if(!iReset)
         oDat <= 0;
        else
         oDat <= iDat1 | iDat2;
    
endmodule

其對(duì)應(yīng)RTL圖為:


image.png

可優(yōu)化為:


image.png

更進(jìn)一步的,在下面設(shè)計(jì)中可以做到更好

oDat = !iDat3 & (iDat1 | iDat2)

可以用以下方式實(shí)現(xiàn)

module setreset (
    output reg oDat,
    input iClk,
    input iDat1, iDat2, iDat3);
    
    always @(posedge iClk)
        if(iDat3)
         oDat <= 0;
        else if(iDat1)
         oDat <= 1;
        else
         oDat <= iDat2;
    
endmodule

其對(duì)應(yīng)RTL圖為


image.png

最后屯吊,總結(jié)起來一句話:在考慮設(shè)計(jì)的面積優(yōu)化時(shí)送巡,盡可能少的時(shí)候復(fù)位。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盒卸,一起剝皮案震驚了整個(gè)濱河市骗爆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蔽介,老刑警劉巖淮腾,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件糟需,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡谷朝,警方通過查閱死者的電腦和手機(jī)洲押,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來圆凰,“玉大人杈帐,你說我怎么就攤上這事∽ǘぃ” “怎么了挑童?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵垮耳,是天一觀的道長(zhǎng)淘捡。 經(jīng)常有香客問我,道長(zhǎng)朽肥,這世上最難降的妖魔是什么菇民? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任尽楔,我火速辦了婚禮,結(jié)果婚禮上第练,老公的妹妹穿的比我還像新娘阔馋。我一直安慰自己,他們只是感情好娇掏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布呕寝。 她就那樣靜靜地躺著,像睡著了一般婴梧。 火紅的嫁衣襯著肌膚如雪下梢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天塞蹭,我揣著相機(jī)與錄音孽江,去河邊找鬼。 笑死浮还,一個(gè)胖子當(dāng)著我的面吹牛竟坛,可吹牛的內(nèi)容都是我干的闽巩。 我是一名探鬼主播钧舌,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼涎跨!你這毒婦竟也來了洼冻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤隅很,失蹤者是張志新(化名)和其女友劉穎撞牢,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡屋彪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年所宰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片畜挥。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡仔粥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蟹但,到底是詐尸還是另有隱情躯泰,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布华糖,位于F島的核電站麦向,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏客叉。R本人自食惡果不足惜诵竭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望十办。 院中可真熱鬧秀撇,春花似錦、人聲如沸向族。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽件相。三九已至再扭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間夜矗,已是汗流浹背泛范。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留紊撕,地道東北人罢荡。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像对扶,于是被迫代替她去往敵國(guó)和親区赵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容