You are on page 1of 20

Fri Nov 28 22:54:25 2014

filter_pkg.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.numeric_std.all;
package filter_pkg is
--Cantidad de bits que tienen los coeficientes.
constant coef_cantBits : natural := 23;
--Cantidad de bits de las muestras del microfono
constant sample_cantBits : natural := 8;
--Cantidad de coeficientes del filtro
constant cantCoef : natural := 16;
--Matriz que contiene varias muestras de 8 bits
type sample is array(integer range <>) of std_logic_vector(sample_cantBits - 1
downto 0);
--Matriz que contiene varios coeficientes de 23 bits cada uno
type coeficient is array(integer range <>) of signed(coef_cantBits - 1 downto 0);
end filter_pkg;

Page 1

Fri Nov 28 22:29:16 2014

clockDivider.vhd
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

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity clockDivider is
------------------------------ Puertos - clockDivider ------------------------------port(
--INPUTS
clk, reset: in std_logic;
--OUTPUTS
tick20Khz: out std_logic
);
end clockDivider;
---------------------------- ARQUITECTURA - clockDivider ----------------------------architecture Behavioral of clockDivider is
--Creo las senales correspondientes a la maquina de estados
--Necesito al menos 13 bits para contar hasta 5000 (y llegar a frecuencia 20Khz)
signal cont_reg, cont_next: unsigned(12 downto 0);

begin
-------------------------- Logica de estado actual ------------------------------process(clk, reset) begin
if(reset='1') then
cont_reg <= (others=>'0');
elsif (rising_edge(clk)) then
cont_reg <= cont_next; --cambio de estado en los flancos ascendentes
end if;
end process;
-------------------------- Logica del Proximo Estado ---------------------------process(cont_reg) begin
if(cont_reg = 5000) then
--Frecuencia de muestreo = 20Khz = 100Mhz/5000
cont_next <= (others=>'0');
else
cont_next <= cont_reg + 1;
end if;
end process;
------------------------------ Salidas (Moore) -----------------------------process(cont_reg) begin
if(cont_reg > 2499) then
tick20Khz <= '1';
else
tick20Khz <= '0';
end if;

--En 2500 tengo medio ciclo de reloj.

end process;
end Behavioral;

Page 1

Fri Nov 28 22:48:01 2014

generadorDeFlanco.vhd
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

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity generadorDeFlanco is
--------------------------- Puertos - generadorDeFlanco -----------------------------port(
--INPUTS
clk, reset : in std_logic;
start : in std_logic;
--OUTPUTS
done : out std_logic
);
end generadorDeFlanco;
------------------------- ARQUITECTURA - generadorDeFlancos -------------------------architecture Behavioral of generadorDeFlanco is
type estados is (bajo, flanco, alto);
signal state_reg, state_next : estados;
begin
-------------------------- Logica de estado actual ------------------------------process(clk,reset)
begin
if(reset = '1') then
state_reg <= bajo;
elsif(rising_edge(clk)) then
state_reg <= state_next;
end if;
end process;
-------------------------- Logica del Proximo Estado ---------------------------process(state_reg,start)
begin
state_next <= state_reg;
case state_reg is
------------------------ bajo -----------------------when bajo =>
if start = '1' then
state_next <= flanco;
end if;
----------------------- flanco ----------------------when flanco =>
--Solo dura un clock en el estado flanco, para poder
--generar el pulso necesario.
if start = '1' then
state_next <= alto;
else
state_next <= bajo;
end if;
------------------------ alto -----------------------when alto =>

Page 1

Fri Nov 28 22:48:01 2014

generadorDeFlanco.vhd
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

if start = '0' then


state_next <= bajo;
end if;
end case;
end process;
------------------------------ Salidas -----------------------------process(state_reg)
begin
--Cuando hay un '1' a la entrada del modulo, en lugar de quedarse
--en el estado '1' por muchos ciclos, lo que hace es generar
--un pulso que dura solo un ciclo de reloj, solucionando el problema
--que ocaciona la salida "DONE" del modulo PmodMIC.
if(state_reg = flanco) then
done <= '1';
else
done <= '0';
end if;
end process;
end Behavioral;

