【数字IC/FPGA】移位相加乘法器

在硬件设计中,乘法器是非常重要的一个器件,乘法器的种类繁多,常见的有并行乘法器、移位相加乘法器和查找表乘法器,并行乘法器的实现非常简单,在Verilog中只需要通过assign dout=a*b实现即可,若要进行有符号的乘法,只需在变量前加上$signed。查找表乘法器实际上是先将乘法的计算结果提前算好,这样就可以在计算时通过查表的方式直接得到结果,一般用于位宽较小的情况。移位相加乘法器是一种耗费较少资源的算法,其思想是将乘法转化为加法和移位运算,不足之处是计算过程的延时较长,一般用于对性能要求不高的场合。

无符号乘法器

移位相加乘法器的原理:
以a=1011和b=1001相乘为例(均为无符号数)
1.b的第0位为1,所以
result=result+a<<0;
2.b的第二位为0,result保持不变
3.b的第三位也为0,保持不变
4.b的第四位为1,则
result=result+a<<3,得到最终的计算结果
可以看到,W位宽的无符号乘法器,需要W个周期才能计算完成。
下面是无符号乘法的Verilog实现:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/03/18 21:37:17
// Design Name: 
// Module Name: demo
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module demo
(
input logic clk,
input logic rst_n,
input logic vld,
input logic [7:0] dina,
input logic [7:0] dinb,
output logic [15:0] dout,
output logic ovld
);
logic [7:0] reg_a;                   //被乘数
logic [7:0] reg_b;                   //乘数
logic [15:0] psum;
logic [15:0] T;
logic busy;
logic one_bit;
logic [3:0] cnt;
//
always_ff@(posedge clk,negedge rst_n)
if(~rst_n)
begin
    reg_a<=0;
end
else if(vld)
begin
    reg_a<=dina;
end
always_ff@(posedge clk)
if(vld)
    psum<=0;
else if(busy&&one_bit)      //
    psum<=psum+T;
else
    psum<=psum;
//T
always_ff@(posedge clk)
if(vld)
    T<=dina;
else if(busy)
    T<=(T<<1);
//reg_b
always_ff@(posedge clk)
if(vld)
     reg_b<=dinb;
else if(busy)
     reg_b<={1'b0,reg_b[7:1]};
//one_bit
assign one_bit=reg_b[0];
//busy
always_ff@(posedge clk)
if(vld)
    busy<=1;
else if(busy&&cnt==7)
    busy<=0;
//cnt
always_ff@(posedge clk)
if(vld)
    cnt<=0;
else if(busy)
    cnt<=cnt+1;
//dout
assign dout=psum;
//ovld
always_ff@(posedge clk,negedge rst_n)
if(~rst_n)
    ovld<=0;
else if(busy&&cnt==7)
    ovld<=1;
else 
    ovld<=0;
endmodule

经过仿真,发现上述代码功能正确。

有符号乘法器

我们通过调用无符号乘法器,来实现有符号乘法。具体方法为

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/03/23 13:08:23
// Design Name: 
// Module Name: signed_mult
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module signed_mult(
input logic clk,
input logic rst_n,
input logic vld,
input logic [7:0] dina,
input logic [7:0] dinb,
output logic [15:0] dout,
output logic ovld
    );
logic sign_a;
logic sign_b;
logic sign_o;
logic [7:0] unsigned_a;
logic [7:0] unsigned_b;
logic [15:0] unsigned_o;
assign sign_a=dina[7];
assign sign_b=dinb[7];
assign sign_o=sign_a^sign_b;                               //1为负,0为正
assign unsigned_a=(sign_a==1'b1)?~dina+1:dina;
assign unsigned_b=(sign_b==1'b1)?~dinb+1:dinb;
assign dout=(sign_o==1'b1)?~unsigned_o+1:unsigned_o;
//
demo unsigned_mult
(
.clk(clk),
.rst_n(rst_n),
.vld(vld),
.dina(unsigned_a),
.dinb(unsigned_b),
.dout(unsigned_o),
.ovld(ovld)
);
endmodule

以下是仿真波形,测试了a,b均为正,均为负数,一正一负四种情况,结果均正确:
【数字IC/FPGA】移位相加乘法器_第1张图片

你可能感兴趣的:(数字IC设计,数字IC设计)