OpenCores
URL https://opencores.org/ocsvn/all-pole_filters/all-pole_filters/trunk

Subversion Repositories all-pole_filters

[/] [all-pole_filters/] [trunk/] [Circuits/] [lowpass.vhd] - Blame information for rev 13

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 fcorthay
--##############################################################################
2
--
3
--  lowpass
4
--      generic all-pole lowpass filter
5
--
6
--      This circuit simulates an analog ladder filter by replacing the integral
7
--      relations of the LC elements by digital accumulators.
8
--
9
--------------------------------------------------------------------------------
10
--
11
--  Versions / Authors
12
--      1.1 Francois Corthay    added additional w(0) AND w(filterOrder+1)
13
--      1.0 Romain Cheviron     first implementation
14
--
15
--  Provided under GNU LGPL licence: <http://www.gnu.org/copyleft/lesser.html>
16
--
17
--  by the electronics group of "HES-SO//Valais Wallis", in Switzerland:
18
--  <http://isi.hevs.ch/switzerland/robust-electronics.html>.
19
--
20
--------------------------------------------------------------------------------
21
--
22
--  Usage
23
--      Set the input signal bit number with the generic "inputBitNb".
24
--
25
--      Set the output signal bit number with the generic "outputBitNb". This
26
--      value must be greater or equal than "inputBitNb". The additional bits
27
--      are added as LSBs. They allow to increas the resolution as the bandwidth
28
--      is reduced.
29
--
30
--      Define the cutoff frequency with the generic "shiftBitNb". Every
31
--      increment in this value shifts the cutoff frequency down by an octave
32
--      (a factor of 2).
33
--
34
--      In order to define the filter function, the first lines of the
35
--      architecture have to be edited:
36
--          constant "filterOrder" obviously gives the filter order.
37
--          constant "coefficientBitNb" obviously gives the number of bits of
38
--              the coefficients.
39
--          constant "coefficient" give the time constants as unsigned numbers
40
--              ranging from 1 to (2**coefficientBitNb)-1. The relative values
41
--              of the coefficients give the shape of the transfer function.
42
--              The cutoff frequency is furthermore given by the "shiftBitNb"
43
--              generic.
44
--          constant "additionalInternalWBitNb" gives the number of additional
45
--              bits assigned to the internal signals corresponding to the state
46
--              variables of the analog filter. They are used to avoid overflows
47
--              on these signals.
48
--      The values for "shiftBitNb" and "constant additionalInternalWBitNb" can
49
--      be dertermined analytically, but a frequency sweep simulation allows to
50
--      set them iteratively.
51
--
52
--      The input samples are read from the signal "filterIn" at the rising edge
53
--      of "clock" when "en" is '1'.
54
--
55
--      With this, a new output sample is calculated and provided on
56
--      "filterOut". The output changes at the end of the iterative calculation
57
--      of the multiplication, which is roughly n clock periods after "en"
58
--      was '1'. The number of clock periods, n, is equal to the number of bits
59
--      of the coefficients. The output sample remains stable until the next
60
--      sample has been calculated.
61
--
62
--      The "reset" signal is active high.
63
--
64
--------------------------------------------------------------------------------
65
--
66
--  Synthesis results
67
--
68
--      A 3rd order filter with 16 bit input, 16 bit output and 4 bit shift
69
--      gives the following synthesis result on a Xilinx Spartan3-1000:
70
--          Number of Slice Flip Flops:           162 out of  15,360    1%
71
--          Number of 4 input LUTs:               282 out of  15,360    1%
72
--          Average Fanout of Non-Clock Nets:    2.73
73
--
74
--      A 6th order filter with 16 bit input, 16 bit output and 4 bit shift
75
--      gives the following synthesis result on a Xilinx Spartan3-1000:
76
--          Number of Slice Flip Flops:           333 out of  15,360    2%
77
--          Number of 4 input LUTs:               604 out of  15,360    3%
78
--          Average Fanout of Non-Clock Nets:    2.81
79
--
80
--##############################################################################
81
 
82
LIBRARY ieee;
83
  USE ieee.std_logic_1164.all;
84
  USE ieee.numeric_std.all;
85
 
86
ENTITY lowpass IS
87
  GENERIC(
88
    inputBitNb  : positive := 16;
89
    outputBitNb : positive := 16;
90
    shiftBitNb  : positive := 4
91
  );