Page 2

Sat Nov 29 13:45:11 2014

serieParalelo.vhd
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

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.filter_pkg.all;
entity serieParalelo is
------------------------------ Generics - serieParalelo -----------------------------generic (cantSalidas: natural := cantCoef); --Cantidad de salidas en paralelo
------------------------------ Puertos - serieParalelo ------------------------------port(
--INPUTS
clk, reset: in std_logic;
start: in std_logic;
input: in std_logic_vector(11 downto 0); -- 12 bits que vienen del Mic.
--OUTPUTS
--Cant. de salidas en paralelo
output: out sample(cantSalidas-1 downto 0):= (others=>(others=>'0'));
done: out std_logic
);
end serieParalelo;

------------------------- ARQUITECTURA - generadorDeFlancos -------------------------architecture Behavioral of serieParalelo is


signal paralelo_reg, paralelo_next: sample(cantSalidas-1 downto 0):= (others=>(
others=>'0'));
begin
-------------------------- Logica de estado actual --------------------------------process(clk, reset) begin
if(reset='1') then
paralelo_reg <= (others=>(others=>'0')); --Pongo la entrada en cero.
elsif (rising_edge(clk)) then
paralelo_reg <= paralelo_next;
end if;
end process;
-------------------------- Logica ded proximo estado --------------------------------Meto el elemento nuevo en la cola del vector de elementos
paralelo_next <= input(11 downto 4) & paralelo_reg(cantSalidas-1 downto 1) when
start = '1'
else paralelo_reg;
---------------------------------- Salida -----------------------------------------done <= start; --Activa el siguiente modulo con la misma frecuencia que entran los
--datos a este.
output <= paralelo_reg;
end Behavioral;

Page 1

Sat Nov 29 03:22:24 2014

voiceFilter.vhd
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

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use work.filter_pkg.all;
entity voiceFilter is
------------------------------ Puertos - voiceFilter ------------------------------port(
--INPUTS
clk,reset : in std_logic;
filterStart : in std_logic;
input : in sample(cantCoef-1 downto 0);
--OUTPUTS
filterDone : out std_logic;
filteredSignal : out std_logic_vector(sample_cantBits-1 downto 0)
);
end voiceFilter;
---------------------------- ARQUITECTURA - voiceFilter ---------------------------architecture Behavioral of voiceFilter is
--Este vector completa los 8 bits del mensaje con ceros para llevarlo a 23 y
--operar con los coeficientes
constant ceros : std_logic_vector(coef_cantBits - sample_cantBits - 2 downto 0) :=
(others => '0');
--Para guardar una muestra de la senal en 23 bits (para operar con los
--coeficientes)
signal input_to_filter : signed(coef_cantBits-1 downto 0);
--Como se multiplexan los productos entre la senal y los coeficientes del filtro,
--esta senal es para manejar un coeficiente del filtro a la vez, en las operaciones.
signal filter_Coef : signed(coef_cantBits-1 downto 0);
--producto entre la senal retrasada i veces y el coeficiente i-esimo
signal producto : signed(coef_cantBits + coef_cantBits - 1 downto 0);
--sumas de los productos senal-coeficientes. (23 + 23) bits
signal suma_reg, suma_next : signed(coef_cantBits + coef_cantBits downto 0);
--Indices para los coeficientes (debido al multiplexado en el producto)
signal coef_reg, coef_next : unsigned(3 downto 0);
--Banderas de control
signal procesando, procesamiento_Completado : std_logic;
--Banderas para marcar el estado del filtro
type filter_State is (esperandoDatos,ocupado,terminado);
signal state_reg, state_next : filter_State;
-- Coeficientes del filtro
--vector de 16 coeficientes x 23 bits.
signal coef_vector : coeficient(cantCoef-1 downto 0) :=
(
to_signed(1,
coef_cantBits),
to_signed(-1,
coef_cantBits),
to_signed(-64,
coef_cantBits),
to_signed(100,
coef_cantBits),
to_signed(-584, coef_cantBits),

Page 1

Sat Nov 29 03:22:25 2014

voiceFilter.vhd
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

to_signed(969,
to_signed(-3103,
to_signed(9874,
to_signed(9874,
to_signed(-3103,
to_signed(969,
to_signed(-584,
to_signed(100,
to_signed(-64,
to_signed(-1,
to_signed(1,

coef_cantBits),
coef_cantBits),
coef_cantBits),
coef_cantBits),
coef_cantBits),
coef_cantBits),
coef_cantBits),
coef_cantBits),
coef_cantBits),
coef_cantBits),
coef_cantBits)

);
begin

