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

ENTITY tb_mix IS
	Generic 
	(
		nbits_wave_in	: integer := 16;
		nbits_wave_out	: integer := 18;		-- Gain of 2.6 (mix + rfgen)
		nbits_phase		: integer := 20;
		nbits_freq		: integer := 20
	);
END tb_mix;

ARCHITECTURE behavior OF tb_mix IS 

	-- Component Declaration for the Unit Under Test (UUT)
	COMPONENT mix
	GENERIC
	(
		nbits_din		: integer;
		nbits_din_frac	: integer;
		nbits_dout		: integer;
		nbits_dout_frac	: integer;
		nbits_phase		: integer;
		nbits_freq		: integer
	);
	PORT
	(
		rst				: in std_logic;
		clk				: in std_logic;
		nco_rst			: in std_logic;
		nco_en			: in std_logic;
		freq_in			: in unsigned(nbits_freq-1 downto 0);
		phase_in		: in unsigned(nbits_phase-1 downto 0);
		din_i			: in  sfixed;
		din_q			: in  sfixed;
		dout_i			: out sfixed;
		dout_q			: out sfixed;
		din_vld			: in std_logic;
		dout_vld		: out std_logic
	);
	END COMPONENT;

	--Constants
	constant fa : REAL := 100.0E6;
	constant frf : REAL := 3.333E5;
	constant flo : REAL := 3.333E5;
	constant df : REAL := 10.0E3;
	constant PERIOD : time := 10 ns;
	constant num_steps : integer := 1000000;

	constant nbits_wave_in_frac : integer := nbits_wave_in-2;
	constant nbits_wave_out_frac : integer := nbits_wave_out-2;
	
	SIGNAL rfgen_freq_word : integer := integer(frf/fa*2.0**nbits_freq);
	SIGNAL freq_word : integer := integer(flo/fa*2.0**nbits_freq);
	SIGNAL dfreq_word : integer := integer(df/fa*2.0**nbits_freq);

	--Inputs
	SIGNAL clk			: std_logic := '0';
	SIGNAL srst			: std_logic := '1';
	SIGNAL mix_nco_rst	: std_logic := '0';
	SIGNAL mix_nco_en	: std_logic := '0';
	SIGNAL mix_freq_in	: unsigned(nbits_freq-1 downto 0) := (others => '0');
	SIGNAL mix_phase_in	: unsigned(nbits_phase-1 downto 0) := (others => '0');

	--Outputs
	SIGNAL mix_din_i	: sfixed(shi(nbits_wave_in, nbits_wave_in_frac) downto slo(nbits_wave_in, nbits_wave_in_frac));
	SIGNAL mix_din_q	: sfixed(shi(nbits_wave_in, nbits_wave_in_frac) downto slo(nbits_wave_in, nbits_wave_in_frac));
	SIGNAL mix_dout_i	: sfixed(shi(nbits_wave_out, nbits_wave_out_frac) downto slo(nbits_wave_out, nbits_wave_out_frac));
	SIGNAL mix_dout_q	: sfixed(shi(nbits_wave_out, nbits_wave_out_frac) downto slo(nbits_wave_out, nbits_wave_out_frac));
	SIGNAL mix_dout_vld	: std_logic;
	SIGNAL mix_din_vld	: std_logic := '0';
	
	SIGNAL rfgen_nco_rst	: std_logic := '0';
	SIGNAL rfgen_nco_en		: std_logic := '0';
	SIGNAL rfgen_freq_in	: unsigned(nbits_freq-1 downto 0) := (others => '0');
	SIGNAL rfgen_phase_in	: unsigned(nbits_phase-1 downto 0) := (others => '0');

	--Outputs
	signal rfgen_din_i		: sfixed(shi(nbits_wave_in, nbits_wave_in_frac) downto slo(nbits_wave_in, nbits_wave_in_frac)) := to_sfixed(0.0, shi(nbits_wave_in, nbits_wave_in_frac), slo(nbits_wave_in, nbits_wave_in_frac));
	signal rfgen_din_q		: sfixed(shi(nbits_wave_in, nbits_wave_in_frac) downto slo(nbits_wave_in, nbits_wave_in_frac)) := to_sfixed(1.0, shi(nbits_wave_in, nbits_wave_in_frac), slo(nbits_wave_in, nbits_wave_in_frac));
	SIGNAL rfgen_dout_i		: sfixed(shi(nbits_wave_in, nbits_wave_in_frac) downto slo(nbits_wave_in, nbits_wave_in_frac));
	SIGNAL rfgen_dout_q		: sfixed(shi(nbits_wave_in, nbits_wave_in_frac) downto slo(nbits_wave_in, nbits_wave_in_frac));
	SIGNAL rfgen_dout_vld	: std_logic;
	SIGNAL fileout_enable   : std_logic := '0';

