1 |
3 |
plutonium |
-- optimized version of a 10 tap FIR hilbert filter
|
2 |
|
|
-- The impulse response is h={-0.1066 0 -0.1781 0 -0.5347 0 0.5347 0 0.1781 0 0.1066}
|
3 |
|
|
--
|
4 |
|
|
-- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
|
5 |
|
|
-- as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
|
6 |
|
|
--
|
7 |
|
|
-- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
8 |
|
|
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
9 |
|
|
--
|
10 |
|
|
-- You should have received a copy of the GNU General Public License along with this program;
|
11 |
|
|
-- if not, see <http://www.gnu.org/licenses/>.
|
12 |
|
|
|
13 |
|
|
-- Package Definition
|
14 |
|
|
|
15 |
|
|
library ieee;
|
16 |
|
|
use ieee.std_logic_1164.all;
|
17 |
|
|
use IEEE.STD_LOGIC_arith.all;
|
18 |
|
|
|
19 |
|
|
package hilbert_filter_pkg is
|
20 |
|
|
component hilbert_filter
|
21 |
|
|
generic(
|
22 |
|
|
input_data_width : integer;
|
23 |
|
|
output_data_width : integer;
|
24 |
|
|
internal_data_width : integer
|
25 |
|
|
);
|
26 |
|
|
port(
|
27 |
|
|
clk : in std_logic;
|
28 |
|
|
clk_enable : in std_logic;
|
29 |
|
|
reset : in std_logic;
|
30 |
|
|
filter_in : in std_logic_vector(15 downto 0); -- sfix16_en15
|
31 |
|
|
filter_out : out std_logic_vector(15 downto 0) -- sfix16_en10
|
32 |
|
|
);
|
33 |
|
|
end component;
|
34 |
|
|
end hilbert_filter_pkg;
|
35 |
|
|
|
36 |
|
|
package body hilbert_filter_pkg is
|
37 |
|
|
end hilbert_filter_pkg;
|
38 |
|
|
|
39 |
|
|
-- Entity Definition
|
40 |
|
|
|
41 |
|
|
library ieee;
|
42 |
|
|
use ieee.std_logic_1164.all;
|
43 |
|
|
use ieee.numeric_std.all;
|
44 |
|
|
|
45 |
|
|
use work.resize_tools_pkg.all;
|
46 |
|
|
|
47 |
|
|
entity hilbert_filter is
|
48 |
|
|
generic(
|
49 |
|
|
input_data_width : integer := 16;
|
50 |
|
|
output_data_width : integer := 16;
|
51 |
|
|
internal_data_width : integer := 16
|
52 |
|
|
);
|
53 |
|
|
port(
|
54 |
|
|
clk : in std_logic;
|
55 |
|
|
clk_enable : in std_logic;
|
56 |
|
|
reset : in std_logic;
|
57 |
|
|
filter_in : in std_logic_vector(15 downto 0); -- sfix16_en15
|
58 |
|
|
filter_out : out std_logic_vector(15 downto 0) -- sfix16_en10
|
59 |
|
|
);
|
60 |
|
|
|
61 |
|
|
end hilbert_filter;
|
62 |
|
|
|
63 |
|
|
|
64 |
|
|
architecture hilbert_filter_arch of hilbert_filter is
|
65 |
|
|
|
66 |
|
|
constant no_of_coefficients : integer := 3;
|
67 |
|
|
|
68 |
|
|
constant h0_real : real := -32.0/256.0; -- -0.106635588611691;
|
69 |
|
|
constant h2_real : real := -54.0/256.0;-- -0.178063554399423;
|
70 |
|
|
constant h4_real : real := -163.0/256.0;-- -0.534697271169593;
|
71 |
|
|
|
72 |
|
|
constant h0_int : std_logic_vector(internal_data_width-1 downto 0) := std_logic_vector(to_signed(integer(h0_real * 2.0**(internal_data_width-1)),internal_data_width));
|
73 |
|
|
constant h2_int : std_logic_vector(internal_data_width-1 downto 0) := std_logic_vector(to_signed(integer(h2_real * 2.0**(internal_data_width-1)),internal_data_width));
|
74 |
|
|
constant h4_int : std_logic_vector(internal_data_width-1 downto 0) := std_logic_vector(to_signed(integer(h4_real * 2.0**(internal_data_width-1)),internal_data_width));
|
75 |
|
|
|
76 |
|
|
|
77 |
|
|
type xmh_type is array(0 to no_of_coefficients-1) of std_logic_vector(internal_data_width-1 downto 0);
|
78 |
|
|
signal xmh : xmh_type; --x mult with coeff. h
|
79 |
|
|
signal xmhd : xmh_type; --xmh delayed one clock
|
80 |
|
|
|
81 |
|
|
signal xmhd0inv : std_logic_vector(internal_data_width-1 downto 0);
|
82 |
|
|
signal xmhd0invd : std_logic_vector(internal_data_width-1 downto 0);
|
83 |
|
|
signal xmhd0invdd : std_logic_vector(internal_data_width-1 downto 0);
|
84 |
|
|
|
85 |
|
|
type tmp_type is array(0 to no_of_coefficients) of std_logic_vector(internal_data_width-1 downto 0);
|
86 |
|
|
signal t : tmp_type; --temporary signal ater each addition
|
87 |
|
|
signal td : tmp_type; --t delayed one clock
|
88 |
|
|
signal tdd : tmp_type; --t delayed two clocks
|
89 |
|
|
|
90 |
|
|
signal y : std_logic_vector(internal_data_width-1 downto 0);
|
91 |
|
|
|
92 |
|
|
begin
|
93 |
|
|
|
94 |
|
|
xmh(0) <= std_logic_vector(shift_left(signed(resize_to_msb_trunc(filter_in,internal_data_width/2)) * signed(resize_to_msb_round(h0_int,internal_data_width/2)),1));
|
95 |
|
|
xmh(1) <= std_logic_vector(shift_left(signed(resize_to_msb_trunc(filter_in,internal_data_width/2)) * signed(resize_to_msb_round(h2_int,internal_data_width/2)),1));
|
96 |
|
|
xmh(2) <= std_logic_vector(shift_left(signed(resize_to_msb_trunc(filter_in,internal_data_width/2)) * signed(resize_to_msb_round(h4_int,internal_data_width/2)),1));
|
97 |
|
|
|
98 |
|
|
xmhd0inv <= std_logic_vector(to_signed(-1 * to_integer(signed(xmhd(0))),internal_data_width));
|
99 |
|
|
|
100 |
|
|
t(0) <= std_logic_vector(signed(xmhd0invdd) - signed(xmhd(1)));
|
101 |
|
|
t(1) <= std_logic_vector(signed(tdd(0)) - signed(xmhd(2)));
|
102 |
|
|
t(2) <= std_logic_vector(signed(tdd(1)) + signed(xmhd(2)));
|
103 |
|
|
t(3) <= std_logic_vector(signed(tdd(2)) + signed(xmhd(1)));
|
104 |
|
|
y <= std_logic_vector(signed(tdd(3)) + signed(xmhd(0)));
|
105 |
|
|
|
106 |
|
|
process (clk, reset)
|
107 |
|
|
begin
|
108 |
|
|
if reset = '1' then
|
109 |
|
|
for i in 0 to no_of_coefficients-1 loop
|
110 |
|
|
xmhd(i) <= (others => '0');
|
111 |
|
|
end loop;
|
112 |
|
|
for i in 0 to no_of_coefficients loop
|
113 |
|
|
td(i) <= (others => '0');
|
114 |
|
|
tdd(i) <= (others => '0');
|
115 |
|
|
end loop;
|
116 |
|
|
xmhd0invd <= (others => '0');
|
117 |
|
|
xmhd0invdd <= (others => '0');
|
118 |
|
|
filter_out <= (others => '0');
|
119 |
|
|
elsif clk'event and clk = '1' then
|
120 |
|
|
if clk_enable = '1' then
|
121 |
|
|
for i in 0 to no_of_coefficients-1 loop
|
122 |
|
|
xmhd(i) <= xmh(i);
|
123 |
|
|
end loop;
|
124 |
|
|
for i in 0 to no_of_coefficients loop
|
125 |
|
|
td(i) <= t(i);
|
126 |
|
|
tdd(i) <= td(i);
|
127 |
|
|
end loop;
|
128 |
|
|
xmhd0invd <= xmhd0inv;
|
129 |
|
|
xmhd0invdd <= xmhd0invd;
|
130 |
|
|
filter_out <= resize_to_msb_trunc(y,output_data_width);
|
131 |
|
|
end if;
|
132 |
|
|
end if;
|
133 |
|
|
end process;
|
134 |
|
|
|
135 |
|
|
end hilbert_filter_arch;
|