--------------------------------------------------------------------------- -- NCO core -- by Paul Maddox -- Www.FPGA.Wavesynth.com -- -- Simple NCO core, -- -- Has sync in and out (maskable), -- 8 Bit control word (for allowing sync-in to work), -- 8 Bit data bus in (easy interface to 8bit micro) -- 3 bit address bus to select what the value on the 8bit bus is (control word, or byte for frequency control), -- High impedance outputs (allowing several NCOs to be connected to a common output), -- Top 8 bits of accumulator are outputted (allowing 256byte resoloution waveforms to be played back from RAM/ROM) ---------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------- -- Copyright (c) 2002, Paul Maddox -- All rights reserved. -- -- Redistribution and use in source and binary forms, -- with or without modification, -- are permitted provided that the following conditions are met: -- -- * Redistributions of source code must retain the above copyright notice, -- this list of conditions and the following disclaimer. -- * Redistributions in binary form must reproduce the above copyright notice, -- this list of conditions and the following disclaimer in the -- documentation and/or other materials provided with the distribution. -- * Neither the name of Modulus electronics nor the names of its contributors -- may be used to endorse or promote products derived from this software -- without specific prior written permission. -- -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- ---------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -- Libraries we're going to be using ---------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; ---------------------------------------------------------------------------- -- package setup -- what the things outputs/inputs are ---------------------------------------------------------------------------- package nco_pack is component nco_comp port ( sync_in :in std_logic; -- sync 'SYNC IN' clk_in :in std_logic; -- NCO clock enable :in std_logic; -- async ENABLE for outputs write :in std_logic; -- Async WRITE IN data_sel :in std_logic_vector (2 downto 0); -- Selector for data_bus data_bus :in std_logic_vector (7 downto 0); -- 8Bit data bus for loading values sync_out :out std_logic; -- SYNC OUT high when output wave position = 00 wave_out :out std_logic_vector (7 downto 0) -- 16Bit address to drive EPROM/SRAM ); end component; end nco_pack; ---------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library work; use work.nco_pack.all; ---------------------------------------------------------------------------- -- Entity -- What the 'Pins' do ---------------------------------------------------------------------------- entity nco_comp is port ( sync_in :in std_logic; -- sync 'SYNC IN' clk_in :in std_logic; -- NCO clock enable :in std_logic; -- async ENABLE for outputs write :in std_logic; -- Async WRITE IN data_sel :in std_logic_vector (2 downto 0); -- Selector for data_bus data_bus :in std_logic_vector (7 downto 0); -- 8Bit data bus for loading values sync_out :out std_logic; -- SYNC OUT high when output wave position = 00 wave_out :out std_logic_vector (7 downto 0):=X"00" -- 16Bit address to drive EPROM/SRAM ); end nco_comp; ---------------------------------------------------------------------------- -- Architecture -- What's used 'inside' and declare additional variables to play with ---------------------------------------------------------------------------- architecture arch_nco_comp of nco_comp is signal control :std_logic_vector (7 downto 0):=X"00"; -- Holds control word, sync maskis bit 0 signal freq :std_logic_vector (23 downto 0):=X"000000"; -- 24 But frequency control value signal phase :std_logic_vector (31 downto 0):=X"00000000"; -- 32 Bit accumulator (top 8 are output) ---------------------------------------------------------------------------- -- Begin/Process -- the actual process that happens inside the module ---------------------------------------------------------------------------- begin process (sync_in, clk_in, control) -- clk/sync process begin if clk_in'event and clk_in='1' then -- increase phase by freq on each clock if (sync_in ='1' and control(0)='1') then -- we only sync on a clk if SYNC in is allowed (bit 0 of 'control') phase(31 downto 0) <= x"00000000"; else -- if not sync then carry on adding. phase(31 downto 0) <= phase(31 downto 0) + freq(23 downto 0); end if; end if; end process; process (write) -- if we get a write begin if write'event and write='0'then -- if we have had a falling edge if data_sel="000" then -- lowest byte of freq freq(7 downto 0) <= data_bus (7 downto 0); end if; if data_sel="001" then -- Middle Byte of freq freq(15 downto 8) <= data_bus (7 downto 0); end if; if data_sel="010" then -- Top byte of freq freq(23 downto 16) <= data_bus (7 downto 0); end if; if data_sel="100" then -- control word (bit 0 is Sync enable) control (7 downto 0) <= data_bus (7 downto 0); end if; end if; end process; wave_out <= phase(31 downto 24) when (enable = '1') else "ZZZZZZZZ"; -- when enable is high output top 8bits of accumulator sync_out <= '1' when (phase (31 downto 16) = x"0000") else '0'; -- Set sync out when top 16 bits are at zero (start of waveform) end arch_nco_comp; ----------------------------------------------------------------------------