【Verilog】表示式位寬與符號判斷機制
緣起於p1課下alu算數位移設計。查了好多資料,最後發現還是主要在翻譯官方文件。浪費了超多時間啊,感覺還是沒搞透,還是先以應用為導向放一放,且用且歸納
1.表示式位寬 expression bit length
身為硬體描述語言,Verilog表示式運算過程中必然要嚴肅考慮位寬問題
表示式的位寬由式中運算元和語境決定
表示式按位寬確定方式分為兩類:
- self-determined expression
位寬僅有表示式自身確定,不會受語境影響也不影響語境中其他表示式(在複合表示式中某些位置上的子表示式,如i>>j
中的表示式j
、i?j:k
中的表示式i
)。 - context-determined expression
位寬由表示式本身和其所屬表示式(父子表示式)共同決定(如阻塞賦值操作的RHS位寬由其自身和LHS被賦值變數的位寬決定)。
下表中i
,j
,k
表示"單運算元表示式",L(i)
表示表示式i的位寬
有些根本性的理解不是很到位
例1:所謂中間值位寬
例2:三元運算子表示式位寬
例3:綜合由語境決定位寬
2.表示式符號性 expression signedness
Verilog計算表示式前,需要確定表示式的符號性,規則如下:
- 僅取決於RHS運算元,與LHS無關(與位寬確定有別,如
assign a = b ? c : d;
中LHS符號性與a
自身無關) - 十進位制數視為signed
- 進製表示數視為unsigned,除非使用進位制前加s特殊標明(
4'd3
無符號,4'sd3
無符號) - 位選擇(不論是否選全)、位拼接(不論運算元)結果視為unsigned
- 比較表示式結果視為unsigned
- 實數強轉整形表示式結果視為signed
- self-determined expression:符號性取決於其中運算元
- context-determined expression:
- 若存在運算元為real,則結果視為real
- 若存在運算元為unsigned,則結果視為unsigned
- 若所有運算元為signed,則結果視為signed
- 若存在運算元為real,則結果視為real
- 變數本身是unsigned(不過存了01串罷了,不要因為
reg [3:0]a = 2'sb11
確定整個表示式的符號性後,便會向內層表示式傳遞符號性,直至各運算元。
$signed(exp)
函式計算傳入的exp
並返回與其值和位寬均相同的資料,將其符號性改為signed。可以看作遮蔽了外部表示式的符號性傳遞。
例:含三元運算子的表示式
testbench中使ALUop恆為
3'd5
,A=4'b1101
input [3:0] A, input [3:0] B, input [2:0] ALUOp, output [3:0] C
assgin C = (ALUOp == 3'd5) ? A >>> B : 4'sd0;
分析:
在三元運算子(ALUop == 3'd5)
屬於self-determined表示式,不會影響符號性判斷。因而看後半部分。4'sd0
為符號數;A >>> B
表示式中B
為self-determined表示式(運算元),所以符號性僅看A
。A
無符號,因而總表示式RHS無符號。
傳遞符號性後,A
無符號數經算數位移值為4'b0110
,再賦給C
。
assgin C = (ALUOp == 3'd5) ? $signed(A) >>> B : 4'sd0;
分析:
$signed()
使$signed(A)
表示式有符號,則$signed(A) >>> B
表示式有符號,則總表示式RHS有符號。
傳遞符號性後,$signed(A)
(A
相當於被$signed()
隔絕,仍無符號)被視為有符號數,算數位移後值為4'b1110
assgin C = (ALUOp == 3'd4) ? A + B :
(ALUOp == 3'd5) ? $signed(A) >>> B : 4'sd0 ;
分析:
巢狀式三元運算子的結構。A + B
表示式無符號(其中中A
、B
無符號),因而總表示式RHS無符號。
傳遞符號性:(ALUOp == 3'd5) ? $signed(A) >>> B : 4'sd0
無符號;$signed(A) >>> B
無符號;$signed(A)
無符號(A
被$signed()
保護),算數位移後值為4'b0110
assgin C = (ALUOp == 3'd4) ? A + B :
(ALUOp == 3'd5) ? $signed($signed(A) >>> B) : 4'sd0 ;
分析:
同上,總表示式RHS無符號。
傳遞符號性:(ALUOp == 3'd5) ? $signed(A) >>> B : 4'sd0
無符號;$signed($signed(A) >>> B)
無符號。$signed(A) >>> B
被保護,因而$signed(A)
仍視為有符號,算數位移後值為4'b1110
。