User:1sfoerster/enes245/fall2014/FIR FPGA SDR filter

=Problem= We are now living in an age of Information Technology; most of information technology is based on DSP( digital signal processing). Telecommunication, speech processing, consumer electronics, image processing and biomedical systems are some applications of DSP. Filtering is the most common part of DSP and it is used in all the previously mentioned applications. So what are filters? filters are mainly used in signal processing to remove unwanted frequencies from an incoming signal. FIR's and IIR's are described as the two filter types found in Software Defined Radio. The goal is to build a FIR in a papilio to and figure out how they work. Ultimately the goal is to connect it to open source SDR software running in a computer. FIR's and IIR's are described as the two filter types found in Software Defined Radio. The goal is to build a FIR in a papilio to and figure out how they work. Ultimately the goal is to connect it to open source SDR software running in a computer.

=Conceive= start reading here:
 * Read this Filters in VHDL
 * Read this |Project Resources
 * Read this Filter Project
 * Read this FIR filter basics.
 * Read this wikipedia FIR entry
 * Read this paper up to figure 2.

=Design=

Repeat this project

* 3 Bit counter for synchronization. * 5 ,32 bit IIR coefficients registers. * 2  2 stage delay lines *  2 state-fsm for synchronizing the math operations. * multipliers(32 X32 bits) * 32 bit to 18 bit truncation for the DAC output * 32 bits and 18 bits truncation blocks. Next, I will write theVHDL code performing the desired filtering.

--/////////////// STATE MACHINE TO CONFIGURE THE AC97 //////////////////--

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;

-- one can add extra inputs and signals to control the input to LM4550 (ac97) register map below see volume and source for example entity ac97cmd is	port (		 clk     			: in  std_logic;		 ac97_ready_sig   : in  std_logic;		 cmd_addr 			: out std_logic_vector(7 downto 0);		 cmd_data 			: out std_logic_vector(15 downto 0);		 latching_cmd		: out std_logic;		 volume   			: in  std_logic_vector(4 downto 0);  			-- input for encoder for volume control 0->31		 source   			: in  std_logic_vector(2 downto 0)); 			-- 000 = Mic, 100=LineIn end ac97cmd;

architecture arch of ac97cmd is	signal cmd 		: std_logic_vector(23 downto 0); signal atten  : std_logic_vector(4 downto 0);							-- used to set atn in 04h ML4:0/MR4:0 type state_type is (S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11); signal cur_state, next_state : state_type; begin -- parse command from data cmd_addr <= cmd(23 downto 16); cmd_data <= cmd(15 downto 0); atten     <= std_logic_vector(31 - unsigned(volume));      		-- convert vol to attenuation

