module multipier_module
(
input clk,
input rst_n,
input Start_Sig,
input [7:0]Multiplicand,
input [7:0]Multiplier,
output Done_Sig,
output [15:0]Product
);
reg[1:0]i;
reg[7:0]Mcand;
reg[7:0]Mer;
reg[15:0]Temp;
reg isNeg;
reg isDone;
always@(posedge clk or negedge rst_n)
if(!rst_n)
begin //初始化
i<=2'd0;
Mcand<=8'd0;
Mer<=8'd0;
Temp<=8'd0;
isNeg<=1'b0;
isDone<=1'b0;
end
else if(Start_Sig)
case(i)
0:
begin
isNeg<=Multiplicand[7]^Multiplier[7]; //判断符号
Mcand<=Multiplicand[7]?(~Multiplicand+1'b1):Multiplicand; //取乘数的整数部分
Mer<=Multiplier[7]?(~Multiplier+1'b1):Multiplier;
Temp<=16'd0;
i<=i+1'b1;
end
1: //重复加几次的操作
if(Mer==0)i<=i+1'b1;
else begin Temp<=Temp+Mcand;Mer<=Mer-1'b1;end
2: //产生完成信号
begin isDone <= 1'b0; i<=2'd0; end
3:
begin isDone <= 1'b0; i<=2'd0; end
endcase
assign Done_Sig=isDone;
assign product=isNeg?(~Temp + 1'b1):Temp; //如果isNeg是负值,取反加1 否则就是Temp的值
endmodule
//multipier_module.vt
module multipier_module_simulation();
reg clk;
reg rst_n;
reg Start_Sig;
reg[7:0]Multiplicand;
reg[7:0]Multiplier;
wire Done_Sig;
wire[15:0]Product;
initial
begin
rst_n=0; #10; rst_n=1;
clk=1;forever #10 clk=~clk;
end
multiplier_module U1
(
.clk(clk),
.rst_n(rst_n),
.Start_Sig(Start_Sig),
.Multiplicand(Multiplicand),
.Multiplier(Mulitiplier),
.Done_Sig(Done_Sig),
.product(Product)
);
reg[3:0]i;
always@(posedge clk or negedge rst_n)
if(!rst_n)
begin
i<=4'd0;
Start_Sig<=1'b0;
Multiplicand<=8'd0;
Multiplier<=8'd0;
end
else
case(i)
0:
if(Done_Sig)begin Start_Sig<=1'b0;i<=i+1’b1;end
else begin Multiplicand<=8'd10; Multiplilier<=8'd2;Start_Sig<=1'b1;end
1:
if(Done_Sig)begin Start_Sig<=1'b0;i<=i+1'b1;end
else begin Multiplicand<=8'd2;Multiplier<=8'd10;Start_Sig<=1'b1;end
2:
if(Done_Sig)begin Start_Sig<=1'b0;i<=i+1'b1;end
else begin Multiplicand<=8'd11;Mulitiplier<=8'b11111011;Start_Sig<=1'b1;end
3:
if(Done_Sig)begin Start_Sig<=1'b0;i<=i+1'b1; end
else begin Multiplicand<=8'b11111011;Mulitiplier<=8'b11110101;Start_Sig<=1'b1;end
4:
begin i<=4'd4;end
endcase
endmodule
上述实验是传统乘法器,的编写及其例化,但verilog的执行时间取决于被乘数,因此在实验二中对传统乘法器进行改进,即在累加操作之间,对乘数和被乘数进行比较大小,累加二者较小的次数 。
实验二改进的传统乘法器:
1 初始化之际,取乘数和被乘数的正负关系,然后取乘数和被乘数的正值。
2 乘数和被乘数比较,如果被乘数小于乘数,则乘数和被乘数互换。
3 每一次累加操作,递减一次乘数,直到乘数的值为0,表示操作结束。
4 输出结果根据正负关系取得。
//multiplier_module_2.v
module multiplier_module_2
(
input clk,
input rst_n,
input Start_Sig, //这是一个开始标志的寄存器
input [7:0]Multiplicand,
input [7:0]Multiplier,
output Done_Sig,
output [15:0]Product
);
reg[2:0]i;
reg[7:0]Mcand; //乘数的数值部分(去掉符号)
reg[7:0]Mer; //被乘数的数值部分
reg[15:0]Temp; //乘积16位
reg isNeg;
reg isDone;
always@(posedge clk or negedge rst_n)
if(!rst_n)
begin
i<=3'd0;
Mcand<=8'd0;
Mer<=8'd0;
Temp<=16'd0;
isNeg<=1'b0;
isDone<=1'b0;
end
else if(Start_Sig)
case(i)
0:
begin //算出来符号,并且对乘数和被乘数都取整数准备计算
isNeg<=Multiplicand[7]^Multiplier[7];
Mcand<=Multiplicand[7]?(~Multiplicand+1'b1):Multiplicand;
Mer<=Multiplier[7]?(~Multiplier+1'b1):Multiplier;
Temp<=16'd0;
i<=i+1'b1;
end
1:
begin //比较乘数和被乘数的大小并交换位置
{Mcand,Mer}<=Mcand<Mer?{Mer,Mcand}:{Mcand,Mer};
i<=i+1'b1;
end
2: //交换后的乘数累加次数
if(Mer==0)i<=i+1'b1;
else begin Temp<=Temp+Mcand;Mer<=Mer-1'b1;end
3: //回0步骤
begin isDone<=1'b1;i<=i+1'b1;end
4: //回0步骤
begin isDone<=1'b0;i<=3'd0;end
endcase
assign Done_Sig=isDone; //结束信号
assign Product=isNeg?(~Temp+1'b1):Temp; //如果乘积Temp是负数同样需要在原来的基础上进行取反后+!操作
emdmodule
补码存在的意义就是避免计算机做减法。为啥要避免计算机做减法?因为已经有加法器,且用加法器就能够实现减法,所以就将减法操作转换为加法操作。
实验三:Booth算法乘法器
module booth_multiplier_module
(
input clk, input rst_n,input Start_Sig, input[7:0]A, input [7:0]B,
output [15:0]Product, output Done_Sig,
output [7:0]SQ_a, output[7:0]SQ_s, output [16:0]SQ_p
);
reg[3:0]i;
reg[7:0]a; //a寄存器用来寄存A值
reg[7:0]s; //s寄存器用来寄存-1(A)的值
reg[16:0]p;
reg[3:0]X; //X表示n位,表示n次循环
reg isDone;
always@(posedge clk or negedge rst_n)
if(!rst_n)
begin
i<=4'd0;
a<=8'd0;
s<=8'd0;
s<=8'd0;
p<=17'd0;
X<=4'd0;
end
else if(Start_Sig)
case(i)
0:
//初始化a,s的值,将P[8:1]位给B,其余位均为0
begin a<=A;s<=(~A+1'b1);p<={8’d0,B,1'b0};i<=i+1'b1;end
1: //判断p[1:0]的操作
if(X==8)begin X<=4'd0; i<=i+4'd2;end
else if(p[1:0]==2'b01)begin p<={p[16:9]+a,p[8:0]};i<=i+1'b1;end
else if(p[1:0]==2'b10)begin p<={p[16:9]+s,p[8:0]};i<=i+1'b1;end
else i<=i+1'b1;
2: //向右移动1位是补0还是补1,完全取决于p[16]
begin p<={p[16],p[16:1]};X<=X+1'b1;i<=i-1'b1;end
3:
begin isDone<=1'b1;i<=i+1'b1;end
4:
begin isDone<=1'b0;i<=4'd0;end
endcase
assign Done_Sig=isDone;
assign product=p[16:1];
assign SQ_a=a;
assign SQ_s=S;
assign SQ_p=p;
endmodule
// Booth算法乘法器改进
module booth_multiplier_module_2
(
input clk, input rst_n, input Start_Sig, input [7:0]A, input [7:0]B.
output Done_Sig, output [15:0]Product, output [7:0]SQ_a, output [7:0]SQ_s, output [16:0]SQ_p
);
reg[3:0]i;
reg[7:0]a;
reg[7:0]s;
reg[16:0]p;
reg[7:0]Diff1;
reg[7:0]Diff2;
reg isDone;
always@(posedge clk or negedge rst_n)
if(!rst_n)
begin
i<=4'd0;
a<=8'd0;
s<=8'd0;
p<=17'd0;
Diff1<=8'd0;
Diff2<=8'd0;
isDone<=1'b0;
end
else if(Start_Sig)
case(i)
0:
begin
a<=A;
s<=(~A+1'b1);
p<={8'd0,B,1'b0};
Diff<=8'd0;
Diff<=8'd0;
i<=i+1'b1;
end
1,2,3,4,5,6,7,8: //8个循环操作使p空间的操作和移位可以在同一个时钟内完成
begin
Diff1=p[16:9]+a;
Diff2=p[16:9]+s;
if(p[1:0]==2'b01)p<={Diff1[7],Diff1,p[8:1]};
else if(p[1:0]==2'b10)p<={Diff2[7],Diff2,p[8:1]};
else p<={p[16],p[16:1]};
i<=i+1'b1;
end
9:
begin isDone<=1'b1;i<=i+1'b1;end
10:
begin isDone<=1'b0;i<=4'd0;end
endcase
assign Done_Sig=isDone;
assign Product=p[16:1];
assign SQ_a=a;
assign SQ_p=s;
assign SQ_p=p;
endmodule