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

Subversion Repositories fir_filter

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 9 to Rev 10
    Reverse comparison

Rev 9 → Rev 10

/fir_filter/tags/filtro_FIR.vhd File deleted \ No newline at end of file
/fir_filter/tags/testbench/simulation.do
0,0 → 1,25
quit -sim
 
vcom -work work -2002 -explicit -check_synthesis -novitalcheck -novital -source -O0 -debug -stats=none F:/Filtro_FIR/src/FIR_low_area.vhd
vcom -work work -2002 -explicit -check_synthesis -novitalcheck -novital -source -O0 -stats=none F:/Filtro_FIR/testbench/FIR_low_area_tb.vhd
 
vsim -gui work.fir_low_area_tb
 
add wave -position insertpoint \
/fir_low_area_tb/data_length \
/fir_low_area_tb/bits_resol \
/fir_low_area_tb/taps \
/fir_low_area_tb/hn\
/fir_low_area_tb/areset \
/fir_low_area_tb/clock_fs \
/fir_low_area_tb/freq_xn
 
add wave -noupdate -format Analog-Interpolated -height 74 -max 2047.0 -min -2048.0 -radix decimal /fir_low_area_tb/duv_fir_signed/xn
add wave -noupdate -format Analog-Interpolated -height 74 -max 2047.0 -min -2048.0 -radix decimal /fir_low_area_tb/duv_fir_signed/yn
 
add wave -noupdate -format Analog-Interpolated -height 74 -max 4095.0 -min 0 -radix unsigned /fir_low_area_tb/duv_fir_unsigned/xn
add wave -noupdate -format Analog-Interpolated -height 74 -max 4095.0 -min 0 -radix unsigned /fir_low_area_tb/duv_fir_unsigned/yn
 
 
 
run -all
/fir_filter/tags/testbench/filtro_fir.m
1,79 → 1,83
clear all;
format long g;
 
%%%%%%%%%%%%%%%%%%%% h[n] %%%%%%%%%%%%%%%%%%%%%%%%%
 
figure(1);
 
%XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
% OBTENCION DE COEFICIENTES PARA
% filtro_FIR.vhd
%XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
% http://t-filter.appspot.com/fir/index.html
 
fs = 32e6
orden = 31 % = coeficientes -1
fc = 10e3 % frec de corte
fs=64e6
order=31
fc=2e6
input_size=8
 
bits_entrada = 8
%%%%%%%%%%%%%%%%%%%% h[n] %%%%%%%%%%%%%%%%%%%%%%%%%
 
% NOTA: las ilustraciones que se muestran tienen los valores
% redondeados por lo que para verlos correctamente (en la
% linea de comandos) descomentar el penultimo parrafo al
% final de este archivo (y_u, y_delta, y_rampas)
fnyquist=fs/2;
 
%XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
%XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
%normalized cut-off frequency
wn=fc/fnyquist;
 
h= fir1(order,wn,'low')
 
wn = 2*fc/fs
figure(1);
stem(h);
title('h(n)');grid on;
 
h=fir1(orden,wn) % coeficientes del filtro FIR
 
stem(h);
title('h(n) = coeficientes filtro FIR');grid on;
%%%%%%%%%%%%%%%%%%%% H[z] %%%%%%%%%%%%%%%%%%%%%%%%%
 
figure(2);
freqz(h);
 
%%%%%%%%%%%%%%%%%%%% x[n] %%%%%%%%%%%%%%%%%%%%%%%%%
 
figure(2);
num_cycles=16;
amplitude=2^input_size-1;
freq=fc/4;
 
num_muestras=64;
magnitud=2^bits_entrada-1; % amplitud de las entradas 0:1:255 (A)
% entrada impulsional delta[n]
num_samples=num_cycles*(fs/freq);
 
