一、整数乘法器
1.1 整数的概念
整数在IEEE的规定上有,短整数 short integer ,中整数 integer 和 长整数 long integer ,他们之间的关系如下:
整数 | 字节空间 | 取值范围 |
---|---|---|
短整数 | 一个字节 | -127 ~ 127 |
整数 | 二个字节 | -32767~32767 |
长整数 | 四个字节 | -2147483647~2147483647 |
若无特殊说明,以下都以短整数举例。
四个结论:
- 短整数的最高位是符号位,正值的符号位是“0”,负值的符号位是“1”。
- 正值用原码表示,负值用补码表示。
- 正值(8’b0000_0100)“取反加一”就得到负值(8’b1111_1100) ; 同理,负值(8’b1111_1100)“取反加一”就得到正值(b’b0000_0100)。
- 8’b1000_0000既不是正数也不是负数也不是0,它是划分正值和负值的边界线。
1 | +4 即 8'b0000_0100; |
1.2 传统乘法器
在传统概念上,乘法等价于“重复几次”,也就是累加操作。比如:B=4,那么A x B等价于A重复加四次。那如果B=-4应该怎么理解呢?
先来看一组例子:1
2
3
4
5A x B = C;
3 x 4 = 12;
-3x 4 = -12;
3 x-4 = -12;
-3x-4 = 12;
其中,C的值可以看成由两部分构成:正负和数值。
撇开正负不看,乘积的数值就是A和B绝对值相乘的结果。那么乘积的正负如何确定呢?
其实正负号的运算规则和数字电路中的“异或运算”一样。
A | B | C(A⊕B) |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
其中,0表示正号,1表示负号。
因此,传统乘法器实现的大致操作如下:
- 在初始化之际,取乘数和被乘数的正负关系,然后取乘数和被乘数的正值。
- 每一次累加操作,递减一次乘数。直到乘数的值为零,表示操作结束。
- 输出结果根据正负关系取得。
其实传统的乘法器是很容易的,但是随着整数的出现,负值和正值也随着出现,这也使得设计多了一点难度。但是只要掌握负值和正值的关系以后,乘法只作正值也“无问题” ,只要在结果输出之前“下一点手脚”就行了。
1.3 传统乘法器的改进
传统的乘法器虽然简单,但是它有一个致命的问题。就是被乘数越大就越消耗时钟。那么要解决这个问题就要了解为什么会产生这个问题。还是举例来说:
假设A=10 , B=20 , A x B ,那么时钟的消耗至少需要 20个,因为A值需要累加20次才能得到结果。回顾一下乘法法则:A x B = B x A。如果以B作为基础,那么B值只需要累加10次就能得到结果,这样就可以节省时钟的消耗。
因此我们可以这样改进:在进行累加操作之前,增加一个比较步骤。如果被乘数小于乘数,那么被乘数和乘数互换。1
{Multiplier , Multiplicand} = Multiplicand < Multiplier ? {Multiplicand ,Multiplier} : {Multiplier ,Multiplicand};
于是,改进版传统乘法器实现的大致操作如下:
- 在初始化之际,取乘数和被乘数的正负关系,然后取被乘数和乘数的正值。
- 乘数和被乘数比较,如果被乘数小于乘数,结果乘数和被乘数互换。
- 每一次累加操作,递减一次乘数。直到乘数的值为零,表示操作结束。
- 输出结果根据正负关系取得。
传统的乘法器无论如何改进也好,当遇见如 127 x 127 的乘数和被乘数,咋样也看不出什么可以优化的地方…
1.4 补码的意义
上面也说到过一点,就是实现正数和负数之间的转换,也就是说使符号位能与有效值部分一起参加运算,从而简化运算规则。
另外,还有一点就是使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计。