BEGIN

	-- Instantiate the Unit Under Test (UUT)
	uut: mix 
	GENERIC MAP
	(
		nbits_din		=> nbits_wave_in,
		nbits_din_frac	=> nbits_wave_in_frac,
		nbits_dout		=> nbits_wave_out,
		nbits_dout_frac	=> nbits_wave_out_frac,
		nbits_phase		=> nbits_phase,
		nbits_freq		=> nbits_freq
	)
	PORT MAP
	(
		rst			=> srst,
		clk			=> clk,
		nco_rst		=> mix_nco_rst,
		nco_en		=> mix_nco_en,
		freq_in		=> mix_freq_in,
		phase_in	=> mix_phase_in,
		din_i		=> mix_din_i,
		din_q		=> mix_din_q,
		dout_i		=> mix_dout_i,
		dout_q		=> mix_dout_q,
		din_vld		=> mix_din_vld,
		dout_vld	=> mix_dout_vld
	);

	rfgen1: mix 
	GENERIC MAP
	(
		nbits_din		=> nbits_wave_in,
		nbits_din_frac	=> nbits_wave_in_frac,
		nbits_dout		=> nbits_wave_in,
		nbits_dout_frac	=> nbits_wave_in_frac,
		nbits_phase		=> nbits_phase,
		nbits_freq		=> nbits_freq
	)
	PORT MAP
	(
		rst			=> srst,
		clk			=> clk,
		nco_rst		=> rfgen_nco_rst,
		nco_en		=> rfgen_nco_en,
		freq_in		=> rfgen_freq_in,
		phase_in	=> rfgen_phase_in,
		din_i		=> rfgen_din_i,
		din_q		=> rfgen_din_q,
		dout_i		=> rfgen_dout_i,
		dout_q		=> rfgen_dout_q,
		din_vld		=> '1',
		dout_vld	=> rfgen_dout_vld
	);

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

	mix_din_i	<= rfgen_dout_i;
	mix_din_q	<= to_sfixed(0.0, mix_din_q);
	mix_din_vld	<= rfgen_dout_vld;
	
	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(flo));

		wait for 2*PERIOD;
		-------------------------------------------
		-- 1
		mix_phase_in <= to_unsigned(0,nbits_phase);
		wait until rising_edge(clk);
		
		mix_freq_in <= to_unsigned(1411,nbits_freq);
		wait until rising_edge(clk);

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

		wait for 40*PERIOD;
		-------------------------------------------
		mix_freq_in <= to_unsigned(643,nbits_freq);
		wait until rising_edge(clk);

		wait for 40*PERIOD;
		-------------------------------------------
		mix_phase_in <= to_unsigned(800,nbits_phase);
		wait until rising_edge(clk);

		wait for 20*PERIOD;
		-------------------------------------------
		mix_phase_in <= to_unsigned(45072,nbits_phase);
		wait until rising_edge(clk);

		wait for 20*PERIOD;
		-------------------------------------------
		mix_phase_in <= to_unsigned(20593,nbits_phase);
		wait until rising_edge(clk);

		-------------------------------------------
		mix_freq_in <= to_unsigned(freq_word,nbits_freq);
		wait until rising_edge(clk);
	
		wait for 20*PERIOD;
		fileout_enable <= '1';

		wait for 200000*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;
			
			mix_freq_in <= to_unsigned(freq_word,nbits_freq);
			wait until rising_edge(clk);
	
		end loop;
		
		mix_nco_en <= '0';
		wait for 20*PERIOD;
		fileout_enable <= '0';
		wait until rising_edge(clk);
		mix_nco_rst <= '1';
		wait until rising_edge(clk);
		mix_nco_rst <= '0';
		wait for 20*PERIOD;
		mix_nco_en <= '1';
		wait for 20*PERIOD;
		wait until rising_edge(clk);
		mix_nco_rst <= '1';
		wait until rising_edge(clk);
		mix_nco_rst <= '0';
		wait for 20*PERIOD;
		mix_nco_en <= '0';
		wait for 20*PERIOD;
		wait until rising_edge(clk);
		mix_nco_en <= '1';
		wait until rising_edge(clk);
		mix_nco_en <= '0';
		wait for 20*PERIOD;
		wait until rising_edge(clk);
		srst <= '1';
		wait until rising_edge(clk);
		srst <= '0';
		mix_freq_in <= to_unsigned(freq_word,nbits_freq);
		wait until rising_edge(clk);
		
		wait for 20*PERIOD;
		mix_nco_en <= '1';
		wait for 20*PERIOD;
		wait until rising_edge(clk);
		srst <= '1';
		wait until rising_edge(clk);
		srst <= '0';
		wait for 20*PERIOD;
		mix_nco_en <= '0';

		wait for 20*PERIOD;

		assert false report "Test finished" severity error;
		wait; 
	END PROCESS;
	
	
	rfgen_ctrl : PROCESS

	BEGIN
			wait for 20*PERIOD;
			wait until rising_edge(clk) and srst = '0';
			rfgen_freq_in <= to_unsigned(rfgen_freq_word,nbits_freq);
			wait until rising_edge(clk);
			
			wait for 20*PERIOD;
			rfgen_nco_en <= '1';
	
			wait for 20*PERIOD;

		wait; 
	END PROCESS;

	tb_fo : PROCESS(clk)
	file RESULT_Ii:      text open write_mode is "i_in.txt"; 
	file RESULT_Qi:      text open write_mode is "q_in.txt"; 
	file RESULT_Io:      text open write_mode is "i_out.txt"; 
	file RESULT_Qo:      text open write_mode is "q_out.txt"; 
	variable L:         line;

	BEGIN
		if rising_edge(clk) and fileout_enable = '1' then
			if rfgen_dout_vld = '1' then
				fprint(RESULT_Ii, L,"%s\n", REAL'image(to_real(rfgen_dout_i)));
				fprint(RESULT_Qi, L,"%s\n", REAL'image(to_real(rfgen_dout_q)));
			end if;
			if mix_dout_vld = '1' then
				fprint(RESULT_Io, L,"%s\n", REAL'image(to_real(mix_dout_i)));
				fprint(RESULT_Qo, L,"%s\n", REAL'image(to_real(mix_dout_q)));
			end if;
		end if;

	END PROCESS;


END;
