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

来源:互联网 发布:新浪微博pv和uv数据 编辑:程序博客网 时间:2024/06/05 03:00

在数字逻辑系统中,只存在高电平和低电平,因此用其表示数字只有整数形式,并存在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

演示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    endassign q = ra * rb;endmodule



























0 0