知识储备
首先来回顾一下乘法是如何在计算机中实现的。
假设现在有两个32位带符号定点整数x和y,我们现在要让x和y相乘,然后把乘积存放在z中,大家知道,两个32位数相乘,结果不会超过64位,因此z的长度应该为64位。
z = x * y中,x是被乘数,在Verilog代码中 multiplicand表示,y是乘数,在代码中用multiplier表示。因为x和y都是带符号数,所以应该是用补码乘法,但是如果对x和y求绝对值,让两个绝对值相乘,然后再判断正负,效果和补码乘法是相同。后面给出的Verilog代码就是基于这种思路编写的。两个32位整数相乘,实际上是进行了32次加法操作。下面以两个4位二进制数相乘来说明乘法实现的过程。
从上图中可以看到,被乘数x为1000,乘数y为1001,上面的乘法过程是手工运算的一个步骤,而计算机在做乘法时就是模拟上述手工运算的执行过程。因为是两个4位数相乘,所以结果应该是四个数加和得到的。先判断y的最低位是0还是1,如果是1,则需要把x加到部分积上,若为0,则需要把0加到部分积上(实际上加0的这个过程计算机并不执行,因为加0对部分积没有任何影响),x左移一位,之后再让y右移一位,若y为0,则循环结束,否则继续此循环过程。流程图如下。
流程图中,x因为需要左移,所以32位长度的x应该用一个64位寄存器来存储,这样才能保证x左移后不会发生高位丧失。
代码实现与分析
multiply.v文件如下
`timescale 1ns / 1ps
//*************************************************************************
// > 文件名: multiply.v
// > 描述 :乘法器模块,低效率的迭代乘法算法,使用两个乘数绝对值参与运算
// > 作者 : LOONGSON
// > 日期 : 2016-04-14
//*************************************************************************
module multiply( // 乘法器
input clk, // 时钟
input mult_begin, // 乘法开始信号
input [31:0] mult_op1, // 乘法源操作数1
input [31:0] mult_op2, // 乘法源操作数2
output [63:0] product, // 乘积
output