----------------------------------------------
-- MSS copyright 2003-2007
-- Filename: RAISED_COS2_40.VHD
-- Author: Alain Zarembowitch / MSS
-- Inheritance: RAISED_COS8_25.VHD 1/24/06, RAISED_COS4E.VHD, 3-1-03
-- Edit date: 5/27/07
-- Revision: 1
--
-- VHDL code for single raised cosine FIR. No decimation.
-- This is a full raised cosine filter, NOT SQUARE ROOT!
-- 40% rolloff. Single stream. 
-- Input: 2 samples / symbol
-- Output: 2 samples / symbol
-- Maximum rate: TWO input sample per CLK.
-- Latency is 5 CLK.
-- 
-- Coefficients: 
--coeff(1) = 0
--coeff(2) = 1
--coeff(3) = 0
--coeff(4) = 4 (instead of 5)
--coeff(5) = 0
--coeff(6) = -10 = -8 -2
--coeff(7) = 0;
--coeff(8) = -8
--coeff(9) = 0
--coeff(10) = 88 = 64 + 16 + 8 (instead of 87)
--coeff(11) = 0
--coeff(12) = -304 = -256 - 64 + 16 (instead of -305)
--coeff(13) = 0
--coeff(14) = 1256 = 1024 + 256 - 16 -8;	
--coeff(15) = 2048
-- See Matlab program RAISEDCOS_2_40.m
----------------------------------------------      
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
Library UNISIM;
use UNISIM.vcomponents.all;

entity RAISED_COS2_40 is
    port (
		CLK: in std_logic;
			-- reference clock for synchronous design
        	-- Input to Output Processing latency 5 CLK periods.

		--// INPUTS 
		SAMPLE_CLK_IN: in std_logic;
			-- read input samples at rising_edge of CLK and SAMPLE_CLK_IN  = '1'.
			-- One CLK wide pulse.
		DATA0_IN: in std_logic_vector(13 downto 0);
		DATA180_IN: in std_logic_vector(13 downto 0);
			-- input signal. Two samples separated in real-time by 1/2 symbol.
			-- 180 deg sample lags 0 deg sample.
			-- read at rising edge of CLK when SAMPLE_CLK_IN = '1'

		--// OUTPUTS 
		SAMPLE_CLK_OUT: out std_logic;
			-- Latency between input and output samples: 5 CLKs
		DATA0_OUT: out std_logic_vector(13 downto 0);
		DATA180_OUT: out std_logic_vector(13 downto 0)
			-- filtered output signal. Two samples separated in real-time by 1/2 symbol.
			-- 180 deg sample lags 0 deg sample.
			-- Read at rising edge of CLK and SAMPLE_CLK_OUT = '1'.
    );
end entity;

architecture RAISED_COS_arch of RAISED_COS2_40 is
-----------------------------------------------------------------
-- COMPONENTS
-----------------------------------------------------------------
component RAISED_COS2_40CORE is
    port (
		CLK: in std_logic;
			-- reference clock for synchronous design
		 FIL_IN0: in std_logic_vector(13 downto 0);
		 FIL_IN1: in std_logic_vector(13 downto 0);
		 FIL_IN2: in std_logic_vector(13 downto 0);
		 FIL_IN3: in std_logic_vector(13 downto 0);
		 FIL_IN4: in std_logic_vector(13 downto 0);
		 FIL_IN5: in std_logic_vector(13 downto 0);
		 FIL_IN6: in std_logic_vector(13 downto 0);
		 FIL_IN7: in std_logic_vector(13 downto 0);
		 FIL_IN8: in std_logic_vector(13 downto 0);
		 FIL_IN9: in std_logic_vector(13 downto 0);
		 FIL_IN10: in std_logic_vector(13 downto 0);
		 FIL_IN11: in std_logic_vector(13 downto 0);
		 FIL_IN12: in std_logic_vector(13 downto 0);
		 FIL_IN13: in std_logic_vector(13 downto 0);
		 FIL_IN14: in std_logic_vector(13 downto 0);
		 FIL_IN15: in std_logic_vector(13 downto 0);
		 FIL_IN16: in std_logic_vector(13 downto 0);
		 FIL_IN17: in std_logic_vector(13 downto 0);
		 FIL_IN18: in std_logic_vector(13 downto 0);
		 FIL_IN19: in std_logic_vector(13 downto 0);
		 FIL_IN20: in std_logic_vector(13 downto 0);
		 FIL_IN21: in std_logic_vector(13 downto 0);
		 FIL_IN22: in std_logic_vector(13 downto 0);
		 FIL_IN23: in std_logic_vector(13 downto 0);
		 FIL_IN24: in std_logic_vector(13 downto 0);
		 FIL_IN25: in std_logic_vector(13 downto 0);
		 FIL_IN26: in std_logic_vector(13 downto 0);
		 FIL_IN27: in std_logic_vector(13 downto 0);

		DATA_OUT: out std_logic_vector(13 downto 0)
        	-- Input to Output Processing latency 4 CLK periods.
    );
