无符号乘法器的两种写法:移位相加和流水线
相比于有符号乘法器,无符号乘法器就不需要考虑符号位的判断,直接计算即可。乘法器简单理解也就是每一位相乘过后相加取和的结果,唯独需要考虑的是:“每一位相乘”,这就需要考虑进行移位操作。而两种不同的写法就是是否添加了寄存器,有符号乘法器的详细例子:https://www.cnblogs.com/shadow-fish/p/13368689.html。
1:两个N位二进制数相乘结果为2N位。
out_c = out_c + ((b_in[i]==1'b1)?({4'b0,a_in}<<i):0); //这个跟下方的主要部分是一致的。
移位相加型乘法器
module shift_add(a,b,out);
input [3:0]a;
input [3:0]b;
output [7:0]out;
reg [7:0]out_c;
integer i;
always@(a or b) begin
out_c = 8'b0;
for(i=0;i<=3;i=i+1) begin
out_c = out_c + ((b[i]==1'b1)?(a<<i):0);
end
end
assign out = out_c;
endmodule
tb文件:
`timescale 1ns/1ps
module shift_add_tb;
reg [3:0]a;
reg [3:0]b;
wire [7:0]out;
shift_add u1(
.a(a),
.b(b),
.out(out)
);
initial begin
a=4'b1101;
b=4'b0011;
#20;
a=4'b1011;
b=4'b1100;
end
endmodule
流水线设计--添加寄存器:先将相邻的乘积进行相加,然后再输出最终结果
module pipline_add (
clk,rst,a,b,out
);
input clk;
input rst;
input [3:0]a; //被乘数
input [3:0]b; //乘数
output [7:0]out;
reg [7:0]out;
reg [7:0]out_1;
reg [7:0]out_2;
reg [7:0]out_3;
reg [7:0]out_4;
reg [7:0]out_5;
reg [7:0]out_6;
always @(posedge clk or negedge rst) begin
if(!rst) begin
out <= 8'b0;
out_1 <= 8'b0;
out_2 <= 8'b0;
out_3 <= 8'b0;
out_4 <= 8'b0;
out_5 <= 8'b0;
out_6 <= 8'b0;
end
else begin
out_1 <= ((b[0]==1'b1)?({4'b0,a}):8'b0); //判断乘数位是否为1,若是,则结果进行对应位的移位
out_2 <= ((b[1]==1'b1)?({3'b0,a,1'b0}):8'b0);
out_3 <= ((b[2]==1'b1)?({2'b0,a,2'b0}):8'b0);
out_4 <= ((b[3]==1'b1)?({1'b0,a,3'b0}):8'b0);
out_5 <= out_1 + out_2; //添加流水线
out_6 <= out_3 + out_4;
out <= out_5 + out_6;
end
end
endmodule
tb文件:
`timescale 1ns/1ps
module pipline_add_tb;
reg clk;
reg rst;
reg [3:0]a;
reg [3:0]b;
wire [7:0]out;
pipline_add u1(
.clk(clk),
.rst(rst),
.a(a),
.b(b),
.out(out)
);
initial begin
clk = 1'b0;
rst = 1'b0;
#5;
rst = 1'b1;
end
always #5 clk = ~clk;
initial begin
a = 4'b1101;
b = 4'b1000;
#60;
a = 4'b0110;
b = 4'b1001;
#80;
$stop();
end
endmodule
此上均是只进行了功能仿真,未进行时序仿真。