OpenCores
URL https://opencores.org/ocsvn/astron_adder/astron_adder/trunk

Subversion Repositories astron_adder

[/] [astron_adder/] [trunk/] [common_adder_tree_a_str.vhd] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 danv
-------------------------------------------------------------------------------
2
--
3
-- Copyright (C) 2009
4
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
5
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
6
--
7
-- This program is free software: you can redistribute it and/or modify
8
-- it under the terms of the GNU General Public License as published by
9
-- the Free Software Foundation, either version 3 of the License, or
10
-- (at your option) any later version.
11
--
12
-- This program is distributed in the hope that it will be useful,
13
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
-- GNU General Public License for more details.
16
--
17
-- You should have received a copy of the GNU General Public License
18
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
--
20
-------------------------------------------------------------------------------
21
 
22
LIBRARY IEEE, common_pkg_lib, common_components_lib;
23
USE IEEE.std_logic_1164.ALL;
24
USE common_pkg_lib.common_pkg.ALL;
25
 
26
ARCHITECTURE str OF common_adder_tree IS
27
 
28
  -- common_add_sub pipelining
29
  CONSTANT c_pipeline_in  : NATURAL := 0;
30
  CONSTANT c_pipeline_out : NATURAL := g_pipeline;
31
 
32
  -- There is no need to internally work with the adder tree sum width for
33
  -- worst case bit growth of c_sum_w = g_dat_w+ceil_log2(g_nof_inputs),
34
  -- because any MSbits that are not in the output sum do not need to be kept
35
  -- at the internal stages either. The worst case bit growth for
36
  -- g_nof_inputs = 1 still becomes ceil_log2(g_nof_inputs) = 1, which can be
37
  -- regarded as due to an adder stage that adds 0 to the single in_dat.
38
  -- However it also does not cause extra logic to internally account for bit
39
  -- growth at every stage, because synthesis will optimize unused MSbits away
40
  -- when g_sum_w < c_sum_w.
41
 
42
  CONSTANT c_w            : NATURAL := g_dat_w;                          -- input data width
43
  CONSTANT c_sum_w        : NATURAL := g_dat_w+ceil_log2(g_nof_inputs);  -- adder tree sum width
44
 
45
  CONSTANT c_N            : NATURAL := g_nof_inputs;            -- nof inputs to the adder tree
46
  CONSTANT c_nof_stages   : NATURAL := ceil_log2(c_N);          -- nof stages in the adder tree
47
 
48
  -- Allocate c_sum_w for each field and allocate c_N fields for the input
49
  -- stage and use this array for all stages. Hence the stage vectors
50
  -- are longer than necessary and wider than necessary, but that is OK, the
51
  -- important thing is that they are sufficiently long.
52
  TYPE t_stage_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_N*c_sum_w-1 DOWNTO 0);
53
 
54
  SIGNAL adds    : t_stage_arr(-1 TO c_nof_stages-1);
55
 
56
BEGIN
57
 
58
  -- The tabel below lists how many two port adders (+) and one port pipes (.)
59
  -- to match the adder latency, there are at each stage of the adder tree.
60
  --
61
  --         nof +,.   nof +,.   nof +,.   nof +,.        nof +,.
62
  --         stage 0   stage 1   stage 2   stage 3   -->  total
63
  -- N =  2    1,0       -         -         -              1
64
  --      3    1,1       1,0       -         -              3
65
  --      4    2,0       1,0       -         -              3
66
  --      5    2,1       1,1       1,0       -              6
67
  --      6    3,0       1,1       1,0       -              6
68
  --      7    3,1       2,0       1,0       -              7
69
  --      8    4,0       2,0       1,0       -              7
70
  --      9    4,1       2,1       1,1       1,0           11  < N + nof stages
71
  --     10    5,0       2,1       1,1       1,0           11
72
  --     11    5,1       3,0       1,1       1,0           12
73
  --     12    6,0       3,0       1,1       1,0           12
74
  --     13    6,1       3,1       2,0       1,0           14
75
  --
76
  --                                                                   input     output   nof
77
  --  stage   nof +                     nof .                         width     width    input
78
  --    -     -                         -                              -         w+0     -
79
  --    0    (N+0)/2                  ((N+0)/1) MOD 2                  w+0       w+1     N
80
  --    1    (N+1)/4                  ((N+1)/2) MOD 2                  w+1       w+2    (N+0)/2  + ((N+0)/1) MOD 2
