--------------------------------------------------------------------------------
-- 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 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.nco_pkg.all;
use work.PCK_FIO.all;

ENTITY tb_nco IS
	Generic (
		nbits_wave		: integer := 18;
		nbits_phase		: integer := 16; 
		nbits_lut_depth	: integer := 12; 
		nbits_dither	: integer := 4; 
		nbits_lfsr		: integer := 12; 
		q_phase			: phase_relation_t := phase_270deg;
		has_pipe_reg	: boolean := true;
		has_out_reg		: boolean := true
	        );
END tb_nco;

ARCHITECTURE behavior OF tb_nco IS 

	-- Component Declaration for the Unit Under Test (UUT)
	COMPONENT nco
	GENERIC (
		nbits_wave		: integer;
		nbits_phase		: integer;
		nbits_lut_depth	: integer;
		nbits_dither	: integer;
		nbits_lfsr		: integer;
		q_phase			: phase_relation_t;
		has_pipe_reg	: boolean;
		has_out_reg		: boolean
		);
	PORT(
		srst		: in std_logic;
		clk			: in std_logic;
--		ce			: in std_logic;
		pacc_clr	: in std_logic;
		pacc_inc	: in std_logic;
		freq_in		: in unsigned(nbits_phase-1 downto 0);
		freq_load	: in std_logic;
		phase_in	: in unsigned(nbits_phase-1 downto 0);
		phase_load	: in std_logic;
		phase_out	: out unsigned(nbits_phase-1 downto 0);
		wave_out_i	: out sfixed;
		wave_out_q	: out sfixed;
		out_valid	: out std_logic;
		debug_out	: out debug_out_t
	);
	END COMPONENT;

	--Constants
	constant fa : REAL := 100.0E6;
	constant f : REAL := 5.0*fa/24.0;
	constant df : REAL := 10.0E3;
	constant PERIOD : time := 10 ns;
	constant nbits_wave_frac : integer := nbits_wave;
	
	SIGNAL freq_word : integer := integer(f/fa*2.0**nbits_phase);
	SIGNAL dfreq_word : integer := integer(df/fa*2.0**nbits_phase);

	--Inputs
	SIGNAL clk         : std_logic := '0';
--	SIGNAL ce          : std_logic := '0';
	SIGNAL srst        : std_logic := '1';
	SIGNAL pacc_clr   : std_logic := '0';
	SIGNAL pacc_inc   : std_logic := '0';
	SIGNAL phase_load  : std_logic := '0';
	SIGNAL freq_load   : std_logic := '0';
	SIGNAL freq_in     : unsigned(nbits_phase-1 downto 0);
	SIGNAL phase_in    : unsigned(nbits_phase-1 downto 0);

	--Outputs
	SIGNAL wave_out_i  : sfixed(sproto(nbits_wave, nbits_wave_frac)'high downto sproto(nbits_wave, nbits_wave_frac)'low);
	SIGNAL wave_out_q  : sfixed(sproto(nbits_wave, nbits_wave_frac)'high downto sproto(nbits_wave, nbits_wave_frac)'low);
	SIGNAL out_valid   : std_logic;
	SIGNAL phase_out   : unsigned(nbits_phase-1 downto 0);
	SIGNAL debug_out   : debug_out_t;
	
	SIGNAL fileout_enable   : std_logic := '0';

