verilog中有符号数和无符号数在赋值、运算中的区别

赋值

有符号数的赋值和无符号数的赋值

verilog默认的寄存器类型(reg)和线网类型(wire)的值是无符号数的,但同时verilog提供了signed关键字作为有符号数的标志。首先来测试一下有无signed关键字对于赋值上的影响。代码段如下所示:
verilog中有符号数和无符号数在赋值、运算中的区别
用Modelsim进行了仿真,仿真结果如下所示。
verilog中有符号数和无符号数在赋值、运算中的区别
如图可见,有无signed关键字对于赋值来说没有任何影响,不论是wire类型的直连还是reg类型的阻塞赋值,本质意义上都是“0”和“1”的传递,是否带符号都是人为加给电路的意义。在Modelsim中,你想将其看作无符号数就将其Radix成unsigned,你想将其看作有符号数就将其Radix成decimal,但是他们的binary形式都是一模一样的。所以,signed关键字不会对赋值产生任何影响。

加减法运算

两个无符号数的加减法运算

下面测试一下两个不带signed关键字(也就是默认的无符号数)的加减法运算。代码段如下图所示:
verilog中有符号数和无符号数在赋值、运算中的区别
unsigned_A赋值为1001,unsigned_B赋值为1011。对于无符号数的定义,1001代表十进制的9,1011代表十进制的11,那么能不能得到正确的结果呢?Modelsim仿真结果如下图所示:
verilog中有符号数和无符号数在赋值、运算中的区别
显而易见,加法是正确的!1001+1011按照二进制加法计算的确等于10100,也就是十进制的20,如假包换。但是减法的结果111110是十进制的62,显然不是9减11的正确结果,因为两个运算数都是无符号数,小减大却不够减,产生了溢出。再说把111110当作有符号数来看确实是-2。

两个有符号数的加减法运算

那么两个有符号数的加减法运算会是怎样的呢?测试代码段很简单就不贴出来了,Modelsim仿真结果如下图所示(二进制视角):
verilog中有符号数和无符号数在赋值、运算中的区别
如图所示,将这张图与上一张图进行对比,上一张图的第一个计算结果010100在这张图里变成了110100,这也就是有无signed关键字的区别!区别在于无符号数计算时,1001被当作十进制的+9,1011被当作十进制的+11;而在有符号数计算时,1001被当作十进制-7,1011被当作十进制-5。两个有符号数的加减法被视为有符号数的计算,第一位会作为符号位被特殊处理,最终得出的结果也需要Radix成有符号的decimal模式进行观测,不然会一头雾水:为啥9和11加起来得到了52???

有无符号数的混合加减法

那么一个有符号数和一个无符号数的计算是哪一种计算方法呢?测试代码段和仿真结果贴出来:
verilog中有符号数和无符号数在赋值、运算中的区别
verilog中有符号数和无符号数在赋值、运算中的区别
由此可见,只要有一个数是无符号数,那么计算过程就按照无符号数的来。下面进入乘法的测试。

乘法运算

无符号数/无符号数的乘法运算

verilog中有符号数和无符号数在赋值、运算中的区别
verilog中有符号数和无符号数在赋值、运算中的区别
verilog中有符号数和无符号数在赋值、运算中的区别
乘法的测试结果如图所示,只需自己定义好有无符号,位宽留够,则不存在溢出的问题。看结果时,选择对应的模式(unsigned还是decimal)即可。

有无符号数的混合乘法

和加减法一样,只要有一个参与计算的数是无符号数,那么计算过程就按照无符号数的计算来做。仿真结果如下图所示:
verilog中有符号数和无符号数在赋值、运算中的区别
若上图的计算结果按照无符号的unsigned模式理解就没问题,但按照带符号的decimal模式理解就错了,(+9)*(-5)是不会得到99的,如果想得到正确的-45计算结果,需要将9这个数定义为带符号数(这样做的话4位的位宽就不够了,带符号数的1001并不能代表+9而是-7,需要拓宽成5位,用01001才能表示+9)。