目录
1.1.1 n位add1 + n位add2 赋给 n位sum(有进位导致溢出)
1.1.2 n位add1 + n位add2 赋给 n-1位sum(有无进位 都会溢出)
1.2.1 n位add1 + n位add2 赋给 n+1位sum(sum的位宽刚刚好)
1.2.2 n位add1 + n位add2 赋给 n+2位sum(sum的位宽多一位,会扩位,最高位添0)
1.3.1 n位add1 + n位add2 移位再赋给 n位sum
1.3.2 n位add1 + n位add2 移位再赋给 n+1位sum
1.3.2 算术移位>>>(无符号数的算术移位>>>与逻辑移位>>结果相同)
表示范围:-2^N -1 ~ 2^N -1,表示形式:以补码形式存储(需要考虑最高位:符号位)
2.3 赋给位宽足够的数(高位数据不会被截断,符号位得以保留)
2.4.1 n位add1 + n位add2 移位再赋给 n位sum
2.4.2 n位add1 + n位add2 移位再赋给 n+2位sum
2.4.3 n位add1 + n位add2 移位再赋给 n位sum
2.4.4 算术右移:n位add1 + n位add2 移位后再赋给 n位sum
参考资料:
Verilog有符号数与无符号数的数值运算_ChuanjieZhu-CSDN博客_verilog有符号数
Verilog关于signed、有符号数、算数移位、$signed()的使用_szsfate的博客-CSDN博客
一、 无符号数
表示范围:0~2^N-1,表示形式:原码
1.1 高位溢出赋给一个位宽不够的数
1.1.1 n位add1 + n位add2 赋给 n位sum(有进位导致溢出)
wire [3:0] a=4'b1111;//15
wire [3:0] b=4'b0010;//2
wire [3:0] c;
assign c = a + b;//17=10001
a + b = 1_0001,c保留低4位=0001
1.1.2 n位add1 + n位add2 赋给 n-1位sum(有无进位 都会溢出)
wire [3:0] a=4'b1111;
wire [3:0] b=4'b0010;
wire [2:0] c;
assign c = a + b;
a + b = 1_0001,c只保留低3位=001
1.2 高位溢出赋给一个位宽足够的数
1.2.1 n位add1 + n位add2 赋给 n+1位sum(sum的位宽刚刚好)
wire [3:0] a=4'b1111;
wire [3:0] b=4'b0010;
wire [4:0] c;
assign c = a + b;
a + b = 1_0001,c的值刚刚好=10001
1.2.2 n位add1 + n位add2 赋给 n+2位sum(sum的位宽多一位,会扩位,最高位添0)
wire [3:0] a=4'b1111;
wire [3:0] b=4'b0010;
wire [5:0] c;
assign c = a + b;
a + b = 1_0001,c = 01_0001,高位添一位为0。
1.3 对中间结果移位
1.3.1 n位add1 + n位add2 移位再赋给 n位sum
wire [3:0] a=4'b1111;
wire [3:0] b=4'b0010;
wire [3:0] c;
assign c =(( a + b) >> 1);
a+b=10001,如果先移位为01000,再赋值后c应该为1000,而结果不一致;
只能是先赋值c为0001,再移位为0000(无符号数的移位,高位添0),与结果一致。(先赋值再移位加了括号也是一样,就相当于(c=a+b)>>1)
1.3.2 n位add1 + n位add2 移位再赋给 n+1位sum
wire [3:0] a=4'b1111;
wire [3:0] b=4'b0010;
wire [4:0] c;
assign c =(( a + b) >> 1);
a+b=1_0001,赋给c为1_0001,再移位一次,c为0_1000(这里其实现移位再赋值,结果也正确,所以位宽不够的时候才会先赋值再移位)
1.3.2 算术移位>>>(无符号数的算术移位>>>与逻辑移位>>结果相同)
wire [3:0] a=4'b1111;
wire [3:0] b=4'b0010;
wire [4:0] c;
assign c = ((a + b)>>>1) ;
>>>算数右移,无符号数还是补0.
二、有符号数
表示范围:-2^N -1 ~ 2^N -1,表示形式:以补码形式存储(需要考虑最高位:符号位)
2.1 正常运算(没有进位,位宽一致)
2.1.1 -1 + 2
wire signed [3:0] a=4'b1111;//-1
wire signed [3:0] b=4'b0010;//2
wire signed [3:0] c;
assign c =a + b;
a=4‘b1111( 补码)=4'b1110(反码)=4'b1001(原码)=4'd-1;
b=4'd2;
a + b = 0_001 = +1(最高位为符号位,不会向上进位了,即无符号数4'b1111+4'b0010=5'b10001,而有符号数4'b1111+4'b0010=4'b0001)
最后:c = 0001
2.1.2 -2 + 1
wire signed [3:0] a=4'b1110;//-2
wire signed [3:0] b=4'b0001;//1
wire signed [3:0] c;
assign c =a + b;
c = a + b = 4'b1110 + 4'b0001 = 4'b1111(补码) = 4'b1110(反码)=4‘b1001(原码)=4'd-1
2.2 赋给位宽不够的数(有进位,导致高位会被截断)
2.2.1 正数运算:7 + 2
wire signed [3:0] a=4'b0111;//7
wire signed [3:0] b=4'b0010;//2
wire signed [3:0] c;
assign c =a + b; //9=1001
a(0_0111) + b(0_0010) = 5'b0_1001(符号位不参与运算),而c = 4'b1001,结果是个负数,结果不正确了(因为高位是符号位,被截断了)
如位宽够用c = 5'b01001 = 5'd9(高位数据被截断了,导致结果不正确)
2.2.2 负数运算:-7 + -2
wire signed [3:0] a=4'b1001;//-7
wire signed [3:0] b=4'b1110;//-2
wire signed [3:0] c;
assign c =a + b;//-9=10111
a + b =1_0111 c = 4'b0111(补码),是个正数,结果也不正确了
如位宽够用c = 5'b10111 = 5'd-9(高位数据被截断了,导致结果不正确)
2.3 赋给位宽足够的数(高位数据不会被截断,符号位得以保留)
2.3.1 正数运算:7 + 2
wire signed [3:0] a=4'b0111;
wire signed [3:0] b=4'b0010;
wire signed [4:0] c;
assign c =a + b;
a + b = 0_1001,c = 5'b01001 = 5’d9(结果正确了)
2.3.2 负数运算:-7 + -2
wire signed [3:0] a=4'b1001;//-7
wire signed [3:0] b=4'b1110;//-2
wire signed [4:0] c;
assign c =a + b;//-9=10111
a + b = 1_0111,c = 5'b1_0111 = 5'd-9 结果正确。
2.4 给中间结果移位
2.4.1 n位add1 + n位add2 移位再赋给 n位sum
wire signed [3:0] a=4'b1001;//-7
wire signed [3:0] b=4'b1110;//-2
wire signed [3:0] c;
assign c =(( a + b ) >> 1); //-9=10111
a + b = 1_0111(补码) = 1_0110(反码) = 1_1001(原码) = -9 ,
先赋值:c = 0111,
再逻辑右移(添0):c=0011(逻辑移位,不管是有符号数还是无符号数都是添0,)
2.4.2 n位add1 + n位add2 移位再赋给 n+2位sum
wire signed [3:0] a=4'b1001;//-7
wire signed [3:0] b=4'b1110;//-2
wire signed [5:0] c;
assign c = ((a + b)>>1) ;
a + b = 1_0111(补码)=1_0110(反码)=1_1001(原码)=-9
先赋值:c = a + b = 1_10111(补码)= 1_10110(反码) = 1_01001(原码) = -9
所以当c的位比a+b的和还高一位时,c除了最高位符号位不变外,次高位补1,而不是补0了.
即无符号数的扩位是添0,有符号数的扩位是跟随MSB。
再移位:c = 011011(逻辑右移:不管是signed还是unsigned都是添0)
2.4.3 n位add1 + n位add2 移位再赋给 n位sum
wire signed [3:0] a=4'b0111;//7
wire signed [3:0] b=4'b0010;//2
wire signed [3:0] c;
assign c =(( a + b ) >> 1);//9=01001
a + b = 0_1001;
先赋值:c = 1001;
再移位:c = 0100(逻辑右移,最高位补0)
2.4.4 算术右移:n位add1 + n位add2 移位后再赋给 n位sum
wire signed [3:0] a=4'b1001;//-7
wire signed [3:0] b=4'b1110;//-2
wire signed [3:0] c;
assign c = ((a + b)>>>1) ; //-9=10111
a + b = 1_0111;
先赋值:c = 0111;
再移位:c = 0011
>>>算数右移:截断赋值然后把最高位当符号位,补最高位。
2.4.4 算术右移:n位add1 + n位add2 移位后再赋给 n+1 位sum
wire signed [3:0] a=4'b1001;
wire signed [3:0] b=4'b1110;
wire signed [4:0] c;
assign c = ((a + b)>>>1) ;
a + b = 1_0111
先赋值 c = 1_0111;
再移位c = 1_1011;
>>>算数右移:把最高位当符号位,补最高位。
2.4.5 逻辑右移与算术右移
wire signed [3:0] a=4'b1001;
wire signed [3:0] b=4'b1110;
wire [3:0] c,d;
assign c=a>>1;
assign d=a>>>1;
逻辑右移,补0:c = 4'b0100;
算术右移,补最高位:d = 4'b1100
三、有符号数和无符号数混合运算
3.1 混合计算规则:
只有两个操作数都是有符号数,才会把两个操作数都看作有符号数计算,否则无论是有符号数还是无符号数都会按照无符号数计算。
wire [3:0] a=4'b1001;
wire signed [3:0] b=4'b1110;
wire signed [4:0] c;
assign c = ((a + b)>>>1); //-9=10111
a + b = 1_0111(无符号数);
先赋值:c = 1_0111(无符号数);
再计算:c = 0_1011(无符号数)
3.2 混合赋值规则:
把a赋给b,若a是有符号数,则b高位用a的最高位填充,若a是无符号数,b的高位用0填充 。
wire [3:0] a=4'b1001;
wire signed [3:0] b=4'b1001;
wire signed [4:0] c,d;
assign c=a;
assign d=b;
c = 0_1001;(a是无符号数,c的最高位用0填充)
d = 1_1001;(b是有符号数,d的最高位跟b的最高位一致)
四、练习
wire [2:0] a = 3’b101;
wire signed [2:0] a_s = 3’b101;
wire [2:0] b = 3'b110;
wire signed [2:0 ] b_s = 3'b011;
wire [4:0] an;
wire signed [4:0] bn_s, en_s;
assign an = a - b;
assign bn_s = a_s + b_s;
assign en_s = {3{2’d2}};
问:an、bn_s、en_s的值是多少?
分析:
减法运算 转换为 补码的加法运算
注意减法运算无法直接进行,需要将两数的补码相加代替上述的减法运算。举一个生活中常见的事例。例如,你在5点钟的时候发现手表停在了10点上了,因而必须把表针拨回到5点。这时有两种拨法:第一种是往回拨5格,10-5=5;另一种是往前拨7格,10+7=17(由于表盘的最大数只有12,超过12以后的进位自动消失,于是就只剩下减去12以后的余数了,即17-12=5)。这个例子说明10-5的减法可以用10+7的加法运算代替。因为5和7相加正好等于产生进位的模式12,所以我们称7为-5对模12的补数,也称为补码(Complement)。因此:
① 无符号数:3’b101(原码) - 3'b110(原码) = 3’b101(补码) + 3'b010(补码)= 3'b111(补码)
如果是signed,此时MSB = 1,应该以1扩位,即an = 5'b11_111;
不过这里a、b和an都是unsigned,应该以0扩位才对,即an = 5'b00_111;
不过仿真的结果是5'b11_111,这一点不甚明白!
② 有符号数:3’b101(补码,-3) + 3'b011(补码,+3) = 3'b000(补码)
此时MSB = 0,就按照MSB来扩位,则bn_s = 5'b00_000;与仿真结果一致
③:3{2’d2} = 6'b101010; MSB被截位后,en_s = 5'b01010