采用HDL代码描述加法运算只需要用操作符“+”即可,这看似很简单,这里我们以两个4-bit数相加为例,对输入/输出数据均寄存,从而形成如下图所示电路。
此电路对应的HDL代码如下图所示。这里采用了SystemVerilog语言。有两点值得注意:一是两个N位数相加,无论是有符号数还是无符号数,其结果都有可能是N+1位,故输出比输入位宽多1位,这样才能保证不会发生溢出(Overflow)。二是默认情况下,代码中的logic表示的都是无符号数,但是对于下面这段代码,无符号数和有符号数均适用,这是因为有符号数是以二进制补码表示的。
为了进一步说明,我们看如下例子。数据a二进制形式位1001,既可以看作无符号数9(十进制),也可以看作有符号数-7(十进制);数据b二进制形式为1010,既可以看作无符号数10(十进制),也可以看作有符号数-6(十进制)。最终结果的二进制形式为10011,既可以看作无符号数19(十进制),也可以看作有符号数-13(十进制)。
这里两个4-bit数相加和设置为5-bit,如果和设置为6-bit,有符号数和无符号数的结果是否一致呢?对于无符号数,sum[5]补0,如图中红色方框所示。
对于有符号数,sum[5]则是sum[4]的复制版本,实质上是符号位扩展。
本质上,在赋值时,如果把一个N位数据a赋值给一个位宽M的数据b(这里M>N),且两个数据均为同一类型(都是有符号或无符号),此时是将N位数据做符号位扩展为M位再赋值给b。因此,对于两个N位数据相加,如果输出位宽选择大于N+1,那么上述代码只适合于无符号数,对于有符号数需要在logic后加关键字signed,如下图所示。
如果两个位宽不等的数相加,同样需要指明是有符号数还是无符号数。例如,一个4-bit数和一个3-bit数相加,如下图所示。如果a二进制为1001,对应无符号数9(十进制),b二进制形式为101,对应无符号数5(十进制),两个无符号数相加,先将b高位补0,最终和为01110;如果将a和b看作有符号数,则要将b符号位扩展为1101,最终和为10110。符号位扩展是工具完成的,无需人工干预。
总体而言,在描述加法运算时,如果两个数据均为N位,那么和要设置为N+1位,此时无符号数的描述方式也适合于有符号数。如果两个数一个是N位,一个是M位,且M>N,那么和要设置为M+1位,此时要明确指出是有符号数还是无符号数。