--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:   17:16:42 13.05.2007
-- Design Name:   tb_fir_stage
-- Module Name:   tb_fir_stage.vhd
-- Project Name:  fir_stage
-- 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 ieee_proposed;
use ieee_proposed.fixed_float_types.all;
use ieee_proposed.fixed_pkg.all;

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

use work.PCK_FIO.all;

ENTITY tb_fir_parallel IS
	Generic (
		ntaps				: integer := 33;
		nbits_in			: integer := 16;
		nbits_in_frac		: integer := 16;
		nbits_stages		: integer := 16;
		nbits_stages_frac	: integer := 15;
		nbits_out			: integer := 16;
		nbits_out_frac		: integer := 16;
		has_in_reg			: boolean := false;
		has_pipe_reg		: boolean := true;
		has_out_reg			: boolean := false;
		fir_mode			: fir_parallel_mode_t := transposed;
		rounding			: boolean := true;
		saturating			: boolean := true
	        );
END tb_fir_parallel;

ARCHITECTURE behavior OF tb_fir_parallel IS 

	-- Component Declaration for the Unit Under Test (UUT)
	COMPONENT fir_parallel
	GENERIC
	(
		ntaps				: integer;
		nbits_in			: integer;
		nbits_in_frac		: integer;
		nbits_stages		: integer;
		nbits_stages_frac	: integer;
		nbits_out			: integer;
		nbits_out_frac		: integer;
		has_in_reg			: boolean;
		has_pipe_reg		: boolean;
		has_out_reg			: boolean;
		fir_mode			: fir_parallel_mode_t;
		rounding			: boolean;
		saturating			: boolean
	);
	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 COMPONENT;

	-------------------------------------------------------------------------------
	--Constants
	constant PERIOD : time := 10 ns;
	constant zero_in : sfixed := to_sfixed(0, nbits_in, nbits_in_frac);

	--Inputs
	SIGNAL clk         : std_logic := '0';
	SIGNAL srst        : std_logic := '1';
	SIGNAL in_valid    : std_logic := '0';
	SIGNAL x_in        : sfixed(shi(nbits_in, nbits_in_frac) downto slo(nbits_in, nbits_in_frac));

	--Outputs
	SIGNAL y_out       : sfixed(shi(nbits_out, nbits_out_frac) downto slo(nbits_out, nbits_out_frac));
	SIGNAL out_valid   : std_logic := '0';

	SIGNAL fileout_enable   : std_logic := '1';
	
	-- Test coefficients
	SIGNAL coeff_in : sfixed_array_t(0 to ntaps-1, shi(nbits_stages, nbits_stages_frac) downto slo(nbits_stages, nbits_stages_frac)) := to_sfixed_array(FilterCoef_Lowpass(ntaps, 0.125, 1.0), nbits_stages, nbits_stages_frac);
	
	SIGNAL xi, yo : real := 0.0;
	
	-- file I/O
	subtype sample_t is integer range -32768 to 32767;
	type file_t is file of sample_t;
	
	-------------------------------------------------------------------------------
BEGIN

	xi <= to_real(x_in);
	yo <= to_real(y_out);
	
	----------------------------------------
	-- Instantiate the Unit Under Test (UUT)
	----------------------------------------
		uut_fir_parallel: fir_parallel
		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,
			has_in_reg			=> has_in_reg,
			has_pipe_reg		=> has_pipe_reg,
			has_out_reg			=> has_out_reg,
			fir_mode			=> fir_mode,
			rounding			=> rounding,
			saturating			=> saturating
		)
		PORT MAP
		(
			srst		=> srst,
			clk			=> clk,
			h_in		=> coeff_in,
			in_valid	=> in_valid,
			d_in		=> x_in,
			out_valid	=> out_valid,
			d_out		=> y_out
		);

	----------------------------------------
	-- Finished instantiation
	----------------------------------------
	tb_clk : PROCESS
	BEGIN
		clk <= not clk;
		wait for PERIOD/2;
	END PROCESS;

	tb : PROCESS
	file fi : file_t open read_mode is "wav_in.dat";
	variable si : sample_t;
	
	BEGIN

		-- Wait 100 ns for global reset to finish
		wait for 4*PERIOD;
		srst <= '0';
		------------------------------------------
		wait for 2*PERIOD;
		
		while not endfile(fi) loop
			read(fi, si);
			x_in <= to_sfixed(to_signed(si, x_in'length));
			in_valid <= '1';
			wait for PERIOD;
			wait until rising_edge(clk);
		end loop;	
		------------------------------------------
		in_valid <= '0';
		
		wait for 20*PERIOD;

		assert false report "Test finished" severity error;
		wait; 
	END PROCESS;
	
	tb_fo : PROCESS(clk, fileout_enable, out_valid)
	file fo : file_t open write_mode is "wav_out.dat";
	variable so : sample_t;

	BEGIN
		if rising_edge(clk) and fileout_enable = '1' and out_valid = '1' then
			so := to_integer(to_signed(y_out));
			write(fo, so);
		end if;

	END PROCESS;
	
END;
