Verilog基础知识(有符号数运算规则,加减运算,乘法运算中的符号位拓展问题)

rule of thumb

  1. The format of the signed type is two’s complement. 有符号数均为补码表示
  2. If any operand in an expression is unsigned the operation is considered to be unsigned. 只有计算表达式右边有无符号数,整个计算式都按照无符号数规则运算
  3. 只有算式右边全为有符号数,运算才会自动补齐所需的bit数,n+n=n+1.n*n=2n
  4. The value -4 represented as a 3bit signed hex value would be specified as -3’sh4. A decimal number is always signed. verilog2001中用’s来特别声明有符号数,十进制的数都是有符号数
  5. Type casting using $unsigned will make the operation unsigned. The operand will be sign extended with 0’s if necessary. $usigned()函数在高位补0
  6. A=$signed(B) will extend using sign bit. $unsigned()函数会在高位补与符号位相同的bit

basic signed addition

两个n bit数相加,得到n+1 bit结果,比如-2(3’sb110)+3(3’sb011)=1(4’sb0011)

//Code Example 1: Addition - Verilog 1995
module add_signed_1995 (
input [2:0] A,
input [2:0] B,
output [3:0] Sum
);
assign Sum = {A[2],A} + {B[2],B};
endmodule // add_signed_1995
//Code Example 2: Addition - Verilog 2001
module add_signed_2001 (
input signed [2:0] A,
input signed [2:0] B,
output signed [3:0] Sum
);
assign Sum = A + B;
endmodule // add_signed_2001

signed + unsigned

如果是两个3bit有符号数+1bit进位。如果在verilog2001中直接用符号位拓展

sum=A+B+carry_in //整个计算式会转换成无符号计算,signed to unsigned conversion occurs
sum=A+B+$signed(carry_in) //就会出现当carry_in=1时候拓展为4'b1111,这时候本来是加1,却变成了减1
sum = A + B + $signed({1'b0,carry_in}) //正确的做法

正确的做法是

// Code Example 3: Add with Carry - Verilog 1995
module add_carry_signed_1995 ( 
input [2:0] A,dsa
input [2:0] B,
input carry_in,
output [3:0] Sum
); 
assign Sum = {A[2],A} + {B[2],B} + carry_in; 
endmodule //add_carry_signed_1995
// Code Example 5: Add with Carry - Correct
module add_carry_signed_final (
input signed [2:0] A,
input signed [2:0] B,
input carry_in,
output signed [3:0] Sum
);
assign Sum = A + B + $signed({1'b0,carry_in});
endmodule // add_carry_signed_final

basic signed multiplication

两个n bit数相乘,得到2n bit结果。如果-3(3’sb101) * 2 (3’sb010) 得到正确结果 -6 (6’sb111010)。但如果乘数是负数,则最高位的乘积需要以减法参与运算,而不是加法。

// Code Example 6: Signed Multiply - Verilog 1995
module mult_signed_1995 (
input [2:0] a,
input [2:0] b,
output [5:0] prod
);
wire [5:0] prod_intermediate0;
wire [5:0] prod_intermediate1;
wire [5:0] prod_intermediate2;
wire [2:0] inv_add1;
assign prod_intermediate0 = b[0] ? {{3{a[2]}}, a} : 6'b0;
assign prod_intermediate1 = b[1] ? {{2{a[2]}}, a, 1'b0} : 6'b0;
// Do the invert and add1 of a.
assign inv_add1 = ~a + 1'b1;
assign prod_intermediate2 = b[2] ? {{1{inv_add1[2]}},
inv_add1, 2'b0} : 6'b0;
assign prod = prod_intermediate0 + prod_intermediate1 +
prod_intermediate2;
endmodule
// Code Example 7: Signed Multiply - Verilog 2001
module mult_signed_2001 (
input signed [2:0] a,
input signed [2:0] b,
output signed [5:0] prod
);
assign prod = a*b;
endmodule

signed * unsigned

prod = a*b; //整个运算变成无符号,-3(3'sb101)*2(3'b010)变成5(6'b000101)*2(6'b000010)=10(6'b001010)
prod = a*$signed(b); //当乘数的MSB=1的时候会出错,2(3'sb010)*7(3'b111)变成
                     //-2(6'sb000010)*-1(6'sb111111)=2(6'sb110010)
prod = a*$signed({1'b0,b}); //正确做法
// Code Example 11: Signed by Unsigned Multiply
module mult_signed_unsigned_2001 (
input signed [2:0] a,
input [2:0] b,
output signed [5:0] prod
);
assign prod = a*$signed({1'b0,b});
endmodule

signed shift

逻辑移位’>>’, ‘<<‘会补零,算术移位’<<<’, '>>>'会补符号位

A = 8'sb10100011
A>>3; //8'b00010100 
A>>>3;  //8'b11110100
  • 26
    点赞
  • 210
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值