FM Modulation with Xilinix DDS

FM Modulation Theory

Frequency Modulation (FM) is a form of angle modulation in which the instantaneous frequency of a carrier signal is varied in proportion to the amplitude of a modulating (baseband) signal. Unlike amplitude modulation (AM), the carrier amplitude remains constant, which makes FM more robust to noise and amplitude disturbances.

The instantaneous frequency of a signal is defined as the rate of change of its instantaneous phase with respect to time. Mathematically, the instantaneous frequency fi(t) is given by:

fi(t) =  1 / (2π)  ·  dθ(t) / dt

For a sinusoidal carrier with nominal frequency fc, the instantaneous phase θ(t) can be expressed as:

θ(t) = 2πfct + φ(t)

where φ(t) is the phase deviation introduced by the modulating signal. In FM, this phase deviation is proportional to the integral of the message signal. If the modulating signal is m(t), normalized to the range [-1, 1], the instantaneous frequency of an FM signal is:

fi(t) = fc + Δf · m(t)

where Δf is the peak frequency deviation, defined as the maximum departure of the instantaneous frequency from the carrier frequency. The value of Δf determines the occupied bandwidth of the FM signal.

The resulting FM waveform can be written as:

s(t) = Ac cos [ 2πfct + 2πΔf ∫ m(τ) dτ ]

For the common case of a single-tone modulating signal m(t) = sin(2πfmt), the FM signal simplifies to:

s(t) = Ac cos [ 2πfct + β sin(2πfmt) ]

The parameter β is called the modulation index and is defined as:

β = Δf / fm

The modulation index indicates the relative amount of frequency variation in the FM signal. A small value of β (typically β < 1) corresponds to narrowband FM, while a larger value of β (typically β > 1) results in wideband FM. In FM broadcast systems, Δf is typically 75 kHz, resulting in a wideband FM signal.

Implementation

The FM modulation signal generated in this demonstration uses the following
parameters. These parameters are selected for the ease of simulation and visualization:

  • Carrier frequency (Fc): 100 Hz
  • Modulating frequency (Fm): 5 Hz
  • Frequency deviation (Δf): 50 Hz
  • Sampling frequency (Fs): 200 MHz

To achieve the desired modulated signal, we need two DDS instantions: One that generates the message signal with a 5Hz frequecy and the other DDS to generate the carrier frequency of 100 Hz.

The following discrete-time equation is the core relationship implemented
in hardware
for FM modulation. It defines how the
phase accumulator is updated on every clock cycle and is used
directly to generate the phase increment applied to the DDS:

Φ[n] = Φ[n − 1]
+ 2N · fc / Fs
+ 2N · Δf / Fs · m[n]

At each sample n, the phase accumulator Φ is increased by a
constant term that sets the carrier frequency and by a second term proportional
to the modulating signal m[n], which introduces the desired
frequency deviation. The accumulator naturally performs the required integration of the instantaneous frequency, and the resulting phase value is then used by the DDS to generate the FM-modulated output waveform.

To achieve the desired modulated signal, we need two DDS IP Cores: One that generates the message signal with a 5Hz frequecy and the other DDS to generate the carrier frequency of 100 Hz. Below are screenshot showing how each of these DDS Icores was configured.

Figure1: DDS configuration: clock frequency, phase and output width

Figure2: DDS implementation setup

Figure3: Phase increment corresponding value for 5Hz

Figure4: DDS summary for 5 Hz message signal

Multiplying the Frequency Deviation Δf with cos(2πfmt)

In the FM phase term, the modulating waveform cos(2 π fm t) must be normalized to lie between −1 and +1. This is important because the frequency deviation is proportional to the instantaneous value of the message signal, and exceeding this range would unintentionally increase the modulation index and distort the FM signal.

In a DDS-based implementation, the DDS output is typically represented as a 32-bit signed or unsigned integer. To convert this digital value into a properly normalized signal in the range −1 to +1, the DDS output is divided by 232. This scaling ensures that the modulating signal has the correct amplitude and that the resulting frequency deviation matches the intended FM design parameters.

In this design, a Multiplier IP core is used to multiply the frequency deviation Δf by the normalized message signal generated by the DDS. This operation scales the message signal so that its amplitude produces the desired frequency deviation in the FM modulator.

Since the DDS output and the frequency deviation Δf are represented using fixed-point arithmetic, the result of the multiplication has a wider bit width. To restore the correct numerical range, the multiplier output is right-shifted by 32 bits. This shift effectively normalizes the result and ensures that the scaled modulating signal fits correctly into the phase accumulator input without overflow or unintended distortion.

To represent a 50 Hz frequency deviation in a DDS-based FM modulator, the deviation must be converted into a phase increment value that matches the DDS phase accumulator resolution.

For a DDS with a 29-bit phase accumulator and a sampling frequency of 200 MHz, the frequency resolution is:

ΔfLSB = Fs / 229 

This means that each LSB of the phase increment corresponds to approximately 0.3725 Hz of frequency change.

To achieve a 50 Hz peak frequency deviation, the required DDS phase increment deviation is:

ΔPhase Increment = 134

and adding it to the carrier phase increment produces a frequency deviation of ±50 Hz around the carrier frequency.

Figure 5: Multiplier Setup

Adding the Carrier Frequency (100 Hz) to the Product of the Message Signal and Frequency Deviation

The carrier frequency used in this demonstration is 100Hz. Using the equation below we computed that the phase increment value for DDS needs to be: 268 ; for a sampling frequency of 200MHz and phase width of 29 bits.

(Fc / Fs) × 229

268 is entered into the adder IP core as shown below as a binary constant:

