四位booth乘法的verilog实现
最近做了一个四位的booth乘法器的实验,在这里记录一下我的实验过程,需要说明的是,我认为最好的方法是使用有限状态机的方法(做完之后才知道),我这里的方法是根据比较的结果来生成使能信号,进而控制运算模块的运算。
算法流程
先简单介绍一下在这篇文章中booth乘法的前期准备及算法流程:
首先,符号是会参与运算的,booth乘法也是计算补码的,得出的结果也是补码。
1、先对被乘数进行符号拓展,就是将被乘数变成双符号位。
2、部分积寄存器pi置0,乘数寄存器放入乘数,但是乘数寄存器需要在最后一位添加一位0,所以乘数寄存器是有5位的,还需要一个计数器来计数运算了多少次。
3、比较乘数寄存器的末两位,如果两位是00或者11,则部分积寄存器和乘数寄存器都右移一位,如果是01,则部分积寄存器加乘数的补码,部分积寄存器和乘数寄存器再右移一位,如果是10,则部分积寄存器减乘数的补码,部分积寄存器和乘数寄存器再右移一位。同时计数器加1。(这里的右移一位会把部分积寄存器的最后一位移入乘数寄存器,而乘数寄存器的最后一位会被舍弃)
4、重复4次(4位的乘法器是比较4次),结果的低4位是乘数寄存器的高四位,结果的高3位是部分积寄存器的低3位。(这里结果取了7位,因为取8位也只不过是多了一位的符号位)
| 比较结果 | 运算 |
|---|---|
| 00 | 部分积寄存器和乘数寄存器都右移一位 |
| 01 | 则部分积寄存器加乘数的补码,部分积寄存器和乘数寄存器再右移一位 |
| 10 | 部分积寄存器减乘数的补码,部分积寄存器和乘数寄存器再右移一位 |
| 11 | 部分积寄存器和乘数寄存器都右移一位 |
使能信号表如下:
| 乘数低两位比较结果 | 使能信号g |
|---|---|
| 00 | 00 |
| 11 | 00 |
| 01 | 01 |
| 10 | 10 |
得出最终实现方案的尝试
下面是我做的第一个没有用计数器的方案,这是一个存在问题的方案。
module subtracter(input [3:0]X1,X2,output [6:0]Y);reg [9:0]p=0;reg [4:0]x_0;reg [4:0]x_1;reg z1,c1,z2,c2,z3,c3,z4,c4,c5,z5;reg [3:0]t;always @ (*) beginp=10'b0;p[4:1]=X2; //这里是一个全加器,用来算乘数[-x]补码,因为可能是我本地软件的原因,我用+运算符算不出来,所以只能这样。{c1,z1}=!X1[0]+1;{c2,z2}=!X1[1]+c1;{c3,z3}=!X1[2]+c2;{c4,z4}=!X1[3]+c3;t={z4,z3,z2,z1};x_0={!X1[3],t};x_1={X1[3],X1};repeat (4) beginif(p[1]^~p[0]) beginp={p[9],p[9:1]};endelse if(p[1]===1'b0) begin{c1,z1}=p[5]+x_1[0]+1'b0;{c2,z2}=p[6]+x_1[1]+c1;{c3,z3}=p[7]+x_1[2]+c2;{c4,z4}=p[8]+x_1[3]+c3;{c5,z5}=p[9]+x_1[4]+c4;p[9:5]={z5,z4,z3,z2,z1};p={p[9],p[9:1]};endelse begin{c1,z1}=p[5]+x_0[0]+1'b0;{c2,z2}=p[6]+x_0[1]+c1;{c3,z3}=p[7]+x_0[2]+c2;{c4,z4}=p[8]+x_0[3]+c3;{c5,z5}=p[9]+x_0[4]+c4;p[9:5]={z5,z4,z3,z2,z1};p={p[9],p[9:1]};//p[8]=1'b1;end endendassign Y=p[7:1];
endmodule
问题
可以发现的是,这里没有用计数器而是用了repeat来让模块重复运算4次,这样就存在着在综合的过程中加法器会出现不确定个数的情况,可能会有多个加法器,在芯片的加法器个数有限的情况下,显然是不符合实际的,因此我改用了生成使能信号来告诉运算模块进行专门运算,这样就能够解决上述的问题。但是我的这种方法还是用了两个加法器。
接下来就是最终方案:
module subtracter(input [3:0]X1,X2,output [6:0]Y,input CLK);reg [9:0]p=0;//我将乘数寄存器与部分积寄存器定义为一个10位的寄存器类型的数据reg [4:0]x_0;//用来存拓展符号位之后的[-x]补码reg [4:0]x_1;//用来存拓展符号位之后的[x]补码reg [1:0]f; //用来存乘数寄存器低两位,其实可以不用reg [1:0]g;//使能信号寄存器reg [3:0]t;wire [9:0]p_1;//用来接收运算模块的结果reg re;//使能信号,初始化各个寄存器的值integer count;//计数器reg z1,c1,z2,c2,z3,c3,z4,c4,c5,z5;always @ (X1 or X2) begin re=1'b1; //当乘数或者被乘数发生变化的时候,这个信号会置1endalways @ (posedge CLK) beginif (re) beginp=10'b0;p[4:1]=X2;{c1,z1}=!X1[0]+1;{c2,z2}=!X1[1]+c1;{c3,z3}=!X1[2]+c2;{c4,z4}=!X1[3]+c3;t={z4,z3,z2,z1};x_0={!X1[3],t};x_1={X1[3],X1};count=0;re=1'b0;endelse beginf={p[1],p[0]};case(f)2'b00: g=2'b00;2'b11: g=2'b00;2'b01: g=2'b01;2'b10: g=2'b10;default: g=2'b11;//表示保持之前的p寄存器的结果endcaseif(count==4||count>4) beging=2'b11;//当运算过4次之后,运算不会进行endcount=count+1;endend AL ALU (x_0,x_1,g,p,p_1,CLK);always @ (CLK) beginp=p_1;endassign Y=p_1[7:1];endmodulemodule AL(input [4:0]x_0,x_1,input [1:0]g,input [9:0]p,output reg[9:0]p_1,input CLK);reg c1,c2,c3,c4,c5,z1,z2,z3,z4,z5;always @ (posedge CLK) beginp_1=p;case (g) 2'b00: begin p_1={p_1[9],p_1[9:1]};end2'b01: begin{c1,z1}=p[5]+x_1[0]+1'b0;{c2,z2}=p[6]+x_1[1]+c1;{c3,z3}=p[7]+x_1[2]+c2;{c4,z4}=p[8]+x_1[3]+c3;{c5,z5}=p[9]+x_1[4]+c4;p_1[9:5]={z5,z4,z3,z2,z1};p_1={p_1[9],p_1[9:1]};end2'b10: begin{c1,z1}=p[5]+x_0[0]+1'b0;{c2,z2}=p[6]+x_0[1]+c1;{c3,z3}=p[7]+x_0[2]+c2;{c4,z4}=p[8]+x_0[3]+c3;{c5,z5}=p[9]+x_0[4]+c4;p_1[9:5]={z5,z4,z3,z2,z1};p_1={p_1[9],p_1[9:1]};end2'b11: p_1=p_1;default: p_1=p_1;endcaseend
endmodule
验证
仿真能够看出模块的逻辑功能是否正确,在仿真的时候,我们的乘法器需要至少4个时钟上升沿才能够算完,如果不满足的话是会显示中间计算结果的。
module one_true_from_subtracter_bench;
reg [3:0]X1,X2;
wire [6:0]Y;
reg CLK;
initialbeginCLK=0;end
always #10CLK=~CLK;
one_true_from_subtracter U0 (X1,X2,Y,CLK);
initial beginX1=4'b1101;X2=4'b0101;#200 X1=4'b1001;X2=4'b1100;#150 X1=4'b1111;X2=4'b1100;#150 X1=4'b1101;X2=4'b0101;#150 X1=4'b1000;X2=4'b1011;//#1 X1=4'b1101;X2=4'b1010;end
endmodule
波形图如下,可以看出我们的模块逻辑功能是正确的。经过4个时钟周期,算出来结果,而在没有新的数据输入的时候,结果是会保持的。

我没有综合,无法得知综合的结果,因为我电脑的问题,综合的时候软件会闪退(哭~)。
可能存在的问题:
我的方法不是一个最佳的解决方式,我用了两个加法器,并且没有综合,不知道综合的时候会不会有问题。
总结
这次的实验做下来,在编程中我其实出现了许多的问题,比如说在判断条件的小于等于,如果用 ‘<=’ 是不行的,在verilog里面这个是非阻塞赋值的符号。我一开始的第一种实现方案其实还是用了软件的思维去写硬件,仿真出来结果也确实是对的。但是硬件与软件不同,虽然说软件跟硬件用代码能够实现某种东西,但是在硬件里面,还需要考虑到的是能不能综合,实际做成电路有没有难度,会不会造成歧义,模块的是否有必要重复存在,成本会不会更高等等。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
