乘法器系列:
- FPGA中有符号数的相乘
- FPGA中乘法器的流水线实现
- Vivado(复数)乘法器IP核的使用
一、流水线乘法器设计
1.1 流水线设计思想简介
📄流水线是一种经典的设计思想,它是将一个处理过程分为若干个子过程,每个子过程由专门的模块进行处理;然后多个过程在时间上错开,这样就可以实现每个子过程和其它过程的子过程并行运行。在输入数据量很多时,使用流水线设计可以大幅减少处理时间,有效地解决了多周期串行计算效率低的问题。
1.2 程序设计
①顶层模块:multiply_top.v
module multiply_top
#(parameter N=5,
parameter M=5)//N>=M,M决定了流水线的级数
(
input clk ,//输入时钟
input rstn ,//复位信号
input [N-1:0] multiplicand ,//被乘数
input [M-1:0] multiplier ,//乘数
input mult_en ,//输入使能信号
output [M+N-1:0] result ,//最后结果
output mult_end_f //第一次运算结束标志
);
//各级间传递数据的数组
wire [N+M-1:0] result_acco_t [M-1:0];
wire [N+M-1:0] multiplicand_t [M-1:0];
wire [M-1:0] multiplier_t [M-1:0];
wire mult_end_t[M-1:0] ;
//第一级需单独例化
multiply_cell #(.N(N), .M(M))
mult_u0
(
.clk (clk) ,
.rstn (rstn) ,
.multiplicand ({{(M){0}},multiplicand}) ,
.multiplier (multiplier) ,
.result_acci (0) ,
.mult_en (mult_en) ,
.mult_end (mult_end_t[0]) ,
.result_acco (result_acco_t[0]) ,
.multiplicand_r(multiplicand_t[0]) ,
.multiplier_r (multiplier_t[0])
);
//其余各级例化
genvar i;
generate
for(i=1;i<=M-1;i=i+1)begin
multiply_cell #(.N(N), .M(M))
u_mult_step
(
.clk (clk) ,
.rstn (rstn) ,
.multiplicand (multiplicand_t[i-1]) ,
.multiplier (multiplier_t[i-1]) ,
.result_acci (result_acco_t[i-1]) ,
.mult_en (mult_end_t[i-1]) ,
.mult_end (mult_end_t[i]) ,
.result_acco (result_acco_t[i]) ,
.multiplicand_r(multiplicand_t[i]) ,
.multiplier_r (multiplier_t[i])
);
end
endgenerate
assign result=result_acco_t[M-1];
assign mult_end_f=mult_end_t[M-1];
endmodule
📄通过generate语句和数组实现各级间信号的传递。
②子模块:multiply_cell.v
/**********************************
=========multiply_cell.v==========
Description : 子级模块
***********************************/
module multiply_cell
#(parameter N=5,
parameter M=5)//N>=M
(
input clk ,
input rstn ,
input [N+M-1:0] multiplicand ,
input [M-1:0] multiplier ,
input [N+M-1:0] result_acci ,//上一级的运算结果输入
input mult_en ,
output reg mult_end ,
output reg [N+M-1:0] result_acco ,//这一级的运算结果输出
//移位的中间结果
output reg [N+M-1:0] multiplicand_r ,
output reg [M-1:0] multiplier_r
);
//一次运算
always @(posedge clk or negedge rstn)begin
if(!rstn)begin
mult_end<='b0;
result_acco<='b0;
multiplicand_r<='b0;
multiplier_r<='b0;
end
else if(mult_en)begin
multiplicand_r<=multiplicand<<1;
multiplier_r<=multiplier>>1;
mult_end<=1'b1;
result_acco<=multiplier[0] ? result_acci+multiplicand:result_acci;
end
else begin
mult_end<='b0;
result_acco<='b0;
multiplicand_r<='b0;
multiplier_r<='b0;
end
end
endmodule
📄子模块中实现了整个乘法过程中的一次运算,包括一次乘数、被乘数的移位和一次累加。
1.3 仿真
📄将M设为5,可以看出,开始时经过5个时钟周期,输出第一个运算结果;而后续每次运算输出都只需要一个时钟周期,实现了流水输出。
注:由于后续结果输出需要一个时钟周期,所以仿真时输入不同运算数据的时间间隔不能小于一个时钟周期。