Figure 6: Adder IP core configuration

Figure7: DDS configuration for streaming

VHDL Top Level Code

Below is copy of the VHDL top level code. It shows how all the IP core block as connected to each other to generate the final FM modulated signal

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--USE ieee.std_logic_arith.all;
use IEEE.numeric_std.all;

entity FM_ModulatorTopLevel is
  port (
    sys_clk : in std_logic; 
    reset_0 : in STD_LOGIC
  );
end FM_ModulatorTopLevel;

architecture behavioral of FM_ModulatorTopLevel is

  signal clk_out_Sig : std_logic;            
  signal locked_Sig  : std_logic;
  signal m_axis_data_tvalid_Sig : std_logic;
  signal Message_Tone : STD_LOGIC_VECTOR(31 DOWNTO 0); 

  signal MessageMultiplied         : STD_LOGIC_VECTOR(39 DOWNTO 0); 
  signal MessageMultipliedShifted  : STD_LOGIC_VECTOR(7 DOWNTO 0);
  signal CarrierPlusMessage        : STD_LOGIC_VECTOR(39 DOWNTO 0); 

  signal DDS1_data_in : STD_LOGIC_VECTOR(31 DOWNTO 0);
  signal DDS1_tvalid_out : STD_LOGIC;
  signal ModulatedSignalOut : STD_LOGIC_VECTOR(31 DOWNTO 0); 

  signal message_pm1 : signed(24 downto 0);
  signal Fm_Plus_Carrier : STD_LOGIC_VECTOR(27 DOWNTO 0); 
  signal Fm_Plus_Carrier_Pudded : STD_LOGIC_VECTOR(31 DOWNTO 0); 

  component clk_wiz_0
    port (
      clk_out1 : out std_logic;
      locked   : out std_logic;
      clk_in1  : in  std_logic
    );
  end component;

  component dds_compiler_0
    port (
      aclk               : in  std_logic;
      m_axis_data_tvalid : out std_logic;
      m_axis_data_tdata  : out std_logic_vector(31 downto 0)
    );
  end component;

  component mult_gen_0
    port (
      CLK : in  std_logic;
      A   : in  std_logic_vector(31 downto 0);
      P   : out std_logic_vector(39 downto 0)
    );
  end component;

  component c_addsub_0
    port (
      A   : in  std_logic_vector(7 downto 0);
      CLK : in  std_logic;
      S   : out std_logic_vector(27 downto 0)
    );
  end component;

  component dds_compiler_1
    port (
      aclk               : in  std_logic;
      s_axis_phase_tvalid: in  std_logic;
      s_axis_phase_tdata : in  std_logic_vector(31 downto 0);
      m_axis_data_tvalid : out std_logic;
      m_axis_data_tdata  : out std_logic_vector(31 downto 0)
    );
  end component;

begin

  Clk_Wizard: clk_wiz_0
    port map (  
      clk_out1 => clk_out_Sig,             
      locked   => locked_Sig,
      clk_in1  => sys_clk
    );

  DDS_0 : dds_compiler_0
    port map (
      aclk               => clk_out_Sig,
      m_axis_data_tvalid => m_axis_data_tvalid_Sig,
      m_axis_data_tdata  => Message_Tone
    ); 

  Multiplier : mult_gen_0
    port map (
      CLK => clk_out_Sig,  
      A   => Message_Tone,
      P   => MessageMultiplied
    );

MessageMultipliedShifted <= MessageMultiplied(39 downto 32);
      
  AdderSub : c_addsub_0
    port map (
      A   => MessageMultipliedShifted, 
      CLK => clk_out_Sig, 
      S   => Fm_Plus_Carrier
    );

  Fm_Plus_Carrier_Pudded  clk_out_Sig,
      s_axis_phase_tvalid => '1',
      s_axis_phase_tdata  => Fm_Plus_Carrier_Pudded,
      m_axis_data_tvalid  => DDS1_tvalid_out,
      m_axis_data_tdata   => ModulatedSignalOut
    );

end behavioral;
  

Simulation Results

Below is screen shot from Vivado simulation showing the FM modulation signal for 5Hz message signal.

Figure 8: Simulation Results 1 of 2

Figure 9: Simulation results 2 of 2
Figure10: FM modulation taken on the scope

Frequency Spectrum

For the given FM modulation with a carrier frequency of 100 Hz, a modulating frequency of 5 Hz, and a peak frequency deviation of 50 Hz, the resulting spectrum consists of a series of discrete spectral lines located at
fc ± n fm, where n = 0, 1, 2, …. These lines are spaced by the modulating frequency (5 Hz) and their amplitudes are determined by the modulation index
β = Δf / fm = 10 through the Bessel functions of the first kind.

Because the modulation index is large (β >> 1), many sidebands carry significant energy, resulting in a wideband FM signal. This shows that the modulation index controls the distribution of energy across the sidebands and directly affects how “wide” the FM signal appears in the frequency domain.

According to Carson’s rule, the approximate total bandwidth occupied by the FM signal is
B ≈ 2(Δf + fm) = 110 Hz. This means most of the spectral energy lies roughly between 45 Hz and 155 Hz around the carrier frequency.

In summary, the frequency deviation determines the number and relative strength of the sidebands, while the spacing between the spectral lines remains fixed by the modulating frequency. This is why, even for large deviations, the sidebands occur at multiples of the modulating frequency around the carrier.

Source Code

For the full VHDL project files, you can visit the GitHub repository:

FM Modulation DDS 100Hz Project
.

I hope you will find this tutorial helpful, and I would really appreciate any feedback or comments in the comments section and via emails.

Author: Farid M