1. 程式人生 > >FPGA高手設計實戰真經100則——摘記

FPGA高手設計實戰真經100則——摘記

《命名規範》

1、  檔案頭:必須包含正確的版權資訊和宣告。可以包含簡短說明、設計工程師名字和電子郵箱、版本幾對該檔案進行更改的列表。

格式:/*--------------------------------------------------------------------------------------------------------------

                    說明……

------------------------------------------------------------------------------------------------------------------*/

2、  一個檔案實現一個verilog模組,模組名稱與檔名相匹配。

//file: my_module.v

module my_module;

//module implementation

endmodule        //my_module

3、  標示符命名兩種風格:

a.  大小寫混合,沒有下劃線,每個單詞第一個字母大寫,如reg MyRegister;

b.  全部小寫,字與字之間用下劃線(推薦),reg my_register;

4、  常用字尾:

_p,_n:正極性或負極性,或兩個差分訊號

_ff,_q:暫存器輸出

_c:組合門驅動的訊號

_cur:現態

_next:次態

_tb:測試平臺

_en:使能

5、  時鐘訊號:wireclk50;    wire clk_200_p,clk_200_n;      wire clk_en;

6、  復位訊號:regreset;//高電平有效       reg reset_n;//低電平有效

7、  埠名稱:_i,_o等等。

《連線模組例項的埠》

有兩種方法:通過名稱和通過順序。推薦用通過名稱方法,允許更多靈活性,例如可以省略一個未連線的埠。雖然程式碼量稍大,但更具有可讀性且不容易出錯,尤其適合具有數百個埠的大型模組。

個人寫法:module名 m(.舊埠(新埠),……);

《使用可變的位元範圍選擇》

看例子:assign qout[24+:8] = din[7-:8];

等價於  assign qout[24:31] = din[7:0];

這種方法不容易出錯,可以防止胃口不匹配情況。

《使用函式》

module function_example(input a,b, outputfunc_out);

         functionfunc_xor;

         inputa,b;

         begin

                   func_xor= a^b;

         end

         endfunction

         assignfunc_out = func_xor(a,b);

endmodule       //function_example

建議使用函式來實現組合邏輯和其他需非阻塞幅值的操作(如同步邏輯)。

《使用generate塊》

使得模組、函式、變數、訊號和連續幅值的多次例化更加容易。

genvar I;

generate

         for(i=0;i<32;i=i+1)

         begin

                   my_modulem(.clk(clk),.di(di[i]),do(do[i]));

         end

         end

endgenerate

關於generate的理解,百度了很多,以下回答我覺得可以接受的:

“1.
只能說在一定的條件下可以替代,因為generate的用法還是很寬泛的,她和module可以說是一個等級的。
在generate中的要求和在module中很類似,因為generate就是生成一個電路,電路結構就是你在generate中表述的內容。所以if,while這些語句都必須在generate中再嵌入一個initial或always塊,然後在這些塊中描述電路特徵
至於例項呼叫的問題,可以被例項呼叫的必須是一個完整的語句塊,有I/O,有語句,那些if,while等語句單獨是不能存在的,所以也就不能例項呼叫(換句話說,如果你吧一個if寫成一個function或者一個module,那麼就可以呼叫了)
2.
我糾正一下自己的回答,說是執行語句可能有些不恰當
可以獨立存在於generate塊或者module的應當是變數宣告,常量定義,assign賦值,門級語句,塊宣告,例項呼叫方法(I/O匹配表)
可能有些遺漏,不過也差不多了,像ifelse,while,for,case這類的語句都是高階語句,是不能獨立出現的,必須放在initial或always塊中

《阻塞和非阻塞語句》

1、  他們永遠不應該混在同一個always塊中,否則會導致不可預知的綜合和模擬後果。雖然一般情況不會產生警告。

2、  在always塊中的阻塞賦值是按著順序執行的。因此建議不要使用多個阻塞賦值修改一個always塊內同一個變數。

《暫存器初始化》

有三種方法:

1、  initial塊中初始化,但只在模擬有用,綜合時忽略。

2、  宣告期間初始化。           reg my_reg = 1’b0;

3、  使用復位reset進行初始化 (if……else……)

《verilog和VHDL混合使用》

只要所有邊界規則得以滿足,就能直接在一起使用。Xilinx規則:

1、  混合使用僅僅限於設計單元的例化。VHDL設計中可以例化verilog模組,verilog設計中可以例化VHDL實體。任何VHDL和verilog之間的其他型別混用是不支援的。

2、  Verilog中例化VHDL,將模組名定義為與要例化的VHDL實體相同,並執行常規的verilog例化。大小寫敏感。

3、  VHDL中例化verilog模組,定義VHDL元件名與想要例化的verilog模組名相同。

《時鐘設計方案》

1、  使用專用的時鐘資源。

內部產生的時鐘是組合邏輯或暫存器輸出。組合邏輯產生的時鐘可能有毛刺,會被錯誤的當成時鐘邊沿造成錯誤。因此不要使用組合邏輯的輸出做時鐘。

其次內部產生的時鐘使用通用佈線資源,與專用時鐘佈線相比延遲較長,會導致時鐘偏移增加,滿足時序的過程更加困難。若大量使用,問題突出。

因此儘可能使用專用時鐘資源(dcm,pll等)。

2、  使用時鐘單個邊沿。使用兩個邊沿帶來的問題是由於時鐘佔空比可能不總是50%,會對電路產生影響。

3、  頻率高情況下(比如高於100M)使用差分時鐘,相比單端時鐘優勢是共模噪聲一直,抗噪聲效能好。高速邏輯下首選。

