Verilog有符号数与无符号数的相互转化
问题描述
把8位有符号数(-128-127)转化为8位无符号数(255-0),转化到255-0是因为该DA模块输入数据越大反而输出电压越小。
一、正数
比较显然,直接用127减该数就可以。
二、负数
举两个例子:
1.-128
-128补码为1000_0000,用127-(-128),计算器计算为:
用Verilog写个简单的模块仿真一下:
module subtraction(
input [7:0] a,
input [7:0] b,
output [7:0] c
);
assign c=b-a;
endmodule
多余的1位Verilog会自动截断掉,结果为1111_1111,即为255。
2.-1
补码为1111_1111。也是类似的,自动把多余的位舍弃掉,结果为1000_0000,即为128:
结论
直接可以通过该语句实现,即用127减一下:
assign c=8'b0111_1111-a;
三、延伸
要将-128-127转化为0-255,该怎么做。与上面的不同,需要用128加原本的数,但128若用有符号数表示,需要9位,那该怎么做,可以先试一试。
以-1为例,补码为1111_1111,还是先用计算器试一下,直接用无符号的128,即1000_0000:
Verilog代码:
module adder(
input [7:0] a,
input [7:0] b,
output [7:0] c
);
assign c=b+a;
endmodule
vivado仿真:
若用十进制表示,有符号十进制:
无符号十进制:
可以看到不管是无符号还是有符号都因为超出了范围(-128-127和0-255),结果是不正确的,但还是能正确将有符号数转化为无符号数(-1变成127)。
总结
其实该问题可以看做补码的计算的问题,总结一下算让我理解了补码存在的意义。
回顾一下补码的定义:
正数和0
正整数的补码是其二进制表示,与原码相同。
负数
求负整数的补码,将其原码除符号位外的所有位取反后加1。
补码让二进制的正负加减运算变得很方便,即使位宽产生溢出也可以通过舍弃多余的高位产生正确的结果(如前面的127-(-1)),比较计算器的结果和vivado仿真的结果。