SystemVerilog符号数位扩展与$signed操作优先级问题咨询
Verilog 位扩展与取反运算优先级异常原理
首先明确两个基础前提:
- 10bit 有符号数的取值范围是
-512 ~ 511,-512的补码表示为10'b1000000000,对其做10bit内的取反运算会发生溢出,补码溢出后结果仍然为10'b1000000000(即十进制的-512) - Verilog 表达式位宽分为上下文决定位宽和自决定位宽:
$signed()的输入参数属于自决定位宽,参数内表达式的位宽仅由内部操作数决定,不会继承外层赋值目标的位宽要求。
两种写法的运算流程差异
1. out = $signed(-sig); 运算顺序(对应sig=-512时out=-512的结果)
- 先计算括号内的
-sig:该表达式在$signed()的参数范围内,属于自决定位宽,仅使用sig本身的10bit位宽运算 - 10bit的
sig=-512取反时溢出,运算结果仍为10bit的-512 $signed()仅转换类型不改变位宽,输出还是10bit的-512- 赋值给12bit的out时做有符号扩展,最终结果为12bit的
-512
2. out = -$signed(sig); 运算顺序(对应sig=-512时out=512的结果)
- 先计算
$signed(sig):sig本身就是signed类型,转换后还是10bit的-512 - 取反运算
-的上下文是赋值给12bit的out,属于上下文决定位宽,所以先将10bit的-512有符号扩展为12bit的-512(补码12'b111000000000) - 对12bit的数值做取反运算,得到12bit的
512(补码12'b001000000000),无溢出 - 直接赋值给out,结果为
512
sig=64时两种写法结果一致的原因
sig=64属于10bit有符号数的正常取值范围,10bit内取反得到-64不会溢出,无论是先取反再扩展,还是先扩展再取反,最终12bit的结果都是-64,因此无差异。
你之前猜测的「$signed()阻塞了位扩展」本质上是对的,核心原因就是
$signed()的参数是自决定位宽,截断了外层位宽要求向内传递,导致括号内的运算只能在原10bit位宽下执行,溢出后得到错误结果。
内容的提问来源于stack exchange,提问作者Yunsung Mo
相关产品推荐
相关产品推荐

