----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
-- --
|
-- --
|
-- THIS VHDL SOURCE CODE IS PROVIDED UNDER THE GNU PUBLIC LICENSE --
|
-- THIS VHDL SOURCE CODE IS PROVIDED UNDER THE GNU PUBLIC LICENSE --
|
-- --
|
-- --
|
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
-- --
|
-- --
|
-- Filename : waveform_gen.vhd --
|
-- Filename : waveform_gen.vhd --
|
-- --
|
-- --
|
-- Author : Simon Doherty --
|
-- Author : Simon Doherty --
|
-- Senior Design Consultant --
|
-- Senior Design Consultant --
|
-- www.zipcores.com --
|
-- www.zipcores.com --
|
-- --
|
-- --
|
-- Date last modified : 24.10.2008 --
|
-- Date last modified : 24.10.2008 --
|
-- --
|
-- --
|
-- Description : NCO / Periodic Waveform Generator --
|
-- Description : NCO / Periodic Waveform Generator --
|
-- --
|
-- --
|
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
|
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_arith.all;
|
use ieee.std_logic_arith.all;
|
|
|
|
|
entity waveform_gen is
|
entity waveform_gen is
|
|
|
port (
|
port (
|
|
|
-- system signals
|
-- system signals
|
clk : in std_logic;
|
clk : in std_logic;
|
reset : in std_logic;
|
reset : in std_logic;
|
|
|
-- clock-enable
|
-- clock-enable
|
en : in std_logic;
|
en : in std_logic;
|
|
|
-- NCO frequency control
|
-- NCO frequency control
|
phase_inc : in std_logic_vector(31 downto 0);
|
phase_inc : in std_logic_vector(31 downto 0);
|
|
|
-- Output waveforms
|
-- Output waveforms
|
sin_out : out std_logic_vector(11 downto 0);
|
sin_out : out std_logic_vector(11 downto 0);
|
cos_out : out std_logic_vector(11 downto 0);
|
cos_out : out std_logic_vector(11 downto 0);
|
squ_out : out std_logic_vector(11 downto 0);
|
squ_out : out std_logic_vector(11 downto 0);
|
saw_out : out std_logic_vector(11 downto 0) );
|
saw_out : out std_logic_vector(11 downto 0) );
|
|
|
end entity;
|
end entity;
|
|
|
|
|
architecture rtl of waveform_gen is
|
architecture rtl of waveform_gen is
|
|
|
|
|
component sincos_lut
|
component sincos_lut
|
|
|
port (
|
port (
|
|
|
clk : in std_logic;
|
clk : in std_logic;
|
en : in std_logic;
|
en : in std_logic;
|
addr : in std_logic_vector(11 downto 0);
|
addr : in std_logic_vector(11 downto 0);
|
sin_out : out std_logic_vector(11 downto 0);
|
sin_out : out std_logic_vector(11 downto 0);
|
cos_out : out std_logic_vector(11 downto 0));
|
cos_out : out std_logic_vector(11 downto 0));
|
|
|
end component;
|
end component;
|
|
|
|
|
signal phase_acc : std_logic_vector(31 downto 0);
|
signal phase_acc : std_logic_vector(31 downto 0);
|
signal lut_addr : std_logic_vector(11 downto 0);
|
signal lut_addr : std_logic_vector(11 downto 0);
|
signal lut_addr_reg : std_logic_vector(11 downto 0);
|
signal lut_addr_reg : std_logic_vector(11 downto 0);
|
|
|
|
|
begin
|
begin
|
|
|
|
|
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
-- Phase accumulator increments by 'phase_inc' every clock cycle --
|
-- Phase accumulator increments by 'phase_inc' every clock cycle --
|
-- Output frequency determined by formula: Phase_inc = (Fout/Fclk)*2^32 --
|
-- Output frequency determined by formula: Phase_inc = (Fout/Fclk)*2^32 --
|
-- E.g. Fout = 36MHz, Fclk = 100MHz, Phase_inc = 36*2^32/100 --
|
-- E.g. Fout = 36MHz, Fclk = 100MHz, Phase_inc = 36*2^32/100 --
|
-- Frequency resolution is 100MHz/2^32 = 0.00233Hz --
|
-- Frequency resolution is 100MHz/2^32 = 0.00233Hz --
|
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
|
|
phase_acc_reg: process(clk, reset)
|
phase_acc_reg: process(clk, reset)
|
begin
|
begin
|
if reset = '0' then
|
if reset = '0' then
|
phase_acc <= (others => '0');
|
phase_acc <= (others => '0');
|
elsif clk'event and clk = '1' then
|
elsif clk'event and clk = '1' then
|
if en = '1' then
|
if en = '1' then
|
phase_acc <= unsigned(phase_acc) + unsigned(phase_inc);
|
phase_acc <= unsigned(phase_acc) + unsigned(phase_inc);
|
end if;
|
end if;
|
end if;
|
end if;
|
end process phase_acc_reg;
|
end process phase_acc_reg;
|
|
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
-- use top 12-bits of phase accumulator to address the SIN/COS LUT --
|
-- use top 12-bits of phase accumulator to address the SIN/COS LUT --
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
|
|
lut_addr <= phase_acc(31 downto 20);
|
lut_addr <= phase_acc(31 downto 20);
|
|
|
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
-- SIN/COS LUT is 4096 by 12-bit ROM --
|
-- SIN/COS LUT is 4096 by 12-bit ROM --
|
-- 12-bit output allows sin/cos amplitudes between 2047 and -2047 --
|
-- 12-bit output allows sin/cos amplitudes between 2047 and -2047 --
|
-- (-2048 not used to keep the output signal perfectly symmetrical) --
|
-- (-2048 not used to keep the output signal perfectly symmetrical) --
|
-- Phase resolution is 2Pi/4096 = 0.088 degrees --
|
-- Phase resolution is 2Pi/4096 = 0.088 degrees --
|
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
|
|
lut: sincos_lut
|
lut: sincos_lut
|
|
|
port map (
|
port map (
|
|
|
clk => clk,
|
clk => clk,
|
en => en,
|
en => en,
|
addr => lut_addr,
|
addr => lut_addr,
|
sin_out => sin_out,
|
sin_out => sin_out,
|
cos_out => cos_out );
|
cos_out => cos_out );
|
|
|
---------------------------------
|
---------------------------------
|
-- Hide the latency of the LUT --
|
-- Hide the latency of the LUT --
|
---------------------------------
|
---------------------------------
|
|
|
delay_regs: process(clk)
|
delay_regs: process(clk)
|
begin
|
begin
|
if clk'event and clk = '1' then
|
if clk'event and clk = '1' then
|
if en = '1' then
|
if en = '1' then
|
lut_addr_reg <= lut_addr;
|
lut_addr_reg <= lut_addr;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process delay_regs;
|
end process delay_regs;
|
|
|
---------------------------------------------
|
---------------------------------------------
|
-- Square output is msb of the accumulator --
|
-- Square output is msb of the accumulator --
|
---------------------------------------------
|
---------------------------------------------
|
|
|
squ_out <= "011111111111" when lut_addr_reg(11) = '1' else "100000000000";
|
squ_out <= "011111111111" when lut_addr_reg(11) = '1' else "100000000000";
|
|
|
-------------------------------------------------------
|
-------------------------------------------------------
|
-- Sawtooth output is top 12-bits of the accumulator --
|
-- Sawtooth output is top 12-bits of the accumulator --
|
-------------------------------------------------------
|
-------------------------------------------------------
|
|
|
saw_out <= lut_addr_reg;
|
saw_out <= lut_addr_reg;
|
|
|
|
|
|
|