說(shuō)起來(lái),FPGA功耗優(yōu)化這個(gè)話題,在圈子里屬于那種"都知道重要,但真到實(shí)戰(zhàn)又不知道從哪下手"的類型。每次項(xiàng)目收尾,看到功耗報(bào)告里那些數(shù)字,很多工程師朋友估計(jì)跟我一樣——頭皮發(fā)麻。
今天想跟大伙兒聊聊一個(gè)相對(duì)冷門但效果顯著的角度:翻轉(zhuǎn)率(Toggle Rate)。這玩意兒聽起來(lái)挺學(xué)術(shù),但理解透了之后,你對(duì)功耗的把控能力會(huì)上一個(gè)臺(tái)階。
功耗到底花在哪了?先搞清楚這個(gè)
在說(shuō)翻轉(zhuǎn)率之前,咱們得先把FPGA功耗的賬算清楚。FPGA的功耗主要由兩部分構(gòu)成:靜態(tài)功耗和動(dòng)態(tài)功耗。靜態(tài)功耗說(shuō)白了就是"漏電"——芯片上電了但沒(méi)干活,晶體管照樣有漏電流在跑。這部分跟工藝、溫度關(guān)系比較大,咱們今天不重點(diǎn)聊。
重點(diǎn)是動(dòng)態(tài)功耗,這玩意兒占到總功耗的60%~80%,是真正的"用電大戶"。動(dòng)態(tài)功耗的來(lái)源就是信號(hào)翻轉(zhuǎn)——當(dāng)電平在0和1之間跳來(lái)跳去的時(shí)候,F(xiàn)PGA內(nèi)部的電容在反復(fù)充放電,這就要耗電。
有個(gè)經(jīng)典公式,大家可以記一下:
動(dòng)態(tài)功耗 = α × C × V2 × f
其中:
·α(Alpha)= 翻轉(zhuǎn)率,也就是每個(gè)時(shí)鐘周期信號(hào)翻轉(zhuǎn)的平均次數(shù)
·C= 負(fù)載電容,跟布線長(zhǎng)度、資源用量有關(guān)
·V= 供電電壓
·f= 工作頻率

FPGA功耗中,動(dòng)態(tài)功耗占比高達(dá)60%~80%
從公式可以看出,翻轉(zhuǎn)率α是跟功耗成正比的。如果能把翻轉(zhuǎn)率降下來(lái),功耗就能直接降下來(lái)。這事兒說(shuō)著簡(jiǎn)單,做起來(lái)其實(shí)有不少門道。
翻轉(zhuǎn)率是個(gè)什么鬼?
翻轉(zhuǎn)率描述的是信號(hào)在單位時(shí)間內(nèi)翻轉(zhuǎn)(0→1或1→0)的次數(shù)。舉個(gè)例子:一個(gè)信號(hào)每個(gè)時(shí)鐘周期都翻轉(zhuǎn)一次,那它的翻轉(zhuǎn)率就是100%;如果每?jī)蓚€(gè)周期才翻一次,翻轉(zhuǎn)率就是50%。
在FPGA里,不同信號(hào)的翻轉(zhuǎn)率差異巨大:
| 信號(hào)類型 | 典型翻轉(zhuǎn)率 | 功耗貢獻(xiàn) |
|---|---|---|
| 時(shí)鐘信號(hào) | 100%(每個(gè)周期都翻) | 極高(占動(dòng)態(tài)功耗20%+) |
| 高頻計(jì)數(shù)器高位 | 50%~100% | 高 |
| 數(shù)據(jù)總線 | 取決于數(shù)據(jù)模式 | 中等 |
| 控制信號(hào) | 通常較低 | 低 |
| 空閑模塊輸入 | 不可控(毛刺?。?/td> | 容易被忽略的"電老虎" |

翻轉(zhuǎn)率與動(dòng)態(tài)功耗呈線性正相關(guān)關(guān)系
有意思的是,時(shí)鐘信號(hào)雖然只占信號(hào)總數(shù)的很小一部分,但因?yàn)樗總€(gè)周期都在翻,而且時(shí)鐘網(wǎng)絡(luò)的扇出極大、負(fù)載很重,所以時(shí)鐘本身的功耗能占到整個(gè)FPGA動(dòng)態(tài)功耗的20%以上。這就是為什么時(shí)鐘管理是低功耗設(shè)計(jì)的"七寸"。
實(shí)戰(zhàn)技巧一:狀態(tài)機(jī)編碼的門道
狀態(tài)機(jī)可以說(shuō)是FPGA設(shè)計(jì)里最常見的結(jié)構(gòu)了,但很多人在寫狀態(tài)機(jī)的時(shí)候,根本沒(méi)考慮過(guò)編碼方式對(duì)功耗的影響。
咱們來(lái)對(duì)比一下三種常見的編碼方式:
| 編碼方式 | 狀態(tài)跳轉(zhuǎn)時(shí)翻轉(zhuǎn)位數(shù) | 功耗表現(xiàn) | 適用場(chǎng)景 |
|---|---|---|---|
| 二進(jìn)制編碼 | 多位同時(shí)翻(如0111→1000會(huì)翻4位) | 高 | 狀態(tài)少、低頻簡(jiǎn)單控制 |
| 格雷碼編碼 | 固定1位 | 低 | 狀態(tài)多、異步系統(tǒng)、計(jì)數(shù)器 |
| 獨(dú)熱碼(One-Hot) | 固定2位(1→0 + 0→1) | 低 | 高速場(chǎng)景、狀態(tài)數(shù)≤16 |

