FPGA设计--数字的表示形式(代码+波形图)

在数字逻辑系统中,只存在高电平和低电平,因此用其表示数字只有整数形式,并存在3种表示方法,即:原码表示法(符号加绝对值)、反码表示法(符号加反码)和补码表示法(符号加补码)。这三种在FPGA开发中都有着广泛的应用,下面分别讨论。

1、原码表示法

原码表示法是机器数的一种简单的表示法,采用符号位级联绝对值的方法表示数字。其最高位为符号位,用0表示正数,1表示负数;其余部分为绝对数值部分。原码一般用二进制形式表示。

例如,X1 = +1010110,X2 = -1001010,则其原码分别为:01010110和11001010

原码表示数的范围与二进制位数有关。当用8位二进制来表示小数原码时,其表示范围:最大值为0.1111111,其真值约为10进制中的0.99;最小值为1.1111111,其真值约为十进制的-0.99。当用8位二进制来表示整数原码时,其表示范围:最大值为01111111,其真值为十进制的127;最小值为11111111,其真值为十进制的-127。

在原码表示法中,对0有两种表示形式,分别记为+0和-0,以8比特数据为例,其相应的表示为:+0=00000000、-0=10000000。

2、反码表示法

反码可由原码得到。如果数字是正数,则其反码与原码一样;如果数字是负数,则其反码是对它的原码(符号位除外)各位取反而得到的。

例如:X1 = +1010110, X2=-1001010,则其相应的反码为01010110、10110101。

3、补码表示法

补码表示法师实际中应用最广泛的数字表示法,其表示规则如下:若是正数,补码、反码和原码的表示是一样的;若是负数,补码、反码和原码的表示都不一样。

由反码与原码之间的关键,负数的补码等于其反码在最低位加1。

4、各类表示方法小结

原码的优点就是乘除运算方便,不论正负数,乘除运算都一样,并以符号位决定结果的正负号;若做加法则需要判断两数符号是否相同;若作减法,还需要判断两数绝对值的大小,以使大数减小数。

补码的优点是,加法运算方便,不论数的正负都可直接相加,而符号位同样参加运算。

例:给出各类码字表示法的基本加法运算实例,并说明各自特点

(1)首先给出原码的运算示例,其中()d代表十进制数。首先给出一个原码的减法计算实例,完成“1 + (-1)= 0“”的操作。

(1)d + (-1)d = (0)d

如果读者直接利用原码来完成上式运算,会发现用符号位的原码进行在加减运算的时候就会出现问题,将数据以8比特的表示形式为例,

(00000001)原 + (10000001)原 = (10000001)原 = (-2)d

计算结果是不对的,问题在于两点:首先,负数的符号位直接改变了计算结果符号;其次,绝对值部分计算也不正确。这说明原码无法直接完成正数和负数的加法。

(2)既然,原码不能完成正、负数相加,那么反码形式可以完成此操作吗?仍然以”1 + (-1) = 0“ 为例,其相应的反码表达式如下:

(00000000)反 + (11111110)反 = (11111111)反 = (-0)d

则发现问题出现在+0和-0上,因为实际的计算中的零没有正负之分的。但上式标明了反码完成正、负数相加后,其绝对值部分是正确的,因此能正确完成正、负数相加的表达形式必定包含反码的特性。

(3)最后给出补码的相关特性说明,负数的补码就是对反码加1,而正数不变。以8比特数据为例,通过(-128)d代替了(-10)d,所以其表示范围为【-128,127】。从直观上,补码消除了(+0)和(-0),并且具备反码特点,那么究竟其能完成正、负加法运算吗?答案是肯定的,下面给出具体实例,所示

(00000001)补 + (11111111)补 = (00000000)补 = (0)d

基于以上讨论,可以得到一个基本结论:只有补码才能正确完成正负加法运算,并将减法运算转化为加法运算,从而简化运算规则。

但对于乘法操作,则以原码形式计算是最方便的,下面有实例。


演示1:原码进行乘法运算 -2 * 2 = -4

module mul(
		input clk,
		input rstn,
		input [7:0] a,
		input [7:0] b,
		
		output [14:0] q_mul,
		output reg [8:0] q_add,
		output reg[7:0] ra,
    output reg[7:0] rb
    );
    
    
    reg [13:0] rmul;
    
    always @(posedge clk or negedge rstn)
    		if(!rstn)
    			begin
    				q_add <= 0;
    				ra <= 0;
    				rb <= 0;
    				
    				rmul <= 0;
    			end
    		else begin
    			
    			//q_mul <= a*b;
    			if(a[7]==1)
    				ra = {a[7],~a[6:0] + 1};
    			else
    				ra = a;
    			if(b[7]==1)
    				rb = {b[7],~b[6:0] + 1};
    			else
    				rb = b;
    			rmul <= ra[6:0]*rb[6:0];
    			
    			
    			q_add <= {a[7],a} + {b[7],b};
    		end
    		
    		assign q_mul = {a[7]^b[7],rmul};
    		
endmodule
FPGA设计--数字的表示形式(代码+波形图)_第1张图片

演示2:通过reg signed实现

module signedMul(
		input clk,
		input rstn,
		input [7:0] a,
		input [7:0] b,
		output [15:0] q
    );
    
     reg signed[7:0] ra;
     reg signed[7:0] rb;
    
    always @(posedge clk or negedge rstn) begin
    		if(~rstn) begin
    			ra <= 0;
    			rb <= 0;
    		end
    		else begin
    			ra <= a;
    			rb <= b;
    		end
    end
		assign q = ra * rb;

endmodule

FPGA设计--数字的表示形式(代码+波形图)_第2张图片


























你可能感兴趣的:(FPGA项目)