--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:   17:16:42 13.05.2007
-- Design Name:   tb_nco
-- Module Name:   tb_nco.vhd
-- Project Name:  nco
-- Target Device:  
-- Tool versions:  
-- Description:   
-- 
--------------------------------------------------------------------------------
LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.MATH_REAL.ALL;
USE ieee.numeric_std.ALL;
use std.textio.all; --  Imports the standard textio package.

library work;
use work.fixed_pkg.all;
use work.filter_pkg.all;
use work.fir_stage_pkg.all;
use work.fir_iterative_pkg.all;

ENTITY syn_fir_iterative IS
	Generic (
		ntaps				: integer := 501;
		nbits_in			: integer := 18;
		nbits_in_frac		: integer := 18;
		nbits_stages		: integer := 20;
		nbits_stages_frac	: integer := 18;
		nbits_out			: integer := 18;
		nbits_out_frac		: integer := 18;
		fir_mode			: fir_iterative_mode_t := symmetric;
		rounding			: boolean := true;
		saturating			: boolean := true
	);
	PORT(
		rst			: in  std_logic;
		clk			: in  std_logic;
		ready_i		: out std_logic;
		x_valid_i	: in  std_logic;
		x_din_i		: in  signed(nbits_in-1 downto 0);
		y_valid_i	: out std_logic;
		y_dout_i	: out signed(nbits_out-1 downto 0);
		ready_q		: out std_logic;
		x_valid_q	: in  std_logic;
		x_din_q		: in  signed(nbits_in-1 downto 0);
		y_valid_q	: out std_logic;
		y_dout_q	: out signed(nbits_out-1 downto 0)
	);
END syn_fir_iterative;

ARCHITECTURE behavior OF syn_fir_iterative IS 

	-- Component Declaration for the Unit Under Test (UUT)
	COMPONENT fir_iterative
	GENERIC
	(
		ntaps				: integer;
		nbits_in			: integer;
		nbits_in_frac		: integer;
		nbits_stages		: integer;
		nbits_stages_frac	: integer;
		nbits_out			: integer;
		nbits_out_frac		: integer;
		fir_mode			: fir_iterative_mode_t;
		rounding			: boolean;
		saturating			: boolean
	);
	PORT
	(
		srst			: in std_logic;
		clk				: in std_logic;
		h_din			: in sfixed;
		h_addr_out		: out unsigned(taps_nbits(ntaps, fir_mode)-1 downto 0);
		ready			: out std_logic;
		x_valid			: in std_logic;
		x_din			: in sfixed;
		y_dout_valid	: out std_logic;
		y_dout			: out sfixed
	);
	END COMPONENT;

	type h_mem_t is array (0 to ntaps-1) of sfixed(sproto(nbits_stages, nbits_stages_frac)'high downto sproto(nbits_stages, nbits_stages_frac)'low);

	function to_h_mem(coef_real : real_array_t; ntaps : integer; proto : sfixed) return h_mem_t is
	variable res : h_mem_t;
	begin
		for i in 0 to ntaps-1 loop
			res(i) := to_sfixed(coef_real(i), proto);
		end loop;
		
		return res;
	end to_h_mem;	
		
		
	--Outputs
	SIGNAL h_i, h_q  : sfixed(sproto(nbits_stages, nbits_stages_frac)'high downto sproto(nbits_stages, nbits_stages_frac)'low);
	SIGNAL x_i, x_q  : sfixed(sproto(nbits_in, nbits_in_frac)'high downto sproto(nbits_in, nbits_in_frac)'low);
	SIGNAL y_i, y_q : sfixed(sproto(nbits_out, nbits_out_frac)'high downto sproto(nbits_out, nbits_out_frac)'low);
	SIGNAL h_addr_i, h_addr_q : unsigned(taps_nbits(ntaps, fir_mode)-1 downto 0);

	-- ROM
	CONSTANT coeffs : real_array_t(0 to ntaps_addr(ntaps, fir_mode)-1) := FilterCoef_Lowpass(ntaps_addr(ntaps, fir_mode), 0.05, 0.05);
	CONSTANT h_mem : h_mem_t := to_h_mem(coeffs, ntaps_addr(ntaps, fir_mode), h_i);


BEGIN

	-- Instantiate the Unit Under Test (UUT)
	inst_fir_iterative_i: fir_iterative 
		GENERIC MAP
		(
			ntaps				=> ntaps,
			nbits_in			=> nbits_in,
			nbits_in_frac		=> nbits_in_frac,
			nbits_out			=> nbits_out,
			nbits_out_frac		=> nbits_out_frac,
			nbits_stages		=> nbits_stages,
			nbits_stages_frac	=> nbits_stages_frac,
			fir_mode			=> fir_mode,
			rounding			=> rounding,
			saturating			=> saturating
		)
		PORT MAP
		(
			srst			=> rst,
			clk				=> clk,
			h_din			=> h_i,
			h_addr_out		=> h_addr_i,
			ready			=> ready_i,
			x_valid			=> x_valid_i,
			x_din			=> x_i,
			y_dout_valid	=> y_valid_i,
			y_dout			=> y_i
		);

	inst_fir_iterative_q: fir_iterative 
		GENERIC MAP
		(
			ntaps				=> ntaps,
			nbits_in			=> nbits_in,
			nbits_in_frac		=> nbits_in_frac,
			nbits_out			=> nbits_out,
			nbits_out_frac		=> nbits_out_frac,
			nbits_stages		=> nbits_stages,
			nbits_stages_frac	=> nbits_stages_frac,
			fir_mode			=> fir_mode,
			rounding			=> rounding,
			saturating			=> saturating
		)
		PORT MAP
		(
			srst			=> rst,
			clk				=> clk,
			h_din			=> h_q,
			h_addr_out		=> h_addr_q,
			ready			=> ready_q,
			x_valid			=> x_valid_q,
			x_din			=> x_q,
			y_dout_valid	=> y_valid_Q,
			y_dout			=> y_q
		);

	x_i <= to_sfixed(x_din_i, x_i);
	y_dout_i <= signed(y_i);

	x_q <= to_sfixed(x_din_q, x_q);
	y_dout_q <= signed(y_q);

	process(clk)
	begin
		if rising_edge(clk) then
			h_i <= h_mem(to_integer(h_addr_i));
			h_q <= h_mem(to_integer(h_addr_q));
		end if;	
	end process;	
	
END;
