沒想到啊沒想到啊,有一天會被濃眉大眼的assign背刺!想當年在always消失術里,在X態分析里,在xprop平替策略里,把assign捧的這么高,優點說了800多項,然后今天一仿真出bug了?!
還有有符號數和無符號數,我都吹出去了已經大成大成了,這還能出錯?!
萬事皆有可能,于是就出現了這個事。
事情的根源簡化完就是下面這個語法,當sel為0時輸出i_a高位補零的右移結果(相當于視i_a為無符號數),sel為1時輸出i_a高位補符號位的輸出結果相當于視i_a為有符號數):
//test
wire [31:0]i_a = 32'hff00_0000;
wire sel = 1'b1;
wire [31:0]en0 = (sel == 1'b0) ? i_a > >> 8 :
$signed(i_a) > >> 8;
wire [31:0]en1_mid = $signed(i_a) > >> 8;
wire [31:0]en1 = (sel == 1'b0) ? i_a > >> 8 : en1_mid;
好,大家先看著這en0和en1的值。
en0和en1的值分別是啥呢?
en0 = 32'h00ff_0000;
en1 = 32'hffff_0000;
問題出在哪呢?前面咱們總結過:有符號數和無符號數運算,結果為無符號數。這句話不太嚴謹,應該完善為:有符號數和無符號數運算,所有的運算數會被視為無符號數,結果為無符號數。
因為en0運算公式中,有符號數和無符號數混合運算了,有符號數和無符號數混合時會自動將所有的變量視為無符號數進行運算,而這個混合運算很難發現:
wire [31:0]en0 = (sel == 1'b0) ? i_a > >> 8 : $signed(i_a) > >> 8;
對,i_a >>> 8是個無符號數的運算!/(ㄒoㄒ)/~~所以帶著signed(i_a) >>> 8也變成了無符號數的運算。所以說如果把signed(i_a) >>> 8單提出來先算好,再參與選擇邏輯就是預期的結果了。
那么最后一個小問題,選擇邏輯參與不參與這個有符號數和無符號數的爭端呢?不參與,比如代碼改成這樣:
wire [31:0]en0 = (sel == 1'b0) ? $signed(i_a > >> 8) : $signed(i_a) > >> 8;
我把前面的運算結果通過$signed擴了一下,然后再仿真:
這說明了兩個問題:
1.選擇邏輯沒有參與到有符號數和無符號數的判定中;
2.判定時signed(i_a) >>> 8,看的是同一級別的其他運算項的符號屬性,比如此時他看的是signed(...);
再改一下就又回去了:
wire [31:0]en0 = (sel == 1'b0) ? $signed(i_a > >> 8) + 1'b1 : $signed(i_a) > >> 8;
-
仿真器
+關注
關注
14文章
1016瀏覽量
83635
發布評論請先 登錄
相關推薦
評論