delta=[];
delta(1:num_muestras)=zeros(1);
delta(num_muestras/2)=ones(1)*magnitud;
subplot(2,3,1); axis([0 64 0 max(delta)]); stem(delta); title('x[n]=A delta[n]'); grid on;
n=0:1/(fs/freq):num_cycles;
sin=amplitude*sin(2*pi*n);
x=sin+(amplitude/20)*randn(size(n));
 
% ventana rectangular u[n]
figure(3);
subplot(2,2,1);
str=sprintf('x[n]: f=%g Hz max=%g+noise',freq,max(sin));
stem(x); title(str); grid on;
 
u=[];
u(1:num_muestras)=zeros(1);
u(num_muestras/4 :num_muestras/4+7)=ones(1)*magnitud;
subplot(2,3,2); axis([0 64 0 max(u)]); stem(u); title('x[n]=A u[n]'); grid on;
%%%%%%%%%%%%%%%%%%%% x[z] %%%%%%%%%%%%%%%%%%%%%%%%%
 
% rampa rampas[n]
% NFFT = 2^nextpow2(num_samples);
% f = (1:NFFT/2+1)*(fs/NFFT); % wn=1 <> fs/2
 
rampas=[];
rampas(1:num_muestras)=zeros(1);
for R = 1:(num_muestras/4)
rampas(R)=magnitud/(num_muestras/4)*R;
end
for R = (num_muestras/4+1):num_muestras/2
rampas(R)=magnitud/(num_muestras/4)*(R-(num_muestras/4));
end
subplot(2,3,3); axis([0 64 0 max(rampas)]); stem(rampas); title('x[n]=A rampas[n]'); grid on;
% X = fft(x,NFFT);
% peakpowerX = max(X).*conj(max(X))/NFFT;
 
%%%%%%%%%%%%%%%%%%%%% y[n] %%%%%%%%%%%%%%%%%%%%%%%%
subplot(2,2,2);
% stem(f,2*abs(X(1:NFFT/2+1)));
% str=sprintf('x[z] peak power=%g',peakpowerX);
% title(str); grid on;
% xlabel('f[Hz]')
% ylabel('|x[z]|')
periodogram(x,rectwin(length(x)),length(x),fs);
 
y_u=filter(h,1,u); % respuesta a: A u[n]
y_delta=filter(h,1,delta); % respuesta a: A delta[n]
y_rampas=filter(h,1,rampas);% respuesta a: A rampas[n]
 
subplot(2,3,4); axis([0 64 0 max(y_delta)]); stem(y_delta); title('y[n]'); grid on;
subplot(2,3,5); axis([0 64 0 max(y_u)]); stem(y_u); title('y[n]'); grid on;
subplot(2,3,6); axis([0 64 0 max(y_rampas)]); stem(y_rampas); title('y[n]'); grid on;
% %%%%%%%%%%%%%%%%%%%% y[n] %%%%%%%%%%%%%%%%%%%%%%%
 
y=filter(h,1,x);
subplot(2,2,3);
str=sprintf('y[n]: fc=%g Hz peak=%g',fc,max(y(length(h):num_samples)));
stem(y); title(str); grid on;
 
%%%%%%%%%%%%%%%%%%%% y[z] %%%%%%%%%%%%%%%%%%%%%%%%%
subplot(2,2,4);
periodogram(y,rectwin(length(y)),length(y),fs);
 
 
format;
 
 
/fir_filter/tags/testbench/FIR_low_area_tb.vhd
0,0 → 1,170
 
-- CREATION DATE .......: 08 April 2015
-- AUTHOR ..............: DIEGO PARDO (arroxo2@yahoo.es)
-- REVISION ............: 1.0
-- LAST UPDATE .........: 08 April 2015
-- UPDATED BY ..........: DIEGO PARDO
 
-- TITLE "CONFIGURABLE FIR FILTER TESTBENCH";
--
-- http://t-filter.appspot.com/fir/index.html
 
--=============================================================================
--================================ TESTBENCH ==================================
--=============================================================================
 
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_signed.all;
USE ieee.math_real.all;
 
LIBRARY work;
USE work.fir_package.all;
 
 
ENTITY FIR_low_area_tb IS
END FIR_low_area_tb;
 
 
ARCHITECTURE FIR_low_area_tb_arch OF FIR_low_area_tb IS
-- TESTCASE SETTINGS
--.............................................................................
CONSTANT freq_xn : REAL := 900.0e3; -- input frequency
CONSTANT data_length : NATURAL := 12; -- input bit size
CONSTANT fs_Hz : REAL := 8.0e6; -- sampling frequency
CONSTANT taps : NATURAL := 15; -- order+1
-- transition band: 800e3 to 1.6e6
CONSTANT hn : COEFF_ARRAY := (-0.01259277478717816,
-0.02704833486706803,
-0.031157016036431583,
-0.0033516667471792812,
0.06651710329324828,
0.1635643048779222,
0.249729473226146,
0.2842779082622769,
0.249729473226146,
0.1635643048779222,
0.06651710329324827,
-0.0033516667471792812,
-0.031157016036431583,
-0.027048334867068043,
-0.01259277478717816,
others=>0.0);
CONSTANT bits_resol : NATURAL := 12;
--..............................................................................
 
SIGNAL areset : STD_LOGIC;
SIGNAL clock_fs : STD_LOGIC := '1';
SIGNAL xn_signed : STD_LOGIC_VECTOR(data_length-1 DOWNTO 0);
SIGNAL xn_unsigned : STD_LOGIC_VECTOR(data_length-1 DOWNTO 0);
SIGNAL yn_signed : STD_LOGIC_VECTOR(data_length-1 DOWNTO 0);
SIGNAL yn_unsigned : STD_LOGIC_VECTOR(data_length-1 DOWNTO 0);
SIGNAL radians : REAL := 0.0;
SIGNAL radian_step : REAL := 1.0/(fs_Hz/freq_xn);
CONSTANT PI : REAL := 3.1415926535897932;
CONSTANT num_cycles : NATURAL := 16;
CONSTANT fs_period : TIME := integer(1.0e12/fs_Hz)* 1 ps;
CONSTANT num_samples : NATURAL := num_cycles*integer(round(fs_Hz/freq_xn));
CONSTANT amplitude : REAL := 2.0**real(data_length-1)-1.0;
BEGIN
 
duv_fir_signed: ENTITY work.FIR_low_area
--.............................................
generic map(
data_length => data_length,
data_signed => true,
improv_t => false,
bits_resol => bits_resol,
taps => taps,
coefficients => hn)
port map(
areset => areset,
sreset => '0',
clock_fs => clock_fs,
enable => '1',
xn => xn_signed,
yn => yn_signed
);
 
duv_fir_unsigned: ENTITY work.FIR_low_area
--.............................................
generic map(
data_length => data_length,
data_signed => false,
improv_t => false,
bits_resol => bits_resol,
taps => taps,
coefficients => hn)
port map(
areset => areset,
sreset => '0',
clock_fs => clock_fs,
enable => '1',
xn => xn_unsigned,
yn => yn_unsigned
);
sampling_clock: process
--.............................................
begin
clock_fs <= '1';
wait for fs_period/2;
clock_fs <= '0';
wait for fs_period/2;
end process;
xn_sinus: process
--.............................................
variable seed1,seed2 : positive;
variable rand : real;
variable noise_n : real;
variable sinus_n : real;
begin
UNIFORM(seed1, seed2, rand); -- uniform 0.0 to 1.0
noise_n := 2.0*(rand-0.5) * (amplitude/20.0);
sinus_n := amplitude * sin(2.0*PI*radians) + noise_n;
-- saturation control
if sinus_n > amplitude then
sinus_n := amplitude;
elsif sinus_n < -amplitude then
sinus_n := -amplitude;
end if;
xn_signed <= std_logic_vector(conv_signed(integer(round(sinus_n)),data_length));
xn_unsigned <= std_logic_vector(conv_unsigned(integer(round(amplitude + sinus_n)),data_length));
if radians >= 1.0 then
radians <= 0.0;
else
radians <= radians + radian_step;
end if;
wait until rising_edge(clock_fs);
end process;
reset: process
--.............................................
begin
areset <= '1';
wait for 10 ns;
areset <= '0';
wait;
end process;
sim_time: process
--.............................................
begin
wait for num_samples*fs_period;
assert false report "SIMULATION END" severity failure;
end process;
END FIR_low_area_tb_arch;
 
 
/fir_filter/tags/FIR_low_area.vhd
0,0 → 1,523
 
