目录
1、原理分析
这里以二进制数data_a[3:0]与data_b[2:0]的乘法为例,
其中可以看出,data_a [ i ] ( i = 0,1,2,3 )分别对 data_b [2:0] 进行了乘法操作,但是 data_a [ 1 ] 比data_a [ 0 ] 对data_b的操作结果高一位,所以每次 data_a [ i ] 进行乘法操作后需要对 data_b 左移一位,再和 data_a [ i+1 ] 进行乘法操作,总共进行的乘法操作次数为 data_a 的位宽,移位操作次数为 data_a 的位宽减1。
由于 data_b 为三位宽,进行左移操作的时候会导致首位丢失,如1 1 1<<1 = 1 1 0,故我们需要对data_b 进行补零操作,补零个数为移位操作次数。同时为了保证data_a [ i ] 同 data_b 的每一位进行运算,需要将data_a [ i ] 拓展后和data_b(或补零移位后的 data_b )进行与(&)操作。如
最后,将每一次与(&)的结果相加得最后乘法器结果。
2、源程序代码
//方案1
module shift_mult
#(
parameter sizea = 8,
parameter sizeb = 8
)
(
input wire [sizea-1:0] a ,
input wire [sizeb-1:0] b ,
output reg [sizea+sizeb-1:0] result
);
integer index ;
reg [sizea+sizeb-1:0] reg_b ;
always@(*) begin
result= 0;
reg_b = {{(sizea-1){1'b0}}, b };
for(index = 0;index < sizea;index = index + 1) begin
result= result + ({ (sizea+sizeb){a[index]}} & (reg_b << index));
end
end
endmodule
//方案2
module shift_mult
#(
parameter sizea = 8,
parameter sizeb = 8
)
(
input wire [sizea-1:0] a ,
input wire [sizeb-1:0] b ,
output reg [sizea+sizeb-1:0] result
);
reg [sizea+sizeb-1:0] shift_a;
reg [sizeb-1:0] shift_b;
always@(*)begin
shift_a = a;
shift_b = b;
result = 0;
repeat(sizeb) begin
if(shift_b[0])
result = result + shift_a;
else
result = result;
shift_a = shift_a <<1;
shift_b = shift_b >>1;
end
end
endmodule
3、仿真代码
`timescale 1ns/1ns
module shift_mult_tb();
parameter sizea = 8;
parameter sizeb = 8;
reg [sizea-1:0] a;
reg [sizeb-1:0] b;
wire [sizea+sizeb-1:0] res_ture;
wire [sizea+sizeb-1:0] result;
wire t_or_f;
initial begin
repeat(100) begin
a <= $random;
b <= $random;
#20;
end
end
assign res_ture = a * b;
assign t_or_f = (res_ture == result) ? 1'b1 : 1'b0;
shift_mult
#(
.sizea(sizea),
.sizeb(sizeb)
)
shift_mult_inst
(
.a(a),
.b(b),
.result(result)
);
endmodule