01 位寬不匹配
Verilog編碼中,常見的位寬不匹配錯誤,有賦值左右位寬不匹配(《=,=),比較位寬(》,《,》=,《=)不匹配,計算位寬(+,-)不匹配
位寬不匹配會導致DC之后的網表與預期差異較大,導致功能不正確,通過spyglass lint檢測可以發現所有位寬不匹配的情況,而vcs編譯只能發現少數連線位寬不匹配的情況。
02 位寬不匹配的危害
下文以比較位寬不匹配為例,講解位寬不匹配的危害。
注意:
1) 在條件判斷中(if語句),不建議使用加減后結果直接進行比較,禁止進行加減運算后與位寬不匹配的數據/變量進行比較。
2) 拼接符號中“{}”,不允許使用加減乘除等運算,綜合類軟件無法正確判斷數據運算結果位寬。數字運算必須先通過wire指定位寬,然后通過assign得到運算結果
錯誤案例1
如下代碼,代碼本意是:當cnt0與cnt1之和大于8的時候,count加1。
錯誤代碼中:
比較數據是4’h8,此時綜合完成后的網表中,會將cnt0與cnt1之和截位成4bit,再與4’h8比較,如果cnt0與cnt1之和為5’h10000,在此會截位為4’h0000,反而小于4’h8,與預期功能不符
正確代碼&推薦代碼中:
先定義:wire [4:0] cnt_add ; 指定cnt_add位寬為5bit,然后assign cnt_add = (cnt0+cnt1) ;最后與5’h8比較,因為通過wire指定了位寬,所以對于各類綜合軟件而言都不會發生截位,不會發生錯誤。
正確代碼&不推薦中
直接將4’h8修改為5’h8,也避免了cnt0+cnt1累加截位,但是spyglass lint會報warning,
不推薦。
reg [3:0] cnt0 ;
reg [3:0] cnt1 ;
reg [4:0] count ;
reg ov_nc ;
//-------------case 1-----------------
//wrong code
always @ (posedge clk or negedge rst_n)
if(!rst_n)begin
count 《= 5‘b0 ;
end
else if((cnt0+cnt1)》4’h8) //should be 5‘h8
begin
{ov_nc, count} 《= count +1’b1;
end
//right ,but not recommended
always @ (posedge clk or negedge rst_n)
if(!rst_n)begin
count 《= 5‘b0 ;
end
else if((cnt0+cnt1)》5’h8) //should be 5‘h8
begin
{ov_nc, count} 《= count +1’b1;
//right code and recommended 正確且推薦
wire [4:0] cnt_add ;
assign cnt_add = (cnt0+cnt1) ;
always @ (posedge clk or negedge rst_n)
if(!rst_n)begin
count 《= 5‘b0 ;
end
else if(cnt_add 》5’h8) // (cnt0+cnt1) is 5 bits
begin
{ov_nc, count} 《= count +1‘b1;
end
錯誤案例2
NOTE: 拼接符號中“{}”,不允許使用加減乘除等運算,綜合類軟件無法正確判斷數據運算結果位寬。數字運算必須先通過wire指定位寬,然后通過assign得到運算結果。
錯誤代碼中:
{1’b0,(cnt0+cnt1)} ,在if語句()拼接符號中,綜合軟件無法識別 (cnt0+cnt1)應該是多少bit,(cnt0+cnt1)可能會是5bit,也可能是4bit。
正確代碼&推薦代碼中
通過 wire [4:0] cnt_add ; assign cnt_add = (cnt0+cnt1) ; 指定了(cnt0+cnt1)之和為5bit,利用拼接符指定{1‘b0,cnt_add}為6bit,然后與6bit的cnt2比較。
正確代碼&不推薦中
通過 wire [4:0] cnt_add ; assign cnt_add = (cnt0+cnt1) ; 指定了(cnt0+cnt1)之和為5bit,但是直接與6bit的cnt2比較,各類綜合軟件也會正確識別位寬,不會發生截位,但是spyglass lint會報warning,雖然功能正確,但是不推薦。
//-------------case 2-----------------//
reg [3:0] cnt0 ;
reg [3:0] cnt1 ;
reg [5:0] cnt2 ;
//wrong code
always @ (posedge clk or negedge rst_n)
if(!rst_n)begin
count 《= 5’b0 ;
end
else if({1‘b0,(cnt0+cnt1)}《cnt2) //
begin
{ov_nc, count} 《= count +1’b1;
end
//right code and not recommended 正確不推薦
wire [4:0] cnt_add ;
assign cnt_add = (cnt0+cnt1) ;
always @ (posedge clk or negedge rst_n)
if(!rst_n)begin
count 《= 5‘b0 ;
end
else if(cnt_add《cnt2) //
begin
{ov_nc, count} 《= count +1’b1;
end
//right code and recommended 正確且推薦
wire [4:0] cnt_add ;
assign cnt_add = (cnt0+cnt1) ;
always @ (posedge clk or negedge rst_n)
if(!rst_n)begin
count 《= 5‘b0 ;
end
else if({1’b0,cnt_add}《cnt2) //
begin
{ov_nc, count} 《= count +1‘b1;
end
跨時鐘模塊錯用軟復位造成的危害
01 配置信號跨時鐘要求使用硬復位
在IC設計中,硬復位用于配置寄存器和配置信號的跨時鐘模塊。即一個配置信號cfg_mac_mode是由硬復位驅動的,如果要同步到其他時鐘域,跨時鐘模塊需要使用硬復位,而不能使用軟復位。
02 ? ?配置信號跨時鐘錯用軟復位的危害
而在上電復位過程中,硬復位和軟復位一般處于復位狀態,需要依次釋放,一般先釋放硬復位,配置好配置信號,然后才釋放軟復位。
正確設計:
采用硬復位做為同步跨時鐘模塊的復位信號,跨時鐘同步的配置信號在軟復位釋放前已經保持穩定,在軟復位釋放后,數據流進入模塊的時候,不會隨數據流一塊跳變。
錯誤設計:
采用軟復位做為同步跨時鐘模塊的復位信號,只有當軟復位釋放后才能變成我們期待的值,因此,在軟復位釋放后,數據流進入模塊的時候,同步后的配置信號會隨數據流一塊跳變,造成功能錯誤。
來源:
https://blog.csdn.net/icxiaoge/article/details/93305256
https://blog.csdn.net/icxiaoge/article/details/102632152
評論