移位累加乘法器的计算过程类似手算十进制乘法的过程。具体细节可参见中文版《数字设计---原理与实践(第3版)》P316 组合乘法器一节。
现以4位无符号数乘法为例加以说明。
两个无符号的4位数相乘结果为8位数。因此先定义两个8位的变量 a,c, 用来缓存被加数和输出结果,定义一个4位变量 b 来缓存加数。
常规的计算过程是:将4位被加数赋值给 a 的低四位,然后与 b 的最低位相乘,接着a 左移一位后与b的第2位相乘,再与之前的结果相加,依次进行下去,直到计算完成为止。4位数据相乘需要做3次移位和3次加法。
这里需要用到verilog的移位运算符,当将一个数移位后再赋值给一个相同位宽的变量时(比如这里的a移位后再赋值给a),如果使用左移<<运算,则移出的最高位被截掉,最低位补0;若使用右移>>运算,则移出的最低位被截掉,最高位补0 。
因为这里的移位相加没有严格的顺序要求,因此既可以使用左移,也可以使用右移,当然左移位更符合我们的思维。
Verilog代码:
module multi44(dina,dinb,dout,clk,rst);
input clk, rst;
input [3:0] dina, dinb;
output [7:0] dout;
reg [7:0] dout;
reg [7:0] a, c;
reg [3:0] b;
reg [1:0] i;
reg state;
always @ (posedge clk or negedge rst)
begin
if(!rst)
begin
a<=0; b<=0; c<=0;
state<=0; dout<=0;
i<=0;
end
else
case(state)
1'b0: //初始化和输出结果
begin
a[4:1]<=dina; //装载被乘数dina(相当于已经左移1位)
b<=dinb; //乘数dinb缓存
i<=1;
//初始化输出中间结果
if(dinb[0]==1)
c<={4'b0,dina};
else
c<=0;
//输出
dout<=c;
state<=1;
end
1'b1: //移位-相加
begin
if(b[i]==1)
c<=c+a; //与上一次移位后的a相加
if (i==3)
begin
a<=0;
state<=0;
end
else
begin
a<=(a<<1); //左移一位,下次使用
i<=i+1;
state<=1;
end
end
default: dout<=0;
endcase
end
endmodule
用Modelsim仿真结果如下:
由此可以看出,4位的乘法需要4个时钟周期。选择spartan xc3s400综合后的最小时钟周期如下:
占用资源情况如下: