1 |
10 |
arroxo2 |
|
2 |
|
|
-- CREATION DATE .......: 02 Jul 2007 (Filtro_FIR.vhd)
|
3 |
|
|
-- AUTHOR ..............: DIEGO PARDO (arroxo2@yahoo.es)
|
4 |
|
|
-- REVISION ............: 2.0
|
5 |
|
|
-- LAST UPDATE .........: 08 April 2015
|
6 |
|
|
-- UPDATED BY ..........: DIEGO PARDO
|
7 |
|
|
|
8 |
|
|
-- TITLE "CONFIGURABLE FIR FILTER";
|
9 |
|
|
--
|
10 |
|
|
-- Generic VHDL (suitable for ALTERA, XILINX, MICROSEMI, etc)
|
11 |
|
|
-- Low resources occupation (fixed-point implementation)
|
12 |
|
|
--
|
13 |
|
|
|
14 |
|
|
|
15 |
|
|
--=============================================================================
|
16 |
|
|
--============================= LOCAL PACKAGE =================================
|
17 |
|
|
--=============================================================================
|
18 |
|
|
|
19 |
|
|
LIBRARY ieee;
|
20 |
|
|
USE ieee.std_logic_1164.all;
|
21 |
|
|
USE ieee.std_logic_arith.all;
|
22 |
|
|
USE ieee.std_logic_signed.all;
|
23 |
|
|
USE ieee.math_real.all;
|
24 |
|
|
|
25 |
|
|
|
26 |
|
|
PACKAGE fir_package IS
|
27 |
|
|
|
28 |
|
|
CONSTANT max_coef: NATURAL:= 128; -- (increase if needed)
|
29 |
|
|
TYPE COEFF_ARRAY IS ARRAY (0 to max_coef-1) OF REAL;
|
30 |
|
|
FUNCTION decimal_to_signed (c_real: IN REAL; CONSTANT precision: IN NATURAL) RETURN SIGNED;
|
31 |
|
|
|
32 |
|
|
END fir_package;
|
33 |
|
|
|
34 |
|
|
|
35 |
|
|
PACKAGE body fir_package IS
|
36 |
|
|
|
37 |
|
|
FUNCTION decimal_to_signed (c_real: IN REAL; CONSTANT precision: IN NATURAL) RETURN SIGNED IS
|
38 |
|
|
-- SIGNED = REAL / 2^(-precision) = REAL * 2^precision, with IEEE rounding
|
39 |
|
|
CONSTANT RESOLUCION : REAL := "**"(2,REAL(INTEGER(precision)));
|
40 |
|
|
BEGIN
|
41 |
|
|
RETURN (SIGNED(CONV_STD_LOGIC_VECTOR(INTEGER(ROUND ("*"(c_real,RESOLUCION))),precision+1)));
|
42 |
|
|
END FUNCTION;
|
43 |
|
|
|
44 |
|
|
END fir_package;
|
45 |
|
|
|
46 |
|
|
|
47 |
|
|
|
48 |
|
|
--=============================================================================
|
49 |
|
|
--================================== ENTITY ===================================
|
50 |
|
|
--=============================================================================
|
51 |
|
|
|
52 |
|
|
LIBRARY work;
|
53 |
|
|
USE WORK.fir_package.all;
|
54 |
|
|
|
55 |
|
|
LIBRARY ieee;
|
56 |
|
|
USE ieee.std_logic_1164.all;
|
57 |
|
|
USE ieee.std_logic_arith.all;
|
58 |
|
|
USE ieee.std_logic_signed.all;
|
59 |
|
|
USE ieee.math_real.all;
|
60 |
|
|
|
61 |
|
|
--.............................................................................
|
62 |
|
|
-- GAIN 1.0
|
63 |
|
|
-- SATURATION CONTROL Yes (output)
|
64 |
|
|
-- OUTPUT ROUNDING Yes (IEEE)
|
65 |
|
|
-- IMPLEMENTED BY Fixed-Point (configurable resolution)
|
66 |
|
|
-- 3rd-PARTY IPs No (generic VHDL)
|
67 |
|
|
--.............................................................................
|
68 |
|
|
|
69 |
|
|
ENTITY FIR_low_area IS
|
70 |
|
|
GENERIC(
|
71 |
|
|
data_length : NATURAL := 8; -- input/output length (number of bits)
|
72 |
|
|
data_signed : BOOLEAN := false; -- input/output type (signed or unsigned)
|
73 |
|
|
improv_t : BOOLEAN := false; -- minimal timing improvement by adding one extra output cycle delay (use only if needed)
|
74 |
|
|
bits_resol : NATURAL := 16; -- number of bits for the internal operations with decimals in fixed point. Recommended: bits_resol > taps. THIS SETTING IS CRITICAL FOR P&R RESULTS (MAX FREQ)
|
75 |
|
|
taps : NATURAL := 5; -- =order+1, 2 coefficients as minimum (order=1)
|
76 |
|
|
coefficients : COEFF_ARRAY :=( -- normalized coefficients bi: (bo,b1, ..., bN). They must be symmetric (but sign)
|
77 |
|
|
-0.11735685282030676,
|
78 |
|
|
0.23471370564061372,
|
79 |
|
|
0.7066280917835991,
|
80 |
|
|
0.23471370564061372,
|
81 |
|
|
-0.11735685282030676,
|
82 |
|
|
OTHERS=>0.0) -- (always end with "others=>0.0")
|
83 |
|
|
);
|
84 |
|
|
PORT(
|
85 |
|
|
areset : IN STD_LOGIC; -- active high
|
86 |
|
|
sreset : IN STD_LOGIC; -- active high
|
87 |
|
|
clock_fs : IN STD_LOGIC;
|
88 |
|
|
enable : IN STD_LOGIC;
|
89 |
|
|
xn : IN STD_LOGIC_VECTOR(data_length-1 DOWNTO 0); -- FILTER INPUT (any fixed-point format, e.g. whole numbers)
|
90 |
|
|
yn : OUT STD_LOGIC_VECTOR(data_length-1 DOWNTO 0) -- FILTER OUTPUT (keeps same fixed-point format of input)
|
91 |
|
|
);
|
92 |
|
|
END FIR_low_area;
|
93 |
|
|
|
94 |
|
|
|
95 |
|
|
|
96 |
|
|
ARCHITECTURE FIR_low_area_arch OF FIR_low_area IS
|
97 |
|
|
|
98 |
|
|
type ENTRADA_xn IS ARRAY (taps-2 DOWNTO 0) OF SIGNED(data_length DOWNTO 0); -- A(data_length,0) : x[n-k]
|
99 |
|
|
type VALORES_h IS ARRAY (taps-1 DOWNTO 0) OF SIGNED(bits_resol DOWNTO 0); -- A(0,bits_resol) : h[n-k]
|
100 |
|
|
|
101 |
|
|
SIGNAL REGISTRO_xn : ENTRADA_xn;
|
102 |
|
|
|
103 |
|
|
SIGNAL yn_1, yn_2 : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0);
|
104 |
|
|
SIGNAL yn_aux : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0); -- yn_1 + yn_2
|
105 |
|
|
SIGNAL yn_comb : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0);
|
106 |
|
|
SIGNAL yn_sync : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0);
|
107 |
|
|
|
108 |
|
|
SIGNAL yn_unsigned : STD_LOGIC_VECTOR(data_length-1 DOWNTO 0);
|
109 |
|
|
SIGNAL yn_signed : STD_LOGIC_VECTOR(data_length-1 DOWNTO 0);
|
110 |
|
|
|
111 |
|
|
CONSTANT SIGNED_MAX : INTEGER := 2**(yn'length-1)-1;
|
112 |
|
|
CONSTANT SIGNED_MIN : INTEGER := -1 * 2**(yn'length-1);
|
113 |
|
|
|
114 |
|
|
|
115 |
|
|
BEGIN
|
116 |
|
|
|
117 |
|
|
|
118 |
|
|
ASSERT (bits_resol >= 4)
|
119 |
|
|
REPORT "PLEASE INCREASE RESOLUTION BITS (result will be poor)" SEVERITY FAILURE;
|
120 |
|
|
|
121 |
|
|
-- pragma translate_off
|
122 |
|
|
process
|
123 |
|
|
VARIABLE sum_coeff : real;
|
124 |
|
|
begin
|
125 |
|
|
sum_coeff := 0.0;
|
126 |
|
|
FOR ind IN 0 TO (taps-1) LOOP
|
127 |
|
|
sum_coeff := sum_coeff + coefficients(ind);
|
128 |
|
|
END LOOP;
|
129 |
|
|
ASSERT sum_coeff = 1.0
|
130 |
|
|
REPORT "COEFFICIENTS ARE NOT NORMALIZED" SEVERITY WARNING;
|
131 |
|
|
wait;
|
132 |
|
|
end process;
|
133 |
|
|
-- pragma translate_on
|
134 |
|
|
|
135 |
|
|
|
136 |
|
|
-- =======================================================================================
|
137 |
|
|
-- HALF FILTERING OPERATIONS (1/2)
|
138 |
|
|
-- (DOES NOT INCLUDE INITIAL AND FINAL COEFFICIENTS, INCLUDES CENTRE COEFFICIENT (WHEN "taps" EVEN)
|
139 |
|
|
-- =======================================================================================
|
140 |
|
|
|
141 |
|
|
process1:
|
142 |
|
|
PROCESS (clock_fs, areset)
|
143 |
|
|
VARIABLE xn_a_pares : SIGNED (data_length+1 DOWNTO 0); -- to sum x[n-k] with symmetric coefficients
|
144 |
|
|
VARIABLE REGISTRO_h : VALORES_h := (OTHERS => (OTHERS => '0')); -- it stores the coefficients (avoids registers)
|
145 |
|
|
VARIABLE producto : SIGNED (data_length+1+bits_resol+1 DOWNTO 0); -- product of xn_a_pares by symmetric coefficient
|
146 |
|
|
VARIABLE yn_aux : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0); -- partial sum
|
147 |
|
|
VARIABLE signos_bi : STD_LOGIC_VECTOR (1 DOWNTO 0); -- signs of the symmetric coefficients
|
148 |
|
|
VARIABLE indice1 : NATURAL;
|
149 |
|
|
VARIABLE margen : NATURAL;
|
150 |
|
|
|
151 |
|
|
BEGIN
|
152 |
|
|
IF (areset = '1') THEN
|
153 |
|
|
yn_1 <= (OTHERS => '0');
|
154 |
|
|
|
155 |
|
|
ELSIF rising_edge(clock_fs) THEN
|
156 |
|
|
IF (sreset = '1') THEN
|
157 |
|
|
yn_1 <= (OTHERS => '0');
|
158 |
|
|
ELSE
|
159 |
|
|
|
160 |
|
|
IF (enable = '1') THEN
|
161 |
|
|
|
162 |
|
|
-- variable avoids h[n] register, REGISTRO_h(0) = bN
|
163 |
|
|
FOR ind IN 0 TO (taps-1) LOOP
|
164 |
|
|
REGISTRO_h(ind) := decimal_to_signed (coefficients(taps-1-ind),bits_resol);
|
165 |
|
|
END LOOP;
|
166 |
|
|
|
167 |
|
|
yn_aux := (OTHERS => '0');
|
168 |
|
|
|
169 |
|
|
-- symmetric coefficients (but first and last ones):
|
170 |
|
|
-- In this cycle x[n-k] has not been applied yet to the shift register of x[n]
|
171 |
|
|
IF (taps > 3) THEN
|
172 |
|
|
|
173 |
|
|
indice1 := (taps/2)+(taps MOD 2);
|
174 |
|
|
margen := ((taps-1)-(taps/2))/2 - (taps MOD 2);
|
175 |
|
|
|
176 |
|
|
FOR i IN indice1 TO (indice1 + margen) LOOP
|
177 |
|
|
|
178 |
|
|
-- symmetric bi signs
|
179 |
|
|
signos_bi(1):= REGISTRO_h(i)(bits_resol);
|
180 |
|
|
signos_bi(0):= REGISTRO_h(taps-1-i)(bits_resol);
|
181 |
|
|
|
182 |
|
|
CASE signos_bi IS
|
183 |
|
|
WHEN "00" => xn_a_pares:= "+"( CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2), CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));
|
184 |
|
|
WHEN "01" => xn_a_pares:= "+"( CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));
|
185 |
|
|
WHEN "10" => xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2), CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));
|
186 |
|
|
WHEN OTHERS => xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));
|
187 |
|
|
END CASE;
|
188 |
|
|
|
189 |
|
|
producto := "*"(xn_a_pares, ABS(REGISTRO_h(i)));
|
190 |
|
|
yn_aux := "+"(yn_aux, producto);
|
191 |
|
|
END LOOP;
|
192 |
|
|
END IF;
|
193 |
|
|
|
194 |
|
|
---------------------------------------------------------------
|
195 |
|
|
-- central coefficient operation (when taps is even)
|
196 |
|
|
---------------------------------------------------------------
|
197 |
|
|
-- non-symmetric coefficient
|
198 |
|
|
|
199 |
|
|
IF (taps MOD 2)/=0 THEN
|
200 |
|
|
producto := "*"(CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps/2))),data_length+2), REGISTRO_h(taps/2));
|
201 |
|
|
yn_aux := "+"(yn_aux, producto);
|
202 |
|
|
END IF;
|
203 |
|
|
|
204 |
|
|
---------------------------------------------------------------
|
205 |
|
|
-- output of processo1
|
206 |
|
|
---------------------------------------------------------------
|
207 |
|
|
-- yn_1 has decimal part (bits_resol bits)
|
208 |
|
|
|
209 |
|
|
yn_1 <= yn_aux;
|
210 |
|
|
|
211 |
|
|
END IF;
|
212 |
|
|
END IF;
|
213 |
|
|
END IF;
|
214 |
|
|
END PROCESS process1;
|
215 |
|
|
|
216 |
|
|
|
217 |
|
|
-- =======================================================================================
|
218 |
|
|
-- HALF FILTERING OPERATIONS (2/2)
|
219 |
|
|
-- (INCLUDINF INITIAL AND FINAL COEFFICIENTS)
|
220 |
|
|
-- =======================================================================================
|
221 |
|
|
|
222 |
|
|
process2:
|
223 |
|
|
PROCESS (clock_fs, areset)
|
224 |
|
|
VARIABLE xn_a_pares : SIGNED (data_length+1 DOWNTO 0); -- to sum x[n-k] with symmetric coefficients
|
225 |
|
|
VARIABLE REGISTRO_h : VALORES_h := (OTHERS => (OTHERS => '0')); -- it stores the coefficients (avoids registers)
|
226 |
|
|
VARIABLE producto : SIGNED (data_length+1+bits_resol+1 DOWNTO 0); -- product of xn_a_pares by symmetric coefficient
|
227 |
|
|
VARIABLE yn_aux : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0); -- partial sum
|
228 |
|
|
VARIABLE signos_bi : STD_LOGIC_VECTOR (1 DOWNTO 0); -- signs of the symmetric coefficients
|
229 |
|
|
VARIABLE indice1 : NATURAL;
|
230 |
|
|
VARIABLE margen : NATURAL;
|
231 |
|
|
|
232 |
|
|
BEGIN
|
233 |
|
|
IF (areset = '1') THEN
|
234 |
|
|
yn_2 <= (OTHERS => '0');
|
235 |
|
|
|
236 |
|
|
ELSIF rising_edge(clock_fs) THEN
|
237 |
|
|
IF (sreset = '1') THEN
|
238 |
|
|
yn_2 <= (OTHERS => '0');
|
239 |
|
|
ELSE
|
240 |
|
|
|
241 |
|
|
IF (enable = '1') THEN
|
242 |
|
|
|
243 |
|
|
-- variable avoids h[n] register, REGISTRO_h(0) = bN
|
244 |
|
|
FOR ind IN 0 TO (taps-1) LOOP
|
245 |
|
|
REGISTRO_h(ind) := decimal_to_signed (coefficients(taps-1-ind),bits_resol);
|
246 |
|
|
END LOOP;
|
247 |
|
|
|
248 |
|
|
|
249 |
|
|
yn_aux := (OTHERS => '0');
|
250 |
|
|
|
251 |
|
|
-- symmetric coefficients (but first and last ones). When taps < 7 the operations are resolved by process1:
|
252 |
|
|
-- In this cycle x[n-k] has not been applied yet to the shift register of x[n]
|
253 |
|
|
IF (taps > 6) THEN
|
254 |
|
|
|
255 |
|
|
indice1 := (taps/2)+(taps MOD 2);
|
256 |
|
|
margen := ((taps-1)-(taps/2))/2 - (taps MOD 2);
|
257 |
|
|
|
258 |
|
|
FOR i IN (indice1 + margen + 1) TO (taps-2) LOOP
|
259 |
|
|
|
260 |
|
|
-- symmetric bi signs
|
261 |
|
|
signos_bi(1):= REGISTRO_h(i)(bits_resol);
|
262 |
|
|
signos_bi(0):= REGISTRO_h(taps-1-i)(bits_resol);
|
263 |
|
|
|
264 |
|
|
CASE signos_bi IS
|
265 |
|
|
WHEN "00" => xn_a_pares:= "+"( CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2), CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));
|
266 |
|
|
WHEN "01" => xn_a_pares:= "+"( CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));
|
267 |
|
|
WHEN "10" => xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2), CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));
|
268 |
|
|
WHEN OTHERS => xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));
|
269 |
|
|
END CASE;
|
270 |
|
|
|
271 |
|
|
producto:= "*"(xn_a_pares, ABS(REGISTRO_h(i)));
|
272 |
|
|
yn_aux := "+"(yn_aux, producto);
|
273 |
|
|
END LOOP;
|
274 |
|
|
END IF;
|
275 |
|
|
|
276 |
|
|
----------------------------------------------------------------
|
277 |
|
|
-- first and last coefficients operation (symmetric)
|
278 |
|
|
----------------------------------------------------------------
|
279 |
|
|
-- The initial coefficient multiplies x[n] (not registered yet)
|
280 |
|
|
|
281 |
|
|
signos_bi(1):= REGISTRO_h(taps-1)(bits_resol);
|
282 |
|
|
signos_bi(0):= REGISTRO_h(0)(bits_resol);
|
283 |
|
|
|
284 |
|
|
CASE signos_bi IS
|
285 |
|
|
|
286 |
|
|
WHEN "00" => if (data_signed = true) then
|
287 |
|
|
xn_a_pares:= "+"( CONV_SIGNED(conv_integer( signed(xn)),data_length+2), CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
|
288 |
|
|
else
|
289 |
|
|
xn_a_pares:= "+"( CONV_SIGNED(conv_integer(unsigned(xn)),data_length+2), CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
|
290 |
|
|
end if;
|
291 |
|
|
WHEN "01" => if (data_signed = true) then
|
292 |
|
|
xn_a_pares:= "+"( CONV_SIGNED(conv_integer( signed(xn)),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
|
293 |
|
|
else
|
294 |
|
|
xn_a_pares:= "+"( CONV_SIGNED(conv_integer(unsigned(xn)),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
|
295 |
|
|
end if;
|
296 |
|
|
WHEN "10" => if (data_signed = true) then
|
297 |
|
|
xn_a_pares:= "+"(-CONV_SIGNED(conv_integer( signed(xn)),data_length+2), CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
|
298 |
|
|
else
|
299 |
|
|
xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(unsigned(xn)),data_length+2), CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
|
300 |
|
|
end if;
|
301 |
|
|
WHEN OTHERS => if (data_signed = true) then
|
302 |
|
|
xn_a_pares:= "+"(-CONV_SIGNED(conv_integer( signed(xn)),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
|
303 |
|
|
else
|
304 |
|
|
xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(unsigned(xn)),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
|
305 |
|
|
end if;
|
306 |
|
|
END CASE;
|
307 |
|
|
|
308 |
|
|
producto := "*"(xn_a_pares, ABS(REGISTRO_h(taps-1)));
|
309 |
|
|
yn_aux := "+"(yn_aux, producto);
|
310 |
|
|
|
311 |
|
|
---------------------------------------------------------------
|
312 |
|
|
-- output of processo2
|
313 |
|
|
---------------------------------------------------------------
|
314 |
|
|
-- yn_2 has decimal part (bits_resol bits)
|
315 |
|
|
|
316 |
|
|
yn_2 <= yn_aux;
|
317 |
|
|
|
318 |
|
|
END IF;
|
319 |
|
|
END IF;
|
320 |
|
|
END IF;
|
321 |
|
|
END PROCESS process2;
|
322 |
|
|
|
323 |
|
|
|
324 |
|
|
-- =======================================================================================
|
325 |
|
|
-- SHIT REGISTER: x[n-k]
|
326 |
|
|
-- =======================================================================================
|
327 |
|
|
|
328 |
|
|
process_reg:
|
329 |
|
|
PROCESS (clock_fs, areset)
|
330 |
|
|
BEGIN
|
331 |
|
|
IF (areset = '1') THEN
|
332 |
|
|
REGISTRO_xn <= (OTHERS => (OTHERS => '0'));
|
333 |
|
|
|
334 |
|
|
ELSIF rising_edge(clock_fs) THEN
|
335 |
|
|
IF (sreset = '1') THEN
|
336 |
|
|
REGISTRO_xn <= (OTHERS => (OTHERS => '0'));
|
337 |
|
|
ELSE
|
338 |
|
|
|
339 |
|
|
IF (enable = '1')THEN
|
340 |
|
|
|
341 |
|
|
---------------------------------------------------------------
|
342 |
|
|
-- x[n-k], it is not applied instantaneously (scheduled)
|
343 |
|
|
---------------------------------------------------------------
|
344 |
|
|
-- right-shift
|
345 |
|
|
|
346 |
|
|
FOR i IN 0 TO (taps-3) LOOP -- (ignored when taps=2)
|
347 |
|
|
REGISTRO_xn(i)<= REGISTRO_xn(i+1);
|
348 |
|
|
END LOOP;
|
349 |
|
|
|
350 |
|
|
if (data_signed = true) then
|
351 |
|
|
REGISTRO_xn(taps-2) <= CONV_SIGNED(conv_integer( signed(xn)),data_length+1);
|
352 |
|
|
else
|
353 |
|
|
REGISTRO_xn(taps-2) <= CONV_SIGNED(conv_integer(unsigned(xn)),data_length+1);
|
354 |
|
|
end if;
|
355 |
|
|
|
356 |
|
|
END IF;
|
357 |
|
|
END IF;
|
358 |
|
|
END IF;
|
359 |
|
|
|
360 |
|
|
END PROCESS process_reg;
|
361 |
|
|
|
362 |
|
|
|
363 |
|
|
-- =======================================================================================
|
364 |
|
|
-- OUTPUT (neither saturation control nor IEEE rounding)
|
365 |
|
|
-- =======================================================================================
|
366 |
|
|
-- SUM of process1 and process2 outputs
|
367 |
|
|
|
368 |
|
|
yn_comb <= yn_1 + yn_2;
|
369 |
|
|
yn_sync <= yn_1 + yn_2 when rising_edge(clock_fs);
|
370 |
|
|
|
371 |
|
|
yn_aux <= yn_sync when (improv_t = true) else yn_comb;
|
372 |
|
|
|
373 |
|
|
|
374 |
|
|
---------------------------------------------------------------
|
375 |
|
|
-- OUTPUT (with saturation control and IEEE rounding)
|
376 |
|
|
---------------------------------------------------------------
|
377 |
|
|
|
378 |
|
|
-- yn_aux of type A(_,bits_resol):
|
379 |
|
|
-- whole part: 'LEFT downto bits_resol
|
380 |
|
|
-- decimal part: (bits_resol-1) downto 0
|
381 |
|
|
--
|
382 |
|
|
-- |<------------------------------------------ yn_aux ------------------------------------------->|
|
383 |
|
|
-- [yn_aux'left] ..... [bits_resol+data_length-1] ..... [bits_resol] [bits_resol-1] .........[0]
|
384 |
|
|
-- |<------------ yn_signed/unsigned ------------>|<----- (decimal part) ----->|
|
385 |
|
|
|
386 |
|
|
|
387 |
|
|
-- unsigned output:
|
388 |
|
|
yn_unsigned <=
|
389 |
|
|
(OTHERS => '0') WHEN yn_aux(bits_resol+data_length+1) = '1' ELSE -- negative overflow
|
390 |
|
|
(OTHERS => '1') WHEN yn_aux(bits_resol+data_length) = '1' ELSE -- positive overflow
|
391 |
|
|
STD_LOGIC_VECTOR(yn_aux(bits_resol+data_length-1 DOWNTO bits_resol))+1 WHEN yn_aux(bits_resol-1) = '1' and STD_LOGIC_VECTOR(yn_aux(bits_resol+data_length-1 downto bits_resol)) /= (yn'range => '1') ELSE -- positive IEEE rounding (avoids positive overflow)
|
392 |
|
|
STD_LOGIC_VECTOR(yn_aux(bits_resol+data_length-1 DOWNTO bits_resol)); -- truncated
|
393 |
|
|
|
394 |
|
|
-- signed output:
|
395 |
|
|
yn_signed <=
|
396 |
|
|
STD_LOGIC_VECTOR(CONV_SIGNED(SIGNED_MIN,data_length)) WHEN yn_aux(bits_resol+data_length) = '1' and yn_aux(bits_resol+data_length-1) = '0' ELSE -- negative overflow
|
397 |
|
|
STD_LOGIC_VECTOR(CONV_SIGNED(SIGNED_MAX,data_length)) WHEN yn_aux(bits_resol+data_length) = '0' and yn_aux(bits_resol+data_length-1) = '1' ELSE -- positive overflow
|
398 |
|
|
STD_LOGIC_VECTOR(yn_aux(bits_resol+data_length-1 DOWNTO bits_resol))+1 WHEN yn_aux(bits_resol-1) = '1' and -- positive or negative IEEE rounding (avoids positive overflow)
|
399 |
|
|
(yn_aux(bits_resol+data_length-1) = '1' or STD_LOGIC_VECTOR(yn_aux(bits_resol+data_length-2 downto bits_resol)) /= (yn_aux(bits_resol+data_length-2 downto bits_resol)'range => '1')) ELSE
|
400 |
|
|
STD_LOGIC_VECTOR(signed(yn_aux(bits_resol+data_length-1 DOWNTO bits_resol))); -- truncated
|
401 |
|
|
|
402 |
|
|
-- FINAL OUTPUT
|
403 |
|
|
yn <= yn_signed when (data_signed = true) else yn_unsigned;
|
404 |
|
|
|
405 |
|
|
|
406 |
|
|
END FIR_low_area_arch;
|
407 |
|
|
|
408 |
|
|
|
409 |
|
|
|
410 |
|
|
--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
411 |
|
|
--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
412 |
|
|
--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
413 |
|
|
--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
414 |
|
|
|
415 |
|
|
|
416 |
|
|
-------------------------------------------------------------------------------
|
417 |
|
|
-- DESCRIPTION
|
418 |
|
|
-------------------------------------------------------------------------------
|
419 |
|
|
--
|
420 |
|
|
------------------
|
421 |
|
|
-- DELAY
|
422 |
|
|
------------------
|
423 |
|
|
-- clock_fs period x taps
|
424 |
|
|
--
|
425 |
|
|
------------------
|
426 |
|
|
-- AREA
|
427 |
|
|
------------------
|
428 |
|
|
-- bits_resol stablishes the precision of the filtering operations (resources)
|
429 |
|
|
--
|
430 |
|
|
------------------
|
431 |
|
|
-- OUTPUT ERROR
|
432 |
|
|
------------------
|
433 |
|
|
-- maximum output error:
|
434 |
|
|
--
|
435 |
|
|
-- ------------------------------------------------------
|
436 |
|
|
-- | taps * [2^(-bits_resol)] * [(2^data_length)-1)] |
|
437 |
|
|
-- ------------------------------------------------------
|
438 |
|
|
-- (taps = order+1)
|
439 |
|
|
--
|
440 |
|
|
------------------------------------------------------------------------------
|
441 |
|
|
-- Operations:
|
442 |
|
|
------------------------------------------------------------------------------
|
443 |
|
|
--
|
444 |
|
|
-- h[n] = A(0,bits_resol) with resolution = 2^(-bits_resol)
|
445 |
|
|
-- x[n] = A(data_length,0)
|
446 |
|
|
--
|
447 |
|
|
-- y[n] = sum{x[n-k] x h[k]}
|
448 |
|
|
-- x[n-i] x h[i] = A(data_length,0) x A(0,bits_resol) = A(data_length+0+1,bits_resol)
|
449 |
|
|
-- y[n] = A(data_length+1+[taps]-1,bits_resol)
|
450 |
|
|
--
|
451 |
|
|
------------------------------------------------------------------------------
|
452 |
|
|
-- Implementation:
|
453 |
|
|
------------------------------------------------------------------------------
|
454 |
|
|
--
|
455 |
|
|
-- -FIR direct form II-
|
456 |
|
|
--
|
457 |
|
|
-- 3 process() in parallel:
|
458 |
|
|
--
|
459 |
|
|
-- process1(): 1/2 part of the filtering operations
|
460 |
|
|
-- process2(): 2/2 part of the filtering operations
|
461 |
|
|
-- process_reg(): x[n-k]
|
462 |
|
|
--
|
463 |
|
|
-- FIR filters have symmetric coefficients (but sign):
|
464 |
|
|
--
|
465 |
|
|
-- e.g. taps=5 and positive h[n] coefficients:
|
466 |
|
|
-- x[n-3]*h(3) + x[n-1]*h[1] = (x[n-3]+x[n-1])*h[3], because h[1]=h[3]
|
467 |
|
|
--
|
468 |
|
|
---------------
|
469 |
|
|
--
|
470 |
|
|
-- x: products by means of process1() and centre coefficient
|
471 |
|
|
-- o: products by means of process2() and first-last coefficients
|
472 |
|
|
--
|
473 |
|
|
--
|
474 |
|
|
-- taps bi prod process1() prod process2()
|
475 |
|
|
--
|
476 |
|
|
-- 2 x x 0 1 bo=b1
|
477 |
|
|
-- 3 o x o 1 b1 1 bo=b2
|
478 |
|
|
-- 4 o x x o 1 b1=b2 1 bo=b3
|
479 |
|
|
-- 5 o x x x o 2 b1=b3, b2 1 bo=b4
|
480 |
|
|
-- 6 o x x x x o 2 b1=b4, b2=b3 1 bo=b5
|
481 |
|
|
-- 7 o o x x x o o 2 b2=b4, b3 2 bo=b6, b1=b5
|
482 |
|
|
-- 8 o o x x x x o o 2 b2=b5, b3=b4 2 bo=b7, b1=b6
|
483 |
|
|
-- 9 o o x x x x x o o 3 b2=b6, b3=b5, b4 2 bo=b8, b1=b7
|
484 |
|
|
-- 10 o o x x x x x x o o 3 b2=b7, b3=b6, b4=b5 2 bo=b9, b1=b8
|
485 |
|
|
-- 11 o o o x x x x x o o o 3 b3=b7, b4=b6, b5 3 bo=b10, b1=b9, b2=b8
|
486 |
|
|
-- 12 o o o x x x x x x o o o 3 b3=b8, b4=b7, b5=b6 3 bo=b11, b1=b10, b2=b9
|
487 |
|
|
-- 13 o o o x x x x x x x o o o 4 b3=b9, b4=b8, b5=b7, b6 3 bo=b12, b1=b11, b2=b10
|
488 |
|
|
-- 14 o o o o x x x x x x o o o o 4 b4=b9, b5=b8, b6=b7 4 bo=b13, b1=b12, b2=b11, b3=b10
|
489 |
|
|
-- 15 o o o o x x x x x x x o o o o 4 b4=b10,b5=b9, b6=b8, b7 4 bo=b14, b1=b13, b2=b12, b3=b11
|
490 |
|
|
-- (etc)...
|
491 |
|
|
|
492 |
|
|
-------------------------------------------------------------------------------
|
493 |
|
|
-- Fixed-Point Arithmetic: An Introduction
|
494 |
|
|
-- Randy Yates
|
495 |
|
|
-- March 3, 2001 11:52
|
496 |
|
|
-------------------------------------------------------------------------------
|
497 |
|
|
--
|
498 |
|
|
-- A(a,b): a = whole part, b = decimal part
|
499 |
|
|
--
|
500 |
|
|
-- length = (a+b) +1 bits (sign)
|
501 |
|
|
-- resolution (steps) = 2^(-b)
|
502 |
|
|
-- maximum value = 2^a - 2^(-b)
|
503 |
|
|
-- minimum value = -2^(-a)
|
504 |
|
|
--
|
505 |
|
|
-- Operations:
|
506 |
|
|
--
|
507 |
|
|
-- A(x,y) * A(z,n) = A(x+z+1,y+n), length = (x+z+1+y+n) +1 bits (sign)
|
508 |
|
|
-- A(x,y) + A(x,y) = A(x+1,y) , length = (x+1+y) +1 bits (sign)
|
509 |
|
|
-- A(x,y) + A(x,y) + A(x,y)= A(x+2,y) , length = (x+2+y) +1 bits (sign)
|
510 |
|
|
--
|
511 |
|
|
|
512 |
|
|
------------------------------------------------------------------------------
|
513 |
|
|
-- TYPES CONVERSION (OF CONSTANT VALUES)
|
514 |
|
|
------------------------------------------------------------------------------
|
515 |
|
|
--
|
516 |
|
|
-- REAL -> INTEGER -> STD_LOGIC_VECTOR -> SIGNED:
|
517 |
|
|
--
|
518 |
|
|
-- SIGNED(CONV_STD_LOGIC_VECTOR(INTEGER(ROUND(<real_value>))))
|
519 |
|
|
--
|
520 |
|
|
-- SIGNED -> STD_LOGIC_VECTOR -> INTEGER -> REAL:
|
521 |
|
|
--
|
522 |
|
|
-- ROUND(REAL(CONV_INTEGER(CONV_STD_LOGIC_VECTOR(<signed_value>))))
|
523 |
|
|
--
|