-- CREATION DATE .......: 02 Jul 2007 (Filtro_FIR.vhd)
-- AUTHOR ..............: DIEGO PARDO (arroxo2@yahoo.es)
-- REVISION ............: 2.0
-- LAST UPDATE .........: 08 April 2015
-- UPDATED BY ..........: DIEGO PARDO
 
-- TITLE "CONFIGURABLE FIR FILTER";
--
-- Generic VHDL (suitable for ALTERA, XILINX, MICROSEMI, etc)
-- Low resources occupation (fixed-point implementation)
--
 
 
--=============================================================================
--============================= LOCAL PACKAGE =================================
--=============================================================================
 
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_signed.all;
USE ieee.math_real.all;
 
 
PACKAGE fir_package IS
 
CONSTANT max_coef: NATURAL:= 128; -- (increase if needed)
TYPE COEFF_ARRAY IS ARRAY (0 to max_coef-1) OF REAL;
FUNCTION decimal_to_signed (c_real: IN REAL; CONSTANT precision: IN NATURAL) RETURN SIGNED;
 
END fir_package;
 
 
PACKAGE body fir_package IS
 
FUNCTION decimal_to_signed (c_real: IN REAL; CONSTANT precision: IN NATURAL) RETURN SIGNED IS
-- SIGNED = REAL / 2^(-precision) = REAL * 2^precision, with IEEE rounding
CONSTANT RESOLUCION : REAL := "**"(2,REAL(INTEGER(precision)));
BEGIN
RETURN (SIGNED(CONV_STD_LOGIC_VECTOR(INTEGER(ROUND ("*"(c_real,RESOLUCION))),precision+1)));
END FUNCTION;
END fir_package;
 
 
 
--=============================================================================
--================================== ENTITY ===================================
--=============================================================================
 
LIBRARY work;
USE WORK.fir_package.all;
 
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_signed.all;
USE ieee.math_real.all;
 
--.............................................................................
-- GAIN 1.0
-- SATURATION CONTROL Yes (output)
-- OUTPUT ROUNDING Yes (IEEE)
-- IMPLEMENTED BY Fixed-Point (configurable resolution)
-- 3rd-PARTY IPs No (generic VHDL)
--.............................................................................
 
ENTITY FIR_low_area IS
GENERIC(
data_length : NATURAL := 8; -- input/output length (number of bits)
data_signed : BOOLEAN := false; -- input/output type (signed or unsigned)
improv_t : BOOLEAN := false; -- minimal timing improvement by adding one extra output cycle delay (use only if needed)
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)
taps : NATURAL := 5; -- =order+1, 2 coefficients as minimum (order=1)
coefficients : COEFF_ARRAY :=( -- normalized coefficients bi: (bo,b1, ..., bN). They must be symmetric (but sign)
-0.11735685282030676,
0.23471370564061372,
0.7066280917835991,
0.23471370564061372,
-0.11735685282030676,
OTHERS=>0.0) -- (always end with "others=>0.0")
);
PORT(
areset : IN STD_LOGIC; -- active high
sreset : IN STD_LOGIC; -- active high
clock_fs : IN STD_LOGIC;
enable : IN STD_LOGIC;
xn : IN STD_LOGIC_VECTOR(data_length-1 DOWNTO 0); -- FILTER INPUT (any fixed-point format, e.g. whole numbers)
yn : OUT STD_LOGIC_VECTOR(data_length-1 DOWNTO 0) -- FILTER OUTPUT (keeps same fixed-point format of input)
);
END FIR_low_area;
 
 
 