end component;
-----------------------------------------------------------------
-- SIGNALS
-----------------------------------------------------------------
-- suffix _D denotes a one-CLK delayed version of the net with the same name
constant N: integer := 13;   -- precision

-- Filter input
signal FIL_IN0: std_logic_vector(N downto 0);
signal FIL_IN1: std_logic_vector(N downto 0);
signal FIL_IN2: std_logic_vector(N downto 0);
signal FIL_IN3: std_logic_vector(N downto 0);
signal FIL_IN4: std_logic_vector(N downto 0);
signal FIL_IN5: std_logic_vector(N downto 0);
signal FIL_IN6: std_logic_vector(N downto 0);
signal FIL_IN7: std_logic_vector(N downto 0);
signal FIL_IN8: std_logic_vector(N downto 0);
signal FIL_IN9: std_logic_vector(N downto 0);
signal FIL_IN10: std_logic_vector(N downto 0);
signal FIL_IN11: std_logic_vector(N downto 0);
signal FIL_IN12: std_logic_vector(N downto 0);
signal FIL_IN13: std_logic_vector(N downto 0);
signal FIL_IN14: std_logic_vector(N downto 0);
signal FIL_IN15: std_logic_vector(N downto 0);
signal FIL_IN16: std_logic_vector(N downto 0);
signal FIL_IN17: std_logic_vector(N downto 0);
signal FIL_IN18: std_logic_vector(N downto 0);
signal FIL_IN19: std_logic_vector(N downto 0);
signal FIL_IN20: std_logic_vector(N downto 0);
signal FIL_IN21: std_logic_vector(N downto 0);
signal FIL_IN22: std_logic_vector(N downto 0);
signal FIL_IN23: std_logic_vector(N downto 0);
signal FIL_IN24: std_logic_vector(N downto 0);
signal FIL_IN25: std_logic_vector(N downto 0);
signal FIL_IN26: std_logic_vector(N downto 0);
signal FIL_IN27: std_logic_vector(N downto 0);
signal FIL_IN28: std_logic_vector(N downto 0); 

signal SAMPLE_CLK_IN_D: std_logic;
signal SAMPLE_CLK_IN_D2: std_logic;
signal SAMPLE_CLK_IN_D3: std_logic;
signal SAMPLE_CLK_IN_D4: std_logic;
-----------------------------------------------------------------
-- IMPLEMENTATION
-----------------------------------------------------------------
begin   

-- shift in two input samples at a time
SHIFT_001: process(CLK)
begin
	if(rising_edge(CLK)) then
		if(SAMPLE_CLK_IN = '1') then		
			FIL_IN0 <= DATA180_IN; 
			FIL_IN1 <= DATA0_IN;            
			FIL_IN2 <= FIL_IN0;                                                
			FIL_IN3 <= FIL_IN1;                                                
			FIL_IN4 <= FIL_IN2;                                                
			FIL_IN5 <= FIL_IN3;                                                
			FIL_IN6 <= FIL_IN4;                                                
			FIL_IN7 <= FIL_IN5;                                                
			FIL_IN8 <= FIL_IN6;                                                
			FIL_IN9 <= FIL_IN7;                                                
			FIL_IN10 <= FIL_IN8;                                                
			FIL_IN11 <= FIL_IN9;                                                
			FIL_IN12 <= FIL_IN10;                                                
			FIL_IN13 <= FIL_IN11;                                                
			FIL_IN14 <= FIL_IN12;                                                
			FIL_IN15 <= FIL_IN13;                                                
			FIL_IN16 <= FIL_IN14;
			FIL_IN17 <= FIL_IN15;                                                
			FIL_IN18 <= FIL_IN16;                                                
			FIL_IN19 <= FIL_IN17;                                                
			FIL_IN20 <= FIL_IN18;                                                
			FIL_IN21 <= FIL_IN19;                                                
			FIL_IN22 <= FIL_IN20;                                                
			FIL_IN23 <= FIL_IN21;                                                
			FIL_IN24 <= FIL_IN22;                                                
			FIL_IN25 <= FIL_IN23;                                                
			FIL_IN26 <= FIL_IN24;                                                
			FIL_IN27 <= FIL_IN25;                                                
			FIL_IN28 <= FIL_IN26; 
		end if;
	end if;
