-- -- nco.vhd -- -- This module implements an NCO (Numericaly Controlled Oscilator). -- It uses the phase acumulation method with a non-compressed LUT. -- To use a square wave output set lut_out_size to "1". If lut_out_size -- is bigger than 1 then you must provide a file named "wave.hex" in -- intel-hex format that contains the wave samples of your intended -- signal (usually a sinewave). -- -- Parameters: -- -- acc_size - Acumulator size in bits. -- lut_addr_size - Number or address bits of the LUT. -- lut_out_size - LUT output resolution in bits. -- phase_size - Number of bits of the phase modulation signal. -- -- Ports: -- -- nco_clk - The Clock. -- freq - Frequency control signal. It is acc_size bits wide. -- The output frequency is given by [(F/2^acc_size)*freq] -- where F is the nco_clock frequency. -- phase - Phase control signal. It is phase_size bits wide. -- The most significant bit makes 180 degrees phase -- changes, the next bit makes 90 degree phase changes, -- and so on... -- nco_output - The output of the oscilator. -- It has lut_out_size bits of amplitude resolution. -- period - This signal is "0" during the first half period and -- "1" during the second half period. -- -- Dependencies: -- -- * acumul.vhd -- * lpm_rom -- * lpm_add_sub -- LIBRARY ieee; USE ieee.std_logic_1164.all; LIBRARY lpm; USE lpm.lpm_components.lpm_rom; USE lpm.lpm_components.lpm_add_sub; ENTITY nco IS GENERIC (acc_size: positive := 24; lut_addr_size: positive := 9; lut_out_size: positive := 8; phase_size: positive := 1); PORT(nco_clk: IN std_logic; freq: IN std_logic_vector(acc_size-1 downto 0); phase: IN std_logic_vector(phase_size-1 downto 0)); nco_output: OUT std_logic_vector(lut_out_size-1 downto 0); period: OUT std_logic; END nco; ARCHITECTURE archnco OF nco IS -- output of the acumulator signal addr1: std_logic_vector(acc_size-1 downto 0); -- output of the phase adder signal addr2: std_logic_vector(acc_size-1 downto 0); BEGIN acc: work.acumul GENERIC MAP (acc_size) PORT MAP (nco_clk, freq, addr1); gen1: if (phase_size>0) generate -- This is only generated when we need to phase modulate. add: lpm_add_sub GENERIC MAP (LPM_WIDTH => phase_size, LPM_DIRECTION => "ADD", LPM_REPRESENTATION => "UNSIGNED") PORT MAP (dataa => addr1(acc_size-1 downto acc_size-phase_size), datab => phase, result => addr2(acc_size-1 downto acc_size-phase_size)); addr2(acc_size-phase_size-1 downto 0) <= addr1(acc_size-phase_size-1 downto 0); end generate; notgen1: if (phase_size=0) generate -- This is only generated when we donīt need to phase modulate. addr2 <= addr1; end generate; gen2: if (lut_out_size>1) generate -- This is only generated when LUT output resolution is bigger -- than 1 bit. lut: lpm_rom GENERIC MAP (lpm_width => lut_out_size, lpm_widthad => lut_addr_size, lpm_file => "wave.hex", lpm_address_control => "unregistered", lpm_outdata => "unregistered") PORT MAP (address => addr2(acc_size-1 downto (acc_size-lut_addr_size)), q => nco_output); end generate; notgen2: if (lut_out_size=1) generate -- This is only generated when LUT output resolution is 1 bit, -- which means that the output is a square wave. nco_output(0) <= addr2(acc_size-1); end generate; period <= addr1(acc_size-1); END archnco; -- -- END nco.vhd --