OpenCores
URL https://opencores.org/ocsvn/lpd8806/lpd8806/trunk

Subversion Repositories lpd8806

[/] [lpd8806/] [trunk/] [dds_pack.vhd] - Rev 5

Compare with Previous | Blame | View Log

--------------------------------------------------------------------------
-- Package of dds components
--
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
library work;
use work.sine_lut_pkg.all;
 
package dds_pack is
 
  component dds_constant_squarewave
    generic (
      OUTPUT_FREQ  : real;   -- Desired output frequency
      SYS_CLK_RATE : real;   -- underlying clock rate
      ACC_BITS     : integer -- Bit width of DDS phase accumulator
    );
    port ( 
 
      sys_rst_n    : in  std_logic;
      sys_clk      : in  std_logic;
      sys_clk_en   : in  std_logic;
 
      -- Output
      pulse_o      : out std_logic;
      squarewave_o : out std_logic
    );
  end component;
 
  component dds_squarewave
    generic (
      ACC_BITS     : integer -- Bit width of DDS phase accumulator
    );
    port ( 
 
      sys_rst_n    : in  std_logic;
      sys_clk      : in  std_logic;
      sys_clk_en   : in  std_logic;
 
      -- Frequency setting
      freq_i       : in  unsigned(ACC_BITS-1 downto 0);
 
      -- Output
      pulse_o      : out std_logic;
      squarewave_o : out std_logic
    );
  end component;
 
  component dds_sine_non_power_of_two
    generic(
      PHI_WIDTH : integer  -- Bits in phase accumulator.  Must hold numbers greater than full sinewave lut length...
      );
    port(
      clk_i     : in  std_logic;
      rst_n_i   : in  std_logic;
      clk_en_i  : in  std_logic;
      ftw_i     : in  unsigned(PHI_WIDTH-1 downto 0);
      accum_o   : out unsigned(PHI_WIDTH-1 downto 0);
      sine_o    : out signed(AMPL_WIDTH-1 downto 0)
      );
  end component;
 
end dds_pack;
 
package body dds_pack is
end dds_pack;
 
-------------------------------------------------------------------------------
-- Direct Digital Synthesizer Constant Squarewave module
-------------------------------------------------------------------------------
--
-- Author: John Clayton
-- Update: Sep.  5, 2002 copied this file from "auto_baud_pack.vhd"
--                       Added tracking functions, and debugged them.
--
-- Description
-------------------------------------------------------------------------------
-- This is a simple direct digital synthesizer module.  It includes a phase
-- accumulator which increments in order to produce the desired output
-- frequency in its most significant bit, which is the squarewave output.
--
-- In addition to the squarewave output there is a pulse output which is
-- high for one sys_clk period, during the sys_clk period immediately
-- preceding the rising edge of the squarewave output.
--
-- NOTES:
--   The accumulator increment word is:
--        increment = Fout*2^N/Fsys_clk
--
--   Where N is the number of bits in the phase accumulator.
--
--   There will always be jitter with this type of clock source, but the
--   long time average frequency can be made arbitrarily close to whatever
--   value is desired, simply by increasing N.
--
--   To reduce jitter, use a higher underlying system clock frequency, and
--   for goodness sakes, try to keep the desired output frequency much lower
--   than the system clock frequency.  The closer it gets to Fsys_clk/2, the
--   closer it is to the Nyquist limit, and the output jitter is much more
--   significant at that point.
--
--
 
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
 
  entity dds_constant_squarewave is
    generic (
      OUTPUT_FREQ  : real := 8000.0;     -- Desired output frequency
      SYS_CLK_RATE : real := 48000000.0; -- underlying clock rate
      ACC_BITS     : integer := 16       -- Bit width of DDS phase accumulator
    );
    port ( 
 
      sys_rst_n    : in  std_logic;
      sys_clk      : in  std_logic;
      sys_clk_en   : in  std_logic;
 
      -- Output
      pulse_o      : out std_logic;
      squarewave_o : out std_logic
    );
  end dds_constant_squarewave;
 
architecture beh of dds_constant_squarewave is
 
-- Constants
constant DDS_INCREMENT : integer := integer(OUTPUT_FREQ*(2**real(ACC_BITS))/SYS_CLK_RATE);
 
signal dds_phase      : unsigned(ACC_BITS-1 downto 0); -- phase accumulator register
signal dds_phase_next : unsigned(ACC_BITS-1 downto 0);
 
