編寫可綜合的FPGA代碼
在接觸Verilog 語法參考手冊的時候,我們發(fā)現(xiàn)其提供了一組非常豐富的功能來描述硬件。所以大家往往會疑惑那些Verilog語句是可綜合的,那些是只能用于寫Testbench的,其實,參考手冊中只有一小部分語句是可綜合的,但是這一小部分可綜合的語法確是我們應(yīng)用最為頻繁的,可綜合的意思就是可以通過物理工具進行編譯、綜合、布局布線,最終在FPGA上實現(xiàn)。
參考下面的例子。
reg [7:0] memory[1:2**22];
Initial begin
memory[1]=8’h1;
memory[2]=8’h2;
end
該示例雖然可以正常的仿真,但是用FPGA工具編譯綜合,最終在FPGA上實現(xiàn)。代碼中定義了一個4M Byte的存儲器,其實在FPGA中時沒有這樣的物理資源可以與其對應(yīng)的,另外,F(xiàn)PGA編譯綜合工具在編譯的時候也將忽略Initial塊語句。
本文重點介紹如何設(shè)計可綜合的Verilog代碼。在設(shè)計可綜合的Verilog代碼的時候,我們應(yīng)該遵循怎樣的原則。
1. 堅持FPGA的同步設(shè)計原則
包括以下幾個方面:
使用同步復(fù)位電路。
避免使用鎖存器; 盡可能使用同步寄存器。
避免使用門控,派生或分頻時鐘。
使用時鐘使能,而不是多個時鐘。
實現(xiàn)所有異步信號的正確同步。
2. 理解綜合工具的能力和局限性
充分了解綜合工具的能力和局限性將有助于提高FPGA設(shè)計的性能、邏輯性、以及資源利用率和可生產(chǎn)性。熟悉特定FPGA系列的內(nèi)部構(gòu)造,以及綜合工具所忽略或不支持的語言以及建議的寄存器,狀態(tài)機,三態(tài)和其他推薦的編碼風格非常重要。
3. 忽略語言結(jié)構(gòu)
FPGA綜合工具會忽略延遲值和時間標度編譯器指令。設(shè)計人員經(jīng)常利用延遲來使分析仿真波形變得更容易,如下例所示。
`define DLY 1
always @(posedge clk) begin
Data_out
end
因為潛在的綜合和仿真失配,所以不鼓勵使用這樣的結(jié)構(gòu)。例如,如果上例中的“DLY超過時鐘周期,則綜合電路可能在功能上不正確,因為它不會匹配仿真結(jié)果。絕大多數(shù)FPGA綜合工具都忽略編譯器指令,例如celldefine和endcelldefine。
FPGA綜合工具忽略initial塊描述。
綜合工具為Verilog門級原語(如nmos,pmos,cmos,pullup,pulldown,
tranif0,tranif1,tran等)提供各種級別的支持。例如,XST不支持Verilog tranif原語,而Synplify則支持。 盡管Xilinx FPGA體系結(jié)構(gòu)不具有門級原語的直接等價物,但一些綜合工具將其轉(zhuǎn)換為功能等效的門級開關(guān)。 以下是nmos轉(zhuǎn)換的一個例子。
module nmos_switch(output out,intput data,control);
Assign out =control?Data :1’bz ;
endmoudle
4. 不支持的語句結(jié)構(gòu)
不支持的語句結(jié)構(gòu)包括有:用戶自定義的原語(UDP),repeat,wait,
fork/join,deassign ,event,force/release 語句。也不支持模塊內(nèi)寄存器和網(wǎng)絡(luò)的分層引用,如:
module mymodule1;
assign my_net =top.my_mudule2.my_net ;
endmoudle
相等和不相等運算符(===和!==)的支持級別取決于綜合工具。有些綜合工具在遇到一個等式和不等式運算符時會產(chǎn)生一個錯誤,而另一些則會將運算符轉(zhuǎn)換為邏輯等式(==和!=)。
5. 2種狀態(tài)和4種狀態(tài)的比較
4態(tài)值(‘0’,‘1’,‘x’,‘z’)本質(zhì)上是不可綜合的。 FPGA架構(gòu)僅支持2態(tài)值(邏輯“0”和“1”),綜合工具將應(yīng)用不同的規(guī)則來優(yōu)化“z”和“x”綜合的過程。這將導(dǎo)致綜合和仿真結(jié)果之間的不匹配和其他錯誤。 在實現(xiàn)三態(tài)IO緩沖區(qū)的時候只使用‘z’值。
6. translate_on/translate_off
translate_off和translate_on表示讓綜合工具忽略Verilog代碼的一部分。這些指令通常用于忽略IP核模型中的行為代碼部分。以下是使用這些指令的示例。
module bram_2k_9 ( input clka, input [0 : 0] wea,
input [10 : 0] addra,
output [8 : 0] douta,
input [8 : 0] dina);
// synthesis translate_off
// behavioral description of bram_2k_9
// synthesis translate_on
endmodule // bram_2k_9
7. 特殊的編譯指令也無法被綜合
syn_keep指令可防止綜合工具刪除指定的信號。它適用于網(wǎng)絡(luò)和組合邏輯。 該指令通常用于禁用不需要的優(yōu)化,并保留手動創(chuàng)建的復(fù)制。綜合工具不同syn_keep的作用可能會不同。例如,XST不會將約束傳播到綜合網(wǎng)表,這并不妨礙物理實現(xiàn)工具的優(yōu)化。syn_preserve防止寄存器優(yōu)化。XST還支持“Equivalent Register Removal”選項,相當于syn_preserve。syn_noprune確保如果未使用實例化原型的輸出,則原型未被優(yōu)化。XST也支持“Optimize Instantiated Primittives”選項,相當于syn_noprune。
8. parallel_case和full_case
如果在case,casex或casez語句中指定了full_case指令,則會阻止綜合工具創(chuàng)建其他邏輯以涵蓋未描述的條件。使用full_case指令可能會有更緊湊的效果。parallel_case指令強制將case語句綜合成為并行復(fù)用器而不是優(yōu)先級編碼結(jié)構(gòu)。使用parallel_case指令可能會提高電路的時序性能。
full_case和parallel_case指令的確切作用取決于綜合工具。而且,使用這些指令也會導(dǎo)致綜合和仿真不匹配。出于這些原因,不建議在FPGA設(shè)計中使用full_case和parallel_case指令。相反,設(shè)計師可以通過一個case語句的實現(xiàn)來達到同樣的效果。例如,刪除重疊的大小寫條件會導(dǎo)致不必要的parallel_case指令。
9. 編譯器指令 `default_nettype
Verilog-2001標準定義了一個`default_nettype編譯器指令。 如果該指令被分配為“無”,則必須聲明所有的1bit 信號網(wǎng)絡(luò)。
// no `default_nettype
wire sum; // declaration is not required
assign sum = a + b;
`default_nettype none
wire sum; // must be declared
assign sum = a + b;
評論
查看更多