Main Content

dsphdl.NCO

Generate real or complex sinusoidal signals

Description

The NCO System object™ generates real or complex sinusoidal signals, while providing hardware-friendly control signals. A numerically-controlled oscillator (NCO) accumulates a phase increment and uses the quantized output of the accumulator as the index to a lookup table that contains the sine wave values. The wrap around of the fixed-point accumulator and quantizer data types provide periodicity of the sine wave, and quantization reduces the necessary size of the table for a given frequency resolution.

High level architecture of an NCO

For an example of how to generate a sine wave using this System object, see Design a HDL-Compatible NCO Source. For more information on configuration and implementation, refer to the Algorithms section.

The NCO System object provides these features.

  • Optional frame-based output.

  • A lookup table compression option to reduce the lookup table size. This compression results in less than one LSB loss in precision. See Lookup Table Compression for more information.

  • An optional input argument for external dither.

  • An optional reset argument that resets the phase accumulator to its initial value.

  • An optional output argument for the current NCO phase.

To generate real or complex sinusoidal signals:

  1. Create the dsphdl.NCO object and set its properties.

  2. Call the object with arguments, as if it were a function.

To learn more about how System objects work, see What Are System Objects?

Note

You can also generate HDL code for this hardware-optimized algorithm, without creating a MATLAB® script, by using the DSP HDL IP Designer app. The app provides the same interface and configuration options as the System object.

Creation

Description

hdlnco = dsphdl.NCO creates a numerically controlled oscillator (NCO) System object, hdlnco, that generates a real or complex sinusoidal signal. The amplitude of the generated signal is always 1.

hdlnco = dsphdl.NCO(Name=Value) sets properties using one or more name-value arguments. For example,

hdlnco = dsphdl.NCO(NumQuantizerAccumulatorBits=12, ...
                    AccumulatorWL=16);

example

hdlnco = dsphdl.NCO(Inc,'PhaseIncrementSource','Property') creates an NCO with the PhaseIncrement property set to Inc, an integer scalar. To use the PhaseIncrement property, set the PhaseIncrementSource property to 'Property'. You can add other Name,Value pairs before or after PhaseIncrementSource.

Properties

expand all

Note

This object supports floating-point types for simulation but not for HDL code generation. When all input values are fixed-point type or all input arguments are disabled, the object determines the output type using the OutputDataType property. When any input value is floating-point type, the object ignores the OutputDataType property. In this case, the object returns the waveform and optional Phase as floating-point values.

Unless otherwise indicated, properties are nontunable, which means you cannot change their values after calling the object. Objects lock when you call them, and the release function unlocks them.

If a property is tunable, you can change its value at any time.

For more information on changing property values, see System Design in MATLAB Using System Objects.

Waveform Generation

You can set the phase increment with an input argument or by specifying a value for the property. Specify 'Property' to configure the phase increment using the PhaseIncrement property. Specify 'Input port' to set the phase increment using the inc argument.

Phase increment for generated waveform, specified as an integer. The object casts this value to match the accumulator word length.

Dependencies

To enable this property, set the PhaseIncrementSource property to 'Property'.

Data Types: single | double | int8 | int16 | int32 | uint8 | uint16 | uint32 | fixdt([],N,0)

You can set the phase offset with an input argument or by specifying a value for the property. Specify 'Property' to configure the phase increment using the PhaseOffset property. Specify 'Input port' to set the phase increment using the offset argument.

Phase offset for the generated waveform, specified as an integer.

Dependencies

To enable this property, set the PhaseOffsetSource property to 'Property'.

Data Types: single | double | int8 | int16 | int32 | uint8 | uint16 | uint32 | fixdt([],N,0)

You can set the number of dither bits from an input argument or from a property, or you can disable dither. Specify 'Property' to configure the number of dither bits using the NumDitherBits property. Specify 'Input port' to set the number of dither bits using the dither argument. Specify 'None' to disable dither.

Number of dither bits, specified as a positive integer.

Dependencies

To enable this property, set the DitherSource property to 'Property'.

Vector size for frame-based output, specified as a positive integer. When you set this value to 1, the object has scalar input and output. When this value is greater than 1, the Dither input argument must be a column vector of length SamplesPerFrame and the Y and Phase output arguments return column vectors of length SamplesPerFrame.

Lookup table compression, specified as a logical 0 (false) or 1 (true). By default, the object implements a noncompressed lookup table, and the output matches the output of the dsp.NCO System object. When you enable this option, the object implements a compressed lookup table. The Sunderland compression method reduces the size of the lookup table, losing less than one LSB of precision. The spurious free dynamic range (SFDR) is empirically 1-3 dB lower than the noncompressed case. The hardware savings of the compressed lookup table allow room to improve performance by increasing the word length of the accumulator and the number of quantize bits. For details of the compression method, see Algorithms.

Type of output waveform. If you select 'Sine' or 'Cosine', the object returns a sin or cos value. If you select 'Complex exponential', the output value, exp, is of the form cosine + j*sine. If you select 'Sine and cosine', the object returns two values, sin and cos.

When you set the Waveform property to 'Complex exponential' or 'Sine and cosine', the object implements a 1/8 sine wave lookup table for each of the sine and cosine parts of the waveform, and uses control logic to select and invert the values to generate both sine and cosine waveforms. This optimization means that dual output mode uses similar hardware resources compared to single output mode.

Set this property to 1 (true) to return the current NCO phase in the phase output argument. The phase is the output of the quantized accumulator with offset and increment applied. If quantization is disabled, this argument returns the output of the accumulator with offset and increment applied.

When this property is 1 (true), the object accepts a ResetAccum input argument. When the ResetAccum argument is 1 (true), the object resets the accumulator to its initial value.

Data Types

This property is read-only.

Overflow mode for fixed-point operations.

This property is read-only.

Rounding mode for fixed-point operations.

This property is read-only.

Accumulator data type description. The object defines the fixed-point data type using the AccumulatorSigned, AccumulatorWL, and AccumulatorFL properties.

This property is read-only.

Signed or unsigned accumulator data format. All output is signed format.

Accumulator word length, in bits, specified as an integer. This value must include the sign bit.

When the PhaseQuantization property is 0, then AccumulatorWL determines the LUT size. For HDL code generation, the LUT size must be between 2 and 217 entries. When you set the LUTCompress property to 1 (true), AccumulatorWL must be an integer in the range [5,21]. When you set the LUTCompress property to 0 (false), AccumulatorWL must be an integer in the range [3,19]. For more information on how this parameter affects the LUT size, see the Lookup Table Compression section.

When you set the PhaseQuantization property to 1, there is no limit to the accumulator word length property value.

This property is read-only.

Accumulator fraction length, in bits. The accumulator operates on integers. If the phase increment is fixed-point type with a fractional part, the object returns an error.

Whether to quantize accumulated phase, specified as 1 (true) or 0 (false). When this property is enabled, the object quantizes the result of the phase accumulator to a fixed bit-width. The object uses this quantized value to select a waveform value from the lookup table. Quantizing the output of the phase accumulator enables you to reduce the lookup table size without lowering the frequency resolution. Select the size of the lookup table by using the NumQuantizerAccumulatorBits property.

When you disable this property, the object uses the full accumulator value as the address of the lookup table.

Number of quantizer accumulator bits, specified as an integer greater than 4 and less than the AccumulatorWL property value. For HDL code generation, this parameter value must result in a LUT size between 2 and 217 entries.

When you set the LUTCompress property to 1 (true), AccumulatorWL must be an integer in the range [5,21]. When you set the LUTCompress property to 0 (false), AccumulatorWL must be an integer in the range [3,19]. For more information on how this parameter affects the LUT size, see the Lookup Table Compression section.

When you set the QuantizePhase property to true, there is no limit to the NumQuantizerAccumulatorBits property value.

Dependencies

To enable this property, set the PhaseQuantization property to 1 (true).

Output data type. If you specify 'Binary point scaling', the object defines the fixed-point data type using the OutputSigned, OutputWL, and OutputFL properties.

This parameter is ignored if any input is of floating-point type. In that case, the output data type is double.

This property is read-only.

Signed or unsigned output data format. All output is signed format.

Output word length, in bits, specified as an integer. This value must include the sign bit.

Output fraction length, in bits, specified as a scalar integer.

Usage

Description

The object returns the waveform value, Y, as a sine value, a cosine value, a complex exponential value, or a [Sine,Cosine] pair of values, depending on the Waveform property.

[Y,ValidOut] = hdlnco(Inc,ValidIn) returns a sinusoidal signal, Y, generated by the HDLNCO System object, using the phase increment, Inc. When ValidIn is true, Inc is added to the accumulator. The Inc argument is optional. Alternatively, you can specify the phase increment as a property.

[Y,ValidOut] = hdlnco (ValidIn) returns a waveform, Y, using waveform parameters from properties rather than input arguments.