ARCHITECTURE FIR_low_area_arch OF FIR_low_area IS
 
type ENTRADA_xn IS ARRAY (taps-2 DOWNTO 0) OF SIGNED(data_length DOWNTO 0); -- A(data_length,0) : x[n-k]
type VALORES_h IS ARRAY (taps-1 DOWNTO 0) OF SIGNED(bits_resol DOWNTO 0); -- A(0,bits_resol) : h[n-k]
 
SIGNAL REGISTRO_xn : ENTRADA_xn;
SIGNAL yn_1, yn_2 : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0);
SIGNAL yn_aux : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0); -- yn_1 + yn_2
SIGNAL yn_comb : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0);
SIGNAL yn_sync : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0);
SIGNAL yn_unsigned : STD_LOGIC_VECTOR(data_length-1 DOWNTO 0);
SIGNAL yn_signed : STD_LOGIC_VECTOR(data_length-1 DOWNTO 0);
 
CONSTANT SIGNED_MAX : INTEGER := 2**(yn'length-1)-1;
CONSTANT SIGNED_MIN : INTEGER := -1 * 2**(yn'length-1);
 
BEGIN
 
 
ASSERT (bits_resol >= 4)
REPORT "PLEASE INCREASE RESOLUTION BITS (result will be poor)" SEVERITY FAILURE;
-- pragma translate_off
process
VARIABLE sum_coeff : real;
begin
sum_coeff := 0.0;
FOR ind IN 0 TO (taps-1) LOOP
sum_coeff := sum_coeff + coefficients(ind);
END LOOP;
ASSERT sum_coeff = 1.0
REPORT "COEFFICIENTS ARE NOT NORMALIZED" SEVERITY WARNING;
wait;
end process;
-- pragma translate_on
-- =======================================================================================
-- HALF FILTERING OPERATIONS (1/2)
-- (DOES NOT INCLUDE INITIAL AND FINAL COEFFICIENTS, INCLUDES CENTRE COEFFICIENT (WHEN "taps" EVEN)
-- =======================================================================================
process1:
PROCESS (clock_fs, areset)
VARIABLE xn_a_pares : SIGNED (data_length+1 DOWNTO 0); -- to sum x[n-k] with symmetric coefficients
VARIABLE REGISTRO_h : VALORES_h := (OTHERS => (OTHERS => '0')); -- it stores the coefficients (avoids registers)
VARIABLE producto : SIGNED (data_length+1+bits_resol+1 DOWNTO 0); -- product of xn_a_pares by symmetric coefficient
VARIABLE yn_aux : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0); -- partial sum
VARIABLE signos_bi : STD_LOGIC_VECTOR (1 DOWNTO 0); -- signs of the symmetric coefficients
VARIABLE indice1 : NATURAL;
VARIABLE margen : NATURAL;
 
BEGIN
IF (areset = '1') THEN
yn_1 <= (OTHERS => '0');
ELSIF rising_edge(clock_fs) THEN
IF (sreset = '1') THEN
yn_1 <= (OTHERS => '0');
ELSE
IF (enable = '1') THEN
-- variable avoids h[n] register, REGISTRO_h(0) = bN
FOR ind IN 0 TO (taps-1) LOOP
REGISTRO_h(ind) := decimal_to_signed (coefficients(taps-1-ind),bits_resol);
END LOOP;
yn_aux := (OTHERS => '0');
-- symmetric coefficients (but first and last ones):
-- In this cycle x[n-k] has not been applied yet to the shift register of x[n]
IF (taps > 3) THEN
indice1 := (taps/2)+(taps MOD 2);
margen := ((taps-1)-(taps/2))/2 - (taps MOD 2);
FOR i IN indice1 TO (indice1 + margen) LOOP
-- symmetric bi signs
signos_bi(1):= REGISTRO_h(i)(bits_resol);
signos_bi(0):= REGISTRO_h(taps-1-i)(bits_resol);
CASE signos_bi IS
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));
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));
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));
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));
END CASE;
producto := "*"(xn_a_pares, ABS(REGISTRO_h(i)));
yn_aux := "+"(yn_aux, producto);
END LOOP;
END IF;
---------------------------------------------------------------
-- central coefficient operation (when taps is even)
---------------------------------------------------------------
-- non-symmetric coefficient
IF (taps MOD 2)/=0 THEN
producto := "*"(CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps/2))),data_length+2), REGISTRO_h(taps/2));
yn_aux := "+"(yn_aux, producto);
END IF;
---------------------------------------------------------------
-- output of processo1
---------------------------------------------------------------
-- yn_1 has decimal part (bits_resol bits)
yn_1 <= yn_aux;
END IF;
END IF;
END IF;
END PROCESS process1;
 
