有关Verilog中有符号数的运算(基于Verilog2001版本)
一、基本概念
在Verilog中,数字都是以2进制来表现的,无符号数直接表现为它的2进制原码,而有符号数则表现为它的2进制补码。使用补码,可以将符号位和数值域统一处理,同时,加法和减法也可以统一处理。
1.真值
真值是指在数值前面用“+”号表示正数,用“-”号表示负数的带符号二进制数。例如+1101(+13)、-0010(-2)等。
2.原码
符号位用0表示正,用1表示负;数值位不变,即与真值的数值位相同。增加原码的位宽时,直接在高位补0即可。
例如:4位宽的1101(13) -> 6位宽的001101(13)
3.补码
符号位用0表示正,用1表示负。数值位与符号位相关,当为正数时,数值位不变,即与真值的数值位相同;当为负数时,数值位是真值的数值位按位取反,并在末位加1。在增加补码的位宽时,由于最高位的符号位以及补码的特性,不能直接在高位补0,而是要根据符号位来决定在高位补0还是1。
符号位为0时,高位补0:
5位宽的01101(+13) -> 7位宽的0001101(+13)
符号位为1时,高位补1:
补0错误:5位宽的10010(-13) -> 7位宽的0010010(+17)
补1正确:5位宽的10010(-13) -> 7位宽的1110010(-13)
二、有符号与无符号计算的区别
1.无符号数的加减运算
在Verilog里,进行无符号数的加减运算时,系统会自动将所有数据的位宽提高至于最宽数据的位宽相同。
例如wire [2:0]a;wire [3:0]b;wire [4:0]c;
在计算c <= a + b;时,系统会自动将a和b变为与c相同位宽的5位宽数据,而提高位宽的方式是在高位补0,也就是c <= {0,0,a} + {0,b};
2.有符号数的加减运算
在Verilog里,有符号数一律以补码来表示,因此有符号数的最高为符号位,在进行加减运算时,系统在识别到运算的数为有符号数后,在补齐位宽时不是单纯的补0了,而是根据符号位来决定是补0还是补1。
创建信号的时候,加上signed,就会使创建的数变为有符号数,例如wire signed [2:0]a;wire signed[3:0]b;wire signed[4:0]c;
此时在计算c <= a + b;时,系统会自动将a和b变为与c相同位宽的5位宽数据,而提高位宽的方式是在高位补与符号位相同的值,这里假设a为负数,b为正数,因此补位后的算式为c <= {1,1,a} + {0,b};
三、如何进行有符号运算
1.在创建信号的时候,使用signed关键字
例如:wire signed [2:0]a;wire signed[3:0]b;wire signed[4:0]c;
c <= a + b;
2.在运算的时候,使用$signed()函数
例如:wire [2:0]a;wire [3:0]b;wire [4:0]c;
c <= $signed(a) + $signed(b);