To use this syntax, set the PhaseIncrementSource, PhaseOffsetSource, and DitherSource properties to 'Property'. These properties are independent of each other. For example:

hdlnco = dsphdl.NCO(PhaseIncrementSource='Property', ...
       PhaseIncrement=phIncr,...
       PhaseOffset=phOffset,...
       NumDitherBits=4)

example

[Y,ValidOut] = hdlnco(Inc,Offset,Dither,ValidIn) returns a waveform, Y, with phase increment, Inc, phase offset, Offset, and dither, Dither.

This syntax applies when you set the PhaseIncrementSource, PhaseOffsetSource, and DitherSource properties to 'Input port'. These properties are independent of each other. You can mix and match the activation of these arguments. PhaseIncrementSource is 'Input port' by default. For example:

hdlnco = dsphdl.NCO(PhaseOffsetSource='Input port',...
                    DitherSource='Input port')
for k = 1:1/Ts
   y(k) = hdlnco(phIncr,phOffset,ditherBits,true);
end

example

[Y,Phase,ValidOut] = hdlnco(___) returns a waveform, Y, and current phase, Phase. The phase is the output of the quantized accumulator.

To use this syntax, set the PhasePort property to true. This syntax can include any of the arguments from other syntaxes.

[___] = hdlnco(___,ResetAccum,ValidIn) resets the accumulator value, but does not reset the output samples in the pipeline. If ValidIn is true, then the object continues to generate the output waveform starting from the reset accumulator value.

To use this syntax, set the ResetAction property to 1 (true). This syntax can include any of the arguments from other syntaxes.

Input Arguments

expand all

Phase increment, specified as a scalar integer. The object casts this value to match the accumulator word length.

The software supports double and single data types for simulation, but not for HDL code generation.

Dependencies

To enable this argument, set the PhaseIncrementSource property to 'Input port'.

Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | fixdt([],N,0)

Control signal that enables NCO operation, specified as a logical scalar. When ValidIn is true, the object increments the phase and captures any input values. When ValidIn is false, the object holds the phase accumulator and ignores any input values.

When the SamplesPerFrame property value is greater than 1, this signal enables processing of SamplesPerFrame samples.

Data Types: logical

Phase offset, specified as a scalar integer.

double and single data types are supported for simulation but not for HDL code generation.

Dependencies

To enable this argument, set the PhaseOffsetSource property to 'Input port'.

Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | fixdt([],N,0)

Dither, specified as an integer or as a column vector of integers. The length of the vector must equal the SamplesPerFrame property value.

The software supports double and single data types for simulation, but not for HDL code generation.

Dependencies

To enable this argument, set the DitherSource property to 'Input port'.

Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | fixdt([],N,0)

Control signal that resets the accumulator, specified as a logical scalar. When this signal is true, the object resets the accumulator to its initial value. This signal does not reset the output samples in the pipeline.

Dependencies

To enable this argument, set the ResetAction property to 1 (true).

Data Types: logical

Output Arguments

expand all

Generated waveform, returned as a scalar or a vector of length SamplesPerFrame. This argument can be a sin or cos value, an exp value representing cosine + j*sine, or a pair of arguments in the form [Sine,Cosine].

If any input is of floating-point type, the object returns floating-point values for the waveform and Phase arguments, otherwise the object returns values using the type defined by the OutputDataType property.

The software supports double and single data types for simulation, but not for HDL code generation.

Dependencies

By default, the output waveform is a sine wave. The format of the output waveform depends on the Waveform property.

Control signal that indicates validity of output data, specified as a logical scalar. When validOut is true, the values of Y and Phase are valid. When validOut is false, the values of Y and Phase are not valid.

When the SamplesPerFrame property value is greater than 1, this signal indicates the validity of all elements in the output vectors.

Data Types: logical

Current phase of the NCO, returned as a scalar or as a vector of length SamplesPerFrame. The phase is the output of the quantized accumulator with offset and increment applied. If quantization is disabled, this port returns the output of the accumulator with offset and increment applied.

The values are of type fixdt(1,N,0), where N is the NumQuantizerAccumulatorBits property value. If quantization is disabled, then N is the AccumulatorWL property value.

If any input argument is floating-point type, the object returns the Phase argument as a floating point value. Floating-point types are supported for simulation but not for HDL code generation.

Dependencies

To enable this argument, set the PhasePort property to 1 (true).

Data Types: single | double | fixdt(1,N,0)

Object Functions

To use an object function, specify the System object as the first input argument. For example, to release system resources of a System object named obj, use this syntax:

release(obj)

expand all

