--------------------------------------------------------------------------------
-- Company: <Name>
--
-- File: Systolic_FIR_Filter.vhd
-- File history:
--    
--
-- Description: This Design illustrates the implementation of 16-Tap Systolic FIR 
--				

--
-- Targeted device: <Family::SmartFusion2> <Die::M2S050> <Package::896 FBGA>
-- Author: PHANIKIRAN T
--
--------------------------------------------------------------------------------

library IEEE;

use IEEE.std_logic_1164.all;
use IEEE.std_logic_signed.all;
use IEEE.numeric_std.all;

entity Systolic_FIR_Filter is

generic (
			N : integer := 16;
			M : integer := 30 --2*(N-1)
		);

port (
    	Clk 	: in std_logic;
    	resetn	: in std_logic;
		Xn_in	: in std_logic_vector(17 downto 0);
		Yn_out	: out std_logic_vector(43 downto 0)	 
);
end Systolic_FIR_Filter;

architecture SystolicFIR_Filter_arch of Systolic_FIR_Filter is
   
component multadd is
    -- Port list
    port(
        -- Inputs
        A0        : in  std_logic_vector(17 downto 0);
        A0_ACLR_N : in  std_logic;
        A0_EN     : in  std_logic;
        A0_SCLR_N : in  std_logic;
        B0        : in  std_logic_vector(17 downto 0);
        B0_ACLR_N : in  std_logic;
        B0_EN     : in  std_logic;
        B0_SCLR_N : in  std_logic;
        CDIN      : in  std_logic_vector(43 downto 0);
        CLK       : in  std_logic;       
        P_ACLR_N  : in  std_logic;
        P_EN      : in  std_logic;
        P_SCLR_N  : in  std_logic;
        -- Outputs
        CDOUT     : out std_logic_vector(43 downto 0);
        P         : out std_logic_vector(43 downto 0)
        );
end component multadd;

component multadd_0 is
    -- Port list
    port(
        -- Inputs
        A0        : in  std_logic_vector(17 downto 0);
        A0_ACLR_N : in  std_logic;
        A0_EN     : in  std_logic;
        A0_SCLR_N : in  std_logic;
        B0        : in  std_logic_vector(17 downto 0);
        B0_ACLR_N : in  std_logic;
        B0_EN     : in  std_logic;
        B0_SCLR_N : in  std_logic;
        CDIN      : in  std_logic_vector(43 downto 0);
        CLK       : in  std_logic;
        P_ACLR_N  : in  std_logic;
        P_EN      : in  std_logic;
        P_SCLR_N  : in  std_logic;
        -- Outputs
        CDOUT     : out std_logic_vector(43 downto 0);
        P         : out std_logic_vector(43 downto 0)
        );
end component multadd_0;

-- signal, component etc. declarations

TYPE CDIN_ARRAY1 IS ARRAY (0 to N-1) OF std_logic_vector(43 DOWNTO 0);
TYPE Xreg_ARRAY1 IS ARRAY (0 to M) OF std_logic_vector(17 DOWNTO 0);
TYPE Coef_ARRAY1 IS ARRAY (0 to N-1) OF std_logic_vector(17 DOWNTO 0);

signal CDIN : CDIN_ARRAY1;
signal P	: CDIN_ARRAY1;

signal Xreg : Xreg_ARRAY1;
signal Coef : Coef_ARRAY1 := (

								"000000000000000101",-->  5				
								"000000000000000011",-->  3				
								"000000000000000111",-->  7				
								"111111111111111100",--> -4				
								"000000000000000001",-->  1				
								"111111111111111110",--> -2				
								"111111111111111111",--> -1				
								"000000000000000100",-->  4			

								"000000000000000101",-->  5				
								"000000000000000011",-->  3				
								"000000000000000111",-->  7				
								"111111111111111100",--> -4				
								"000000000000000001",-->  1				
								"111111111111111110",--> -2				
								"111111111111111111",--> -1				
								"000000000000000100" -->  4
								);


begin


	U_0: multadd
			port map(
				 --Inputs
 					A0  		=> Xreg(0),
			  		A0_ACLR_N 	=> resetn,
        			A0_EN     	=> '1',
       				A0_SCLR_N 	=> '1',
        			B0        	=> Coef(0),
        			B0_ACLR_N 	=> resetn,
        			B0_EN     	=> '1',
        			B0_SCLR_N 	=> '1',

        			CDIN      	=> (others => '0'),
        			CLK         => Clk,
        			P_ACLR_N  	=> resetn,
        			P_EN      	=> '1',
        			P_SCLR_N  	=> '1',
       			 -- Outputs
        			CDOUT     	=> CDIN(0),
        			P         	=> P(0)
				);

 U1: for i in 1 to N-1 generate

			UUT_1: multadd_0 
			port map(
				-- Inputs
 					A0  		=> Xreg(2*i),
			  		A0_ACLR_N 	=> resetn,
        			A0_EN     	=> '1',
       				A0_SCLR_N 	=> '1',
        			B0        	=> Coef(i),
        			B0_ACLR_N 	=> resetn,
        			B0_EN     	=> '1',
        			B0_SCLR_N 	=> '1',
        			CDIN      	=> CDIN(i-1),
        			CLK         => Clk,
        			P_ACLR_N  	=> resetn,
        			P_EN      	=> '1',
        			P_SCLR_N  	=> '1',
       			 -- Outputs
        			CDOUT     	=> CDIN(i),
        			P         	=> P(i)
				);


 		end generate;


		process(clk, resetn)
		begin
			if (resetn = '0') then
				Xreg(0)  <= (others => '0');  
			else
				if(rising_edge(clk))then
					Xreg(0)	<= Xn_in;
				end if;
			end if;
		end process;


	L0:for i in 1 to 2*N - 2 generate

		process(clk, resetn)
		begin
			if (resetn = '0') then
				Xreg(i)  <= (others => '0');  
			else
				if(rising_edge(clk))then
					Xreg(i)	<= Xreg(i-1);
				end if;
			end if;
		end process;

	  end generate;	

	Yn_out <= P(N-1);
	


end SystolicFIR_Filter_arch;
