一開始接觸到FPGA,肯定都知道”復位“,即簡單又復雜。簡單是因為初學時,只需要按照固定的套路——按鍵開關復位,見寄存器就先低電平復位一次,這樣一般情況可以解決99%的問題,甚至簡單的設計,就不可能有問題。復雜是因為復位本身是對大規模的硬件單元進行一種操作,必須要結核底層的設計來考慮問題。
1. 常見問題
自己在學習實踐過程中,以及看到網友詢問的,有關FPGA復位設計大概有以下幾類問題:
我板子上沒有設計按鍵復位怎么辦?
怎么設計上電復位?不可能上電都要去按鍵吧
同步復位還是異步復位?各自優勢是啥?
高電平復位還是低電平復位?
……
歸根結底,就是怎樣設計復位,我可能給不出完美的答案,但查閱了一些資料,總結了一些設計中考慮的因素,在加上參考文獻,應該能解決99.9%的疑惑。
2. 常見的復位方式
我們習慣上通常使用的復位有三種方式:
硬件開關:復位信號接一個撥碼開關或按鍵,或者RC電路
控制芯片:控制芯片產生復位脈沖。
沒有專門的電源或控制芯片,甚至連按鍵都忘記設計的情況下,有人提出可不可以拿內部計數器做一個所謂的上電“軟”復位,如下代碼所示,當cnt計數到一定的值時,產生一個復位脈沖信號。
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt else
begin
if(cnt cnt else
cnt end
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
rst_nr0 rst_nr1 end
else if(cnt == 23‘d50_00000)
begin
rst_nr0 rst_nr1 end
else
begin
rst_nr0 rst_nr1 end
end
沒有設計外部硬件復位的同學又會反駁,我rst_n都沒有!去掉復位,默認上電cnt = 0,可不可以?既然默認cnt = 0了,那其他所有的寄存器不都默認為0了嗎?接著往下分析。
3. 合理的復位設計
從參考文獻中得出有關復位設計的幾條重要結論,有助于我們明確復位設計的方向,如下:
1. 低電平復位并不是最合理的處理方式;
2. 建議采用異步復位同步化(異步復位同步釋放處理);
3. 全局復位并不是最佳方式;
4. 并不是所有時序電路都要加復位;
對上述結論分析,見后續總結。
3.1 復位電平
有關復位電平,實際上是跟FPGA芯片內部的觸發器結構有關,在之前的博文有提到過。作為xilinx 7系列觸發器,其 R 端口既可用作同步置位/復位端口,也可用作異步預設/清除端口,但無論哪種方式,都是高電平有效。Altera的是低電平有效。
當在7系列芯片上采用低電平復位,會有什么問題呢?如下:
如果RTL代碼采用了低電平有效的復位模式,綜合器將在復位信號驅動寄存器SR控制端之前的插入一個反相器(interver)。你必須使用一個查找表(look up table)來實現反向器,以利用LUT的輸入端口。低電平有效的控制信號帶來的額外的邏輯可能拉長了執行時間(runtime),將導致更低的FPGA資源利用率,也將影響時序和功耗。
到底我想說點什么呢?盡可能的在HDL代碼或者實例化的模塊中使用高電平有效的控制信號。如果在設計中,你不能夠改變這些控制信號的極性,你需要在代碼的頂層文件反轉這些控制信號。采用這種方式描述電路的話,這些反向器將被吸收到I/O邏輯中,而不需要使用額外的FPGA邏輯、路徑。
所以再次強調:復位電平的選擇跟芯片結構有關!
3.2 異步復位同步化
異步復位同步化簡單的說就是將異步復位信號在相關的時鐘域模塊中進行同步化處理。單純的同步復位、異步復位以及其他的一些復位方式,都存在一些缺陷,比如抗噪聲、存在亞穩態等問題,深入學習可以查閱相關文獻。
異步復位同步化處理的結構代碼及schematic(xilinx 7系列)如下:
module rst_signal(
input clk,
input rst,
output sys_rst
);
reg r1_rst,r2_rst;
always@(posedge clk or negedge rst) begin
if(rst) begin
r1_rst r2_rst end else begin
r1_rst r2_rst end
end
assign sys_rst = r2_rst;
endmodule
可以看到,模塊將系統輸入的異步復位信號進行同步,產生了一個后續邏輯使用的同步化了的異步復位,隨后即可將該復位信號sys_rst用于其他模塊的復位。為了減少亞穩態對上述同步器中的兩個寄存器的影響,這兩個寄存器應該在FPGA中被放置的越靠近越好(相應的約束:set_property ASYNC_REG TRUE [get_cells [list r1_rst_reg r2_rst_reg]]),盡量減少布線延遲。
以上只是一個基本原理示意,在實際使用過程中還應注意以下兩點:
外部輸入異步復位信號應該增加濾波和去抖處理;
在復位之前,確保由 MMCM 或PLL 生成的時鐘是穩定且被鎖定的;
將異步復位信號分別引入不同的時鐘域進行同步化
綜上,復位處理的原理圖如下所示:
3.3 恰到好處的復位
看似簡單的復位,實際上不簡單,來系數復位的N宗罪:
復位網絡需要占用布線資源;
導致其余信號的布線信號受到影響,降低了它們布線的自由度;
增加的布線網絡往往需要使用更高速率的芯片;
復位網絡占用大量布線資源,使得Place&Route的時間大大增加;
復位信號需要占用大量的邏輯資源;
復位信號需要使用觸發器的專用復位管腳;
可操作的復位信號往往導致D觸發器的輸入前增加額外的門操作或專用的復位信號輸入;
增大整個設計 的尺寸;
額外的邏輯消耗降低了系統的性能;
阻止了使用高效特征,如Xilinx FPGA特有的SRL16E 移位寄存器。
簡單的說,復位的存在會對FPGA的綜合面積產生影響,主要體現在兩個方面:第一、在編寫代買的時候,習慣給所有時序電路都加上復位信號,這樣往往會導致資源無形的浪費;第二,沒有合理的設計復位電路會產生額外的資源消耗。
什么時候可以叫復位呢?一般判斷原則是:
類似于移位寄存器這類直通型電路,只起到一個傳輸信號的作用,本身不會對信號產生任何影響。其傳輸信號正確與否,在于其輸入端的信號是否正確。因此,此類電路自身無需加復位信號,而只需再起輸入端口加復位信號(也就是數據來源處的電路),以控制輸入數據。
4. 補充
4.1 所謂的上電初始化
當一個Xilinx的FPGA芯片被重新配置時,每一個單元都將被初始化。在某種意義上講,這是一個上電之后的“終極的”全局復位操作,因為它不僅僅是對所有的觸發器進行了復位操作,還初始化了所有的RAM單元。隨著Xilinx FPGA芯片內部的嵌入式RAM資源越來越多,這種“終極的”全局復位操作越來越有意義。對所有的RAM單元進行預定義,在軟件仿真和實際操作中都是非常有幫助的,因為這樣避免了在上電時采用復雜的啟動順序來清除存儲單元內容的操作。
所以在xilinx平臺,開篇的“軟”復位,實際上是沒有多大意義的。
綜上,采用以上總結的復位處理方法,應該能解決99.9%的問題了
評論
查看更多