stepRun System object algorithm
releaseRelease resources and allow changes to System object property values and input characteristics
resetReset internal states of System object

Examples

collapse all

This example shows how to design an HDL-compatible NCO source.

Write a function that creates and calls the System object™, based on the waveform requirements. You can generate HDL from this function.

function yOut = HDLNCO510(validIn)
%HDLNCO510 
% Generates one sample of NCO waveform using the dsphdl.NCO System object(TM)
% validIn is a logical scalar value
% phase increment, phase offset, and dither are fixed.
% You can generate HDL code from this function.

  persistent nco510;
  
  if isempty(nco510)
  % Since calculation of the object parameters results in constant values, this
  % code is not included in the generated HDL. The generated HDL code for
  % the NCO object is initialized with the constant property values. 

   F0 = 510;     % Target output frequency in Hz
   dphi = pi/2;  % Target phase offset
   df = 0.05;    % Frequency resolution in Hz
   minSFDR = 96; % Spurious free dynamic range(SFDR) in dB 
   Ts = 1/4000;  % Sample period in seconds

   % Calculate the number of accumulator bits required for the frequency
   % resolution and the number of quantized accumulator bits to satisfy the SFDR 
   % requirement. 
   Nacc = ceil(log2(1/(df*Ts)));
   % Actual frequency resolution achieved = 1/(Ts*2^Nacc)
   Nqacc = ceil((minSFDR-12)/6);
   % Calculate the phase increment and offset to achieve the target frequency
   % and offset.
   phIncr = round(F0*Ts*2^Nacc);
   phOffset = 2^Nacc*dphi/(2*pi);
   nco510 = dsphdl.NCO(PhaseIncrementSource='Property', ...
       PhaseIncrement=phIncr, ...
       PhaseOffset=phOffset, ...
       NumDitherBits=4, ...
       NumQuantizerAccumulatorBits=Nqacc, ...
       AccumulatorWL=Nacc);
  end    
  
  yOut = nco510(validIn);
  
end
% Copyright 2012-2023 The MathWorks, Inc.

Call the object to generate data points in a sine wave. The input to the object is a valid control signal.

Ts = 1/4000;
y = zeros(1,1/Ts);
for k = 1:1/Ts
   y(k) = HDLNCO510(true);
end

Plot the mean-square spectrum of the 510 Hz sine wave generated by the NCO.

sa = spectrumAnalyzer(SampleRate=1/Ts);
sa.SpectrumType = 'Power density';
sa.PlotAsTwoSidedSpectrum = false;
sa(y')

Algorithms

expand all

The frequency resolution of the sine wave depends on the size of the accumulator. Given a sample time, Ts, and the desired output frequency resolution Δf, calculate the necessary accumulator word length, N.

N=ceil(log2(1TsΔf))

For a desired output frequency Fo, calculate the phase increment.

phase increment=round(F0Ts2N)

Quantizing the output of the phase accumulator enables you to reduce the lookup table size without lowering the frequency resolution. Calculate the quantized word length to achieve a desired spurious free dynamic range (SFDR).

Q=ceil(SFDR126)

Phase offset and dither are optionally added at the accumulator stage. For a desired phase offset (in radians) of the output waveform, calculate the phase offset value that the object adds in the accumulator.

phase offset=2Ndesired phase offset2π

The NCO implementation depends on whether you enable the LUTCompress property.

Without lookup table compression, the object uses the same quarter-sine lookup table as the dsp.NCO object. The size of the LUT is 2Q-2×W bits, where Q is NumQuantizerAccumulatorBits and W is OutputWL.

Architecture of the NCO, showing where each block parameter affects the calculation

The object casts the phase increment value to match the accumulator word length.

If you do not enable PhaseQuantization, then Q=N, where N is AccumulatorWL. Consider the impact on simulator memory and hardware resources when you select these parameters.

When you set the Waveform property to 'Complex exponential' or 'Sine and cosine', the object implements a 1/8 sine wave lookup table for each of the sine and cosine parts of the waveform, and uses control logic to select and invert the values to generate both sine and cosine waveforms. This optimization means that dual output mode uses similar hardware resources compared to single output mode.

For an example of how to generate a sine wave using this System object, see Design a HDL-Compatible NCO Source.

References

[1] Cordesses, L., "Direct Digital Synthesis: A Tool for Periodic Wave Generation (Part 1)." IEEE Signal Processing Magazine. Volume 21, Issue 4, July 2004, pp. 50–54.

Extended Capabilities

Version History

Introduced in R2013a

expand all

See Also

Objects

Blocks