81
  --    2    (N+3)/8                  ((N+3)/4) MOD 2                  w+2       w+3    (N+3)/8  + ((N+3)/4) MOD 2
82
  --    3    (N+7)/16                 ((N+7)/8) MOD 2                  w+3       w+4    (N+7)/16 + ((N+7)/8) MOD 2
83
  --                                                                               
84
  --    j    (N+(2**j)-1)/(2**(j+1))  ((N+(2**j)-1)/(2**j)) MOD 2      w+j       w+j+1
85
 
86
  -- Keep in_dat in stage -1 of adds. Store each subsequent stage of the adder
87
  -- tree in into adds. Until finally the total sum in the last stage.
88
 
89
  gen_tree : IF g_nof_inputs > 1 GENERATE
90
    -- Input wires
91
    adds(-1)(in_dat'RANGE) <= in_dat;
92
 
93
    -- Adder tree
94
    gen_stage : FOR j IN 0 TO c_nof_stages-1 GENERATE
95
      gen_add : FOR i IN 0 TO (c_N+(2**j)-1)/(2**(j+1)) - 1 GENERATE
96
        u_addj : ENTITY work.common_add_sub
97
        GENERIC MAP (
98
          g_direction       => "ADD",
99
          g_representation  => g_representation,
100
          g_pipeline_input  => c_pipeline_in,
101
          g_pipeline_output => c_pipeline_out,
102
          g_in_dat_w        => c_w+j,
103
          g_out_dat_w       => c_w+j+1
104
        )
105
        PORT MAP (
106
          clk     => clk,
107
          clken   => clken,
108
          in_a    => adds(j-1)((2*i+1)*(c_w+j)-1 DOWNTO (2*i+0)*(c_w+j)),
109
          in_b    => adds(j-1)((2*i+2)*(c_w+j)-1 DOWNTO (2*i+1)*(c_w+j)),
110
          result  => adds(j)((i+1)*(c_w+j+1)-1 DOWNTO i*(c_w+j+1))
111
        );
112
      END GENERATE;
113
 
114
      gen_pipe : IF ((c_N+(2**j)-1)/(2**j)) MOD 2 /= 0 GENERATE
115
        u_pipej : ENTITY common_components_lib.common_pipeline
116
        GENERIC MAP (
117
          g_representation => g_representation,
118
          g_pipeline       => g_pipeline,
119
          g_in_dat_w       => c_w+j,
120
          g_out_dat_w      => c_w+j+1
121
        )
122
        PORT MAP (
123
          clk     => clk,
124
          clken   => clken,
125
          in_dat  => adds(j-1)((2*((c_N+(2**j)-1)/(2**(j+1)))+1)*(c_w+j)-1 DOWNTO
126
                               (2*((c_N+(2**j)-1)/(2**(j+1)))+0)*(c_w+j)),
127
          out_dat => adds(j)(((c_N+(2**j)-1)/(2**(j+1))+1)*(c_w+j+1)-1 DOWNTO
128
                             ((c_N+(2**j)-1)/(2**(j+1))  )*(c_w+j+1))
129
        );
130
      END GENERATE;
131
    END GENERATE;
132
 
133
    -- Map final sum to larger output vector using sign extension or to smaller width output vector preserving the LS part
134
    sum <= RESIZE_SVEC(adds(c_nof_stages-1)(c_sum_w-1 DOWNTO 0), g_sum_w) WHEN g_representation="SIGNED" ELSE
135
           RESIZE_UVEC(adds(c_nof_stages-1)(c_sum_w-1 DOWNTO 0), g_sum_w);
136
  END GENERATE;  -- gen_tree
137
 
138
  no_tree : IF g_nof_inputs = 1 GENERATE
139
    -- For g_nof_inputs = 1 gen_tree yields wires sum <= in_dat, therefore
140
    -- here use common_pipeline to support g_pipeline. Note c_sum_w =
141
    -- g_dat_w+1 also for g_nof_inputs = 1, because we assume an adder stage
142
    -- that adds 0 to the single in_dat.
143
    u_reg : ENTITY common_components_lib.common_pipeline
144
    GENERIC MAP (
145
      g_representation => g_representation,
146
      g_pipeline       => g_pipeline,
147
      g_in_dat_w       => g_dat_w,
148
      g_out_dat_w      => g_sum_w
149
    )
150
    PORT MAP (
151
      clk     => clk,
152
      clken   => clken,
153
      in_dat  => in_dat,
154
      out_dat => sum
155
    );
156
  END GENERATE;  -- no_tree
157
 
158
END str;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.