URL
https://opencores.org/ocsvn/adder_tree/adder_tree/trunk
Subversion Repositories adder_tree
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/adder_tree/trunk/trunk/adder_tree.sv
0,0 → 1,77
`ifndef _adder_tree_ |
`define _adder_tree_ |
|
// DELAY = $clog2(N) |
(* multstyle = "dsp" *) module adder_tree #(parameter |
N = 32, DATA_WIDTH = 33, RESULT_WIDTH = ((N-1) < 2**$clog2(N)) ? DATA_WIDTH + $clog2(N) : DATA_WIDTH + $clog2(N) + 1 |
)( |
input clock, clock_ena, |
input signed [DATA_WIDTH-1:0] data[N-1:0], |
output signed [RESULT_WIDTH-1:0] result |
); |
generate |
if (N == 2) |
add #(.DATAA_WIDTH(DATA_WIDTH), .DATAB_WIDTH(DATA_WIDTH), .RESULT_WIDTH(RESULT_WIDTH)) |
add_inst(.clock(clock), .clock_ena(clock_ena), .dataa(data[0]), .datab(data[1]), .result(result)); |
else |
begin |
localparam RES_WIDTH = (RESULT_WIDTH > DATA_WIDTH + 1) ? DATA_WIDTH + 1 : RESULT_WIDTH; |
localparam RESULTS = (N % 2 == 0) ? N/2 : N/2 + 1; |
|
wire signed [RES_WIDTH-1:0] res[RESULTS - 1:0]; |
|
add_pairs #(.N(N), .DATA_WIDTH(DATA_WIDTH), .RESULT_WIDTH(RES_WIDTH)) |
add_pairs_inst(.clock(clock), .clock_ena(clock_ena), .data(data), .result(res)); |
|
adder_tree #(.N(RESULTS), .DATA_WIDTH(RES_WIDTH)) |
adder_tree_inst(.clock(clock), .clock_ena(clock_ena), .data(res), .result(result)); |
end |
endgenerate |
|
endmodule :adder_tree |
|
////////////////////// |
module add_pairs #(parameter |
N = 32, DATA_WIDTH = 18, RESULT_WIDTH = DATA_WIDTH + 1, RESULTS = (N % 2 == 0) ? N/2 : N/2 + 1 |
)( |
input clock, clock_ena, |
input signed [DATA_WIDTH-1:0] data[N - 1:0], |
output signed [RESULT_WIDTH-1:0] result[RESULTS - 1:0] |
); |
genvar i; |
|
generate |
for (i = 0; i < N/2; i++) |
begin :a |
add #(.DATAA_WIDTH(DATA_WIDTH), .DATAB_WIDTH(DATA_WIDTH), .RESULT_WIDTH(RESULT_WIDTH)) |
add_inst(.clock, .clock_ena, .dataa(data[2*i]), .datab(data[2*i + 1]), .result(result[i])); |
end |
|
if (RESULTS == N/2 + 1) |
begin |
reg [RESULT_WIDTH-1:0] res; |
|
always @(posedge clock) |
if (clock_ena) |
res <= data[N-1]; |
|
assign result[RESULTS-1] = res; |
end |
endgenerate |
endmodule :add_pairs |
|
////////////////////// |
module add #(parameter |
DATAA_WIDTH = 16, DATAB_WIDTH = 17, RESULT_WIDTH = (DATAA_WIDTH > DATAB_WIDTH) ? DATAA_WIDTH + 1 : DATAB_WIDTH + 1 |
)( |
input clock, clock_ena, |
input signed [DATAA_WIDTH-1:0] dataa, |
input signed [DATAB_WIDTH-1:0] datab, |
output reg signed [RESULT_WIDTH-1:0] result |
); |
always_ff @(posedge clock) |
if (clock_ena) |
result <= dataa + datab; |
endmodule :add |
|
`endif |
/adder_tree/trunk/trunk/adder_tree_tb.sv
0,0 → 1,79
timeunit 1ns; |
timeprecision 1ps; |
|
module adder_tree_tb; |
|
localparam N = 10; |
localparam DATA_WIDTH = 12; |
localparam RESULT_WIDTH = ((N-1) < 2**$clog2(N)) ? DATA_WIDTH + $clog2(N) : DATA_WIDTH + $clog2(N) + 1; |
|
bit clock = 0, clock_ena = 1; |
|
logic signed [DATA_WIDTH-1:0] data[N-1:0]; |
wire signed [DATA_WIDTH-1:0] data_in[N-1:0]; // alias for wave form |
|
wire signed [RESULT_WIDTH-1:0] result; |
bit signed [RESULT_WIDTH-1:0] sum = 0; |
|
always #10ns clock++; |
|
initial begin |
static bit sign = 0, error = 0; |
|
repeat(10) @(posedge clock); |
|
// Test 1 |
for (int i = 0; i < N; i++) |
begin |
data[i] = i + 1; |
if (sign++) data[i] = -data[i]; |
end |
|
sum = 0; |
for (int i = 0; i < N; i++) |
sum += data[i]; |
|
repeat(100) @(posedge clock); |
assert (sum == result) else error |= 1; |
|
// Test 2 |
for (int i = 0; i < N; i++) |
data[i] = data[i]*(i+1); |
|
sum = 0; |
for (int i = 0; i < N; i++) |
sum += data[i]; |
|
repeat(100) @(posedge clock); |
assert (sum == result) else error |= 1; |
|
// Test 3 |
for (int i = 0; i < N; i++) |
data[i] = $signed( {1'b0, {(DATA_WIDTH-1){1'b1}}} ); // max value |
|
sum = 0; |
for (int i = 0; i < N; i++) |
sum += data[i]; |
|
repeat(100) @(posedge clock); |
assert (sum == result) else error |= 1; |
|
if (error) |
$display("ERROR"); |
else |
$display("Test OK!"); |
|
$stop(2); |
end |
|
adder_tree #(.N(N), .DATA_WIDTH(DATA_WIDTH)) dut(.*); |
|
genvar j; |
|
generate for (j = 0; j < N; j++) |
begin :gen |
assign data_in[j] = data[j]; |
end |
endgenerate |
|
endmodule |