ddfs¶
Dependencies¶
Description¶
This package provides a set of functions and a component used for
implementing a Direct Digital Frequency Synthesizer (DDFS). The DDFS
component is a simple accumulator that increments by a pre computed value
each cycle. The MSB of the accumulator switches at the requested frequency
established by the ddfs_increment()
function. The provided functions perform
computations with real values and, as such, are only synthesizable when
used to define constants.
There are two sets of functions for generating the increment values needed by the DDFS accumulator. One set is used to compute static increments that are assigned to constants. The other functions work in conjunction with a procedure to dynamically generate the increment value using a single inferred multiplier.
It is possible to generate multiple frequencies by computing more than one
increment constant and multiplexing between them. The ddfs_size()
function
should be called with the smallest target frequency to be used to
guarantee the requested tolerance is met. You can alternately set a fixed size and compute the
effective tolerance with ddfs_tolerance()
.
For simulation reporting, you can compute the effective output frequency with the ddfs_frequency()
function and the error ratio
with ddfs_error()
.
The utility function resize_fractional()
will truncate unwanted LSBs when downsizing the generated DDFS accumulator value.
Example usage¶
The ddfs_size()
and ddfs_increment()
functions are used to compute static increment values:
constant SYS_FREQ : real := 50.0e6; -- 50 MHz
constant TGT_FREQ : real := 2600.0; -- 2600 Hz
constant DDFS_TOL : real := 0.001; -- 0.1%
constant SIZE : natural := ddfs_size(SYS_FREQ, TGT_FREQ, DDFS_TOL);
constant INCREMENT : unsigned(SIZE-1 downto 0) :=
ddfs_increment(SYS_FREQ, TGT_FREQ, SIZE);
...
whistle: ddfs
port map (
Clock => clock,
Reset => reset,
Enable => '1',
Load_phase => '0',
New_phase => unsigned'"",
Increment => INCREMENT,
Accumulator => accum,
Synth_clock => synth_tone, -- Signal with ~2600 Hz clock
Synth_pulse => open
);
...
-- Report the DDFS precision (simulation only)
report "True synthesized frequency: "
& real'image(ddfs_frequency(SYS_FREQ, TGT_FREQ, SIZE)
report "DDFS error: " & real'image(ddfs_error(SYS_FREQ, TGT_FREQ, SIZE)
The alternate set of functions min_fraction_bits()
,
ddfs_dynamic_factor()
, and ddfs_dynamic_inc()
are used to precompute a multiplier factor
that is used to dynamically generate an increment value in synthesizable logic:
constant MIN_TGT_FREQ : natural := 27;
constant MAX_TGT_FREQ : natural := 4200;
constant FRAC_BITS : natural := min_fraction_bits(SYS_FREQ,
MIN_TGT_FREQ, SIZE, DDFS_TOL);
constant DDFS_FACTOR : natural := ddfs_dynamic_factor(SYS_FREQ, SIZE,
FRAC_BITS);
signal dyn_freq : unsigned(bit_size(MAX_TGT_FREQ)-1 downto 0);
signal dyn_inc : unsigned(SIZE-1 downto 0);
...
dyn_freq <= to_unsigned(261, dyn_freq'length); -- Middle C
...
dyn_freq <= to_unsigned(440, dyn_freq'length); -- Change to A4
...
-- Wrap ddfs_dynamic_inc in a sequencial process to synthesize a
-- multiplier with registered product.
dyn: process(clock, reset) is
begin
if reset = '1' then
dyn_inc <= (others => '0');
elsif rising_edge(clock) then
ddfs_dynamic_inc(DDFS_FACTOR, FRAC_BITS, dyn_freq, dyn_inc);
end if;
end process;
fsynth: ddfs
port map (
Clock => clock,
Reset => reset,
Enable => '1',
Load_phase => '0',
New_phase => unsigned'"",
Increment => dyn_inc,
Accumulator => accum,
Synth_clock => synth_tone,
Synth_pulse => open
);
Components¶
ddfs¶
-
ddfs_pkg.
ddfs
¶ Synthesize a frequency using a DDFS.
Generics: - RESET_ACTIVE_LEVEL (std_ulogic) – Asynch. reset control level
Port: - Clock (in std_ulogic) – System clock
- Reset (in std_ulogic) – Asynchronous reset
- Enable (in std_ulogic) – Enable the DDFS counter
- Load_phase (in std_ulogic) – Load a new phase angle
- New_phase (in unsigned) – Phase angle to load
- Increment (in unsigned) – Value controlling the synthesized frequency
- Accumulator (out unsigned) – Internal accumulator value
- Synth_clock (out std_ulogic) – Synthesized frequency
- Synth_pulse (out std_ulogic) – Single cycle pulse for rising edge of synth_clock
ddfs_pipelined¶
-
ddfs_pkg.
ddfs_pipelined
¶ Synthesize a frequency using a DDFS.
Generics: - MAX_CARRY_LENGTH (positive) –
- RESET_ACTIVE_LEVEL (std_ulogic) – Asynch. reset control level
Port: - Clock (in std_ulogic) – System clock
- Reset (in std_ulogic) – Asynchronous reset
- Enable (in std_ulogic) – Enable the DDFS counter
- Load_phase (in std_ulogic) – Load a new phase angle
- New_phase (in unsigned) – Phase angle to load
- Increment (in unsigned) – Value controlling the synthesized frequency
- Accumulator (out unsigned) – Internal accumulator value
- Synth_clock (out std_ulogic) – Synthesized frequency
- Synth_pulse (out std_ulogic) – Single cycle pulse for rising edge of synth_clock
Subprograms¶
-
ddfs_pkg.
ddfs_size
(Sys_freq : real; Target_freq : real; Tolerance : real) → natural¶ - Compute the necessary size of a DDFS accumulator based on system and target frequencies with a specified tolerance. The DDFS accumulator must be at least as large as the result to achieve the requested tolerance.
Parameters: - Sys_freq (real) – Clock frequency of the system
- Target_freq (real) – Desired frequency to generate
- Tolerance (real) – Error tolerance
Returns: Number of bits needed to generate the target frequency within the allowed tolerance.
-
ddfs_pkg.
ddfs_tolerance
(Sys_freq : real; Target_freq : real; Size : natural) → real¶ - Compute the effective frequency tolerance for a specific size and target frequency.
Parameters: - Sys_freq (real) – Clock frequency of the system
- Target_freq (real) – Desired frequency to generate
- Size (natural) – Size of the DDFS counter
Returns: Tolerance for the target frequency with a Size counter.
-
ddfs_pkg.
ddfs_increment
(Sys_freq : real; Target_freq : real; Size : natural) → natural¶ - Compute the natural increment value needed to generate a target frequency.
Parameters: - Sys_freq (real) – Clock frequency of the system
- Target_freq (real) – Desired frequency to generate
- Size (natural) – Size of the DDFS counter
Returns: Increment value needed to generate the target frequency.
-
ddfs_pkg.
ddfs_increment
(Sys_freq : real; Target_freq : real; Size : natural) → unsigned¶ - Compute the unsigned increment value needed to generate a target frequency.
Parameters: - Sys_freq (real) – Clock frequency of the system
- Target_freq (real) – Desired frequency to generate
- Size (natural) – Size of the DDFS counter
Returns: Increment value needed to generate the target frequency.
-
ddfs_pkg.
min_fraction_bits
(Sys_freq : real; Target_freq : real; Size : natural; Tolerance : real) → natural¶ - Find the minimum number of fraction bits needed to meet the tolerance requirement for a dynamic DDFS. The target frequency should be the lowest frequency to ensure proper results.
Parameters: - Sys_freq (real) – Clock frequency of the system
- Target_freq (real) – Lowest desired frequency to generate
- Size (natural) – Size of the DDFS counter
- Tolerance (real) – Error tolerance
Returns: Increment value needed to generate the target frequency.
-
ddfs_pkg.
ddfs_dynamic_factor
(Sys_freq : real; Size : natural; Fraction_bits : natural) → natural¶ - Compute the factor used to generate dynamic increment values.
Parameters: - Sys_freq (real) – Clock frequency of the system
- Size (natural) – Size of the DDFS counter
- Fraction_bits (natural) – Number of fraction bits
Returns: Dynamic increment factor passed into ddfs_dynamic_inc().
-
ddfs_pkg.
ddfs_dynamic_inc
(Dynamic_factor : in natural; Fraction_bits : in natural; Target_freq : in unsigned; Increment : out unsigned)¶ - This procedure computes dynamic increment values by multiplying the result of a previous call to ddfs_dynamic_factor by the integer target frequency. The result is an integer value with fractional bits removed. This can be synthesized by invocation within a synchronous process.
Parameters: - Dynamic_factor (in natural) – Dynamic factor constant
- Fraction_bits (in natural) – Fraction bits for the dynamic DDFS
- Target_freq (in unsigned) – Desired frequency to generate
- Increment (out unsigned) – Increment value needed to generate the target frequency.
-
ddfs_pkg.
ddfs_frequency
(Sys_freq : real; Target_freq : real; Size : natural) → real¶ - Compute the actual synthesized frequency for the specified accumulator size.
Parameters: - Sys_freq (real) – Clock frequency of the system
- Target_freq (real) – Desired frequency to generate
- Size (natural) – Size of the DDFS counter
Returns: Frequency generated with the provided parameters.
-
ddfs_pkg.
ddfs_error
(Sys_freq : real; Target_freq : real; Size : natural) → real¶ - Compute the error between the requested output frequency and the actual output frequency.
Parameters: - Sys_freq (real) – Clock frequency of the system
- Target_freq (real) – Desired frequency to generate
- Size (natural) – Size of the DDFS counter
Returns: Ratio of generated frequency to target frequency.
-
ddfs_pkg.
resize_fractional
(Phase : unsigned; Size : positive) → unsigned¶ - Resize a vector representing a fractional value with the binary point preceeding the MSB.
Parameters: - Phase (unsigned) – Phase angle in range 0.0 to 1.0.
- Size (positive) – Number of bits in the result
Returns: Resized vector containing phase fraction
-
ddfs_pkg.
radians_to_phase
(Radians : real; Size : positive) → unsigned¶ - Convert angle in radians to a fractional phase value.
Parameters: - Radians (real) – Angle to convert
- Size (positive) – Number of bits in the result
Returns: Fraction phase in range 0.0 to 1.0.
-
ddfs_pkg.
degrees_to_phase
(Degrees : real; Size : positive) → unsigned¶ - Convert angle in degrees to a fractional phase value.
Parameters: - Degrees (real) – Angle to convert
- Size (positive) – Number of bits in the result
Returns: Fraction phase in range 0.0 to 1.0.