- The format of the signed type is two’s complement. 有符号数均为补码表示
- If any operand in an expression is unsigned the operation is considered to be unsigned. 只有计算表达式右边有无符号数,整个计算式都按照无符号数规则运算
- 只有算式右边全为有符号数,运算才会自动补齐所需的bit数,n+n=n+1.n*n=2n
- The value -4 represented as a 3bit signed hex value would be specified as -3’sh4. A decimal number is always signed. verilog2001中用’s来特别声明有符号数,十进制的数都是有符号数
- Type casting using $unsigned will make the operation unsigned. The operand will be sign extended with 0’s if necessary. $usigned()函数在高位补0
- 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
//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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
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}) //正确的做法
- 1
- 2
- 3
正确的做法是
// 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
// 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
// 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
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}); //正确做法
- 1
- 2
- 3
- 4
// 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
signed shift
逻辑移位’>>’, ‘<<’会补零,算术移位’<<<’, ‘>>>’会补符号位
A = 8'sb10100011
A>>3; //8'b00010100
A>>>3; //8'b11110100
- 1
- 2
- 3