不同狀態(tài)編碼方式的翻轉(zhuǎn)位數(shù)對(duì)比
我之前踩過(guò)一個(gè)坑:有個(gè)項(xiàng)目需要實(shí)現(xiàn)一個(gè)16狀態(tài)的狀態(tài)機(jī),我圖省事直接用了二進(jìn)制編碼。結(jié)果一跑功耗分析,光狀態(tài)寄存器就吃了不少功耗。后來(lái)改成格雷碼,單是狀態(tài)跳轉(zhuǎn)這一塊,功耗就降了將近30%。
格雷碼的好處在于相鄰狀態(tài)之間永遠(yuǎn)只有1位翻轉(zhuǎn),不會(huì)像二進(jìn)制編碼那樣出現(xiàn)多位同時(shí)跳變的情況。對(duì)于狀態(tài)數(shù)比較多的場(chǎng)景,這個(gè)優(yōu)化效果非常明顯。
小提示:如果狀態(tài)數(shù)剛好是2的冪(比如8、16、32),格雷碼實(shí)現(xiàn)起來(lái)最自然。如果不是2的冪,可能需要做一些額外處理,但值得。
實(shí)戰(zhàn)技巧二:時(shí)鐘使能,別再用組合邏輯門控了
說(shuō)到降低翻轉(zhuǎn)率,時(shí)鐘門控是個(gè)繞不開的話題。但我發(fā)現(xiàn)有些工程師朋友還在用這種寫法:
// 這種寫法看起來(lái)像門控時(shí)鐘,但實(shí)際上會(huì)有毛刺問(wèn)題! assign gated_clk = enable ? clk : 1'b0;
這種組合邏輯實(shí)現(xiàn)的"門控時(shí)鐘"簡(jiǎn)直是功耗和時(shí)序的雙重噩夢(mèng)。毛刺會(huì)在時(shí)鐘上產(chǎn)生額外的窄脈沖,導(dǎo)致寄存器行為不可預(yù)測(cè),而且這些窄脈沖也會(huì)消耗額外的動(dòng)態(tài)功耗。
正確做法是用器件提供的專用時(shí)鐘門控單元(ICG, Integrated Clock Gating)或者時(shí)鐘使能信號(hào)(Clock Enable)。在Xilinx的FPGA里,可以這樣寫:
// 推薦寫法:使用時(shí)鐘使能 always @(posedge clk or negedge rst_n) begin if (!rst_n) data_reg <= 8'b0; else if (enable_signal) // 只有使能有效時(shí)才翻轉(zhuǎn) data_reg <= data_in; end
現(xiàn)代綜合工具會(huì)自動(dòng)識(shí)別這種模式,并利用芯片內(nèi)置的ICG單元來(lái)實(shí)現(xiàn)低功耗門控。這種方式不會(huì)產(chǎn)生毛刺,時(shí)序也更安全。
還有一個(gè)細(xì)節(jié):時(shí)鐘使能阻止的是寄存器的翻轉(zhuǎn),但時(shí)鐘樹本身還在跑。對(duì)于一些需要徹底關(guān)閉的場(chǎng)景(比如某個(gè)模塊長(zhǎng)時(shí)間不用),可以考慮使用BUFGMUX來(lái)直接切斷時(shí)鐘樹,這能把該區(qū)域的時(shí)鐘功耗直接降到接近零。
實(shí)戰(zhàn)技巧三:操作數(shù)隔離,防止"無(wú)效忙碌"
這個(gè)問(wèn)題可能很多人沒(méi)注意到:當(dāng)某個(gè)模塊處于空閑狀態(tài)時(shí),它的輸入端可能還在接收數(shù)據(jù)或者受到噪聲干擾,導(dǎo)致內(nèi)部邏輯持續(xù)在做無(wú)意義的翻轉(zhuǎn)。
舉個(gè)例子,你有一個(gè)乘法器模塊,只有當(dāng)valid信號(hào)為高時(shí)才應(yīng)該工作。但如果沒(méi)有做操作數(shù)隔離,當(dāng)valid為低時(shí),乘法器的輸入端可能還是隨機(jī)變化,導(dǎo)致它白做功。
解決方案是在模塊空閑時(shí)鎖定輸入信號(hào):
// 操作數(shù)隔離示例 wire [7:0] a_safe = module_enable ? a : 8'b0; wire [7:0] b_safe = module_enable ? b : 8'b0; // 只有使能時(shí)才讓乘法器工作 assign result = module_enable ? (a_safe * b_safe) : 32'b0;
這樣一來(lái),當(dāng)模塊空閑時(shí),輸入端被固定在確定電平,不會(huì)產(chǎn)生無(wú)效翻轉(zhuǎn)。
實(shí)戰(zhàn)技巧四:總線數(shù)據(jù)編碼的門道
對(duì)于數(shù)據(jù)總線,其實(shí)也有一些可以減少翻轉(zhuǎn)的編碼技巧。特別是當(dāng)總線在相鄰數(shù)據(jù)之間變化時(shí),如果能預(yù)測(cè)這種變化模式并做一些處理,可以顯著降低翻轉(zhuǎn)率。
一個(gè)經(jīng)典的做法是位反轉(zhuǎn)編碼:
// 簡(jiǎn)單示例:比較前后數(shù)據(jù),如果翻轉(zhuǎn)位超過(guò)一半就反轉(zhuǎn)整個(gè)字 wire [7:0] data_xored = data ^ data_prev; wire [2:0] bit_count = count_bits(data_xored); // 如果翻轉(zhuǎn)位超過(guò)4位,反轉(zhuǎn)編碼 wire need_invert = bit_count > 3'd4; wire [7:0] encoded_data = need_invert ? ~data : data; wire encoding_bit = need_invert;
這個(gè)技巧在高速SerDes接口或者存儲(chǔ)器數(shù)據(jù)總線中用得比較多,能把有效翻轉(zhuǎn)率降低30%~50%。
怎么驗(yàn)證優(yōu)化效果?
說(shuō)了這么多技巧,大家肯定關(guān)心:怎么知道自己優(yōu)化到位了?
這里給大家推薦幾個(gè)方法:
1. Vivado/Xilinx平臺(tái):綜合實(shí)現(xiàn)完成后,運(yùn)行report_power命令生成功耗報(bào)告。重點(diǎn)關(guān)注這幾個(gè)指標(biāo):
| 指標(biāo) | 關(guān)注原因 |
|---|---|
| Clocking功耗占比 | >40%說(shuō)明時(shí)鐘樹過(guò)大,優(yōu)化空間大 |
| Top Switching Nets | 找出翻轉(zhuǎn)率異常高的信號(hào) |
| Power by Resource Type | Logic/BRAM/DSP/IO的功耗分布 |
2. 仿真加翻轉(zhuǎn)率注解:在Vivado里可以對(duì)仿真生成的SAIF文件進(jìn)行功耗估算,這樣能得到更接近實(shí)際工作場(chǎng)景的翻轉(zhuǎn)率數(shù)據(jù)。
3. 功耗優(yōu)化前后對(duì)比:這個(gè)最直接。我一般會(huì)記錄優(yōu)化前后的功耗數(shù)據(jù),做成表格,這樣能清楚地看到每項(xiàng)優(yōu)化的實(shí)際貢獻(xiàn)。
一個(gè)真實(shí)的優(yōu)化案例
給大家分享一個(gè)我之前做的項(xiàng)目:圖像處理流水線,里面有個(gè)狀態(tài)機(jī)控制LED指示燈。