-- USED TO DETERMINE IF THE REGISTER ADDRESS IS VALID -- one can add more with select statments with output signals to do more error checking -	with cmd(23 downto 16) select latching_cmd <= '1' when X"02" | X"04" | X"06" | X"0A" | X"0C" | X"0E" | X"10" | X"12" | X"14" | X"16" | X"18" | X"1A" | X"1C" | X"20" | X"22" | X"24" | X"26" | X"28" | X"2A" | X"2C" | X"32" | X"5A" | X"74" | X"7A" | X"7C" | X"7E" | X"80", '0' when others; -- go through states based on input pulses from ac97 ready signal --	process(clk, next_state, cur_state) begin if(clk'event and clk = '1') then if ac97_ready_sig = '1' then cur_state <= next_state; end if; end if; end process; -- use state machine to configure controller -- refer to register map on LM4550 data sheet -- signals and input busses can be added to control -- the AC97 codec refer to the source and volume to see how -- first part is address, second part after _ is command -- states and input signals can be added for real time configuration of 	-- any ac97 register ---	process (next_state, cur_state, atten, source) begin

case cur_state is			when S0 => cmd <= X"02_0000"; 												-- master volume	0 0000->0dB atten, 1 1111->46.5dB atten next_state <= S2; when S1 => cmd <= X"04" & "000" & atten & "000" & atten;			-- headphone volume next_state <= S4; when S2 => cmd <= X"0A_0000"; 												-- Set pc_beep volume next_state <= S11; when S3 => cmd <= X"0E_8048"; 												-- Mic Volume set to gain of +20db next_state <= S10; when S4 => cmd <= X"18_0808"; 												-- PCM volume next_state <= S6; when S5 => cmd <= X"1A" & "00000" & source & "00000" & source; 	-- Record select reg 000->Mic, 001->CD in l/r, 010->Video in l/r, 011->aux in l/r next_state <= S7;													-- 100->line_in l/r, 101->stereo mix, 110->mono mix, 111->phone input when S6 => cmd <= X"1C_0F0F"; 												-- Record gain set to max (22.5dB gain) next_state <= S8; when S7 => cmd <= X"20_8000"; 												-- PCM out path 3D audio bypassed next_state <= S0; when S8 => cmd <= X"2C_BB80";  											-- DAC rate 48 KHz (BB80),	can be set to 1F40 = 8Khz, 2B11 = 11.025KHz, 3E80 = 16KHz, next_state <= S5;													-- 5622 = 22.05KHz, AC44 = 44.1KHz, BB80 = 48KHz when S9 => cmd <= X"32_BB80"; 												-- ADC rate 48 KHz (BB80),	can be set to 1F40 = 8Khz, 2B11 = 11.025KHz, 3E80 = 16KHz, next_state <= S3;													-- 5622 = 22.05KHz, AC44 = 44.1KHz, BB80 = 48KHz when S10 => cmd <= X"80_0000"; 												-- Extended audio status reg, allows variable sample rate programming (X"2A_0001";) next_state <= S9; when S11 => cmd <= X"80_0000"; next_state <= S1; end case; end process;

end arch;

--/////////////////////// AC97 Driver //////////////////////////////////--

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;

entity ac97 is	port (		n_reset       : in  std_logic;		clk            : in  std_logic;																				-- ac97 interface signals		ac97_sdata_out : out std_logic;								-- ac97 output to SDATA_IN		ac97_sdata_in  : in  std_logic;								-- ac97 input from SDATA_OUT		ac97_sync      : out std_logic;								-- SYNC signal to ac97		ac97_bitclk    : in  std_logic;								-- 12.288 MHz clock from ac97		ac97_n_reset   : out std_logic;								-- ac97 reset for initialization [active low]		ac97_ready_sig : out std_logic; 								-- pulse for one cycle		L_out          : in  std_logic_vector(17 downto 0);	-- lt chan output from ADC		R_out          : in  std_logic_vector(17 downto 0);	-- rt chan output from ADC		L_in           : out std_logic_vector(17 downto 0);	-- lt chan input to DAC		R_in           : out std_logic_vector(17 downto 0);	-- rt chan input to DAC		latching_cmd	: in std_logic;		cmd_addr       : in  std_logic_vector(7 downto 0);		-- cmd address coming in from ac97cmd state machine cmd_data      : in  std_logic_vector(15 downto 0));	-- cmd data coming in from ac97cmd state machine end ac97;

architecture arch of ac97 is

signal Q1, Q2  			: std_logic;								-- signals to deliver one cycle pulse at specified time signal bit_count   		: std_logic_vector(7 downto 0);		-- counter for aligning slots signal rst_counter 	 	: integer range 0 to 4097;				-- counter to set ac97_reset high for ac97 init signal latch_cmd_addr  : std_logic_vector(19 downto 0);		-- signals to latch in registers and commands signal latch_cmd_data  : std_logic_vector(19 downto 0);

signal latch_left_data	: std_logic_vector(19 downto 0); signal latch_right_data : std_logic_vector(19 downto 0);

signal left_data    	: std_logic_vector(19 downto 0); signal right_data   	: std_logic_vector(19 downto 0); signal left_in_data 	: std_logic_vector(19 downto 0); signal right_in_data 	: std_logic_vector(19 downto 0); begin

-- concat for 18 bit usage can concat further for 16 bit use -- by using <& "0000"> and  -	left_data <= L_out & "00"; right_data <= R_out & "00";

L_in <= left_in_data(19 downto 2); R_in <= right_in_data(19 downto 2);

-- Delay for ac97_reset signal, clk = 100MHz -- delay 37.89 us / 10 ns = 3789 for active low reset on init --	process (clk, n_reset) begin if (clk'event and clk = '1') then if n_reset = '0' then rst_counter <= 0; ac97_n_reset <= '0'; elsif rst_counter = 3789 then ac97_n_reset <= '1'; rst_counter <= 0; else rst_counter <= rst_counter + 1; end if; end if; end process; -- This process generates a single clkcycle pulse -- to get configuration data from the ac97cmd FSM -- and lets the user know when a sample is ready ---											process (clk, n_reset, bit_count) begin if(clk'event and clk = '1') then Q2 <= Q1; if(bit_count = "00000000") then Q1 <= '0'; Q2 <= '0'; elsif(bit_count >= "10000001") then Q1 <= '1'; end if; ac97_ready_sig <= Q1 and not Q2; end if; end process; -- ac97-link frame is 256 cycles -- [slot0], [slot1], [slot2], [slot3], [slot4], [slot5] ... [slot9], [slot10], [slot11], [slot12] -- slot 0 [tag phase] is 16 cycles slot1:12 are 20 cycles so 16 + 12 * 20 = 256 cycles -- ac97 link output frame [frame going out] ---	process (n_reset, bit_count, ac97_bitclk) begin if(n_reset = '0') then																-- active low reset bit_count <= "00000000";														-- starts bit count at 0 end if; if (ac97_bitclk'event and ac97_bitclk = '1') then							-- rising edge of ac97_bitclk if bit_count = "11111111" then												-- Generate sync signal for ac97 ac97_sync <= '1';																-- at bitcnt = 255

end if;

if bit_count = "00001111" then												-- at bitcnt = 15 ac97_sync <= '0'; end if;

-- At the end of each frame the user data is latched in 			if bit_count = "11111111" then latch_cmd_addr  <= cmd_addr & "000000000000"; latch_cmd_data  <= cmd_data & "0000"; latch_left_data <= left_data; latch_right_data <= right_data; end if; -- Tag phase if (bit_count >= "00000000") and (bit_count <= "00001111") then	-- bit count 0 to 15 -- Slot 0 : Tag Phase case bit_count is																-- Can create input signals to verify on tag phase when "00000000"     => ac97_sdata_out <= '1';      			-- AC Link Interface ready when "00000001"     => ac97_sdata_out <= latching_cmd;  	-- Vaild Status Adress or Slot request when "00000010"     => ac97_sdata_out <= '1';  				-- Valid Status data when "00000011"     => ac97_sdata_out <= '1';      			-- Valid PCM Data (Left ADC) when "00000100"     => ac97_sdata_out <= '1';      			-- Valid PCM Data (Right ADC) when others => ac97_sdata_out <= '0'; end case; -- starting at slot 1 add 20 bit counts each time elsif (bit_count >= "00010000") and (bit_count <= "00100011") then	-- bit count 16 to 35 -- Slot 1 : Command address (8-bits, left justified) if latching_cmd = '1' then ac97_sdata_out <= latch_cmd_addr(35 - to_integer(unsigned(bit_count))); else ac97_sdata_out <= '0'; end if;

elsif (bit_count >= "00100100") and (bit_count <= "00110111") then	-- bit count 36 to 55 -- Slot 2 : Command data (16-bits, left justified) if latching_cmd = '1' then ac97_sdata_out <= latch_cmd_data(55 - to_integer(unsigned(bit_count))); else ac97_sdata_out <= '0'; end if;

elsif ((bit_count >= "00111000") and (bit_count <= "01001011")) then	-- bit count 56 to 75

-- Slot 3 : left channel ac97_sdata_out <= latch_left_data(19);										-- send out bits and rotate through 20 bit word

latch_left_data <= latch_left_data(18 downto 0) & latch_left_data(19);

elsif ((bit_count >= "01001100") and (bit_count <= "01011111")) then	-- bit count 76 to 95 -- Slot 4 : right channel ac97_sdata_out <= latch_right_data(95 - to_integer(unsigned(bit_count))); else ac97_sdata_out <= '0'; end if;

-- incriment bit counter bit_count <= std_logic_vector(unsigned(bit_count) + 1); end if; end process;

-- ac97 link input frame [frame coming in] ---	process (ac97_bitclk) begin if (ac97_bitclk'event and ac97_bitclk = '0') then								-- clock on falling edge of bitclk if (bit_count >= "00111001") and (bit_count <= "01001100") then 		-- from 115 to 76 -- Slot 3 : left channel left_in_data <= left_in_data(18 downto 0) & ac97_sdata_in;			-- concat incoming bits on end elsif (bit_count >= "01001101") and (bit_count <= "01100000") then 	-- from 77 to 96 -- Slot 4 : right channel right_in_data <= right_in_data(18 downto 0) & ac97_sdata_in;		-- concat incoming bits on end end if; end if; end process;

end arch;

--////////////////////// IIR_Biquad_II /////////////////////////////////--

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL;

entity IIR_Biquad_II is		Port ( 				clk : in STD_LOGIC;				n_reset : in  STD_LOGIC;				sample_trig : in  STD_LOGIC;				X_in : in  STD_LOGIC_VECTOR (17 downto 0);				filter_done : out STD_LOGIC;				Y_out : out  STD_LOGIC_VECTOR (17 downto 0)				); end IIR_Biquad_II;

architecture arch of IIR_Biquad_II is

-- band stop butterworth 2nd order  fo = 59.79, fl = 55Hz, fu = 65Hz, Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB	-- --	--			          b0 + b1*Z^-1 + b2*Z^-2 --				H[z] = - --						 1 + a1*Z^-1 + a2*Z^-2 --	--

-- define biquad coefficients constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_11_1111_1111_1101_1101_1011_0000_1001";				-- b0		~ +0.999869117 constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"10_00_0000_0000_0101_0100_1100_1000_1010";				-- b1		~ -1.999676575 constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"00_11_1111_1111_1101_1101_1011_0000_1001";				-- b2		~ +0.999869117

constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"10_00_0000_0000_0101_0100_1100_1000_1010";				-- a1		~ -1.999676575 constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_11_1111_1111_1011_1011_0110_0001_0011";				-- a2		~ +0.999738235 -- define each pre gain sample flip flop signal ZFF_X0, ZFF_X1, ZFF_X2, ZFF_Y1, ZFF_Y2 : std_logic_vector(31 downto 0) := (others => '0');

-- define each post gain 64 bit sample signal pgZFF_X0_quad, pgZFF_X1_quad, pgZFF_X2_quad, pgZFF_Y1_quad, pgZFF_Y2_quad : std_logic_vector( 63 downto 0) := (others => '0');

-- define each post gain 32 but truncated sample signal pgZFF_X0, pgZFF_X1, pgZFF_X2, pgZFF_Y1, pgZFF_Y2 : std_logic_vector(31 downto 0) := (others => '0');

-- define output double reg signal Y_out_double : std_logic_vector(31 downto 0) := (others => '0'); -- state machine signals type state_type is (idle, run); signal state_reg, state_next : state_type; -- counter signals signal q_reg, q_next : unsigned(2 downto 0); signal q_reset, q_add : std_logic;

-- data path flags signal mul_coefs, trunc_prods, sum_stg_a, trunc_out : std_logic;

begin

-- process to shift samples process(clk, n_reset, Y_out_double, sample_trig) begin if(n_reset = '0') then ZFF_X0 <= (others => '0'); ZFF_X1 <= (others => '0'); ZFF_X2 <= (others => '0'); ZFF_Y1 <= (others => '0'); ZFF_Y2 <= (others => '0');

elsif(rising_edge(clk)) then if(sample_trig = '1') then ZFF_X0 <= X_in(17) & X_in(17) & X_in & B"0000_0000_0000"; ZFF_X1 <= ZFF_X0; ZFF_X2 <= ZFF_X1; ZFF_Y1 <= Y_out_double; ZFF_Y2 <= ZFF_Y1; end if; end if; end process; -- STATE UPDATE AND TIMING process(clk, n_reset) begin if(n_reset = '0') then state_reg <= idle; q_reg <= (others => '0');                              -- reset counter elsif (rising_edge(clk)) then state_reg <= state_next;                               -- update the state q_reg <= q_next; end if; end process; -- COUNTER FOR TIMING q_next <= (others => '0') when q_reset = '1' else              -- resets the counter q_reg + 1 when q_add = '1' else                -- increment count if commanded q_reg; -- process for control of data path flags process( q_reg, state_reg, sample_trig) begin -- defaults q_reset <= '0'; q_add <= '0'; mul_coefs <= '0'; trunc_prods <= '0'; sum_stg_a <= '0'; trunc_out <= '0'; filter_done <= '0'; case state_reg is		when idle => if(sample_trig = '1') then state_next <= run; else state_next <= idle; end if; when run => if( q_reg < B"001") then

q_add <= '1'; state_next <= run; elsif( q_reg < "011") then mul_coefs <= '1'; q_add <= '1'; state_next <= run; elsif( q_reg < "100") then trunc_prods <= '1'; q_add <= '1'; state_next <= run; elsif( q_reg < "101") then sum_stg_a <= '1'; q_add <= '1'; state_next <= run; elsif( q_reg < "110") then trunc_out <= '1'; q_add <= '1'; state_next <= run; else q_reset <= '1'; filter_done <= '1'; state_next <= idle; end if; end case; end process;

-- add gain factors to numerator of biquad (feed forward path) pgZFF_X0_quad <= std_logic_vector( signed(Coef_b0) * signed(ZFF_X0)) when mul_coefs = '1'; pgZFF_X1_quad <= std_logic_vector( signed(Coef_b1) * signed(ZFF_X1)) when mul_coefs = '1'; pgZFF_X2_quad <= std_logic_vector( signed(Coef_b2) * signed(ZFF_X2)) when mul_coefs = '1';

-- add gain factors to denominator of biquad (feed back path) pgZFF_Y1_quad <= std_logic_vector( signed(Coef_a1) * signed(ZFF_Y1)) when mul_coefs = '1'; pgZFF_Y2_quad <= std_logic_vector( signed(Coef_a2) * signed(ZFF_Y2)) when mul_coefs = '1';

-- truncate the output to summation block process(clk, trunc_prods, pgZFF_X0_quad, pgZFF_X1_quad, pgZFF_X2_quad, pgZFF_Y1_quad, pgZFF_Y2_quad) begin if rising_edge(clk) then if (trunc_prods = '1') then pgZFF_X0 <= pgZFF_X0_quad(61 downto 30); pgZFF_X2 <= pgZFF_X2_quad(61 downto 30); pgZFF_X1 <= pgZFF_X1_quad(61 downto 30); pgZFF_Y1 <= pgZFF_Y1_quad(61 downto 30); pgZFF_Y2 <= pgZFF_Y2_quad(61 downto 30); end if; end if; end process;

-- sum all post gain feedback and feedfoward paths -- Y[z] = X[z]*bo + X[z]*b1*Z^-1 + X[z]*b2*Z^-2 - Y[z]*a1*z^-1 + Y[z]*a2*z^-2 process(clk, sum_stg_a) begin if(rising_edge(clk)) then if(sum_stg_a = '1') then Y_out_double <= std_logic_vector(signed(pgZFF_X0) + signed(pgZFF_X1) + signed(pgZFF_X2) - signed(pgZFF_Y1) - signed(pgZFF_Y2)); end if; end if; end process;

-- output truncation block process(clk, trunc_out) begin if rising_edge(clk) then if (trunc_out = '1') then Y_out <= Y_out_double( 30 downto 13); end if; end if; end process; end arch;

-- Pre Generated Example IIR filters --- --- ---

--	-- band pass 2nd order butterworth  f0 = 2000Hz, fl = 1500Hz, fu = 2500 Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB --	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--	--	-- define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_00_0011_1110_1111_1100_1111_0000_1111";				-- b0		~ +0.061511769 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"00_00_0000_0000_0000_0000_0000_0000_0000";				-- b1		~ 0.0 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"11_11_1100_0001_0000_0011_0000_1111_0001";				-- b0		~ -0.061511769

--	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"10_00_1011_1011_0111_1011_1110_0101_0111";				-- a1		~ -1.816910185 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_11_1000_0010_0000_0110_0001_1110_0010";				-- a2		~ +0.876976463

--	-- band pass 2nd order elliptical  fl= 7200Hz, fu = 7400Hz, Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB --	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--	--	-- define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_11_1111_1101_0010_0010_0011_1010_0101";				-- b0		~ +0.9944543 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"10_11_0110_1000_0111_0101_1111_1101_1011";				-- b1		~ -1.1479874 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"00_11_1111_1101_0010_0010_0011_1010_0101";				-- b2		~ +0.9944543

--	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"10_11_0110_1000_0111_0101_1111_1101_1011";				-- a1		~ -1.1479874 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_11_1111_0100_1010_0100_0111_0100_1011";				-- a2		~ +0.9889086

--	 stop band 2nd order butterworth  f0 = 3000Hz, fl = 2000Hz, fu = 4000Hz,  Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB --	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--	--	-- define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_11_1000_1000_1101_1111_0001_1100_0110";				-- b0		~ +0.8836636 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"10_01_0110_1001_1001_0110_1000_0001_1011";				-- b1		~ -1.6468868 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"00_11_1000_1000_1101_1111_0001_1100_0110";				-- b2		~ +0.8836636

--	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"10_01_0110_1001_1001_0110_1000_0001_1011";				-- a1		~ -1.6468868 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_11_0001_0001_1011_1110_0011_1000_1011";				-- a2		~ +0.7673272

--	-- band pass 2nd order elliptical  fl= 2000Hz, fu = 2500Hz, Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB --	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--	--	-- define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_00_0100_1001_0001_0011_0101_0100_0111";				-- b0		~ +0.0713628 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"00_00_0000_0000_0000_0000_0000_0000_0000";				-- b1		~ +0.0 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"11_11_1011_0110_1110_1100_1010_1011_1000";				-- b2		~ -0.0713628

--	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"10_00_1110_0011_0001_0001_1010_1011_1111";				-- a1		~ -1.7782529 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_11_0110_1101_1101_1001_0101_0111_0001";				-- a2		~ +0.8572744

--  -- Used Bilinear Z Transform --	-- low pass 2nd order butterworth  fc = 12000Hz, Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB --	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--	--	-- define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_01_0010_1011_1110_1100_0011_0011_0011";				-- b0		~ +0.292893219 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"00_10_0101_0111_1101_1000_0110_0110_0110";				-- b1		~ +0.585786438 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"00_01_0010_1011_1110_1100_0011_0011_0011";				-- b2		~ +0.292893219

--	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"00_00_0000_0000_0000_0000_0000_0000_0000";				-- a1		~ 0.0 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_00_0000_0000_0000_0101_0111_1101_1000";				-- a2		~ +0.171572875

-- --	-- stop band 2nd order butterworth  f0 = 3000Hz, fl = 2000Hz, fu = 4000Hz,  Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB --	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--	--	-- define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_11_1000_1000_1101_1111_0001_1100_0110";				-- b0		~ +0.8836636 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"10_01_0110_1001_1001_0110_1000_0001_1011";				-- b1		~ -1.6468868 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"00_11_1000_1000_1101_1111_0001_1100_0110";				-- b2		~ +0.8836636

--	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"10_01_0110_1001_1001_0110_1000_0001_1011";				-- a1		~ -1.6468868 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_11_0001_0001_1011_1110_0011_1000_1011";				-- a2		~ +0.7673272

////////////////////// IIR_Biquad_I //////////////////////////////////--

-- This biquad is set up for 18 bit input words with 32 bit coefficients

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL;

entity IIR_Biquad is		Port ( 				clk : in STD_LOGIC;				n_reset : in  STD_LOGIC;				sample_trig : in  STD_LOGIC;				X_in : in  STD_LOGIC_VECTOR (17 downto 0);				filter_done : out STD_LOGIC;				Y_out : out  STD_LOGIC_VECTOR (17 downto 0)				); end IIR_Biquad;

architecture arch of IIR_Biquad is --  -- Used Bilinear Z Transform

-- band stop butterworth 2nd order  fo = 59.79, fl = 55Hz, fu = 65Hz, Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB	-- --	--			          b0 + b1*Z^-1 + b2*Z^-2 --				H[z] = - --						 1 + a1*Z^-1 + a2*Z^-2 --	--

-- define biquad coefficients constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_00_1110_0011_1110_0101_0110_0111_1100";				-- b0		~ +0.2225548 constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"00_01_1100_0111_1100_1010_1100_1000_1110";				-- b1		~ +0.4451095 constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"00_00_1110_0011_1110_0101_0110_0111_1100";				-- b2		~ +0.2225548

constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"11_10_1010_0110_1001_1101_0101_0001_1011";				-- a1		~ -0.3372905 constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_01_0011_1000_0011_1100_1110_1100_0001";				-- a2		~ +0.3049199

-- define each pre gain sample flip flop signal ZFF_X0, ZFF_X1, ZFF_X2, ZFF_Y1, ZFF_Y2 : std_logic_vector(17 downto 0) := (others => '0');

-- define each post gain 64 bit sample signal pgZFF_X0_quad, pgZFF_X1_quad, pgZFF_X2_quad, pgZFF_Y1_quad, pgZFF_Y2_quad : std_logic_vector( 49 downto 0) := (others => '0');

-- define each post gain 32 but truncated sample signal pgZFF_X0, pgZFF_X1, pgZFF_X2, pgZFF_Y1, pgZFF_Y2 : std_logic_vector(17 downto 0) := (others => '0');

-- define output double reg signal Y_out_double : std_logic_vector( 17 downto 0) := (others => '0'); -- state machine signals type state_type is (idle, run); signal state_reg, state_next : state_type; -- counter signals signal q_reg, q_next : unsigned(2 downto 0); signal q_reset, q_add : std_logic;

-- data path flags signal mul_coefs, trunc_prods, sum_stg_a, trunc_out : std_logic;

begin

-- process to shift samples process(clk, n_reset, Y_out_double, sample_trig) begin if(n_reset = '0') then ZFF_X0 <= (others => '0'); ZFF_X1 <= (others => '0'); ZFF_X2 <= (others => '0'); ZFF_Y1 <= (others => '0'); ZFF_Y2 <= (others => '0');

elsif(rising_edge(clk)) then if(sample_trig = '1') then ZFF_X0 <= X_in(17) & X_in(17 downto 1); ZFF_X1 <= ZFF_X0; ZFF_X2 <= ZFF_X1; ZFF_Y1 <= Y_out_double; ZFF_Y2 <= ZFF_Y1; end if; end if; end process; -- STATE UPDATE AND TIMING process(clk, n_reset) begin if(n_reset = '0') then state_reg <= idle; q_reg <= (others => '0');                              -- reset counter elsif (rising_edge(clk)) then state_reg <= state_next;                               -- update the state q_reg <= q_next; end if; end process; -- COUNTER FOR TIMING q_next <= (others => '0') when q_reset = '1' else              -- resets the counter q_reg + 1 when q_add = '1' else                -- increment count if commanded q_reg; -- process for control of data path flags process( q_reg, state_reg, sample_trig) begin -- defaults q_reset <= '0'; q_add <= '0'; mul_coefs <= '0'; trunc_prods <= '0'; sum_stg_a <= '0'; trunc_out <= '0'; filter_done <= '0'; case state_reg is		when idle => if(sample_trig = '1') then state_next <= run; else state_next <= idle; end if; when run => if( q_reg < "001") then

q_add <= '1'; state_next <= run; elsif( q_reg < "011") then mul_coefs <= '1'; q_add <= '1'; state_next <= run; elsif( q_reg < "100") then trunc_prods <= '1'; q_add <= '1'; state_next <= run; elsif( q_reg < "101") then sum_stg_a <= '1'; q_add <= '1'; state_next <= run; elsif( q_reg < "110") then trunc_out <= '1'; q_add <= '1'; state_next <= run; else q_reset <= '1'; filter_done <= '1'; state_next <= idle; end if; end case; end process; -- add gain factors to numerator of biquad (feed forward path) pgZFF_X0_quad <= std_logic_vector( signed(Coef_b0) * signed(ZFF_X0)) when mul_coefs = '1'; pgZFF_X1_quad <= std_logic_vector( signed(Coef_b1) * signed(ZFF_X1)) when mul_coefs = '1'; pgZFF_X2_quad <= std_logic_vector( signed(Coef_b2) * signed(ZFF_X2)) when mul_coefs = '1';

-- add gain factors to denominator of biquad (feed back path) pgZFF_Y1_quad <= std_logic_vector( signed(Coef_a1) * signed(ZFF_Y1)) when mul_coefs = '1'; pgZFF_Y2_quad <= std_logic_vector( signed(Coef_a2) * signed(ZFF_Y2)) when mul_coefs = '1';

-- truncate the output to summation block process(clk, trunc_prods, pgZFF_X0_quad, pgZFF_X1_quad, pgZFF_X2_quad, pgZFF_Y1_quad, pgZFF_Y2_quad) begin if rising_edge(clk) then if (trunc_prods = '1') then pgZFF_X0 <= pgZFF_X0_quad(47 downto 30); pgZFF_X2 <= pgZFF_X2_quad(47 downto 30); pgZFF_X1 <= pgZFF_X1_quad(47 downto 30); pgZFF_Y1 <= pgZFF_Y1_quad(47 downto 30); pgZFF_Y2 <= pgZFF_Y2_quad(47 downto 30); end if; end if; end process;

-- sum all post gain feedback and feedfoward paths -- Y[z] = X[z]*bo + X[z]*b1*Z^-1 + X[z]*b2*Z^-2 - Y[z]*a1*z^-1 + Y[z]*a2*z^-2 process(clk, sum_stg_a) begin if(rising_edge(clk)) then if(sum_stg_a = '1') then Y_out_double <= std_logic_vector(signed(pgZFF_X0) + signed(pgZFF_X1) + signed(pgZFF_X2) - signed(pgZFF_Y1) - signed(pgZFF_Y2)); end if; end if; end process;

-- output truncation block process(clk, trunc_out) begin if rising_edge(clk) then if (trunc_out = '1') then Y_out <= Y_out_double( 17 downto 0); end if; end if; end process; end arch;

--	-- band pass 2nd order butterworth  f0 = 2000Hz, fl = 1500Hz, fu = 2500 Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB --	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--	--	-- define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_00_0011_1110_1111_1100_1111_0000_1111";				-- b0		~ +0.061511769 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"00_00_0000_0000_0000_0000_0000_0000_0000";				-- b1		~ 0.0 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"11_11_1100_0001_0000_0011_0000_1111_0001";				-- b0		~ -0.061511769

--	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"10_00_1011_1011_0111_1011_1110_0101_0111";				-- a1		~ -1.816910185 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_11_1000_0010_0000_0110_0001_1110_0010";				-- a2		~ +0.876976463

--	-- low pass 2nd order butt  fl = 500Hz, Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB --	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--	--	-- --	-- define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_00_0000_0001_0000_1100_0011_1001_1100";				-- b0		~ +0.0010232 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"00_00_0000_0010_0001_1000_0111_0011_1001";				-- b1		~ +0.0020464 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"00_00_0000_0001_0000_1100_0011_1001_1100";				-- b2		~ +0.0010232

--	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"10_00_0101_1110_1011_0111_1110_0110_1000";				-- a1		~ -1.9075016 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_11_1010_0101_0111_1001_0000_0111_0101";				-- a2		~ +0.9115945

-- stop band 2nd order cheb  f0 = 2828.47,  Hz, fl = 2000Hz, fu = 4000Hz,  Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--

define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_11_1000_1000_1101_1111_0001_1100_0110";				-- b0		~ +0.8836636 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"10_01_0110_1001_1001_0110_1000_0001_1011";				-- b1		~ -1.6468868 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"00_11_1000_1000_1101_1111_0001_1100_0110";				-- b2		~ +0.8836636 -- --	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"10_01_0110_1001_1001_0110_1000_0001_1011";				-- a1		~ -1.6468868 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_11_0001_0001_1011_1110_0011_1000_1011";				-- a2		~ +0.7673272

--	-- band pass 2nd order elliptical  fl= 2000Hz, fu = 2500Hz, Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB --	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--	--	-- define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_00_0100_1001_0001_0011_0101_0100_0111";				-- b0		~ +0.0713628 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"00_00_0000_0000_0000_0000_0000_0000_0000";				-- b1		~ +0.0 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"11_11_1011_0110_1110_1100_1010_1011_1000";				-- b2		~ -0.0713628 -- --	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"10_00_1110_0011_0001_0001_1010_1011_1111";				-- a1		~ -1.7782529 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_11_0110_1101_1101_1001_0101_0111_0001";				-- a2		~ +0.8572744

--  -- Used Bilinear Z Transform --	-- low pass 2nd order butterworth  fc = 12000Hz, Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB --	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--	--	-- define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_01_0010_1011_1110_1100_0011_0011_0011";				-- b0		~ +0.292893219 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"00_10_0101_0111_1101_1000_0110_0110_0110";				-- b1		~ +0.585786438 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"00_01_0010_1011_1110_1100_0011_0011_0011";				-- b2		~ +0.292893219 -- --	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"00_00_0000_0000_0000_0000_0000_0000_0000";				-- a1		~ 0.0 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_00_0000_0000_0000_0101_0111_1101_1000";				-- a2		~ +0.171572875

--	-- band stop butterworth 2nd order  fo = 59.79, fl = 55Hz, fu = 65Hz, Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB --	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--	--	-- --	-- define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_11_1111_1111_0101_0100_1000_1000_0001";				-- b0		~ +0.9993459 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"10_00_0000_0001_0110_0110_1111_1010_1110";				-- b1		~ -1.9986306 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"00_11_1111_1111_0101_0100_1000_1000_0001";				-- b2		~ +0.9993459 -- --	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"10_00_0000_0001_0110_0110_1111_1010_1110";				-- a1		~ -1.9986306 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_11_1111_1110_1010_1001_0001_0110_1110";				-- a2		~ +0.9986919

-- --	-- stop band 2nd order ellip  fl = 500Hz, fu = 2000Hz,  Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB --	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--	--	-- --	-- define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_11_1101_0110_1100_0100_0001_0000_0110";				-- b0		~ +0.9597323 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"10_00_0110_0011_0101_0110_0111_0101_0101";				-- b1		~ -1.9029905 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"00_11_1101_0110_1100_0100_0001_0000_0110";				-- b2		~ +0.9597323

--	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"10_00_0110_0011_0101_0110_0111_0101_0101";				-- a1		~ -1.9029905 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_11_1010_1101_1000_1000_0010_0111_1000";				-- a2		~ +0.9194647 --

--	-- low pass 2nd order cheb  fc = 10000Hz, Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB --	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--	--	-- define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_00_1110_0001_0111_1010_1011_1000_0011";				-- b0		~ +0.2201947 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"00_01_1100_0010_1111_0101_0111_0000_0101";				-- b1		~ 0.4403894 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"00_00_1110_0001_0111_1010_1011_1000_0011";				-- b0		~ +0.2201947

--	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"11_10_1100_0101_0000_1101_0101_0000_0100";				-- a1		~ -0.3075664 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_00_1100_0000_1101_1101_1001_0000_0110";				-- a2		~ +0.1883452

--	-- band pass 2nd order cheb  f0 = 2000Hz, fl = 1500Hz, fu = 2500 Fs = 48000Hz, PBR = .08 dB, SBR = .03 dB --	-- b0 + b1*Z^-1 + b2*Z^-2 H[z] = - 1 + a1*Z^-1 + a2*Z^-2

--	--	-- define biquad coefficients --	constant	Coef_b0	:	std_logic_vector(31 downto 0) := B"00_00_0011_1110_1111_1100_1111_0011_0000";				-- b0		~ +0.0615118 --	constant	Coef_b1	:	std_logic_vector(31 downto 0) := B"00_00_0000_0000_0000_0000_0000_0000_0000";				-- b1		~ 0.0 --	constant	Coef_b2	:	std_logic_vector(31 downto 0) := B"11_11_1100_0001_0000_0011_0000_1100_1111";				-- b0		~ -0.0615118

--	constant	Coef_a1	:	std_logic_vector(31 downto 0) := B"10_00_1011_1011_0111_1011_1110_0100_1000";				-- a1		~ -1.8169102 --	constant	Coef_a2	:	std_logic_vector(31 downto 0) := B"00_11_1000_0010_0000_0110_0010_0000_1011";				-- a2		~ +0.8769765

=Next Steps= The simulation of the filter was conclusive and the next step is to implement this filter and useit in a radio project application.