Brightstars Posted March 3, 2018 Report Share Posted March 3, 2018 I try to implement an IIR into my FPGA project(Have a futher understanding of FPGA=>http://www.apogeeweb.net/article/67.html). I've got the coefficients from my matlab program and implement the gain directly into the coefficients, though I don't need an additional gain multiplier. First I generate the product of the A1,A2,B1 and B2 coefficients, then sum them up, summarize the Input signal with the summation of A1 and A2, then multiply it with b0 and finally create the sum of the B0 product and the B1B2 summation. But my filter doesn't behave like it should in the simulation, is this approach faulty by design or is there some error I don't see in the code? LIBRARY ieee; USE ieee.std_logic_1164.ALL; use ieee.NUMERIC_STD.ALL; use ieee.std_logic_signed.all; entity IIR is generic ( OUTPUT_WIDTH : integer := 32; INPUT_WIDTH : integer := 32; B0 : integer := 14419; -- = ((2^31)/1,995) * 0,000013396 B1 : integer := -14105; -- = ((2^31)/1,995) * -0,000013103 B2 : integer := 14419; -- = ((2^31)/1,995) * 0,000013396 A1 : integer := -2147268361; -- = ((2^31)/1,995) * -1,9948 A2 : integer := 1070803162 -- = ((2^31)/1,995) * 0,99477 ); port ( iCLK : in std_logic; iRESET_N : in std_logic; inewValue : in std_logic; -- indicates a new input value iIIR_RX : in std_logic_vector (INPUT_WIDTH-1 downto 0); -- singed is expected oDone : out std_logic; -- Done Flag for next Filter oIIR_TX : out std_logic_vector (OUTPUT_WIDTH-1 downto 0)-- Output ); end entity IIR; architecture BEH_FixCoefficientIIR of IIR is type STATE_TYPE is (idle, mul, s1, s2, s3, s4, convert, finished); signal state : STATE_TYPE; constant cA1 : signed(INPUT_WIDTH-1 downto 0) := to_signed(A1,INPUT_WIDTH);-- A1 constant cA2 : signed(INPUT_WIDTH-1 downto 0) := to_signed(A2,INPUT_WIDTH);-- A2 constant cB0 : signed(INPUT_WIDTH-1 downto 0) := to_signed(B0,INPUT_WIDTH);-- B1 constant cB1 : signed(INPUT_WIDTH-1 downto 0) := to_signed(B1,INPUT_WIDTH);-- B1 constant cB2 : signed(INPUT_WIDTH-1 downto 0) := to_signed(B2,INPUT_WIDTH);-- B1 signal nSUMX : signed(INPUT_WIDTH+1 downto 0); signal nSUMA1A2 : signed(INPUT_WIDTH+1 downto 0); signal nSUMB1B2 : signed(INPUT_WIDTH+1 downto 0); signal nSUMXB0 : signed(INPUT_WIDTH+1 downto 0); signal nB0 : signed((INPUT_WIDTH*2)+1 downto 0); signal nB1 : signed((INPUT_WIDTH*2)+1 downto 0); signal nB2 : signed((INPUT_WIDTH*2)+1 downto 0); signal nA1 : signed((INPUT_WIDTH*2)+1 downto 0); signal nA2 : signed((INPUT_WIDTH*2)+1 downto 0); signal nZ1 : signed(INPUT_WIDTH+1 downto 0); signal nZ2 : signed(INPUT_WIDTH+1 downto 0); signal nY : std_logic_vector(INPUT_WIDTH-1 downto 0); signal nX : signed(INPUT_WIDTH-1 downto 0); begin IIR_STAGES: process (iCLK, iRESET_N) begin if(rising_edge(iCLK)) then if(iRESET_N = '0') then -- Reset Signals and Output nSUMX <= (others => '0'); nSUMA1A2 <= (others => '0'); nSUMB1B2 <= (others => '0'); nSUMXB0 <= (others => '0'); nZ1 <= (others => '0'); nZ2 <= (others => '0'); nB0 <= (others => '0'); nB1 <= (others => '0'); nB2 <= (others => '0'); nA1 <= (others => '0'); nA2 <= (others => '0'); nX <= (others => '0'); nY <= (others => '0'); oDone <= '0'; oIIR_TX <= (others => '0'); state <= idle; else case state is when idle => oDone <= '0'; if(iNewValue = '1') then state <= mul; nX <= signed(iIIR_RX); end if; when mul => -- Multiply signals for sums nA1 <= nZ1 * cA1; nA2 <= nZ2 * cA2; nB1 <= nZ1 * cB1; nB2 <= nZ2 * cB2; state <= s1; when s1 => -- Create sums nSUMA1A2 <= nA1(nA1'left downto INPUT_WIDTH) - nA2(nA2'left downto INPUT_WIDTH); nSUMB1B2 <= nB1(nB1'left downto INPUT_WIDTH) + nB2(nB2'left downto INPUT_WIDTH); state <= s2; when s2 => -- Create Input sum nSUMX <= nX - nSUMA1A2; state <= s3; when s3 => -- Save new values into register and multiply with coefficient B0 for Output-Sum nZ1 <= nSUMX; nZ2 <= nZ1; nB0 <= nSUMX * cB0; state <= s4; when s4 => -- Add XB0 and B1B2 summation nSUMXB0 <= nB0(nB0'left downto INPUT_WIDTH) + nSUMB1B2; state <= convert; when convert => -- convert signed to std logic vector nY <= std_logic_vector(nSUMXB0(nSUMXB0'left downto nSUMXB0'left-INPUT_WIDTH+1)); state <= finished; when finished => -- grab highest bits for output and set Done flag oIIR_TX <= nY(nY'left downto (nY'left - OUTPUT_WIDTH+1)); oDone <= '1'; state <= idle; when others => state <= idle; end case; end if; end if; end process IIR_STAGES; end architecture BEH_FixCoefficientIIR; New Async implementation LIBRARY ieee; USE ieee.std_logic_1164.ALL; use ieee.NUMERIC_STD.ALL; use ieee.std_logic_signed.all; entity IIR is generic ( OUTPUT_WIDTH : integer := 48; INPUT_WIDTH : integer := 48; B0 : integer := 14419; -- = ((2^31)/1,995) * 0,000013396 B1 : integer := -14105; -- = ((2^31)/1,995) * -0,000013103 B2 : integer := 14419; -- = ((2^31)/1,995) * 0,000013396 A1 : integer := -2147268361; -- = ((2^31)/1,995) * -1,9948 A2 : integer := 1070803162 -- = ((2^31)/1,995) * 0,99477 ); port ( iCLK : in std_logic; iRESET_N : in std_logic; inewValue : in std_logic; -- indicates a new input value iIIR_RX : in std_logic_vector (INPUT_WIDTH-1 downto 0); -- singed is expected oDone : out std_logic; -- Done Flag for next Filter oIIR_TX : out std_logic_vector (OUTPUT_WIDTH-1 downto 0)-- Output ); end entity IIR; architecture BEH_FixCoefficientIIR of IIR is constant cA1 : signed(31 downto 0) := to_signed(A1,32);-- A1 constant cA2 : signed(31 downto 0) := to_signed(A2,32);-- A2 constant cB0 : signed(31 downto 0) := to_signed(B0,32);-- B1 constant cB1 : signed(31 downto 0) := to_signed(B1,32);-- B1 constant cB2 : signed(31 downto 0) := to_signed(B2,32);-- B1 signal nSUMX : signed(48 downto 0) := (others => '0'); signal nSUMA1A2 : signed(48 downto 0) := (others => '0'); signal nSUMB1B2 : signed(48 downto 0) := (others => '0'); signal nSUMXB0 : signed(48 downto 0) := (others => '0'); signal nB0 : signed(80 downto 0) := (others => '0'); signal nB1 : signed(80 downto 0) := (others => '0'); signal nB2 : signed(80 downto 0) := (others => '0'); signal nA1 : signed(80 downto 0) := (others => '0'); signal nA2 : signed(80 downto 0) := (others => '0'); signal nZ1 : signed(48 downto 0) := (others => '0'); signal nZ2 : signed(48 downto 0) := (others => '0'); signal nY : std_logic_vector(47 downto 0) := (others => '0'); signal nX : signed(47 downto 0) := (others => '0'); begin nB0 <= nSUMX * cB0; nB1 <= nZ1 * cB1; nB2 <= nZ2 * cB2; nA1 <= nZ1 * cA1; nA2 <= nZ2 * cA2; nSUMA1A2 <= nA1(80 downto 32) + nA2(80 downto 32); nSUMB1B2 <= nB1(80 downto 32) + nB2(80 downto 32); nSUMXB0 <= nB0(80 downto 32) + nSUMB1B2; nSUMX <= nX + nSUMA1A2(48 downto 0); IIR_STAGES: process (iCLK, iRESET_N) begin if(rising_edge(iCLK)) then if(iNewValue = '1') then nX <= signed(iIIR_RX); nZ1 <= nSUMX; nZ2 <= nZ1; oIIR_TX <= std_logic_vector(nSUMXB0(48 downto 1)); end if; end if; end process IIR_STAGES; end architecture BEH_FixCoefficientIIR; Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.