11-03-2011 06:18 PM
Hi, What is the recommended technique to change the frequency of a sine wave at runtime? Do I have to implement a divider by changing the clock counter module for each output frequency? I'm using spartan 3s200 ft256 with DDS 4.0.
thanks.
11-17-2011 12:56 PM
The point is that you should select the bit width of the DDS accumulator and increment port to allow the
frequency resolution you require.
For example for a resolution of 100 Hz at 50 MHz input clock you would need 19 bits. It
is not uncommon to use enough bits to provide fractional Hz resolution. If your output needs to go in
geometric steps rather than linear, the best thing is to either calculate the correct increment setting on
the fly or use a look-up table with the phase increment values for each of your required frequencies.
Note that the fact that you only have 7 or 8 bits of DAC on the output does not mean that you need
to use no more than 8 bits for the accumulator. Just attach the most significant bits of the output
to your sine table.
-- Gabor
11-04-2011 11:34 AM
Normally you just change the "phase increment" to change the frequency. When you
generate the core, on page two of the customization screens, select "streaming" for
the "Phase Increment Programmability" option. Then you will have a directly programmable
output frequency.
See the DDS data sheet (ds558.pdf) for more detail on how to use the phase increment
streaming mode.
-- Gabor
11-04-2011 12:40 PM
Thank you for support. I'll do it and report the results.
11-04-2011 12:50 PM
11-10-2011 04:09 AM
Can you provide more details on what you mean by "the sine wave distorts"? Also if you can show how you increment the phase increment, that will help figure out what's going on.
@emiliano87 wrote:
I change the 'phase increment' on runtime, but when I increment the register the sine wave distorts. And if I change the clock and phase increment I have normal signal in output. My doubt is, for generate signal in frequency range of 100 hz to 1Mhz I should change the clock everytime that the signal distorts with high value of phase increment with a low clock?
11-14-2011 04:37 AM
Hi Jim, I'm using the spartan3 from digilent starter kit. Well, the source clock is 50Mhz and I need generate signal from 100hz to 1Mhz.. I read the Xilinx DDS guide and saw that [ Fout = (Fclk*Phase_inc)/2^B ]. Considering this equation, to get low-frequency signals I think that I need to do a clock divider. The phase increment (8bits) I conected with switches of the board for change the value in runtime. The clock divider I did with a push button that change in runtime the value that should be counted. Using this technique, I cannot yet generate signals with specific frequency. If I do not change the clock and just increment the Phase-Increment, when the value of Phase-Increment is a rather large, the sine wave losing samples and showing like steps. I'm using DDS 4.0.
With a high value in the register of Phase Increment the system removes some samples to get the signal in the frequency desired. Thus, I set the clock to keep the signal always at least 8 or 7 bits.
In the image, the red is the sine with correct clock and phase increment and blue/green the signal if I change only Phase Increment with the same clock.
11-15-2011 03:42 AM
Are you incrementing the phase increment at every clock cycle, or just setting it to the value of the switches? Can you share your HDL?
11-16-2011 11:55 AM
below my HDL code:
Too In annex the source code in pdf.
-----------------------------------------------------------------
ENTITY my_dds IS
PORT(
enable: IN std_logic;
clock: IN std_logic;
sin: OUT std_logic_vector(7 downto 0);
reset: IN std_logic;
led_on: OUT std_logic;
btn_0: IN std_logic;
switch: IN std_logic_vector(7 downto 0)
);
END my_dds;
----------------------------------------------------------------------------------
ARCHITECTURE Behavioral OF my_dds IS
--DDS component
COMPONENT dds_component
PORT (
ce: IN std_logic;
clk: IN std_logic;
pinc_in: IN std_logic_vector(7 downto 0);
sine: OUT std_logic_vector(7 downto 0));
END COMPONENT;
--DCM component
COMPONENT dcm_hardware
PORT(
CLKIN_IN : IN std_logic;
RST_IN : IN std_logic;
CLKFX_OUT : OUT std_logic;
CLKIN_IBUFG_OUT : OUT std_logic;
CLK0_OUT : OUT std_logic;
CLK2X_OUT : OUT std_logic
);
END COMPONENT;
--DDS signals
attribute syn_black_box : boolean;
attribute syn_black_box of dds_component: component is true;
signal wave : std_logic_vector(7 downto 0);
signal wave_inv : std_logic_vector(7 downto 0);
signal phase_inc : std_logic_vector(7 downto 0);
--sinais para geraçao de outro clock
signal clk_new : std_logic;
signal counter:integer;
signal modulo:integer;
signal clk_botao : std_logic;
signal btn_count : integer;
signal step:integer;
signal clk_system:std_logic; --50Mhz board source
signal clk_2x: std_logic; --100Mhz ouput from DCM
BEGIN
gerador: dds_component --DDS 4.0
port map (
ce => enable,
clk => clk_new,
pinc_in => phase_inc,
sine => wave
);
my_dcm: dcm_hardware PORT MAP( --DCM Director Clock Manager
CLKIN_IN => clock,
RST_IN => reset,
CLKFX_OUT => open,
CLKIN_IBUFG_OUT => open,
CLK0_OUT => clk_system,
CLK2X_OUT => clk_2x
);
process(clk_system) --clock button
begin
if(rising_edge(clk_system)) then
if(btn_count = 3000100) then --15kHz button event
clk_botao <= not clk_botao;
btn_count <= 0;
else
btn_count <= btn_count + 1;
end if;
end if;
end process;
process(clk_2x,enable) --clock divisor for DDS
begin
if(clk_2x ='1' and clk_2x'EVENT) then
if(enable = '1') then
if(counter = modulo) then
clk_new <= not clk_new;
counter <= 0;
else counter <= counter + 1;
end if;
else counter <= 0; clk_new <= '0';
end if;
end if;
end process;
process(btn_0,clk_botao)--counter
begin
if(clk_botao = '1' and clk_botao'EVENT) then
if(btn_0 = '1') then
step <= step + 1;
if(step = 11) then
step <= 0;
end if;
end if;
end if;
end process;
process(step,clk_botao)
begin --clock divisor counter
if(rising_edge(clk_botao)) then
case step is
when 1 =>
modulo <= 651;
when 2 =>
modulo <= 195;
when 3 =>
modulo <= 38;
when 4 =>
modulo <= 23;
when 5 =>
modulo <= 18;
when 6 =>
modulo <= 12;
when 7 =>
modulo <= 4;
when 8 =>
modulo <= 3;
when 9 =>
modulo <= 2;
when 10 =>
modulo <= 1;
when others =>
modulo <= 3900;
end case;
end if;
end process;
--phase increment (switch change in runtime by user)
phase_inc <= switch;
--revert bit 7 for compatibility with DAC0800
wave_inv(6 downto 0) <= wave(6 downto 0);
wave_inv(7) <= not wave(7);
--digital signal output (8bit)
sin <= wave_inv;
--indicate that generator is turned on
led_on <= enable;
END Behavioral;
11-16-2011 06:31 PM
Did you write dds_component as well? The ports look different to those produced by the Xilinx DDS compiler. We can't really comment on why a DDS of your own design (or a wrapper around the Xilinx core) might not be working well without seeing the code for that too, for obvious reasons.
I don't really like your use of combinatorial clocks. There are plenty of threads on this forum explaining why they are not optimal, and it's possible that they are causing glitches affecting your design that aren't showing up in simulation. I'm not quite sure why you are using them to drive the DDS clock port. Normally with a DDS you would keep the clock frequency fixed and quite high - considerably higher than the maximum frequency you want to produce - at the very, very least twice as high, but ideally much higher than that.
Only the phase increment should be used to set the output frequency. Your phase increment port should be, by design, wide enough on its own to give you the frequency resolution you require (your 8 bit port is pretty small, but perhaps that's sufficient for your application).
11-17-2011 12:34 PM
The dds_component (DDS4.0) was generated with IP Core Generator and the ports was generated automatically. The combinatorial clocks I'm researching for a better way to use if they will be necessary and actually with 'enable' signal I was solved glitch.
About the signal generate with dds, if I use high clock (50Mhz), according with equation of DDS user guide from Xilinx: fout = (fclk*Phase_inc)/2^bits; Supose that you want generate signals from 100hz to 1Mhz. If I do not change the clock, with Phase_Inc starting = 1 and 8 bit, the first output frequency will be 195Khz and changing Phase_Inc all output signals will have frequency multiple of this primary.
So far I really dont know what is the better to do, but I thank you very much for your help.
11-17-2011 12:56 PM
The point is that you should select the bit width of the DDS accumulator and increment port to allow the
frequency resolution you require.
For example for a resolution of 100 Hz at 50 MHz input clock you would need 19 bits. It
is not uncommon to use enough bits to provide fractional Hz resolution. If your output needs to go in
geometric steps rather than linear, the best thing is to either calculate the correct increment setting on
the fly or use a look-up table with the phase increment values for each of your required frequencies.
Note that the fact that you only have 7 or 8 bits of DAC on the output does not mean that you need
to use no more than 8 bits for the accumulator. Just attach the most significant bits of the output
to your sine table.
-- Gabor
11-18-2011 10:52 AM
Ok Gabor, I will have a look and make new configurations by considering your issues. Soon I'll post the results. Thank you very much.
02-02-2012 11:59 AM