两个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
如果是两个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
两个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
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
逻辑移位’>>’, ‘<<’会补零,算术移位’<<<’, ‘>>>’会补符号位
A = 8'sb10100011
A>>3; //8'b00010100
A>>>3; //8'b11110100