----------------------------------- CONTROL PATH

----------------------------------

-------------------------- Logica de estado actual -----------------------------process(clk,reset)


begin
if(reset = '1') then
state_reg <= esperandoDatos;
elsif(rising_edge(clk)) then
state_reg <= state_next;
end if;
end process;
-------------------------- Logica del Proximo Estado ---------------------------process(state_reg, filterStart, procesamiento_Completado)
begin
state_next <= state_reg;
case state_reg is
------------------------ esperandoDatos -----------------------when esperandoDatos =>
if(filterStart = '1') then
state_next <= ocupado;
end if;
------------------------- ocupado ------------------------when ocupado =>
if(procesamiento_Completado = '1') then
state_next <= terminado;
end if;
------------------------ terminado -----------------------when terminado =>
state_next <= esperandoDatos;
end case;
end process;
------------------------------------- Salidas ----------------------------------process(state_reg,coef_reg)

Page 2

Sat Nov 29 03:22:25 2014

voiceFilter.vhd
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

--Uso esta variable auxiliar para llevar la entrada de 8 bits a 23, completando
--con ceros, y agregando un bit de signo por delante.
variable input_23bits : std_logic_vector(coef_cantBits-1 downto 0);
begin
case state_reg is
----------------------------- esperandoDatos ---------------------------when esperandoDatos =>
procesando <= '0';
filterDone <= '0';
input_to_filter <= (others => '0');
filter_Coef <= (others => '0');
----------------------------- ocupado ----------------------------when ocupado =>
procesando <= '1';
filterDone <= '0';
--Completo la entrada de 8 bits con ceros para dejarla en 23 bits,
--poniendo un cero adelante para representar el signo.
--coef_reg maneja el indice del vector de muestras de entrada
input_23bits := "0" & input(to_integer(coef_reg)) & ceros;
--Convierto a signed para realizar las operacionesc con los coeficientes.
input_to_filter <= signed(input_23bits);
--indexo el coeficiente actual (ya que lo hago multiplexando)
filter_Coef <= coef_vector(to_integer(coef_reg));
--------------------------- terminado -----------------------------when terminado =>
procesando <= '0';
--Como el estado terminado solo dura un clock y luego pasa estar en
--"esperandoDatos". Esto genera el pulso que necesita la activacion de
--la uart en wr_uart
filterDone <= '1';
--Vuelvo a llevar a cero la senal que uso para indexar cada coeficiente
--en la multiplexacion, y la de la senal de entrada.
input_to_filter <= (others => '0');
filter_Coef <= (others => '0');
end case;
end process;
----------------------------------- DATA PATH

-------------------------------------

-------------------------- Logica de estado actual -----------------------------process(clk,reset)


begin

Page 3

Sat Nov 29 03:22:25 2014

voiceFilter.vhd
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

if(reset = '1') then


