芯片設(shè)計(jì):Verilog之常見(jiàn)的位寬不匹配錯(cuò)誤
掃描二維碼
隨時(shí)隨地手機(jī)看文章
1、位寬不匹配
Verilog編碼中,常見(jiàn)的位寬不匹配錯(cuò)誤,有賦值左右位寬不匹配(<=,=),比較位寬(>,<,>=,<=)不匹配,計(jì)算位寬(+,-)不匹配
位寬不匹配會(huì)導(dǎo)致DC之后的網(wǎng)表與預(yù)期差異較大,導(dǎo)致功能不正確,通過(guò)spyglass lint檢測(cè)可以發(fā)現(xiàn)所有位寬不匹配的情況,而vcs編譯只能發(fā)現(xiàn)少數(shù)連線位寬不匹配的情況。
2、位寬不匹配的危害
下文以比較位寬不匹配為例,講解位寬不匹配的危害。
注意:
1) 在條件判斷中(if語(yǔ)句),不建議使用加減后結(jié)果直接進(jìn)行比較,禁止進(jìn)行加減運(yùn)算后與位寬不匹配的數(shù)據(jù)/變量進(jìn)行比較。
2) 拼接符號(hào)中“{}”,不允許使用加減乘除等運(yùn)算,綜合類(lèi)軟件無(wú)法正確判斷數(shù)據(jù)運(yùn)算結(jié)果位寬。數(shù)字運(yùn)算必須先通過(guò)wire指定位寬,然后通過(guò)assign得到運(yùn)算結(jié)果
3、錯(cuò)誤案例1:
如下代碼,代碼本意是:當(dāng)cnt0與cnt1之和大于8的時(shí)候,count加1。
1)錯(cuò)誤代碼中:
比較數(shù)據(jù)是4’h8,此時(shí)綜合完成后的網(wǎng)表中,會(huì)將cnt0與cnt1之和截位成4bit,再與4’h8比較,如果cnt0與cnt1之和為5’h10000,在此會(huì)截位為4’h0000,反而小于4’h8,與預(yù)期功能不符.
2)正確代碼&推薦代碼中:
先定義:wire [4:0] cnt_add ; 指定cnt_add位寬為5bit,然后assign cnt_add = (cnt0+cnt1) ;最后與5’h8比較,因?yàn)橥ㄟ^(guò)wire指定了位寬,所以對(duì)于各類(lèi)綜合軟件而言都不會(huì)發(fā)生截位,不會(huì)發(fā)生錯(cuò)誤。
3)正確代碼&不推薦中
直接將4’h8修改為5’h8,也避免了cnt0+cnt1累加截位,但是spyglass lint會(huì)報(bào)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 recommendedalways @ (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
4、錯(cuò)誤案例2
NOTE: 拼接符號(hào)中“{}”,不允許使用加減乘除等運(yùn)算,綜合類(lèi)軟件無(wú)法正確判斷數(shù)據(jù)運(yùn)算結(jié)果位寬。數(shù)字運(yùn)算必須先通過(guò)wire指定位寬,然后通過(guò)assign得到運(yùn)算結(jié)果。
1)錯(cuò)誤代碼中:
{1'b0,(cnt0+cnt1)} ,在if語(yǔ)句()拼接符號(hào)中,綜合軟件無(wú)法識(shí)別 (cnt0+cnt1)應(yīng)該是多少bit,(cnt0+cnt1)可能會(huì)是5bit,也可能是4bit。
2)正確代碼&推薦代碼中
通過(guò) wire [4:0] cnt_add ; assign cnt_add = (cnt0+cnt1) ; 指定了(cnt0+cnt1)之和為5bit,利用拼接符指定{1'b0,cnt_add}為6bit,然后與6bit的cnt2比較。
3)正確代碼&不推薦中
通過(guò) wire [4:0] cnt_add ; assign cnt_add = (cnt0+cnt1) ; 指定了(cnt0+cnt1)之和為5bit,但是直接與6bit的cnt2比較,各類(lèi)綜合軟件也會(huì)正確識(shí)別位寬,不會(huì)發(fā)生截位,但是spyglass lint會(huì)報(bào)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)}// 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// 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}// begin {ov_nc, count} <= count +1'b1; end
最后,有個(gè)比較判斷的例子,如下:
reg [9:0] a;
reg [7:0] b;
if(a == b + 1) //如果 b = 255時(shí),a與0相比較還是與 9‘h100相比較?
這個(gè)跟編譯器是相關(guān)的,大多數(shù)時(shí)候會(huì)是與9'h100比較,因?yàn)榫C合的時(shí)候verilog會(huì)自動(dòng)擴(kuò)展位寬,但不要過(guò)分相信它。這樣位寬不匹配的代碼永遠(yuǎn)不要出現(xiàn)在代碼里。





