--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:    12:16:14 10/02/05
-- Design Name:    
-- Module Name:    fir_parallel - Behavioral
-- Project Name:   
-- Target Device:  
-- Tool versions:  
-- Description:
--
-- Dependencies:
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
-- 
--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.MATH_REAL.ALL;
USE ieee.numeric_std.ALL;

library ieee_proposed;
use ieee_proposed.fixed_float_types.all;
use ieee_proposed.fixed_pkg.all;

library work;
use work.utils_pkg.all;
use work.fixed_util_pkg.all;
use work.fir_pkg.all;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity fir_parallel is
Generic
(
	ntaps				: integer := 33;
	nbits_in			: integer := 12;
	nbits_in_frac		: integer := 11;
	nbits_stages		: integer := 13;
	nbits_stages_frac	: integer := 11;
	nbits_out			: integer := 12;
	nbits_out_frac		: integer := 11;
	has_in_reg			: boolean := false;
	has_pipe_reg		: boolean := false;
	has_out_reg			: boolean := false;
	fir_mode			: fir_parallel_mode_t := transposed;
	rounding			: boolean := true;
	saturating			: boolean := true
);
Port
(
	srst		: in std_logic;
	clk			: in std_logic;
	h_in		: in sfixed_array_t;
	in_valid	: in std_logic;
	d_in		: in sfixed;
	out_valid	: out std_logic;
	d_out		: out sfixed
);
end fir_parallel;

architecture Behavioral of fir_parallel is

-------------------------------------------------------------------------------
	-- Component Declaration for FIR stage
	COMPONENT fir_stage
	GENERIC
	(
		nbits_in		: integer;
		nbits_in_frac	: integer;
		nbits_out		: integer;
		nbits_out_frac	: integer;
		has_in_reg		: boolean;
		has_pipe_reg	: boolean;
		has_out_reg		: boolean;
		fir_mode		: fir_stage_mode_t;
		rounding		: boolean;
		saturating		: boolean
	);
	PORT
	(
		srst		: in std_logic;
		clk			: in std_logic;
		in_valid	: in std_logic;
		x_in		: in sfixed;
		y_in		: in sfixed;
		h_in		: in sfixed;
		out_valid	: out std_logic;
		x_out		: out sfixed;
		y_out		: out sfixed;
		y_out_clr	: in std_logic
	);
	END COMPONENT;

	-------------------------------------------------------------------------------
	type coeff_array_t is array (natural range <>) of sfixed(shi(nbits_stages, nbits_stages_frac) downto slo(nbits_stages, nbits_stages_frac));
	type stages_array_t is array (natural range <>) of sfixed(shi(nbits_stages, nbits_stages_frac) downto slo(nbits_stages, nbits_stages_frac));

	constant zero_in : sfixed := to_sfixed(0, nbits_in, nbits_in_frac);
	constant fir_stage_mode : fir_stage_mode_t := transposed;

	SIGNAL x_out       : sfixed(shi(nbits_out, nbits_out_frac) downto slo(nbits_out, nbits_out_frac));

	SIGNAL x    	   : stages_array_t(0 to ntaps-2);
	SIGNAL y           : stages_array_t(0 to ntaps-2);
	SIGNAL h           : coeff_array_t(0 to ntaps-1);
	SIGNAL vld		   : unsigned(0 to ntaps-2);
	
	-------------------------------------------------------------------------------
begin

	-- Assign coefficients
    assign_coeffs:
	for i in 0 to ntaps-1 generate
		h(i) <= to_sfixed(h_in, i);
	end generate;	

	----------------------------------------
	-- Instantiate the FIR stages
	----------------------------------------
		uut_first_stage: fir_stage 
		GENERIC MAP
		(
			nbits_in		=> nbits_in,
			nbits_in_frac	=> nbits_in_frac,
			nbits_out		=> nbits_stages,
			nbits_out_frac	=> nbits_stages_frac,
			has_in_reg		=> has_in_reg,
			has_pipe_reg	=> has_pipe_reg,
			has_out_reg		=> has_out_reg,
			fir_mode		=> fir_stage_mode,
			rounding		=> false,
			saturating		=> false
		)
		PORT MAP
		(
			srst		=> srst,
			clk			=> clk,
			in_valid	=> in_valid,
			x_in		=> d_in,
			y_in		=> zero_in,
			h_in		=> h(ntaps-1),
			out_valid	=> vld(0),
			x_out		=> x(0),
			y_out		=> y(0),
			y_out_clr	=> '0'
		);

	----------------------------------------
    gen_stages:
	for i in 1 to ntaps-2 generate
		uut_stages: fir_stage 
		GENERIC MAP
		(
			nbits_in		=> nbits_stages,
			nbits_in_frac	=> nbits_stages_frac,
			nbits_out		=> nbits_stages,
			nbits_out_frac	=> nbits_stages_frac,
			has_in_reg		=> has_in_reg,
			has_pipe_reg	=> has_pipe_reg,
			has_out_reg		=> has_out_reg,
			fir_mode		=> fir_stage_mode,
			rounding		=> false,
			saturating		=> false
		)
		PORT MAP
		(
			srst		=> srst,
			clk			=> clk,
			in_valid	=> vld(i-1),
			x_in		=> x(i-1),
			y_in		=> y(i-1),
			h_in		=> h(ntaps-i-1),
			out_valid	=> vld(i),
			x_out		=> x(i),
			y_out		=> y(i),
			y_out_clr	=> '0'
		);
	end generate;
	
	----------------------------------------
		uut_last_stage: fir_stage 
		GENERIC MAP
		(
			nbits_in		=> nbits_stages,
			nbits_in_frac	=> nbits_stages_frac,
			nbits_out		=> nbits_out,
			nbits_out_frac	=> nbits_out_frac,
			has_in_reg		=> has_in_reg,
			has_pipe_reg	=> has_pipe_reg,
			has_out_reg		=> has_out_reg,
			fir_mode		=> fir_stage_mode,
			rounding		=> rounding,
			saturating		=> saturating
		)
		PORT MAP
		(
			srst		=> srst,
			clk			=> clk,
			in_valid	=> vld(ntaps-2),
			x_in		=> x(ntaps-2),
			y_in		=> y(ntaps-2),
			h_in		=> h(0),
			out_valid	=> out_valid,
			x_out		=> x_out,
			y_out		=> d_out,
			y_out_clr	=> '0'
		);

	----------------------------------------
	-- Finished instantiation
	----------------------------------------
	
end Behavioral;