coef_reg <= (others => '0');
elsif(rising_edge(clk)) then
coef_reg <= coef_next;
end if;
end process;
------------------------ Logica del proximo estado ------------------------------Como se multiplexa la multiplicacion con los distintos coeficientes del filtro,
--aqui recorro todos los coeficientes con el indice coef_next.
coef_next <= coef_reg + 1 when procesando = '1' else (others => '0');
-------------------------------- Salida -----------------------------------------El proceso de filtrado de una muestra se completa cuando se realizo
--la multiplicacion con todos los coeficientes del filtro.
procesamiento_Completado <= '1' when coef_reg = cantCoef-1 else '0';

---------------------------------- FILTRADO -------------------------------------------------------------- Logica de estado actual ------------------------------process(clk,reset)


begin
if(reset = '1') then
suma_reg <= (others => '0');
elsif(rising_edge(clk)) then
suma_reg <= suma_next;
end if;
end process;
------------------------ Logica del proximo estado ------------------------------Realizo la suma de los productos de los coeficientes del filtro con la senal
suma_next <= suma_reg + producto when procesando = '1' else (others => '0');
-------------------------------- Salida -----------------------------------------Producto entre un coeficiente y la entrada correspondiente
producto <= input_to_filter*filter_Coef;
--Senal filtrada. Como anteriormente habia multiplicado los coeficientes del
--filtro y la senal por 2^14 para tener mas resolucion. Aqui descarto los
--primeros 28 bits del resultado que es el equivalente a dividir nuevamente
--por 2^14 los coeficientes y senal respectivamente.
filteredSignal <= std_logic_vector(suma_reg(35 downto 28));
end Behavioral;

Page 4

VoiceFilter_Top.vhd
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

Sat Nov 29 01:43:03 2014

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.filter_pkg.all;

entity VoiceFilter_Top is
----------------------------------- PUERTOS - TOP ---------------------------------port(
clk, reset: in std_logic;
--Puertos de comunicacion Uart
tx_out: out std_logic;
tx_fifo_full: out std_logic;
tx_data_ready: out std_logic;
--Puertos de comunicacion con el modulo del microfono
micData: in std_logic;
micSCLK: out std_logic;
micnCS: out std_logic
);
end VoiceFilter_Top;
-------------------------------- ARQUITECTURA - TOP ------------------------------architecture Behavioral of VoiceFilter_Top is
--------------------------------- Signals ------------------------------------Senales que sirven como buffer para interconectar las salidas
--de los distintos modulos, con la salida del modulo Top.
--Mic IN
signal tick20Khz: std_logic;
--Mic OUT / generadorDeFlancos IN
signal micDone: std_logic;
--Mic, generadorDeFlancos OUT / serieParalelo IN
signal micSample: std_logic_vector(11 downto 0);
signal filterStart: std_logic;
--serieParalelo OUT / voiceFilter IN
signal parallel_data: sample(cantCoef-1 downto 0);
signal serieParaleloStart: std_logic;
--voiceFilter OUT / Uart IN
signal tx_Start: std_logic;
signal filteredSignal: std_logic_vector(sample_cantBits-1 downto 0);

------------------------------ COMPONENTES ---------------------------------------------------------------- clockDivider ---------------------------------component clockDivider


