Verilog 主要用于數(shù)字電路設(shè)計的描述,但不是所有的描述方式都可以被綜合成實際的硬件電路。例如一些用于仿真驗證的關(guān)鍵字,屬于仿真驗證語言,只能在仿真時使用,不能被綜合成電路,如系統(tǒng)任務 $dsiplay, initial 語句等。所以使用 Verilog 設(shè)計數(shù)字電路時,一定要注意電路的可綜合性。testbench 可以隨心所欲,只要能構(gòu)造出需要的仿真激勵條件即可。
所有綜合工具都支持的結(jié)構(gòu)
結(jié)構(gòu)類型 | 關(guān)鍵字 | 描述 |
---|---|---|
端口信號 | inout,input,output | 端口信號只有 3 種 |
參數(shù) | parameter, localparam | --- |
信號變量 | wire, reg, tri, integer | --- |
模塊 | module | --- |
門級原語 | and,nand,or,nor,xor,xnor,buf,not,bufif0,bufif1,notif0,notif1,supply0,supply1 | 直接調(diào)用例化即可 |
例化 | --- | 支持模塊例化、門級原語例化等 |
函數(shù)與任務 | function, task | 支持不含時序結(jié)構(gòu)的表述 |
連續(xù)賦值 | assign | 不支持帶有延遲的表述 |
過程賦值 | always, begin, end | 可設(shè)計時序邏輯或組合邏輯 |
條件語句 | if, case, default | 條件中不能包含"z"或"x"的比較 |
循環(huán)語句 | for, while, forever | while, forever 必須包含 @(posedge clk) 或 @(negedge clk), 避免組合邏輯回路 |
邊沿觸發(fā) | negedge,posedge | --- |
操作符 | --- | 支持除 "===" 與 "!==" 以外的所有操作符 |
所有綜合工具都不支持的結(jié)構(gòu)
結(jié)構(gòu)類型 | 關(guān)鍵字 | 描述 |
---|---|---|
變量類型 | time | 仿真時使用的時間型變量 |
系統(tǒng)任務 | --- | 大多數(shù)系統(tǒng)任務都是輔助仿真,不能綜合為實際電路
例如 $display, $fopen, $finish 等。 |
過程結(jié)構(gòu) | initial | initial 常用作仿真時信號賦初值操作
或控制激勵信號的時序 |
并行語句 | fork, join | 常用作仿真時并行結(jié)構(gòu)的描述
always @(posedge clk) 描述的并行結(jié)構(gòu)可綜合 |
延遲語句 | # | 所有帶延遲標志"#"的表述均不可綜合
但仿真時電路中會有延時,綜合時也不會報錯 |
電平敏感觸發(fā) | wait | 多用于仿真中信號的檢測啟動 |
強制賦值和釋放 | force, release | 多用于仿真中阻斷其他驅(qū)動源,對信號進行強制賦值 |
綜合工具可能支持的結(jié)構(gòu)
結(jié)構(gòu)類型 | 關(guān)鍵字 | 描述 |
---|---|---|
x/z 條件語句 | casex, casez | 有些綜合工具能識別該語句中的非"x/z"比較邏輯 |
不同強度的線網(wǎng) | wand,triand,wor,trior | 當信號有多個驅(qū)動源時需要使用
但現(xiàn)在數(shù)字設(shè)計基本摒棄了這些變量類型 |
實數(shù)變量 | real | 往往用于仿真時的精確計算 |
過程終止 | disable | 終止過程塊執(zhí)行,大多數(shù)綜合工具不支持該命令 |
循環(huán)語句 | repeat, while, forever | repeat 常用作仿真中語句循環(huán)執(zhí)行固定次數(shù)
while, forever 循環(huán)次數(shù)為常量時也可能可綜合 |
用戶自定義原語 | UDP | 其實目前大多數(shù)綜合工具都支持 UDP
只是某些古老的綜合工具不會識別 |
過程連續(xù)賦值 | assign, deassign | 工具大多不支持該操作下 reg 數(shù)據(jù)類型的綜合
支持該操作下 wire 數(shù)據(jù)類型的綜合 |
使用 Verilog 進行數(shù)字設(shè)計時,需要遵循以下原則:可綜合的結(jié)構(gòu)可大膽使用,不可綜合的結(jié)構(gòu)仿真中使用,有些綜合工具支持有些不支持的結(jié)構(gòu)盡量不使用。
除非某些特殊設(shè)計,例如 clkgate, 時鐘切換等電路等,否則設(shè)計中不要編寫潛在的會被綜合成 Latch 的邏輯。詳見《Verilog 教程》章節(jié)《Verilog 避免 Latch》。
變量聲明時不要學 C 語言格式對寄存器變量進行賦初值操作。仿真時變量會有設(shè)置的初值,綜合后寄存器初值是不確定的。如果信號初值會影響邏輯功能,則仿真過程可能會因驗證不充分而錯過查找出邏輯錯誤的機會。
所有內(nèi)部寄存器都應該使用復位進行賦初值操作,以確保系統(tǒng)復位時各寄存器都有穩(wěn)定的狀態(tài)。因為沒有復位端,綜合后電路中寄存器的初始值不能確定,可能會導致功能錯誤。
組合邏輯使用阻塞賦值,時序邏輯使用非阻塞賦值。組合邏輯一般使用連續(xù)賦值語句 assign 描述,always 描述的電路也能被綜合成組合邏輯,例如"與邏輯"可以描述如下:
reg F ; //注意一定要是 reg 型變量
always @(*) begin
F = A & B ;
end
always 語句中被賦值的信號一定要聲明為 reg 型,在組合邏輯中該 reg 變量會被綜合成線網(wǎng),在時序邏輯中該 reg 變量會被綜合成觸發(fā)器。
同一個變量不能受多個時鐘(或 always 塊)控制,也不能受時鐘的雙邊沿控制。此類描述也是不可綜合的。
避免設(shè)計中出現(xiàn) ?X
? 或 ?Z
? 值,因為綜合工具只能識別 ?0
? 或 ?1
? 的邏輯值。
更多建議: