-
Notifications
You must be signed in to change notification settings - Fork 13
/
iir_lpf_complex.vhd
85 lines (75 loc) · 3.17 KB
/
iir_lpf_complex.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
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
-----------------------------------------------------------------------
-- (c) Copyright: OscillatorIMP Digital
-- Author : Ivan Ryger, ivan.ryger@femto-st.fr
-- Creation date : 2021/10/28
-----------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity iir_lpf_complex is
generic(
DATA_WIDTH : natural := 16;
FILTER_COEFF_TWOS_POWER : natural := 10
);
port(
data_i_i : in std_logic_vector(DATA_WIDTH-1 downto 0);
data_q_i : in std_logic_vector(DATA_WIDTH-1 downto 0);
data_en_i : in std_logic;
data_clk_i : in std_logic;
data_rst_i : in std_logic;
data_i_o : out std_logic_vector(DATA_WIDTH-1 downto 0);
data_q_o : out std_logic_vector(DATA_WIDTH-1 downto 0);
data_en_o : out std_logic;
data_clk_o : out std_logic;
data_rst_o : out std_logic
);
end entity;
architecture bhv of iir_lpf_complex is
--recursive filter implementation with transfer function
-- H(z) = 2^(-N)*z^(-1)/(1-(1-2^-N)*z^(-1))
constant INT_SIG_WIDTH : natural := DATA_WIDTH + 2 * FILTER_COEFF_TWOS_POWER;
constant COEFF_WIDTH : natural := FILTER_COEFF_TWOS_POWER;
signal data_i_1,data_i_4 : std_logic_vector(INT_SIG_WIDTH - 1 downto 0) := (others => '0');
signal data_q_1,data_q_4 : std_logic_vector(INT_SIG_WIDTH - 1 downto 0) := (others => '0');
signal data_i_2,data_i_3 : std_logic_vector(INT_SIG_WIDTH - 1 downto 0);
signal data_q_2,data_q_3 : std_logic_vector(INT_SIG_WIDTH - 1 downto 0);
signal en_i_1 : std_logic := '0';
begin
data_i_2 <= std_logic_vector(signed(data_i_1) - signed(data_i_4));
data_q_2 <= std_logic_vector(signed(data_q_1) - signed(data_q_4));
--we add 1/2 LSB to perform rounding instead of truncation - lower quantization noise
data_i_3 <= std_logic_vector(shift_right(signed(data_i_2) + to_signed(2**(COEFF_WIDTH-1),data_i_2'length) , COEFF_WIDTH) + signed(data_i_4));
data_q_3 <= std_logic_vector(shift_right(signed(data_q_2) + to_signed(2**(COEFF_WIDTH-1),data_q_2'length) , COEFF_WIDTH) + signed(data_q_4));
data_i_o <= std_logic_vector(resize(shift_right(signed(data_i_4)+ to_signed(2**(COEFF_WIDTH-1),data_i_2'length) , COEFF_WIDTH),data_i_o'length));
data_q_o <= std_logic_vector(resize(shift_right(signed(data_q_4)+ to_signed(2**(COEFF_WIDTH-1),data_q_2'length) , COEFF_WIDTH),data_q_o'length));
data_en_o <= en_i_1;
data_clk_o <= data_clk_i;
data_rst_o <= data_rst_i;
process(data_clk_i) is
begin
if rising_edge(data_clk_i) then
en_i_1 <= data_en_i;
if (data_rst_i = '1') then
en_i_1 <= '0';
data_i_1 <= (others => '0');
data_q_1 <= (others => '0');
data_i_4 <= (others => '0');
data_q_4 <= (others => '0');
end if;
if (data_en_i = '1') then
data_i_1 <= std_logic_vector(shift_left(resize(signed(data_i_i),INT_SIG_WIDTH),COEFF_WIDTH)); -- sample input data
data_q_1 <= std_logic_vector(shift_left(resize(signed(data_q_i),INT_SIG_WIDTH),COEFF_WIDTH)); -- sample input data
else
data_i_1 <= data_i_1;
data_q_1 <= data_q_1;
end if;
if (en_i_1 = '1') then
data_i_4 <= data_i_3; -- shift register
data_q_4 <= data_q_3;
else
data_i_4 <= data_i_4;
data_q_4 <= data_q_4;
end if;
end if;
end process;
end architecture bhv;