SystemVerilog计算规则:你真的懂赋值规则吗?

最基础的,往往最容易出错。

最近,用到了SystemVerilog去写计算,然后,各种赋值规则,让人眼花缭乱,特此记录。

下面以int类型的赋值为例。

int的赋值方式有三种,分别是:
(1)unsized, unbased integer(e.g., 12)
(2)unsized, based integer (e.g., 'd12, 'sd12)
(3)sized, based integer(e.g., 16’d12, 16’sd12)

特别注意:方式(1)的值,没有进制,都是有符号的数;方式(2)和(3)中,有进制,但是没有标明是有符号的,比如’d12,16’d12,表示的值是无符号的。

int inta, intb, intc, intd;
assign inta = -12;//          2进制:1111_1111_1111_1111_1111_1111_1111_0100      10进制:-12        有符号数
assign intb = -'d12;//        2进制:1111_1111_1111_1111_1111_1111_1111_0100      10进制:-12        无符号数
assign intc = -'sd12;//       2进制:1111_1111_1111_1111_1111_1111_1111_0100      10进制:-12        有符号数
assign intd = -4'sd12;//      2进制:0000_0000_0000_0000_0000_0000_0000_0100      10进制:4        有符号数

int inta3, intb3, intc3, intd3;
assign inta3 = -12/3;//          2进制:1111_1111_1111_1111_1111_1111_1111_1100      10进制:-4
assign intb3 = -'d12/3;//        2进制:0101_0101_0101_0101_0101_0101_0101_0001      10进制:1431655761
assign intc3 = -'sd12/3;//       2进制:1111_1111_1111_1111_1111_1111_1111_1100      10进制:-4
assign intd3 = -4'sd12/3;//      2进制:0000_0000_0000_0000_0000_0000_0000_0001      10进制:1

int inta3n, intb3n, intc3n, intd3n;
assign inta3n = -12/-3;//          2进制:0000_0000_0000_0000_0000_0000_0000_0100      10进制:4
assign intb3n = -'d12/-3;//        2进制:0000_0000_0000_0000_0000_0000_0000_0000      10进制:0
assign intc3n = -'sd12/-3;//       2进制:0000_0000_0000_0000_0000_0000_0000_0100      10进制:4
assign intd3n = -4'sd12/-3;//      2进制:1111_1111_1111_1111_1111_1111_1111_1111      10进制:-1


下面看看这一组的赋值结果。

int intd_2, intd_3, intd_4, intd_5;
assign intd_2 = -2'sd12;//          2进制:0000_0000_0000_0000_0000_0000_0000_0000      10进制:0
assign intd_3 = -3'sd12;//          2进制:0000_0000_0000_0000_0000_0000_0000_0100      10进制:4
assign intd_4 = -4'sd12;//          2进制:0000_0000_0000_0000_0000_0000_0000_0100      10进制:4
assign intd_5 = -5'sd12;//          2进制:1111_1111_1111_1111_1111_1111_1111_0100      10进制:-12

int intb_2, intb_3, intb_4, intb_5;
assign intb_2 = -2'd12;//          2进制:0000_0000_0000_0000_0000_0000_0000_0000      10进制:0
assign intb_3 = -3'd12;//          2进制:1111_1111_1111_1111_1111_1111_1111_1100      10进制:-4
assign intb_4 = -4'd12;//          2进制:1111_1111_1111_1111_1111_1111_1111_0100      10进制:-12
assign intb_5 = -5'd12;//          2进制:1111_1111_1111_1111_1111_1111_1111_0100      10进制:-12

intd_4与intd_3的结果,竟然是一样的。
怎么回事?

这就要研究一下,SystemVerilog中是如何计算的了。
下方以intd_3的计算过程来说明:
intd_3 = -3’sd12

越靠近12的符号,越先处理。

首先是,d,表示10进制,也就是说,12是10进制的数,代表是进制的12.
在计算机内部,运算的数据都是补码形式的。
所以,假设数据是8bits的,那么此时12的补码:0000_1100

其次是,s,表示这个数是有符号的数,即最高位当作符号位。因为0000_1100,最高位是0(最左边的那个0),所以是正数。

然后是,3,这个是sized,表示数据位宽是3位,即从0000_1100中截取最低的3bits(最右边的3位数据),即100.

在然后,将截取的3bits数据展开为8bits,因为是有符号的,按照符号位展开,故100 -> 1111_1100.(如果是无符号的,那么直接在前方补0,如intb_2/3/4/5中的处理)

最后计算负号(-),按照公式-A = 0 + (~A) + 1,即:
A :1111_1100
~A: 0000_0011 (所有位取反,包括符号位和数值位)
-A: 0000_0100(加1)

所以,整个计算过程是:
'sd12:0000_1100
3’sd12:1111_1100
-3’sd12:0000_0100

类似的:
'd12: 0000_1100
3’d12:0000_0100
-3’12:1111_1100

总结:

形式为(-)(size) ’ (sign) (base)(value)

首先根据base 和 value,写出对应的二进制数值;比如’d12:0000_1100
然后根据size截取对应位,根据sign,给欠缺的位补齐,如果是signed,则根据截取的值的最高位进行补齐,如果是unsigned,则直接补0.
最后,如果有负号(-),那么就是目前的所有位(包括符号位)取反,然后加1,得到最终结果。

你可能感兴趣的:(Verilog)