4、  避免使用門控時鐘。根本原因在於fpga採用專用的低延遲時鐘網路,只有整個時鐘系統執行在該網路時,才能達到最高效能。而通過組合邏輯的門控時鐘訊號執行在普通佈線資源上,大大降低效能,甚至帶來保持時間問題。

5、  不建議將時鐘訊號作為通用邏輯的控制、復位(即判斷)或資料輸入。

《跨時鐘域及時鐘同步電路》

實現不同時鐘域之間資料傳輸時,亞穩態需要考慮,即不是0也不是1的過渡狀態,會導致資料破壞。解決方案:

1、  兩個時鐘使用兩個暫存器進行同步。注意,兩個暫存器之間不要有組合邏輯,否則毛刺會影響後面的暫存器。還要注意,後暫存器的時鐘必須比前暫存器的高。反之,資料會被錯過。這個挺好理解。一般還要附加時序約束。以覆蓋兩個時鐘域之間的所有路徑。

一般包括時鐘週期約束以及之間的路徑約束。

2、  使用FIFO。缺點兩個,一個是需要相當多的邏輯和嵌入式儲存器資源。另一個是增加了延遲。

3、  採用格雷碼編碼技術,每次碼字只有一位發生變化,可用於資料匯流排同步。

4、  制定握手協議。一般過程是:傳送源時鐘域的請求,目標域接收請求,執行同步,捕捉資料,並送回一個確認。源時鐘域接收確認,準備傳送下一個資料。好處是它並不需要對資料同步,可以節省大量邏輯資源。缺點是每次傳輸資料,交換請求、確認的過程增加了延遲。

《計算FIFO深度》

使用模式之一是生產者和消費者之間緩衝資料。整個生產者的資料速率不應超過消費者處理資料的速率。FIFO不是旨在克服速率的差異。無論FIFO多深,如果生產者的資料傳輸速率始終比消費者高,那麼終會溢位。FIFO旨在通過緩衝多餘資料的方式,克服暫時的生產者——消費者資料速率差異。

公式:L = T*(P-C)。

《帶符號的算術運算》

例如wire signed [15:0] val;    //unsigned是可選的。

1、  移位運算子,邏輯的表示為<<、>>,帶符號的活算術的表示為<<<、>>>。

其中<<和<<<,將左運算元,移位的位數由右運算元給出。最右邊的位用零填補。

>>將左運算元向右移位,移位的位數由右運算元給出。空出的位用零填補。

>>>要根據結果型別判斷。如果結果賦給不帶符號數,則>>>將用零填補空出位置。如果結果賦給符號數,則運算子要對最左邊的符號進行符號擴充套件(理解)。

2、  算術運算。如果所有運算元都是帶符號的,結果將使用帶符號的算術進行計算。如果有一個運算元是不帶符號的,則使用不帶符號的算術運算。

《復位方案》

1、  非同步復位

a、  缺點:造成設計偶發錯誤,難以發現解決,比如復位延遲問題。另外如果復位訊號由組合邏輯驅動,那麼非同步復位會受到毛刺影響。

b、  優點:不需要時鐘一直有效,可能減少損耗;設計的快速物理實現,更為寬鬆的時序約束。為了滿足這些約束,佈局佈線工具花費的時間和努力更少。

2、  同步復位

建議使用。保證了復位只發生在有效時鐘邊沿。因此對於復位訊號上的小毛刺來說,時鐘作為濾波器使用;從設計的邏輯利用率角度來看非常有利;有助於執行不同的面積優化等等。

3、  沒有復位:設計不靈活,只能上電初始化。

《時序約束》

1、  PERIOD(週期)約束。用於設計始終,並且定義了週期。

NET “clk1”TNM_NET = clk1;

TIMESPEC TS_ clk1=PERIOD “clk1” 5 ns HIGH 50%;

2、  OFFSET IN/OUT(輸入/輸出偏離)約束。規定了外部輸入始終和資料輸入/輸出引腳之間的時序關係。

NET “data_in” OFFSET = IN 5 ns VALID 5 ns BEFORE “clk1”RISING;

規定了data_in在clk1上升沿之前最多有效5ns。

Net “data_out” OFFSET = OUT 4.1 ns AFTER “clk2”;

規定了data_out在clk2變化後最多有效4.1ns。

OFFSET約束適用於與特定IO相連的訊號,或者與多個或全部IO相連的一組訊號,不能用於內部訊號。這個約束規定了fpga輸入和輸出相對於時鐘的有效時序範圍。該範圍不是固定的、可預見的,每次設計都會發生變化。因此建議在IO快中佈局輸入和輸出暫存器(經常讀到這樣的程式),以確保每次設計的時序延遲都相同。

3、  MAXDELAY(最大延遲)和MAXSKEW(最大偏移)

NET “reset” MAXDELAY = 1 ns;

NET “reset” MAXSKEW = 2ns;

4、  FROM:TO約束,規定兩個邏輯組之間的時序約束。

TIMESPEC  “TS_CDC_1”= FROM “clk1” TO “clk2” 5ns;

規定了從clk1到clk2組的路徑不超過5ns。

TIMESPEC  ” TS_CDC_1”= FROM “clk1” TO “clk2” TIG;

從clk1到clk2組間的所有路徑排除在時序分析之外。

5、  TIG:忽略時序。

NET “data_in” TIG;

6、  約束優先順序由低到高:

PERIOD,OFFSET IN/OUT,FROM:TO,MAXDELAY,TIG