并行加法运算的Verilog实现,实现思路:二路归并
代码
/*
* ADD_Parallel.v
* create on: 2021.11.23
* author: 今朝无言
* function: 实现任意个数加数的并行加法
*/
//两两归并,延时达到(NN-1)*delay,为最优状态 bottom-up设计思路
module ADD_Parallel(
datas_packed,
sum
);
parameter dataWidth=16;
parameter N=8;
localparam NN=clogb2(N-1); //NN为N-1的位数
input [0:dataWidth*N-1]datas_packed;
output [dataWidth+NN-1:0]sum;
generate
genvar i;
//二路归并相加
//Ns[i]=Ns[i-1]>>1+Ns[i-1]&1'b1
//即Ns[i]=(N>>i)+|(N-(N>>i)<<i) Ns[i]记录第i层加法的输出结果个数
wire [0:(dataWidth+1)*(N%2==0?N/2:N/2+1)-1]sums[1:NN-1];
ADD_Layer #(dataWidth,N) ADD_Layer_inst1(
.datas_packed(datas_packed),.sums_packed(sums[1])); //第一层加法
for(i=2;i<=NN-1;i=i+1)
begin: add_Layer //后续各层加法
ADD_Layer #(dataWidth+i-1,(N>>(i-1))+|(N-(N>>(i-1))<<(i-1))) ADD_Layer_inst(
.datas_packed(sums[i-1][0:(dataWidth+i-1)*((N>>(i-1))+|(N-(N>>(i-1))<<(i-1)))-1]),
.sums_packed(sums[i][0:(dataWidth+i)*((N>>i)+|(N-(N>>i)<<i))-1]));
end
assign sum=sums[NN-1][0:dataWidth+NN-2]+sums[NN-1][dataWidth+NN-1:2*(dataWidth+NN)-3];
endgenerate
//------------------------log2-----------------------------
function integer clogb2 (input integer depth);
begin
for (clogb2=0; depth>0; clogb2=clogb2+1)
depth = depth >>1;
end
endfunction
endmodule
//********************任意数目的加数进行一层加法************************
module ADD_Layer(
datas_packed,
sums_packed
);
parameter dataWidth=16;
parameter N=4;
input [0:dataWidth*N-1]datas_packed;
output [0:(dataWidth+1)*(N%2==0?N/2:N/2+1)-1]sums_packed;
generate
genvar i;
//数据解包
wire [dataWidth-1:0]datas_unpacked[1:N];
for(i=1;i<=N;i=i+1)
begin: unpack
assign datas_unpacked[i]=datas_packed[(i-1)*dataWidth:i*dataWidth-1];
end
//两两相加
wire [dataWidth:0]sum_arr[1:(N%2==0?N/2:N/2+1)]; //sum的位数为dataWidth+1
for(i=1;i<=N/2;i=i+1)
begin: sum_layer
assign sum_arr[i]=datas_unpacked[2*i-1]+datas_unpacked[2*i];
end
if(N%2==1)begin
assign sum_arr[N/2+1]=datas_unpacked[N];
end
//打包sum_arr
for(i=1;i<=(N%2==0?N/2:N/2+1);i=i+1)
begin: pack
assign sums_packed[(i-1)*(dataWidth+1):i*(dataWidth+1)-1]=sum_arr[i];
end
endgenerate
endmodule
testbench
/******************************FILE HEAD**********************************
* file_name : ADD_Parallel_tb.v
* function : ADD_Parallel模块的testbench
* author : 今朝无言
* date : 2021/11/23
*************************************************************************/
`default_nettype none
`timescale 1ns/1ps
module ADD_Parallel_tb();
reg [8*9-1:0] datas_packed;
wire [8+4-1:0] sum;
ADD_Parallel #(
.dataWidth (8),
.N (9))
ADD_Parallel_inst(
.datas_packed (datas_packed),
.sum (sum)
);
initial begin
datas_packed <= {8'd1,8'd2,8'd3,8'd4,8'd5,8'd6,8'd7,8'd8,8'd9};//45
#20;
datas_packed <= {8'd12,8'd2,8'd3,8'd4,8'd5,8'd6,8'd7,8'd8,8'd9};//56
#20;
$stop();
end
endmodule
//END OF ADD_Parallel_tb.v FILE***************************************************
仿真 & Netlist
时序仿真结果
Netlist(N=17,Width=16)