BEGIN

	-- Instantiate the Unit Under Test (UUT)
	uut: nco 
	GENERIC MAP (
		nbits_wave		=> nbits_wave,
		nbits_phase		=> nbits_phase,
		nbits_lut_depth	=> nbits_lut_depth,
		nbits_dither	=> nbits_dither,
		nbits_lfsr		=> nbits_lfsr,
		q_phase			=> q_phase,
		has_pipe_reg	=> has_pipe_reg,
		has_out_reg		=> has_out_reg
		)
	PORT MAP(
		srst		=> srst,
		clk			=> clk,
--		ce			=> ce,
		pacc_clr	=> pacc_clr,
		pacc_inc	=> pacc_inc,
		freq_in		=> freq_in,
		freq_load	=> freq_load,
		phase_in	=> phase_in,
		phase_load	=> phase_load,
		phase_out	=> phase_out,
		wave_out_i	=> wave_out_i,
		wave_out_q	=> wave_out_q,
		out_valid	=> out_valid,
		debug_out	=> debug_out
	);

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

	tb : PROCESS
	file RESULT_FREQ:   text open write_mode is "freq.txt"; 
	variable L:         line;

	BEGIN

		-- Wait 100 ns for global reset to finish
		wait for 4*PERIOD;
		srst <= '0';

		fprint(RESULT_FREQ, L,"%s\n", REAL'image(f));

		wait for 2*PERIOD;
--		ce <= '1';
		-------------------------------------------
		-- 1
		phase_in <= to_unsigned(0,nbits_phase);
		wait until rising_edge(clk);
		phase_load <= '1';
		wait until rising_edge(clk);
		phase_load <= '0';
		
		freq_in <= to_unsigned(1411,nbits_phase);
		wait until rising_edge(clk);
		freq_load <= '1';
		wait until rising_edge(clk);
		freq_load <= '0';

		wait for 2*PERIOD;
		pacc_inc <= '1';
		
		wait for 2*PERIOD;
		wait until rising_edge(clk);

		wait for 40*PERIOD;
		-------------------------------------------
		freq_in <= to_unsigned(643,nbits_phase);
		wait until rising_edge(clk);
		freq_load <= '1';
		wait until rising_edge(clk);
		freq_load <= '0';

		wait for 40*PERIOD;
		-------------------------------------------
		phase_in <= to_unsigned(800,nbits_phase);
		wait until rising_edge(clk);
		phase_load <= '1';
		wait until rising_edge(clk);
		phase_load <= '0';

		wait for 20*PERIOD;
		-------------------------------------------
		phase_in <= to_unsigned(45072,nbits_phase);
		wait until rising_edge(clk);
		phase_load <= '1';
		wait until rising_edge(clk);
		phase_load <= '0';

		wait for 20*PERIOD;
		-------------------------------------------
		phase_in <= to_unsigned(20593,nbits_phase);
		wait until rising_edge(clk);
		phase_load <= '1';
		wait until rising_edge(clk);
		phase_load <= '0';

		-------------------------------------------
		freq_in <= to_unsigned(freq_word,nbits_phase);
		wait until rising_edge(clk);
		freq_load <= '1';
		wait until rising_edge(clk);
		freq_load <= '0';
	
		wait for 20*PERIOD;
		fileout_enable <= '1';

		wait for 20000*PERIOD;
		fileout_enable <= '0';

		-------------------------------------------
		-- Sweep
		freq_word <= 100;
		for i in 1 to 200 loop
			wait for 20*PERIOD;
			freq_word <= freq_word + dfreq_word;
			
			freq_in <= to_unsigned(freq_word,nbits_phase);
			wait until rising_edge(clk);
			freq_load <= '1';
			wait until rising_edge(clk);
			freq_load <= '0';
	
		end loop;
		
		pacc_inc <= '0';
		wait for 20*PERIOD;
		fileout_enable <= '0';
		wait until rising_edge(clk);
		pacc_clr <= '1';
		wait until rising_edge(clk);
		pacc_clr <= '0';
		wait for 20*PERIOD;
		pacc_inc <= '1';
		wait for 20*PERIOD;
		wait until rising_edge(clk);
		pacc_clr <= '1';
		wait until rising_edge(clk);
		pacc_clr <= '0';
		wait for 20*PERIOD;
		pacc_inc <= '0';
		wait for 20*PERIOD;
		wait until rising_edge(clk);
		pacc_inc <= '1';
		wait until rising_edge(clk);
		pacc_inc <= '0';
		wait for 20*PERIOD;
		wait until rising_edge(clk);
		srst <= '1';
		wait until rising_edge(clk);
		srst <= '0';
		freq_in <= to_unsigned(freq_word,nbits_phase);
		wait until rising_edge(clk);
		freq_load <= '1';
		wait until rising_edge(clk);
		freq_load <= '0';
		
		wait for 20*PERIOD;
		pacc_inc <= '1';
		wait for 20*PERIOD;
		wait until rising_edge(clk);
		srst <= '1';
		wait until rising_edge(clk);
		srst <= '0';
		wait for 20*PERIOD;
		pacc_inc <= '0';

		wait for 20*PERIOD;

		assert false report "Test finished" severity error;
		wait; 
	END PROCESS;
	
	tb_fo : PROCESS(clk, fileout_enable, out_valid)
	file RESULT_I:      text open write_mode is "i_ud.txt"; 
	file RESULT_Q:      text open write_mode is "q_ud.txt"; 
	file RESULT_ID:      text open write_mode is "i_d.txt"; 
	file RESULT_QD:      text open write_mode is "q_d.txt"; 
	file RESULT_LFSR:   text open write_mode is "lfsr.txt"; 
	variable L:         line;

	BEGIN
		if rising_edge(clk) and fileout_enable = '1' and out_valid = '1' then
			fprint(RESULT_I, L,"%s\n", REAL'image(debug_out.i_ud));
			fprint(RESULT_Q, L,"%s\n", REAL'image(debug_out.q_ud));
			fprint(RESULT_ID, L,"%s\n", REAL'image(debug_out.i_d));
			fprint(RESULT_QD, L,"%s\n", REAL'image(debug_out.q_d));
			fprint(RESULT_LFSR, L,"%s\n", INTEGER'image(to_integer(debug_out.lfsr)));
		end if;

	END PROCESS;


END;