end process;

-- Parallel implementation to process two samples per CLK
RAISED_COS2_40CORE_001: RAISED_COS2_40CORE port map(
	CLK => CLK,
	FIL_IN0 => FIL_IN0,
	FIL_IN1 => FIL_IN1,
	FIL_IN2 => FIL_IN2,
	FIL_IN3 => FIL_IN3,
	FIL_IN4 => FIL_IN4,
	FIL_IN5 => FIL_IN5,
	FIL_IN6 => FIL_IN6,
	FIL_IN7 => FIL_IN7,
	FIL_IN8 => FIL_IN8,
	FIL_IN9 => FIL_IN9,
	FIL_IN10 => FIL_IN10,
	FIL_IN11 => FIL_IN11,
	FIL_IN12 => FIL_IN12,
	FIL_IN13 => FIL_IN13,
	FIL_IN14 => FIL_IN14,
	FIL_IN15 => FIL_IN15,
	FIL_IN16 => FIL_IN16,
	FIL_IN17 => FIL_IN17,
	FIL_IN18 => FIL_IN18,
	FIL_IN19 => FIL_IN19,
	FIL_IN20 => FIL_IN20,
	FIL_IN21 => FIL_IN21,
	FIL_IN22 => FIL_IN22,
	FIL_IN23 => FIL_IN23,
	FIL_IN24 => FIL_IN24,
	FIL_IN25 => FIL_IN25,
	FIL_IN26 => FIL_IN26,
	FIL_IN27 => FIL_IN27,
	DATA_OUT => DATA180_OUT
	);
	
-- virtual delay of 1/2 a symbol/bit.
RAISED_COS2_40CORE_002: RAISED_COS2_40CORE port map(
	CLK => CLK,
	FIL_IN0 => FIL_IN1,
	FIL_IN1 => FIL_IN2,
	FIL_IN2 => FIL_IN3,
	FIL_IN3 => FIL_IN4,
	FIL_IN4 => FIL_IN5,
	FIL_IN5 => FIL_IN6,
	FIL_IN6 => FIL_IN7,
	FIL_IN7 => FIL_IN8,
	FIL_IN8 => FIL_IN9,
	FIL_IN9 => FIL_IN10,
	FIL_IN10 => FIL_IN11,
	FIL_IN11 => FIL_IN12,
	FIL_IN12 => FIL_IN13,
	FIL_IN13 => FIL_IN14,
	FIL_IN14 => FIL_IN15,
	FIL_IN15 => FIL_IN16,
	FIL_IN16 => FIL_IN17,
	FIL_IN17 => FIL_IN18,
	FIL_IN18 => FIL_IN19,
	FIL_IN19 => FIL_IN20,
	FIL_IN20 => FIL_IN21,
	FIL_IN21 => FIL_IN22,
	FIL_IN22 => FIL_IN23,
	FIL_IN23 => FIL_IN24,
	FIL_IN24 => FIL_IN25,
	FIL_IN25 => FIL_IN26,
	FIL_IN26 => FIL_IN27,
	FIL_IN27 => FIL_IN28,
	DATA_OUT => DATA0_OUT
	);


RECLOCK_005: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE_CLK_IN_D <= SAMPLE_CLK_IN;
		SAMPLE_CLK_IN_D2 <= SAMPLE_CLK_IN_D;
		SAMPLE_CLK_IN_D3 <= SAMPLE_CLK_IN_D2;
		SAMPLE_CLK_IN_D4 <= SAMPLE_CLK_IN_D3;
		SAMPLE_CLK_OUT <= SAMPLE_CLK_IN_D4;
	end if;
end process;

end RAISED_COS_arch;					