forked from BerkeleyLab/Bedrock
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathiirFilterDoc.html
271 lines (265 loc) · 13.4 KB
/
iirFilterDoc.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>iirFilterDoc</title></head><body>
<h2>Introduction</h2>
<p>This module implements an infinite impulse response filter as a cascaded series of biquad sections. Each section implements the transfer function shown below.<br>
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>Y</mi><mo stretchy="false">(</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mfrac><mrow><msub><mi>b</mi><mn>0</mn></msub><mo>+</mo><msub><mi>b</mi><mn>1</mn></msub><msup><mi>z</mi><mrow><mo>-</mo><mn>1</mn></mrow></msup><mo>+</mo><msub><mi>b</mi><mn>2</mn></msub><msup><mi>z</mi><mrow><mo>-</mo><mn>2</mn></mrow></msup></mrow><mrow><mn>1</mn><mo>+</mo><msub><mi>a</mi><mn>1</mn></msub><msup><mi>z</mi><mrow><mo>-</mo><mn>1</mn></mrow></msup><mo>+</mo><msub><mi>a</mi><mn>2</mn></msub><msup><mi>z</mi><mrow><mo>-</mo><mn>2</mn></mrow></msup></mrow></mfrac><mi>U</mi><mo stretchy="false">(</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="TeX">Y(z)=\frac{b_0 + b_1 z^{-1} + b_2 z^{-2}}{1 + a_1 z^{-1} + a_2 z^{-2}} U(z)</annotation></semantics></math>Filter
latency is five clocks per biquad section and biquad cycle time is six
clocks. Biquad sections are pipelined so a new value can be
written to the filter as often as every sixth clock. DSP blocks
are inferred. Resource consumption is minimized by using
internal DSP block registers for between-sample storage.<br>
</p>
<h2>Clocks</h2>
<p>There are two clock domains.<br>
</p>
<ul>
<li>sysClk<br>
Used for programming filter coefficients.</li>
<li>dataClk<br>
Filter input and output data streams.</li>
</ul>
<h2>Parameters<br>
</h2>
<table style=" text-align: left; width: 80%;" cellspacing="2" cellpadding="2" border="1">
<tbody>
<tr>
<td style="text-align: center;"><span style="font-weight: bold;">Name</span><br>
</td>
<td style="text-align: center;"><span style="font-weight: bold;">Description</span><br>
</td>
</tr>
<tr>
<td style="text-align: center;">COEFFICIENT_WIDTH<br>
</td>
<td style="text-align: left;">Width of coefficients. Maximum value is 54.<br>
</td>
</tr>
<tr>
<td style="text-align: center;">DATA_COUNT<br>
</td>
<td style="vertical-align: top;">Number of data channels.<br>
</td>
</tr>
<tr>
<td style="text-align: center;">DATA_WIDTH<br>
</td>
<td style="text-align: left;">Width of each data channel. Data are signed, two's complement values.<br>
</td>
</tr>
<tr>
<td style="text-align: center;">STAGES</td>
<td style="text-align: left;">Number of biquad stages. Filter order is 2×STAGES.</td>
</tr>
</tbody>
</table>
<h2>Ports</h2>
<table style=" text-align: left; width: 80%;" cellspacing="2" cellpadding="2" border="1">
<tbody>
<tr>
<td style="text-align: center;"><span style="font-weight: bold;">Port</span><br>
</td>
<td style="text-align: center;"><span style="font-weight: bold;">Width</span><br>
</td>
<td style="text-align: center;"><span style="font-weight: bold;">Direct</span><span style="font-weight: bold;">ion</span><br>
</td>
<td style="text-align: center;"><span style="font-weight: bold;">Clock</span><br>
</td>
<td style="text-align: center;"><span style="font-weight: bold;">Description</span><br>
</td>
</tr>
<tr>
<td style="text-align: center;">sysGPIO_Strobe</td>
<td style="text-align: center;">1<br>
</td>
<td style="text-align: center;">In<br>
</td>
<td style="text-align: center;">sysClk<br>
</td>
<td style="text-align: left;">Asserted to write sysGPIO_Out value into filter.</td>
</tr>
<tr>
<td style="text-align: center;">sysGPIO_Out</td>
<td style="text-align: center;">1<br>
</td>
<td style="text-align: center;">In<br>
</td>
<td style="text-align: center;">sysClk<br>
</td>
<td style="text-align: left;">Value written to filter when sysGPIO_Strobe is asserted.</td>
</tr>
<tr>
<td style="text-align: center;">S_TDATA<br>
</td>
<td style="text-align: center;">DATA_COUNT×DATA_WIDTH<br>
</td>
<td style="text-align: center;">In<br>
</td>
<td style="vertical-align: top;">dataClk</td>
<td style="text-align: left;">Filter input data.<br>
</td>
</tr>
<tr>
<td style="text-align: center;">S_TVALID<br>
</td>
<td style="text-align: center;">1<br>
</td>
<td style="text-align: center;">In<br>
</td>
<td style="text-align: center;">dataClk</td>
<td style="text-align: left;">Asserted when S_TDATA is valid. A
filter computation cycle is initiated when S_TDATA and S_TREADY are
asserted simultaneously.<br>
</td>
</tr>
<tr>
<td style="text-align: center;">S_TREADY<br>
</td>
<td style="text-align: center;">1<br>
</td>
<td style="text-align: center;">Out<br>
</td>
<td style="text-align: center;">dataClk</td>
<td style="text-align: left;">Asserted when filter is ready to accept data. <br>
</td>
</tr>
<tr>
<td style="text-align: center;">M_TDATA</td>
<td style="text-align: center;">DATA_COUNT×DATA_WIDTH</td>
<td style="text-align: center;">Out<br>
</td>
<td style="text-align: center;">dataClk</td>
<td style="text-align: left;">Filter output data.<br>
</td>
</tr>
<tr>
<td style="text-align: center;">M_TVALID</td>
<td style="text-align: center;">1<br>
</td>
<td style="text-align: center;">Out<br>
</td>
<td style="text-align: center;">dataClk</td>
<td style="text-align: left;">Asserted when M_TDATA is valid. <br>
</td>
</tr>
<tr>
<td style="text-align: center;">M_TREADY<br>
</td>
<td style="text-align: center;">1<br>
</td>
<td style="text-align: center;">In<br>
</td>
<td style="text-align: center;">dataClk</td>
<td style="text-align: left;">Back pressure from downstream data receiver.
Asserted when downstream receiver is ready to accept data. A filter
computation cycle ends when M_TDATA and M_TREADY are asserted
simultaneously.</td>
</tr>
</tbody>
</table>
<br>
AXI stream notation is used for the data port names although in the strictest sense the input
and output are true AXI streams only if the width of the TDATA lines is a
multiple of eight bits. In all other respects the semantics of the data ports are those
of AXI streams.<br>
All outputs are registered.<br>
<h2>Coefficient Programming</h2>
<p>Coefficient values are two's complement fixed-point values scaled to the range [-2:2). There are two bits to the left of the binary point and COEFFICIENT_WIDTH-2 bits to the right.<br>
</p>
<p>When the most significant bit [31] of sysGPIO_Out is 0 the remaining bits are handled as follows:<br>
</p>
<ul>
<li>The least significant three bits [2:0] are latched and select the address of the biquad coefficient to be written:<br>
<table style="text-align: left; width: 300px; margin-left: 40px;" cellspacing="2" cellpadding="2" border="1">
<tbody>
<tr>
<td style="text-align: center;"><span style="font-weight: bold;">Address</span><br>
</td>
<td style="vertical-align: middle; text-align: center;"><span style="font-weight: bold;">Description</span><br>
</td>
</tr>
<tr>
<td style="text-align: center;">0<br>
</td>
<td style="text-align: center;"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msub><mi>b</mi><mn>0</mn></msub><annotation encoding="TeX">b_0</annotation></semantics></math><br>
</td>
</tr>
<tr>
<td style="text-align: center;">1<br>
</td>
<td style="text-align: center;"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msub><mi>b</mi><mn>1</mn></msub><annotation encoding="TeX">b_1</annotation></semantics></math><br>
</td>
</tr>
<tr>
<td style="text-align: center;">2<br>
</td>
<td style="text-align: center;"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msub><mi>b</mi><mn>2</mn></msub><annotation encoding="TeX">b_2</annotation></semantics></math><br>
</td>
</tr>
<tr>
<td style="text-align: center;">3<br>
</td>
<td style="text-align: center;"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>-</mo><msub><mi>a</mi><mn>2</mn></msub></mrow><annotation encoding="TeX">-a_2</annotation></semantics></math><br>
</td>
</tr>
<tr>
<td style="text-align: center;">4<br>
</td>
<td style="text-align: center;"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>-</mo><msub><mi>a</mi><mn>1</mn></msub></mrow><annotation encoding="TeX">-a_1</annotation></semantics></math><br>
</td>
</tr>
<tr>
<td style="text-align: center;">7<br>
</td>
<td style="text-align: center;">Enable<br>
</td>
</tr>
</tbody>
</table>
Note the order in which the polynomial denominator coefficient values are written and that the values are negated.<br>
Writing any coefficient clears the filter and disables filter operation
until address 7 is written (the actual value written is not
important). This ensures that a consistent set of coefficients is
used for all filter updates.</li>
<li>The next bits [<span style="font-style: italic;">x</span>:3] are latched and select the biquad stage to which a coefficient value will be written.</li>
<li>If coefficient values are wider than 31 bits then bits [<span style="font-style: italic;">y</span>:8] are latched and will be written as the most significant bits of the coefficient value.</li>
</ul>
When the most significant bit [31] of sysGPIO_Out is 1 the least
significant COEFFICIENT_WIDTH bits are the value (or least
significant 31 bits of the value if COEFFICIENT_WIDTH is greater than
31) written to the coefficient at the current biquad stage and address. <br>
<h2>Resource Usage</h2>
<p>A multiplier-accumulator block is allocated for each channel of each
biquad stage. The number of DSP blocks this represents depends on
the coefficient and data widths. For example, a Xilinx 7 Series
device multiplier-accumulator will be implemented with a single DSP
block if the coefficient or data width is 25 bits or fewer and the other
width is 18 bits or fewer. If one of the coefficient or data
widths exceeds these values then each multiplier-accumulator will
consume two DSP blocks. If both the coefficient and data widths
exceed these values then each multiplier-accumulator block will consume
four DSP blocks.<br>
</p>
<h2>Matlab/Octave Example</h2>
<ol>
<li>Create the filter:<br>
<span style="font-family: Courier New,Courier,monospace;">order = 4;<br>
Fs = 100000;</span><span style="font-family: Courier New,Courier,monospace;"><br>
</span><span style="font-family: Courier New,Courier,monospace;">Fc = 10000;</span><span style="font-family: Courier New,Courier,monospace;"><br>
</span><span style="font-family: Courier New,Courier,monospace;">[b,a] = ellip(order,1,40,2*Fc/Fs);</span></li>
<li>Convert the filter to second-order-sytstem representation:<br>
<span style="font-family: Courier New,Courier,monospace;">[sos,g] = tf2sos(b,a);</span></li>
<li>Distribute the gain term so that each biquad stage has unity DC gain:<br>
<span style="font-family: Courier New,Courier,monospace;">[rows,cols] = size(sos);</span><span style="font-family: Courier New,Courier,monospace;"><br>
</span><span style="font-family: Courier New,Courier,monospace;">for i=1:rows</span><span style="font-family: Courier New,Courier,monospace;"><br>
</span><span style="font-family: Courier New,Courier,monospace;"> scale = sum(sos(i,4:6)) / sum(sos(i,1:3));</span><span style="font-family: Courier New,Courier,monospace;"><br>
</span><span style="font-family: Courier New,Courier,monospace;"> sosg(i,:) = [sos(i,1:3) * scale sos(i,4:6)];</span><span style="font-family: Courier New,Courier,monospace;"><br>
</span><span style="font-family: Courier New,Courier,monospace;">end</span></li>
<li>Display the biquad coefficients (<span style="font-style: italic;">b</span><sub>0</sub>, <span style="font-style: italic;">b</span><sub>1</sub>, <span style="font-style: italic;">b</span><sub>2</sub>, 1, <span style="font-style: italic;">a</span><sub>1</sub>, <span style="font-style: italic;">a</span><sub>2</sub>)<br>
<span style="font-family: Courier New,Courier,monospace;">sosg</span><span style="font-family: Courier New,Courier,monospace;"><br>
</span><span style="font-family: Courier New,Courier,monospace;">sosg =</span><span style="font-family: Courier New,Courier,monospace;"><br>
</span><span style="font-family: Courier New,Courier,monospace;"> 0.0527897140085842 0.0142486149708004 0.0527897140085842 1 -1.50880783628479 0.62863587927276</span><span style="font-family: Courier New,Courier,monospace;"><br>
</span><span style="font-family: Courier New,Courier,monospace;"> 0.418168484605259 -0.477106851841725 0.41816848460526 1 -1.52420170321401 0.883431820582802</span><br>
</li>
</ol>
</body></html>