1 |
5 |
fcorthay |
--##############################################################################
|
2 |
|
|
--
|
3 |
|
|
-- bessel6
|
4 |
|
|
-- 6th order Bessel 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.0 Francois Corthay first implementation
|
13 |
|
|
--
|
14 |
|
|
-- Provided under GNU LGPL licence: <http://www.gnu.org/copyleft/lesser.html>
|
15 |
|
|
--
|
16 |
|
|
-- by the electronics group of "HES-SO//Valais Wallis", in Switzerland:
|
17 |
|
|
-- <http://isi.hevs.ch/switzerland/robust-electronics.html>.
|
18 |
|
|
--
|
19 |
|
|
--------------------------------------------------------------------------------
|
20 |
|
|
--
|
21 |
|
|
-- Usage
|
22 |
|
|
-- Set the input signal bit number with the generic "inputBitNb".
|
23 |
|
|
--
|
24 |
|
|
-- Set the output signal bit number with the generic "outputBitNb". This
|
25 |
|
|
-- value must be greater or equal than "inputBitNb". The additional bits
|
26 |
|
|
-- are added as LSBs. They allow to increas the resolution as the bandwidth
|
27 |
|
|
-- is reduced.
|
28 |
|
|
--
|
29 |
|
|
-- Define the cutoff frequency with the generic "shiftBitNb". Every
|
30 |
|
|
-- increment in this value shifts the cutoff frequency down by an octave
|
31 |
|
|
-- (a factor of 2).
|
32 |
|
|
--
|
33 |
|
|
-- The input samples are read from the signal "filterIn" at the rising edge
|
34 |
|
|
-- of "clock" when "en" is '1'.
|
35 |
|
|
--
|
36 |
|
|
-- With this, a new output sample is calculated and provided on
|
37 |
|
|
-- "filterOut". The output changes at the rising edge of "clock" when "en"
|
38 |
|
|
-- is '1'. It remains stable until the next time a sample is calculated.
|
39 |
|
|
--
|
40 |
|
|
-- The "reset" signal is active high.
|
41 |
|
|
--
|
42 |
|
|
--------------------------------------------------------------------------------
|
43 |
|
|
--
|
44 |
|
|
-- Synthesis results
|
45 |
|
|
-- A circuit with 16 bit input, 16 bit output and 4 bit shift gives the
|
46 |
|
|
-- following synthesis result on a Xilinx Spartan3-1000:
|
47 |
|
|
-- Number of Slice Flip Flops: 145 out of 15,360 1%
|
48 |
|
|
-- Number of 4 input LUTs: 366 out of 15,360 2%
|
49 |
|
|
-- Average Fanout of Non-Clock Nets: 2.23
|
50 |
|
|
--
|
51 |
|
|
--##############################################################################
|
52 |
|
|
|
53 |
|
|
LIBRARY ieee;
|
54 |
|
|
USE ieee.std_logic_1164.all;
|
55 |
|
|
USE ieee.numeric_std.all;
|
56 |
|
|
|
57 |
|
|
ENTITY bessel6 IS
|
58 |
|
|
GENERIC(
|
59 |
|
|
inputBitNb : positive := 16;
|
60 |
|
|
outputBitNb : positive := 16;
|
61 |
|
|
shiftBitNb : positive := 4
|
62 |
|
|
);
|
63 |
|
|
PORT(
|
64 |
|
|
clock : IN std_ulogic;
|
65 |
|
|
reset : IN std_ulogic;
|
66 |
|
|
en : IN std_ulogic;
|
67 |
|
|
filterIn : IN signed (inputBitNb-1 DOWNTO 0);
|
68 |
|
|
filterOut : OUT signed (outputBitNb-1 DOWNTO 0)
|
69 |
|
|
);
|
70 |
|
|
END bessel6;
|
71 |
|
|
|
72 |
|
|
--==============================================================================
|
73 |
|
|
|
74 |
|
|
ARCHITECTURE RTL OF bessel6 IS
|
75 |
|
|
|
76 |
|
|
constant filterOrder : natural := 6;
|
77 |
|
|
type natural_vector_t is array(1 to filterOrder) of natural;
|
78 |
|
|
type integer_vector_s is array(1 to filterOrder) of integer;
|
79 |
|
|
-- coefficients: [1, 1/2, 1/2-1/8, 1/4+1/16, 1/4-1/16, 1/16]
|
80 |
|
|
constant t1 : natural_vector_t := (0, 1, 1, 2, 2, 4);
|
81 |
|
|
constant s2 : integer_vector_s := (0, 0, -1, 1, 1, 0);
|
82 |
|
|
constant t2 : natural_vector_t := (0, 0, 3, 4, 4, 0);
|
83 |
|
|
|
84 |
|
|
constant additionalinternalWBitNb: positive := 4;
|
85 |
|
|
constant internalWBitNb: positive := filterOut'length + additionalinternalWBitNb;
|
86 |
|
|
signal inputSignalScaled : signed(internalWBitNb-1 downto 0);
|
87 |
|
|
|
88 |
|
|
constant internalaccumulatorBitNb : positive := internalWBitNb + shiftBitNb;
|
89 |
|
|
type signed_vector_accumulator is array(1 to filterOrder)
|
90 |
|
|
of signed(internalaccumulatorBitNb-1 downto 0);
|
91 |
|
|
type signed_vector_w is array(0 to filterOrder+1)
|
92 |
|
|
of signed(internalWBitNb-1 downto 0);
|
93 |
|
|
signal accumulator : signed_vector_accumulator;
|
94 |
|
|
signal w : signed_vector_w;
|
95 |
|
|
|
96 |
|
|
BEGIN
|
97 |
|
|
------------------------------------------------------------------------------
|
98 |
|
|
-- Scale input signal to internal state variables size
|
99 |
|
|
inputSignalScaled <= SHIFT_LEFT(
|
100 |
|
|
RESIZE(filterIn, inputSignalScaled'length),
|
101 |
|
|
filterOut'length - filterIn'length
|
102 |
|
|
);
|
103 |
|
|
|
104 |
|
|
------------------------------------------------------------------------------
|
105 |
|
|
-- Accumulator chain
|
106 |
|
|
process(reset, clock)
|
107 |
|
|
begin
|
108 |
|
|
if reset = '1' then
|
109 |
|
|
accumulator <= (others => (others => '0'));
|
110 |
|
|
elsif rising_edge(clock) then
|
111 |
|
|
if en = '1' then
|
112 |
|
|
for index in 1 to filterOrder loop
|
113 |
|
|
accumulator(index) <= accumulator(index) + (
|
114 |
|
|
RESIZE(w(index-1), w(index)'length+1) -
|
115 |
|
|
RESIZE(w(index+1), w(index)'length+1)
|
116 |
|
|
);
|
117 |
|
|
end loop;
|
118 |
|
|
end if;
|
119 |
|
|
end if;
|
120 |
|
|
end process;
|
121 |
|
|
|
122 |
|
|
------------------------------------------------------------------------------
|
123 |
|
|
-- Analog filter state variables
|
124 |
|
|
process(accumulator, w, inputSignalScaled)
|
125 |
|
|
begin
|
126 |
|
|
for index in 1 to filterOrder loop
|
127 |
|
|
-- second shift with positive value
|
128 |
|
|
if s2(index) = 1 then
|
129 |
|
|
w(index) <= RESIZE(
|
130 |
|
|
SHIFT_RIGHT(
|
131 |
|
|
accumulator(index),
|
132 |
|
|
t1(index) + shiftBitNb
|
133 |
|
|
) +
|
134 |
|
|
SHIFT_RIGHT(
|
135 |
|
|
accumulator(index),
|
136 |
|
|
t2(index) + shiftBitNb
|
137 |
|
|
),
|
138 |
|
|
w(index)'length
|
139 |
|
|
);
|
140 |
|
|
-- second shift with negative value
|
141 |
|
|
elsif s2(index) = -1 then
|
142 |
|
|
w(index) <= RESIZE(
|
143 |
|
|
SHIFT_RIGHT(
|
144 |
|
|
accumulator(index),
|
145 |
|
|
t1(index) + shiftBitNb
|
146 |
|
|
) -
|
147 |
|
|
SHIFT_RIGHT(
|
148 |
|
|
accumulator(index),
|
149 |
|
|
t2(index) + shiftBitNb
|
150 |
|
|
),
|
151 |
|
|
w(index)'length
|
152 |
|
|
);
|
153 |
|
|
-- single shift
|
154 |
|
|
else
|
155 |
|
|
w(index) <= RESIZE(
|
156 |
|
|
SHIFT_RIGHT(
|
157 |
|
|
accumulator(index),
|
158 |
|
|
t1(index) + shiftBitNb
|
159 |
|
|
),
|
160 |
|
|
w(index)'length
|
161 |
|
|
);
|
162 |
|
|
end if;
|
163 |
|
|
end loop;
|
164 |
|
|
-- w(0) combines input and w(1) for first accumulator
|
165 |
|
|
w(0) <= inputSignalScaled - w(1);
|
166 |
|
|
-- w(filterOrder+1) is a copy of w(filterOrder) for last accumulator
|
167 |
|
|
w(filterOrder+1) <= w(filterOrder);
|
168 |
|
|
end process;
|
169 |
|
|
|
170 |
|
|
------------------------------------------------------------------------------
|
171 |
|
|
-- Scale last state variables to output size
|
172 |
|
|
filterOut <= RESIZE(w(w'high), filterOut'length);
|
173 |
|
|
|
174 |
|
|
END ARCHITECTURE RTL;
|