#0.计算机组底层的电路只认识0和1,并没有任何数制和逻辑的概念。
#1.首先在计算机中数字分为 定点数和浮点数; 定点数又分为定点整数和定点小数;定点整数有无符号和有符号两种 ;这里主要讨论无符号数和有符号数在计算机中是如何存储以及在VerilogHDL语言中如何使用。
#2.VerilogHDL语言中除了integer类型之外的所有数据类型默认都是无符号类型;
#3.符号扩展是用于两个运算操作数的位数不一样的时候,进行位数的统一的操作;这里只讨论相等位数;
一,无符号数
#如果要进行两个无符号数之间的大小比较该如何进行;首先应该注意的就是无符号数在计算机中是以原码形式存储的;原码存储就意味着这种表示方式下,任何计算结果都会是无符号数,这是因为1.存储位数是一定的所以最高位进位会被舍弃掉。2.如下图一样,所有加减的本质就是绕圈顺时针逆时针转。既然是这样,就是说直接用相减看差的方式是不可能得出正确的结果的;
如:*这时候会想:因为Verilog中的数据默认是用无符号形式存储的,因此这个可以直接进行比较大小
if(A - B > 0) C = 1;
else C = 0;
但实际上在无符号数中计算结果永远都是正的!所以这个不行*
#所以真正真确的方式应该是从本质入手,也就是说两个数相减或相加,只要有溢出也就是最高位有进位那么结果一定是不对的,从这里入手在考虑实现细节。
module comparator(
input [3:0]A,
input [3:0]B,
output reg [3:0]C
);
reg [4:0]tempA;
reg [4:0]tempB;
reg [4:0]tempresult;
always@()begin
tempA = {0, A}; //对无符号数进行0扩展,实现标志位
tempB = {0, B};
tempresult = tempA - tempB;
if(tempresult[4] == 0)begin
C = 1; //被减数比较大
end
else if(tempresult[4] == 1)begin //这是有进位了,但是实际是被舍弃的
C = 0; //减数比较大
end
end
endmodule
#BUT!在Verilog中已经有函数可以直接实现这种无符号数之间的转换;
module comparator(
input [3:0]A,
input [3:0]B,
output reg [3:0]C
);
always@()begin
if($unsigned(A) > $unsigned(B)) C = 1; //刚才说过因为Verilog中的数默认是无符号数,因此可以这个函数也可以不写;;但是一定不能写成是相减的形式
else C = 0;
end
endmodule
二,有符号数
#这里需要理解的是,有符号数有两种存储方式:原码形式和补码形式;但是几乎所有的计算机都使用二进制补码表示法来表示存储于n为存储单元的有符号整数。具体一些:假设4‘b1001是一个有符号数,用原码形式4’b1001=-1;但是用补码形式的话4\'b1001=-7.在补码表示法中,对一个正数是直接用原码来表示,只有负数采用补码来表示,这是因为补码(~B+1)实际上是对负数取绝对值的运算,比如4‘b1001在补码下实际值为-7(还不理解就去查一下补码的表),对其进行取反加一就变成4\'b0111=+7;* (实际上有符号数的表示就是用补码来表示的,所以以后的所有情况都只考虑是在补码表示法下的用法)
#这里在说明一下补码表示法下的运算,注意这里的“补码”是一种表示法!不是转换方式,具体来讲就是”正数不变,负数取反加一“;就这么简单。先看一下加法运算:如果4’b0110 + 4\'b1001 就直接进行运算 = 4‘b1111;而实际上原式子用十进制写的话就是 6 + (-7) = -1;而4’b1111在补码表示下就是-1! 在看一下减法运算:如果4\'b0110 - 4\'b1001这时候就需要对被减数进行取反加一操作了,也就是对其加上绝对值~这是什么意思呢? 先看一下原式子的十进制表示:6 - (-7) = 6 + 7;所以实际上之所以要对被减数进行取反加一就是为了”负负得正“。接下来就很简单:4‘b0110 + 4\'b0111 = 4\'b1101; 会发现这时候计算结果4\'b1101补码形式下等于-3,而正确应该是6+7 = 13;为什么呢? 对,是因为溢出了。因为4位有符号数的表示范围:0~7 -1~-8; 但是本质上应该可以理解了。
这里不具体谈如何从最底层进行无符号数的大小比较,主要是因为Verilog中函数已经实现了具体的功能;这里又一些细节:
对两个有符号数。必须考虑两个数是同号还是异号:
A 、 对两个同符号数。因其相减不会溢出,即OF=0。 SF=0:被减数大于减数
SF=1:被减数小于减数
B 、如果比较的两个数符号不相同,此时就有可能出现溢出 ·若OF =0 (即无溢出),则有:
如果被减数大于减数,SF =0,
如果被减数小于减数,SF =1;
如果被减数等于减数,sF =0,同时ZF =1;
·若OF =1(有溢出) .则:
如果被减数大于减数,SF =1
如果被减数小于减数,SF =0。
若OF ⊕SF=0,则dest >src;
若OF ⊕SF=1,则dest <src 。
//比较两个有符号数的大小
module comparator(
input [3:0]A,
input [3:0]B,
input [3:0]C
);
always@()begin
if($signed(A) > $signed(B)) C = 1; //同样这里不能写成减法的形式
else C = 0;
end
endmodule
所以这里需要记住的就是:
有符号数的 (A > B) 和 (A-B>0)是不一样的,因为提供有符号类型的人已经帮你写好了如何进行比较的算法,所以用正确的方式去用,但是如果自己实现的话,就要考虑很多情况。