数字IC设计知识点及综合题详解(提前批、秋招必刷基础题)——(一)无符号变量/有符号变量的运算

目录

一、 无符号数

表示范围:0~2^N-1,表示形式:原码

1.1  高位溢出赋给一个位宽不够的数

1.1.1 n位add1 + n位add2 赋给 n位sum(有进位导致溢出)

1.1.2 n位add1 + n位add2 赋给 n-1位sum(有无进位 都会溢出)

1.2  高位溢出赋给一个位宽足够的数

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.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.1 正常运算(没有进位,位宽一致)

2.1.1  -1 + 2 

2.1.2  -2 + 1

2.2 赋给位宽不够的数(有进位,导致高位会被截断)

2.2.1  正数运算:7 + 2 

2.2.2 负数运算:-7 + -2

2.3 赋给位宽足够的数(高位数据不会被截断,符号位得以保留)

2.3.1 正数运算:7 + 2

2.3.2 负数运算:-7 + -2

2.4 给中间结果移位

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

2.4.5 逻辑右移与算术右移

三、有符号数和无符号数混合运算

3.1 混合计算规则:

3.2 混合赋值规则:

四、练习

减法运算 转换为 补码的加法运算


参考资料:

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

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cheeky_man

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值