LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.all;
USE IEEE.STD_LOGIC_UNSIGNED.all;
entity iir_relax is
generic(Nd : Integer := 8; -- data width
Ns : Integer := 2; -- shift step/tc
Na : Integer :=18); -- acc width
port ( -- note: Nd+3*Ns<Na!
clk : in std_logic;
clr : in std_logic;
ena : in std_logic;
x : in std_logic_vector(Nd-1 downto 0); -- input data
tc : in std_logic_vector( 1 downto 0); -- time constant
y : out std_logic_vector(Nd-1 downto 0)); -- output
end iir_relax;
architecture a of iir_relax is
signal acc : std_logic_vector(Na-1 downto 0);
signal diff : std_logic_vector(Nd downto 0);
signal diffe : std_logic_vector(Na-1 downto 0);
signal y_i : std_logic_vector(Nd-1 downto 0); -- output
constant zero0 : std_logic_vector(3*Ns-1 downto 0) := (others => '0');
constant zero1 : std_logic_vector(2*Ns-1 downto 0) := (others => '0');
constant zero2 : std_logic_vector( Ns-1 downto 0) := (others => '0');
begin
y_i <= acc(Na-1 downto Na-Nd);
y <= y_i;
diff <= ('0' & x) - ('0' & y_i);
process(diff, tc)
begin
diffe <= (others => diff(Nd)); -- fill with the sign bit
case tc is -- overwrite with data & zeroes from the right
when "00" =>
diffe(Nd+3*Ns-1 downto 0) <= diff(Nd-1 downto 0) & zero0;
when "01" =>
diffe(Nd+2*Ns-1 downto 0) <= diff(Nd-1 downto 0) & zero1;
when "10" =>
diffe(Nd+1*Ns-1 downto 0) <= diff(Nd-1 downto 0) & zero2;
when "11" =>
diffe(Nd -1 downto 0) <= diff(Nd-1 downto 0);
when others => diffe <= (others => '-');
end case;
end process;
process(clk) -- the accumulator
begin
if rising_edge(clk) then
if clr='1' then acc <= (others => '0');
elsif ena='1' then acc <= acc + diffe;
end if;
end if;
end process;
end;