--------------------------------------------------------------------------------
-- Company: <Name>
--
-- File: Systolic_Symmetric_FIR.vhd
-- File history:
--    
--
-- Description: This Design illustrates the implementation of Even-Tap Symmetric 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_Symmetric_FIR is

generic (
			N 		: integer := 16;
			EVEN_ODD: integer := 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_Symmetric_FIR;

architecture SystolicFIR_Filter_arch of Systolic_Symmetric_FIR 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;
        C	      : 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/2-1) OF std_logic_vector(43 DOWNTO 0);
TYPE Xreg_ARRAY1 IS ARRAY (0 to N-1) OF std_logic_vector(17 DOWNTO 0);
TYPE Coef_ARRAY1 IS ARRAY (0 to N/2-1) OF std_logic_vector(17 DOWNTO 0);

signal CDOUT: CDIN_ARRAY1;
signal P	: CDIN_ARRAY1;
signal sum	: Coef_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			
								);

signal Y 		: std_logic_vector(43 downto 0);
signal CDIN		: std_logic_vector(43 downto 0);


begin



CDIN <= (others => '0');

			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;

		
   	U0: for i in 1 to N - 1 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;--if
	
	
	  	U1: for i in 0 to N/2-1 generate

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

			end generate;--for

		
	MUL1: multadd_0
			port map(
				-- Inputs
 					A0  		=> sum(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      	=> CDIN,
        			CLK         => Clk,
        			P_ACLR_N  	=> resetn,
        			P_EN      	=> '1',
        			P_SCLR_N  	=> '1',
       			  --Outputs
        			CDOUT     	=> CDOUT(0),
        			P         	=> open
				);



 		U3: for i in 1 to N/2-1 generate
			
			L0: if(i = 25 or i = 48 )generate
			 MUL2: multadd 
				port map(
				 --Inputs
 					A0  		=> sum(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',
        			C	      	=> P(i-1),
        			CLK         => Clk,
        			P_ACLR_N  	=> resetn,
        			P_EN      	=> '1',
        			P_SCLR_N  	=> '1',
       			  --Outputs
        			CDOUT     	=> CDOUT(i),
        			P         	=> P(i)
				);	

			 end generate;


			L1:if(i /= 25 or i /= 48 )generate

				MUL3: multadd_0 
				port map(
				 --Inputs
 					A0  		=> sum(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      	=> CDOUT(i-1),
        			CLK         => Clk,
        			P_ACLR_N  	=> resetn,
        			P_EN      	=> '1',
        			P_SCLR_N  	=> '1',
       			  --Outputs
        			CDOUT     	=> CDOUT(i),
        			P         	=> P(i)
				);
			end generate;


		
		
			M4: if(i = N/2 - 1) generate

					Yn_out <= P(N/2-1);

				end generate;--if

 		end generate;-- for

	



	

end SystolicFIR_Filter_arch;