92
  PORT(
93
    clock     : IN     std_ulogic;
94
    reset     : IN     std_ulogic;
95
    en        : IN     std_ulogic;
96
    filterIn  : IN     signed (inputBitNb-1 DOWNTO 0);
97
    filterOut : OUT    signed (outputBitNb-1 DOWNTO 0)
98
  );
99 13 fcorthay
END lowpass ;
100 9 fcorthay
 
101
--==============================================================================
102
 
103
ARCHITECTURE RTL OF lowpass IS
104
 
105
-- 3rd order Butterworth
106
--
107
--  constant filterOrder : natural := 3;
108
--  constant coefficientBitNb : natural := 8;
109
--  type unsigned_vector_c is array(1 to filterOrder)
110
--    of unsigned(coefficientBitNb-1 downto 0);
111
--  constant coefficient : unsigned_vector_c := (
112
--    to_unsigned(2**7, coefficientBitNb),
113
--    to_unsigned(2**6, coefficientBitNb),
114
--    to_unsigned(2**7, coefficientBitNb)
115
--  );
116
--  constant additionalInternalWBitNb: positive := 2;
117
 
118
-- 6th order Bessel
119
--
120
  constant filterOrder : natural := 6;
121
  constant coefficientBitNb : natural := 8;
122
  type unsigned_vector_c is array(1 to filterOrder)
123
    of unsigned(coefficientBitNb-1 downto 0);
124
  constant coefficient : unsigned_vector_c := (
125
    to_unsigned(215, coefficientBitNb),
126
    to_unsigned( 88, coefficientBitNb),
127
    to_unsigned( 81, coefficientBitNb),
128
    to_unsigned( 61, coefficientBitNb),
129
    to_unsigned( 38, coefficientBitNb),
130
    to_unsigned( 13, coefficientBitNb)
131
  );
132
  constant additionalInternalWBitNb: positive := 4;
133
 
134
  constant internalWBitNb: positive := filterOut'length + additionalInternalWBitNb;
135
  signal inputSignalScaled : signed(internalWBitNb-1 downto 0);
136
 
137
  constant internalAccumulatorBitNb : positive := internalWBitNb + shiftBitNb;
138
  type signed_vector_accumulator is array(1 to filterOrder)
139
    of signed(internalAccumulatorBitNb-1 downto 0);
140
  type signed_vector_w is array(0 to filterOrder+1)
141
    of signed(internalWBitNb-1 downto 0);
142
  signal accumulator : signed_vector_accumulator;
143
  signal w : signed_vector_w;
144
 
145
  type unsigned_vector_coeffShiftReg is array(1 to filterOrder)
146
    of unsigned(coefficientBitNb-1 downto 0);
147
  signal coefficientShiftRegister: unsigned_vector_coeffShiftReg;
148
  signal multiplicandBit: std_ulogic_vector(1 to filterOrder);
149
  type signed_vector_multAcc is array(1 to filterOrder)
150
    of signed(internalAccumulatorBitNb+coefficientBitNb-1 downto 0);
151
  signal multiplicationAccumulator: signed_vector_multAcc;
152
 
153
  signal cycleCounterShiftReg: unsigned(coefficientBitNb downto 0);
154
  signal endOfCycle: std_ulogic;
155
  signal calculating: std_ulogic;
156
 
157
  signal wDebug : signed_vector_w;
158
 
159
BEGIN
160
  ------------------------------------------------------------------------------
161
                          -- Scale input signal to internal state variables size
