突然发现百度和Google都搜索不到参数化加法树的写法,这里贴出一个单周期纯组合逻辑版本供参考。VHDL参数化加法树是类似的,这里就不列出了。
这里实现的是倒二叉树类型的加法树,纯组合逻辑,奇偶加数均支持自动生成。大概是下图的结构
参数有三个:
- IN_WIDTH: 每一个输入加数的位宽;
- NUM: 加数个数;
- OUT_WIDTH: 输出结果尾款,注意加法树每一层中间结果均会增加1bit,输出位宽不能太小,否则会发生截断。
输入输出:
- a: 所有加数concat在一起,位宽IN_WIDTH*NUM
- ans: 结果
下面是systemverilog写法,verilog简单地将logic替换成 reg即可。
/*======================================================
Descripton:
parameterized adder tree, full comb
Create:
Yipeng wangyipengv@outlook.com 20191126
Modify:
Notes:
1. contain constant functions
=========================================================*/
module adder_tree#(
parameter IN_WIDTH = 8,
parameter NUM = 4,
parameter OUT_WIDTH = 32
)(
input logic [NUM * IN_WIDTH - 1 : 0] a,
output logic signed [OUT_WIDTH - 1 : 0] ans
);
genvar i, j;
// - gen adders ----------------------------------------------------------
generate
for(i = 1; i <= gen_level(NUM); i++)begin:gen_add_levels
logic signed [1:gen_num_of_a_level(NUM,i)] [IN_WIDTH + i - 1 : 0] sum; // more bit for every level
if(i == 1) begin // - special for first level -------------------
for(j = 1; j <= gen_num_of_a_level(NUM,i) - 1; j++)begin: gen_add_levels
assign sum[j] = a[(NUM- 2*j + 2) * IN_WIDTH - 1 -: IN_WIDTH] + a[(NUM- 2*j + 1) * IN_WIDTH - 1 -: IN_WIDTH];
end
if(gen_odd_sign(NUM,i) == 1)
assign sum[gen_num_of_a_level(NUM,i)] = a[IN_WIDTH - 1 : 0]; //need auto sign extention
else
assign sum[gen_num_of_a_level(NUM,i)] = a[IN_WIDTH - 1 : 0] + a[2*IN_WIDTH - 1 : IN_WIDTH];
end else if (i == gen_level(NUM)) begin // - output for last level ------------------
assign ans = gen_add_levels[i-1].sum[1] + gen_add_levels[i-1].sum[2]; //need auto sign extention
end else begin // - intermediate levels ------------------
for(j = 1; j <= gen_num_of_a_level(NUM,i) - 1; j++)begin: gen_add_levels
assign sum[j] = gen_add_levels[i-1].sum[(NUM- 2*j + 2) * IN_WIDTH - 1 -: IN_WIDTH] + gen_add_levels[i-1].sum[(NUM- 2*j + 1) * IN_WIDTH - 1 -: IN_WIDTH];
end
if(gen_odd_sign(NUM,i) == 1)
assign sum[gen_num_of_a_level(NUM,i)] = gen_add_levels[i-1].sum[IN_WIDTH - 1 : 0]; //need auto sign extention
else
assign sum[gen_num_of_a_level(NUM,i)] = gen_add_levels[i-1].sum[IN_WIDTH - 1 : 0] + gen_add_levels[i-1].sum[2*IN_WIDTH - 1 : IN_WIDTH];
end
end
endgenerate
// - functions ----------------------------------
function integer gen_level;
input integer num;
begin
gen_level = 0;
while (num > 1) begin
num = $clog2(num);
gen_level++;
end
end
endfunction
function integer gen_odd_sign;
input integer num;
input integer i;
begin
while(i > 1) begin
num = $clog2(num);
i--;
end
gen_odd_sign = (num % 2) == 1;
end
endfunction
function integer gen_num_of_a_level;
input integer num;
input integer i;
begin
while(i > 1) begin
num = $clog2(num);
i--;
end
gen_num_of_a_level = $clog2(num);
end
endfunction
endmodule
版权声明:本文为qq_37151459原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。