--------------------------------------------------------------------------------
-- (c) by c't magazin 
--------------------------------------------------------------------------------
--
-- Design name : CT_Lab_FPGA
--
-- Filename : Frequency_Generator.vhd
-- Version : 1.0
-- Date: 25.7.2008
--
-- Engineer : Klaus Philipp
-- modified by cm 09.12.2008
--------------------------------------------------------------------------------
-- Frequency generator
--
-- The frequency generator is controlled by two registers
-- The N register is 5 bit long
-- The A register is 32 bit long
--
--------------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all; 
use IEEE.std_logic_unsigned.all;
--use IEEE.numeric_std.all;

-- The Unisim Library is used to define Xilinx primitives. It is also used during
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
--
library UNISIM;
use UNISIM.Vcomponents.ALL;

entity Frequency_Generator is
   port (dds_control_word : in std_logic_vector (31 downto 0) := X"10000000";  -- 100 MHz
			dds_scaling_word : in std_logic_vector (4 downto 0)  := "00000";
			RESET    : in    std_logic;
         CLK      : in    std_logic;
         FREQ_OUT : out   std_logic);
end Frequency_Generator;

architecture BEHAVIORAL of Frequency_Generator is

--
-- DDS signals
signal         synth_clk : std_logic;
--
signal phase_accumulator : std_logic_vector (31 downto 0) := X"00000000";
--
signal frequency_divider : std_logic_vector (31 downto 0) := X"00000000";
signal     frequency_out : std_logic;


begin


-- DCM entfernt von cm, CLK von Global 200 MHz

  phase_acc: process(CLK, RESET, dds_control_word)
  begin
    if rising_edge (CLK)
    then 
      phase_accumulator <= phase_accumulator + dds_control_word;
    end if;
	 synth_clk <=phase_accumulator(31);
  end process phase_acc;
  
  freq_divide: process(synth_clk, RESET)
  begin
	 if rising_edge (synth_clk)
	 then
      frequency_divider <= frequency_divider + 1;
    end if;
  end process freq_divide;

  freq_scaling: process(frequency_divider, dds_scaling_word, synth_clk)
  begin
		case dds_scaling_word is
		  when "00000" =>frequency_out <= synth_clk;
		  when "00001" =>frequency_out <= frequency_divider(0); 
		  when "00010" =>frequency_out <= frequency_divider(1);
		  when "00011" =>frequency_out <= frequency_divider(2);
		  when "00100" =>frequency_out <= frequency_divider(3);      
		  when "00101" =>frequency_out <= frequency_divider(4);      
		  when "00110" =>frequency_out <= frequency_divider(5);      
		  when "00111" =>frequency_out <= frequency_divider(6);      
		  when "01000" =>frequency_out <= frequency_divider(7);      
		  when "01001" =>frequency_out <= frequency_divider(8);      
		  when "01010" =>frequency_out <= frequency_divider(9);      
		  when "01011" =>frequency_out <= frequency_divider(10);      
		  when "01100" =>frequency_out <= frequency_divider(11);      
		  when "01101" =>frequency_out <= frequency_divider(12);      
		  when "01110" =>frequency_out <= frequency_divider(13);      
		  when "01111" =>frequency_out <= frequency_divider(14);      

		  -- Don't care used for all other to ensure minimum logic implementation
		  when others =>    frequency_out <= 'X';  

		end case;
 
      -- Pipeline output from multiplexer to maintain performance up to 200MHz

      FREQ_OUT <= frequency_out;   
  end process freq_scaling;

end BEHAVIORAL;