port(
--INPUTS
clk, reset: in std_logic;
--OUTPUTS
Page 1

VoiceFilter_Top.vhd
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

Sat Nov 29 01:43:03 2014

tick20Khz: out std_logic


);
end component;
-------------------------------- micSampler ---------------------------------component PmodMICRefComp
port(
--General usage
CLK
: in std_logic;
RST
: in std_logic;
--Pmod interface signals
SDATA
: in std_logic;
SCLK
: out std_logic;
nCS
: out std_logic;
--User interface signals
DATA
: out std_logic_vector(11 downto 0);
START
: in std_logic;
DONE
: out std_logic
);
end component;
-------------------------------- uart_tx_unit -------------------------------component uart_tx_unit
generic(
DBIT: integer := 8;
-- # data bits
SB_TICK: integer := 16; -- # ticks for stop bits, 16/24/32
-for 1/1.5/2 stop bits
-Selected: 1 stop bit
DVSR: integer := 7; -- baud rate divisor
-- DVSR = 100M/(16*baud rate)
DVSR_BIT: integer := 3; -- # bits of DVSR
FIFO_W: integer := 2
-- # addr bits of FIFO
-- # words in FIFO=2^FIFO_W
);
port(
clk, reset: in std_logic;
-- interfaz hacia el usuario
wr_uart: in std_logic;
w_data: in std_logic_vector(7 downto 0);
tx_full: out std_logic; --Flag de aviso.
-- interfaz hacia la PC
tx: out std_logic;
--Datos de salida a la PC
data_ready : out std_logic
);
end component;
-------------------------------- generadorDeFlanco --------------------------component generadorDeFlanco
port(
--INPUTS
clk, reset : in std_logic;
start : in std_logic;
--OUTPUTS
done : out std_logic
);
end component;
Page 2

VoiceFilter_Top.vhd
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

Sat Nov 29 01:43:03 2014

-------------------------------- serieParalelo ------------------------------component serieParalelo is


generic (cantSalidas: natural := cantCoef); --Cantidad de salidas en paralelo
port(
--INPUTS
clk, reset: in std_logic;
start: in std_logic;
input: in std_logic_vector(11 downto 0); -- 12 bits que vienen del Mic.
--OUTPUTS
--Cant. de salidas en paralelo
output: out sample(cantSalidas-1 downto 0):= (others=>(others=>'0'));
done: out std_logic
);
end component;
-------------------------------- voiceFilter --------------------------------component voiceFilter is
port(
--INPUTS
clk,reset : in std_logic;
filterStart : in std_logic;
input : in sample(cantCoef-1 downto 0);
--OUTPUTS
filterDone : out std_logic;
filteredSignal : out std_logic_vector(sample_cantBits-1 downto 0)
);
end component;
begin
--------------------------- INSTANCIAS A MODULOS ---------------------------Colocacion de modulos dentro del Top y mapeo de puertos.
--Unidad que divide el clock de la FPGA para llevarlo a 10Khz
clockDivider_unit: clockDivider --Para el saveToFile
port map(clk => clk, reset => reset, tick20Khz => tick20Khz);
--Unidadad del muestreador del microfono
micSampler_unit: PmodMICRefComp
port map(CLK => clk, RST => reset,
SDATA => micData, SCLK => micSCLK, nCS => micnCS,
DATA => micSample, START => tick20Khz, DONE => micDone);
--Generador de flanco
generadorDeFlanco_unit : generadorDeFlanco
port map(clk => clk, reset => reset,
start => micDone, done => serieParaleloStart);
--Unidad conversora de serie a paralelo para pasar del microfono al filtro.
serieParalelo_unit: serieParalelo --Para el conversor serie a paralelo
generic map(cantSalidas => cantCoef)
port map(clk => clk, reset => reset,
input => micSample, output => parallel_data,
start => serieParaleloStart, done => filterStart);
--Unidadad del filtro
voiceFilter_unit: voiceFilter --Para el filtro
port map(clk => clk, reset => reset,
Page 3

VoiceFilter_Top.vhd
175
176
177
178
179
180
181
182
183
184
185
186
187
188

Sat Nov 29 01:43:04 2014


filterStart => filterStart, filterDone => tx_Start,
input => parallel_data, filteredSignal => filteredSignal);

--Unidadad que guarda la salida del filtro en un archivo


uart_unit: uart_tx_unit --Para el uart_tx_unit
--Para elegir baudrate = 460800 baud
generic map(DVSR => 14, DVSR_BIT => 4)
port map(clk => clk, reset => reset,
wr_uart => tx_Start, data_ready => tx_data_ready,
w_data => filteredSignal, tx => tx_out,
tx_full => tx_fifo_full);
end Behavioral;

Page 4

You might also like