優(yōu)化前后實(shí)測(cè)數(shù)據(jù)對(duì)比
原始設(shè)計(jì):
| 指標(biāo) | 優(yōu)化前 | 優(yōu)化后 | 提升 |
| 狀態(tài)翻轉(zhuǎn)位數(shù) | 平均1.5位/次 | 1位/次 | ↓33% |
| 無(wú)效時(shí)鐘翻轉(zhuǎn) | 100% | 空閑時(shí)0翻轉(zhuǎn) | 顯著下降 |
| 實(shí)測(cè)總功耗 | 120mW | 82mW | ↓31.6% |
其實(shí)改動(dòng)不大:狀態(tài)機(jī)從二進(jìn)制改成格雷碼,加了時(shí)鐘使能控制。就這兩招,功耗降了將近三分之一。
總結(jié)一下
翻轉(zhuǎn)率優(yōu)化要點(diǎn)
理解公式 :P = α × C × V2 × f,翻轉(zhuǎn)率α跟功耗成正比
狀態(tài)機(jī)編碼 :優(yōu)先考慮格雷碼或獨(dú)熱碼,減少狀態(tài)跳轉(zhuǎn)時(shí)的翻轉(zhuǎn)
時(shí)鐘門控 :用ICG/CE等硬件機(jī)制,不要用組合邏輯直接門控
操作數(shù)隔離 :讓空閑模塊的輸入固定,避免無(wú)效翻轉(zhuǎn)
善用工具 :功耗報(bào)告是優(yōu)化的指南針,看懂它才能精準(zhǔn)發(fā)力
最后說(shuō)一句,功耗優(yōu)化不是一蹴而就的事,也不是單靠某個(gè)技巧就能搞定。它需要咱們?cè)谠O(shè)計(jì)早期就有低功耗的意識(shí),然后在RTL編碼、約束設(shè)置、實(shí)現(xiàn)優(yōu)化這幾個(gè)環(huán)節(jié)都把好關(guān)。
希望今天分享的這些心得對(duì)大家有幫助。如果你們?cè)趯?shí)際項(xiàng)目里有什么好的優(yōu)化經(jīng)驗(yàn)或者踩過(guò)的坑,歡迎在評(píng)論區(qū)聊聊~
—— 專注FPGA,分享實(shí)戰(zhàn)經(jīng)驗(yàn)
-
FPGA
+關(guān)注
關(guān)注
1663文章
22487瀏覽量
638686 -
功耗
+關(guān)注
關(guān)注
1文章
844瀏覽量
33332 -
狀態(tài)機(jī)
+關(guān)注
關(guān)注
2文章
501瀏覽量
29299
原文標(biāo)題:FPGA功耗優(yōu)化新思路,從翻轉(zhuǎn)率入手能省多少電
文章出處:【微信號(hào):FPGA研究院,微信公眾號(hào):FPGA研究院】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
面對(duì)競(jìng)爭(zhēng) Lattice持續(xù)優(yōu)化FPGA成本和功耗
聊一聊FPGA低功耗設(shè)計(jì)的那些事兒
單粒子翻轉(zhuǎn)引起SRAM型FPGA的故障機(jī)理闡述
從翻轉(zhuǎn)率入手優(yōu)化FPGA功耗
評(píng)論