-----------------------------------------------------------------------------
begin
 
  dds_proc: Process(sys_rst_n,sys_clk)
  begin
    if (sys_rst_n = '0') then
      dds_phase <= (others=>'0');
    elsif (sys_clk'event and sys_clk='1') then
      if (sys_clk_en='1') then
        dds_phase <= dds_phase_next;
      end if;
    end if; -- sys_clk
  end process dds_proc;
  dds_phase_next <= dds_phase + DDS_INCREMENT;
  pulse_o <= '1' when sys_clk_en='1' and dds_phase(dds_phase'length-1)='0' and dds_phase_next(dds_phase_next'length-1)='1' else '0';
  squarewave_o <= dds_phase(dds_phase'length-1);
 
end beh;
 
 
-------------------------------------------------------------------------------
-- Direct Digital Synthesizer Constant Squarewave module
-------------------------------------------------------------------------------
--
-- Author: John Clayton
-- Update: Jan. 31, 2013 copied code from dds_constant_squarewave, and
--                       modified it to accept a frequency setting input.
--
-- Description
-------------------------------------------------------------------------------
-- This is a simple direct digital synthesizer module.  It includes a phase
-- accumulator which increments in order to produce the desired output
-- frequency in its most significant bit, which is the squarewave output.
--
-- In addition to the squarewave output there is a pulse output which is
-- high for one sys_clk period, during the sys_clk period immediately
-- preceding the rising edge of the squarewave output.
--
-- NOTES:
--   The accumulator increment word is:
--        increment = Fout*2^N/Fsys_clk
--
--   Where N is the number of bits in the phase accumulator.
--
--   There will always be jitter with this type of clock source, but the
--   long time average frequency can be made arbitrarily close to whatever
--   value is desired, simply by increasing N.
--
--   To reduce jitter, use a higher underlying system clock frequency, and
--   for goodness sakes, try to keep the desired output frequency much lower
--   than the system clock frequency.  The closer it gets to Fsys_clk/2, the
--   closer it is to the Nyquist limit, and the output jitter is much more
--   significant at that point.
--
--
 
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
 
  entity dds_squarewave is
    generic (
      ACC_BITS     : integer := 16       -- Bit width of DDS phase accumulator
    );
    port ( 
 
      sys_rst_n    : in  std_logic;
      sys_clk      : in  std_logic;
      sys_clk_en   : in  std_logic;
 
      -- Frequency setting
      freq_i       : in  unsigned(ACC_BITS-1 downto 0);
 
      -- Output
      pulse_o      : out std_logic;
      squarewave_o : out std_logic
    );
  end dds_squarewave;
 
architecture beh of dds_squarewave is
 
-- Constants
signal dds_phase      : unsigned(ACC_BITS-1 downto 0); -- phase accumulator register
signal dds_phase_next : unsigned(ACC_BITS-1 downto 0);
 
-----------------------------------------------------------------------------
begin
 
  dds_proc: Process(sys_rst_n,sys_clk)
  begin
    if (sys_rst_n = '0') then
      dds_phase <= (others=>'0');
    elsif (sys_clk'event and sys_clk='1') then
      if (sys_clk_en='1') then
        dds_phase <= dds_phase_next;
      end if;
    end if; -- sys_clk
  end process dds_proc;
  dds_phase_next <= dds_phase + freq_i;
  pulse_o <= '1' when sys_clk_en='1' and dds_phase(dds_phase'length-1)='0' and dds_phase_next(dds_phase_next'length-1)='1' else '0';
  squarewave_o <= dds_phase(dds_phase'length-1);
 
end beh;
 
 
-------------------------------------------------------------------------------
-- Direct Digital Synthesizer Arbitrary Length Sinewave Look Up Table module
-------------------------------------------------------------------------------
--
-- Author: John Clayton
-- Update: Jan. 24, 2013 Modified Matlab script "sine_arbitrary_length_lut_gen"
--                       to produce VHDL output which uses the "unsigned" type
--                       from ieee.numeric_std library.
--         Jan. 26, 2013 Rewrote accumulator folding logic.  Added saturation
--                       check to avoid indices beyond the end of the lookup
--                       table.
--
-- Description
-------------------------------------------------------------------------------
-- This is a direct digital synthesizer module, which uses a 1/4 wave lookup
-- to produce sinewave samples.  A Matlab script generates the samples to the
-- desired number of bits, number of samples and amplitude.
--
-- The generated file is the "sine_lut_pkg", although the filename may well
-- be different, such as "sine_lut_5000_x_16.vhd"
--
-- The generated file contains definitions for:
--   constant AMPL_WIDTH : integer
--   constant PHASE_LENGTH : integer
--   constant PHASE_WIDTH  : integer
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
library work;
use work.sine_lut_pkg.all;
use work.convert_pack.all;
 
entity dds_sine_non_power_of_two is
  generic(
    PHI_WIDTH : integer  -- Bits in phase accumulator.  Must hold numbers greater than full sinewave lut length...
    );
  port(
    clk_i    : in  std_logic;
    rst_n_i  : in  std_logic;
    clk_en_i : in  std_logic;
    ftw_i    : in  unsigned(PHI_WIDTH-1 downto 0);
    accum_o  : out unsigned(PHI_WIDTH-1 downto 0);
    sine_o   : out signed(AMPL_WIDTH-1 downto 0)
    );
end dds_sine_non_power_of_two;
 
architecture dds_arch of dds_sine_non_power_of_two is
 
  constant FRAC_BITS     : natural := PHI_WIDTH - PHASE_WIDTH;
  constant Q_PHASE_WIDTH : integer := PHASE_WIDTH-2;  -- Quarter phase takes two bits less to represent
  constant Q_LENGTH      : unsigned(Q_PHASE_WIDTH-1 downto 0) := to_unsigned(PHASE_LENGTH/4,Q_PHASE_WIDTH); -- Quadrant Length
  constant Q_THRESH      : unsigned(PHI_WIDTH-1 downto 0) := to_unsigned(2**FRAC_BITS*PHASE_LENGTH/4,PHI_WIDTH); -- Quadrant Length
 
  signal accum        : unsigned(PHI_WIDTH-1 downto 0);
  signal q_accum      : unsigned(PHI_WIDTH-1 downto 0);
  signal q_accum_next : unsigned(PHI_WIDTH-1 downto 0);
  signal accum_incr   : unsigned(PHI_WIDTH-1 downto 0);
  signal accum_folded : unsigned(PHI_WIDTH-1 downto 0);
  signal lut_out      : unsigned(AMPL_WIDTH-1 downto 0);
  signal lut_out_neg  : unsigned(AMPL_WIDTH-1 downto 0);
 
  signal q_phase      : unsigned(Q_PHASE_WIDTH-1 downto 0);
  signal q_phase_sat  : unsigned(Q_PHASE_WIDTH-1 downto 0);
  signal q_count      : unsigned(1 downto 0);
  signal q_count_r1   : unsigned(1 downto 0);
 
begin
 
  accum_incr   <= unsigned(ftw_i);
  q_accum_next   <= q_accum + accum_incr;
  accum_folded <=            q_accum when q_count(0)='0' else
                  Q_THRESH - q_accum;
  q_phase      <= u_resize(u_resize_l(accum_folded,PHASE_WIDTH),q_phase'length); -- Discard the fractional portion
  lut_out      <= sine_lut(to_integer(q_phase_sat));
  lut_out_neg  <= (not lut_out) + 1;
  sine_o       <= signed(lut_out_neg) when q_count_r1(1) = '1' else signed(lut_out);
  accum_o      <= accum+q_accum;
 
  process (clk_i, rst_n_i)
  begin
    if (rst_n_i = '0') then
      accum       <= (others=>'0');
      q_accum     <= (others=>'0');
      q_count     <= (others=>'0');
      q_count_r1  <= (others=>'0');
      q_phase_sat <= (others=>'0');
    elsif (clk_i'event and clk_i = '1') then
      if (clk_en_i = '1') then
        if (q_accum_next > Q_THRESH) then
          q_accum <= q_accum_next - Q_THRESH;
          q_count <= q_count+1;
          if (q_count="11") then
            accum <= (others=>'0');
          else
            accum   <= accum + Q_THRESH;
          end if;
        else
          q_accum <= q_accum_next;
        end if;
 
        -- Delayed q_count, to match delayed q_phase
        q_count_r1 <= q_count;
        -- Saturate the quarter phase signal, to avoid overflows when looking up sine values
        if (q_phase>=(PHASE_LENGTH/4)) then
          q_phase_sat <= to_unsigned(PHASE_LENGTH/4-1,q_phase_sat'length);
        else
          q_phase_sat <= q_phase;
        end if;
      end if;
    end if;
  end process;
 
end dds_arch;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.