162
  inputSignalScaled <= SHIFT_LEFT(
163
    RESIZE(filterIn, inputSignalScaled'length),
164
    filterOut'length - filterIn'length
165
  );
166
 
167
  ------------------------------------------------------------------------------
168
                                                            -- Accumulator chain
169
  process(reset, clock)
170
  begin
171
    if reset = '1' then
172
      accumulator <= (others => (others => '0'));
173
    elsif rising_edge(clock) then
174
      if en = '1' then
175
        for index in 1 to filterOrder loop
176
          accumulator(index) <= accumulator(index) + (
177
            RESIZE(w(index-1), w(index)'length+1) -
178
            RESIZE(w(index+1), w(index)'length+1)
179
          );
180
        end loop;
181
      end if;
182
    end if;
183
  end process;
184
 
185
  ------------------------------------------------------------------------------
186
                                                      -- Multiplication sequence
187
 
188
                                                            -- Coefficient shift
189
  process(reset, clock)
190
  begin
191
    if reset = '1' then
192
      coefficientShiftregister <= (others => (others => '0'));
193
    elsif rising_edge(clock) then
194
      for index in 1 to filterOrder loop
195
        if en = '1' then
196
          coefficientShiftregister(index) <= coefficient(index);
197
        else
198
          coefficientShiftregister(index) <=
199
            shift_right(coefficientShiftregister(index), 1);
200
        end if;
201
      end loop;
202
    end if;
203
  end process;
204
 
205
  process(coefficientShiftregister)
206
  begin
207
    for index in 1 to filterOrder loop
208
      multiplicandBit(index) <= coefficientShiftregister(index)(0);
209
    end loop;
210
  end process;
211
 
212
                                                 -- Multiplication accumulator
213
  process(reset, clock)
214
  begin
215
    if reset = '1' then
216
      multiplicationAccumulator <= (others => (others => '0'));
217
    elsif rising_edge(clock) then
218
      for index in 1 to filterOrder loop
219
        if en = '1' then
220
          multiplicationAccumulator(index) <= (others => '0');
221
        elsif calculating = '1' then
222
          if multiplicandBit(index) = '0' then
223
            multiplicationAccumulator(index) <=
224
              shift_right(multiplicationAccumulator(index), 1);
225
          else
226
            multiplicationAccumulator(index) <=
227
              shift_right(multiplicationAccumulator(index), 1) +
228
              shift_left(
229
                resize(accumulator(index), multiplicationAccumulator(index)'length),
230
                coefficientBitNb
231
              );
232
          end if;
233
        end if;
234
      end loop;
235
    end if;
236
  end process;
237
 
238
  ------------------------------------------------------------------------------
239
                                                -- Analog filter state variables
240
  process(multiplicationAccumulator, w, inputSignalScaled)
241
  begin
242
    for index in 1 to filterOrder loop
243
      w(index) <= RESIZE(
244
        SHIFT_RIGHT(
245
          multiplicationAccumulator(index),
246
          coefficientBitNb + shiftBitNb
247
        ),
248
        w(index)'length
249
      );
250
    end loop;
251
                           -- w(0) combines input and w(1) for first accumulator
252
    w(0) <= inputSignalScaled - w(1);
253
            -- w(filterOrder+1) is a copy of w(filterOrder) for last accumulator
254
    w(filterOrder+1) <= w(filterOrder);
255
  end process;
256
 
257
  ------------------------------------------------------------------------------
258
                          -- Scale last state variables to output size and latch
259
  process(reset, clock)
260
  begin
261
    if reset = '1' then
262
      filterOut <= (others => '0');
263
    elsif rising_edge(clock) then
264
      if calculating = '0' then
265
        filterOut <= RESIZE(w(w'high), filterOut'length);
266
      end if;
267
    end if;
268
  end process;
269
 
270
  ------------------------------------------------------------------------------
271
                                                 -- Multiplication cycle counter
272
  process(reset, clock)
273
  begin
274
    if reset = '1' then
275
      cycleCounterShiftReg <= (others => '0');
276
    elsif rising_edge(clock) then
277
      cycleCounterShiftReg <= shift_right(cycleCounterShiftReg, 1);
278
      cycleCounterShiftReg(cycleCounterShiftReg'high) <= en;
279
    end if;
280
  end process;
281
 
282
  endOfCycle <= cycleCounterShiftReg(0);
283
  calculating <= '1' when cycleCounterShiftReg /= 0
284
    else '0';
285
 
286
  ------------------------------------------------------------------------------
287
                                                            -- Debug information
288
  process(reset, clock)
289
  begin
290
    if reset = '1' then
291
      wDebug <= (others => (others => '0'));
292
    elsif rising_edge(clock) then
293
      for index in 1 to filterOrder loop
294
        if calculating = '0' then
295
          wDebug <= w;
296
        end if;
297
      end loop;
298
    end if;
299
  end process;
300
 
301
END ARCHITECTURE RTL;

powered by: WebSVN 2.1.0

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