-- =======================================================================================
-- HALF FILTERING OPERATIONS (2/2)
-- (INCLUDINF INITIAL AND FINAL COEFFICIENTS)
-- =======================================================================================
process2:
PROCESS (clock_fs, areset)
VARIABLE xn_a_pares : SIGNED (data_length+1 DOWNTO 0); -- to sum x[n-k] with symmetric coefficients
VARIABLE REGISTRO_h : VALORES_h := (OTHERS => (OTHERS => '0')); -- it stores the coefficients (avoids registers)
VARIABLE producto : SIGNED (data_length+1+bits_resol+1 DOWNTO 0); -- product of xn_a_pares by symmetric coefficient
VARIABLE yn_aux : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0); -- partial sum
VARIABLE signos_bi : STD_LOGIC_VECTOR (1 DOWNTO 0); -- signs of the symmetric coefficients
VARIABLE indice1 : NATURAL;
VARIABLE margen : NATURAL;
BEGIN
IF (areset = '1') THEN
yn_2 <= (OTHERS => '0');
ELSIF rising_edge(clock_fs) THEN
IF (sreset = '1') THEN
yn_2 <= (OTHERS => '0');
ELSE
IF (enable = '1') THEN
-- variable avoids h[n] register, REGISTRO_h(0) = bN
FOR ind IN 0 TO (taps-1) LOOP
REGISTRO_h(ind) := decimal_to_signed (coefficients(taps-1-ind),bits_resol);
END LOOP;
yn_aux := (OTHERS => '0');
-- symmetric coefficients (but first and last ones). When taps < 7 the operations are resolved by process1:
-- In this cycle x[n-k] has not been applied yet to the shift register of x[n]
IF (taps > 6) THEN
indice1 := (taps/2)+(taps MOD 2);
margen := ((taps-1)-(taps/2))/2 - (taps MOD 2);
FOR i IN (indice1 + margen + 1) TO (taps-2) LOOP
-- symmetric bi signs
signos_bi(1):= REGISTRO_h(i)(bits_resol);
signos_bi(0):= REGISTRO_h(taps-1-i)(bits_resol);
CASE signos_bi IS
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));
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));
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));
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));
END CASE;
producto:= "*"(xn_a_pares, ABS(REGISTRO_h(i)));
yn_aux := "+"(yn_aux, producto);
END LOOP;
END IF;
----------------------------------------------------------------
-- first and last coefficients operation (symmetric)
----------------------------------------------------------------
-- The initial coefficient multiplies x[n] (not registered yet)
signos_bi(1):= REGISTRO_h(taps-1)(bits_resol);
signos_bi(0):= REGISTRO_h(0)(bits_resol);
CASE signos_bi IS
WHEN "00" => if (data_signed = true) then
xn_a_pares:= "+"( CONV_SIGNED(conv_integer( signed(xn)),data_length+2), CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
else
xn_a_pares:= "+"( CONV_SIGNED(conv_integer(unsigned(xn)),data_length+2), CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
end if;
WHEN "01" => if (data_signed = true) then
xn_a_pares:= "+"( CONV_SIGNED(conv_integer( signed(xn)),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
else
xn_a_pares:= "+"( CONV_SIGNED(conv_integer(unsigned(xn)),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
end if;
WHEN "10" => if (data_signed = true) then
xn_a_pares:= "+"(-CONV_SIGNED(conv_integer( signed(xn)),data_length+2), CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
else
xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(unsigned(xn)),data_length+2), CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
end if;
WHEN OTHERS => if (data_signed = true) then
xn_a_pares:= "+"(-CONV_SIGNED(conv_integer( signed(xn)),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
else
xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(unsigned(xn)),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
end if;
END CASE;
producto := "*"(xn_a_pares, ABS(REGISTRO_h(taps-1)));
yn_aux := "+"(yn_aux, producto);
---------------------------------------------------------------
-- output of processo2
---------------------------------------------------------------
-- yn_2 has decimal part (bits_resol bits)
yn_2 <= yn_aux;
END IF;
END IF;
END IF;
END PROCESS process2;
-- =======================================================================================
-- SHIT REGISTER: x[n-k]
-- =======================================================================================
process_reg:
PROCESS (clock_fs, areset)
BEGIN
IF (areset = '1') THEN
REGISTRO_xn <= (OTHERS => (OTHERS => '0'));
ELSIF rising_edge(clock_fs) THEN
IF (sreset = '1') THEN
REGISTRO_xn <= (OTHERS => (OTHERS => '0'));
ELSE
IF (enable = '1')THEN
---------------------------------------------------------------
-- x[n-k], it is not applied instantaneously (scheduled)
---------------------------------------------------------------
-- right-shift
FOR i IN 0 TO (taps-3) LOOP -- (ignored when taps=2)
REGISTRO_xn(i)<= REGISTRO_xn(i+1);
END LOOP;
if (data_signed = true) then
REGISTRO_xn(taps-2) <= CONV_SIGNED(conv_integer( signed(xn)),data_length+1);
else
REGISTRO_xn(taps-2) <= CONV_SIGNED(conv_integer(unsigned(xn)),data_length+1);
end if;
END IF;
END IF;
END IF;
END PROCESS process_reg;
 
-- =======================================================================================
-- OUTPUT (neither saturation control nor IEEE rounding)
-- =======================================================================================
-- SUM of process1 and process2 outputs
yn_comb <= yn_1 + yn_2;
yn_sync <= yn_1 + yn_2 when rising_edge(clock_fs);
yn_aux <= yn_sync when (improv_t = true) else yn_comb;
---------------------------------------------------------------
-- OUTPUT (with saturation control and IEEE rounding)
---------------------------------------------------------------
 
-- yn_aux of type A(_,bits_resol):
-- whole part: 'LEFT downto bits_resol
-- decimal part: (bits_resol-1) downto 0
--
-- |<------------------------------------------ yn_aux ------------------------------------------->|
-- [yn_aux'left] ..... [bits_resol+data_length-1] ..... [bits_resol] [bits_resol-1] .........[0]
-- |<------------ yn_signed/unsigned ------------>|<----- (decimal part) ----->|
 
-- unsigned output:
yn_unsigned <=
(OTHERS => '0') WHEN yn_aux(bits_resol+data_length+1) = '1' ELSE -- negative overflow
(OTHERS => '1') WHEN yn_aux(bits_resol+data_length) = '1' ELSE -- positive overflow
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)
STD_LOGIC_VECTOR(yn_aux(bits_resol+data_length-1 DOWNTO bits_resol)); -- truncated
-- signed output:
yn_signed <=
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
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
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)
(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
STD_LOGIC_VECTOR(signed(yn_aux(bits_resol+data_length-1 DOWNTO bits_resol))); -- truncated
-- FINAL OUTPUT
yn <= yn_signed when (data_signed = true) else yn_unsigned;
 
END FIR_low_area_arch;
 
 
 
--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 
-------------------------------------------------------------------------------
-- DESCRIPTION
-------------------------------------------------------------------------------
--
------------------
-- DELAY
------------------
-- clock_fs period x taps
--
------------------
-- AREA
------------------
-- bits_resol stablishes the precision of the filtering operations (resources)
--
------------------
-- OUTPUT ERROR
------------------
-- maximum output error:
--
-- ------------------------------------------------------
-- | taps * [2^(-bits_resol)] * [(2^data_length)-1)] |
-- ------------------------------------------------------
-- (taps = order+1)
--
------------------------------------------------------------------------------
-- Operations:
------------------------------------------------------------------------------
--
-- h[n] = A(0,bits_resol) with resolution = 2^(-bits_resol)
-- x[n] = A(data_length,0)
--
-- y[n] = sum{x[n-k] x h[k]}
-- x[n-i] x h[i] = A(data_length,0) x A(0,bits_resol) = A(data_length+0+1,bits_resol)
-- y[n] = A(data_length+1+[taps]-1,bits_resol)
--
------------------------------------------------------------------------------
-- Implementation:
------------------------------------------------------------------------------
--
-- -FIR direct form II-
--
-- 3 process() in parallel:
--
-- process1(): 1/2 part of the filtering operations
-- process2(): 2/2 part of the filtering operations
-- process_reg(): x[n-k]
--
-- FIR filters have symmetric coefficients (but sign):
--
-- e.g. taps=5 and positive h[n] coefficients:
-- x[n-3]*h(3) + x[n-1]*h[1] = (x[n-3]+x[n-1])*h[3], because h[1]=h[3]
--
---------------
--
-- x: products by means of process1() and centre coefficient
-- o: products by means of process2() and first-last coefficients
--
--
-- taps bi prod process1() prod process2()
--
-- 2 x x 0 1 bo=b1
-- 3 o x o 1 b1 1 bo=b2
-- 4 o x x o 1 b1=b2 1 bo=b3
-- 5 o x x x o 2 b1=b3, b2 1 bo=b4
-- 6 o x x x x o 2 b1=b4, b2=b3 1 bo=b5
-- 7 o o x x x o o 2 b2=b4, b3 2 bo=b6, b1=b5
-- 8 o o x x x x o o 2 b2=b5, b3=b4 2 bo=b7, b1=b6
-- 9 o o x x x x x o o 3 b2=b6, b3=b5, b4 2 bo=b8, b1=b7
-- 10 o o x x x x x x o o 3 b2=b7, b3=b6, b4=b5 2 bo=b9, b1=b8
-- 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
-- 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
-- 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
-- 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
-- 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
-- (etc)...
 
-------------------------------------------------------------------------------
-- Fixed-Point Arithmetic: An Introduction
-- Randy Yates
-- March 3, 2001 11:52
-------------------------------------------------------------------------------
--
-- A(a,b): a = whole part, b = decimal part
--
-- length = (a+b) +1 bits (sign)
-- resolution (steps) = 2^(-b)
-- maximum value = 2^a - 2^(-b)
-- minimum value = -2^(-a)
--
-- Operations:
--
-- A(x,y) * A(z,n) = A(x+z+1,y+n), length = (x+z+1+y+n) +1 bits (sign)
-- A(x,y) + A(x,y) = A(x+1,y) , length = (x+1+y) +1 bits (sign)
-- A(x,y) + A(x,y) + A(x,y)= A(x+2,y) , length = (x+2+y) +1 bits (sign)
--
 
------------------------------------------------------------------------------
-- TYPES CONVERSION (OF CONSTANT VALUES)
------------------------------------------------------------------------------
--
-- REAL -> INTEGER -> STD_LOGIC_VECTOR -> SIGNED:
--
-- SIGNED(CONV_STD_LOGIC_VECTOR(INTEGER(ROUND(<real_value>))))
--
-- SIGNED -> STD_LOGIC_VECTOR -> INTEGER -> REAL:
--
-- ROUND(REAL(CONV_INTEGER(CONV_STD_LOGIC_VECTOR(<signed_value>))))
--

powered by: WebSVN 2.1.0

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