Carrier Mixer (carrier_mixer_xs)

Multiplies the input with a complex carrier wave.

Design

Mixes a complex input with a carrier wave generated by the component.

The mathematical representation of the implementation is given in (24) and (25).

(24)\[g[n] = A \exp{\left(j 2 \pi \frac{\sum_{m=0}^{n-1} \delta[m]}{2^{32}} \right)} * x[n]\]
(25)\[y[n] = \left \lfloor \frac{g[n]}{2^{15}} \right \rfloor\]

In (24) and (25):

  • \(x[n]\) is the input values.

  • \(y[n]\) is the output values.

  • \(\delta[m]\) is the mixer step size values from the instep port. When \(n\) is zero then the instep delta sum will be from zero to \(-1\), in this case this sum is zero.

  • \(A\) is the amplitude of the mixer wave, equal to 1.646760258 * carrier_amplitude property. The 1.646760258 scaling is a result of the gain of the CORDIC algorithm used in the DDS implementation of the carrier generator.

Setting carrier_amplitude at or below 14,060 is guaranteed to not overflow for any valid input. To prevent overflow (26) must hold for the real values, an equivalent expression exists for imaginary values.

(26)\[\frac{A \left(x \cos{ 2 \pi \frac{\sum_{m=0}^{n-1} \delta[m]}{2^{32}}} - j y \sin{ 2 \pi \frac{\sum_{m=0}^{n-1} \delta[m]}{2^{32}}} \right)}{2^{15}} < x_{max}\]

In (26), \(x + jy\) is an input complex sample value. The maximum value \(A\), and so carrier_amplitude, can take occurs when the condition (26) is an equality. Maximisation of the left-hand side of (26) occurs when \(x=x_{max}\), \(y=-x_{max}\), and the input phase maximises \(\cos{\theta} + \sin{\theta}\) which has a maximum of \(\sqrt{2}\). This results in (27).

(27)\[A = \frac{2^{15}}{\sqrt{2}} = 23170.475...\]

As the carrier_amplitude property is scaled by 1.646760258, the limit to carrier_amplitude is \(23170.475... / 1.646760258 = 14070.33...\). As the carrier generator uses an approximation an empirically determined margin is needed for the theoretical maximum to give a tested and supported maximum of 14,060.

\(\delta[m]\) must have an input value for each value on \(x[n]\). Therefore, for a fixed frequency carrier to be multiplied by the input \(x[n]\), then \(\delta[m]\) must have a constant input of the same value.

A block diagram representation of the implementation is given in Figure 328:.

Block diagram outlining carrier mixer implementation.

Figure 328: Block diagram of carrier mixer implementation.

The relation between the output frequency shift and \(\delta[n]\) values is given by (28).

(28)\[ \delta[n] = \frac{2^{32} f}{F_s}\]

In (28):

  • \(f\) is the desired frequency shift.

  • \(F_s\) is the sample rate of the system.

Interface

<?xml version="1.0"?>
<componentspec>
  <property name="instep_opcode_passthrough" type="bool" writable="false" parameter="true" default="false"
    description="When true opcodes from the instep port are passed to the output, when false opcodes from the input port are passed
      to the output."/>
  <property name="carrier_amplitude" type="ushort" writable="true" default="14060"
    description="Amplitude of the carrier mixed with the input signal. Set to :math:`\left \lfloor
      \frac{\text{desired_maximum}}{1.646760258} \right \rfloor`."/>
  <port name="input" producer="false" protocol="complex_short_timed_sample-prot"/>
  <port name="instep" producer="false" protocol="long_timed_sample-prot"/>
  <port name="output" producer="true" protocol="complex_short_timed_sample-prot"/>
</componentspec>

Ports

Inputs:

  • input: Primary input samples port.

    • Protocol: complex_short_timed_sample-prot

    • Optional: False

  • instep: Mixer step size samples port.

    • Protocol: long_timed_sample-prot

    • Optional: False

Outputs:

  • output: Primary output samples port.

    • Protocol: complex_short_timed_sample-prot

    • Optional: False

Opcode Handling

Only values in a sample opcode messages are multiplied together.

Non-sample opcodes from a single input are forwarded onto the output interface. The instep_opcode_passthrough parameter selects which input interface is used for non-sample opcode forwarding. Non-sample opcodes on the other input to what instep_opcode_passthrough is set to are discarded.

Properties

  • instep_opcode_passthrough: When true opcodes from the instep port are passed to the output, when false opcodes from the input port are passed to the output.

    • Type: bool

    • Access:

      • Parameter: True

      • Writable: False

      • Initial: False

      • Volatile: False

    • Default value: false

  • carrier_amplitude: Amplitude of the carrier mixed with the input signal. Set to \(\left \lfloor \frac{\text{desired_maximum}}{1.646760258} \right \rfloor\). The default 14,060 maps to near full-range output on a 16-bit signed value and guarantees overflow-free output for any input. Larger values risk overflow.

    • Type: ushort

    • Access:

      • Parameter: False

      • Writable: True

      • Initial: False

      • Volatile: False

    • Default value: 14060

Implementations

  • carrier_mixer_xs (HDL)

    HDL implementation using a numerically controlled oscillator (NCO) for the carrier generator, which uses the CORDIC algorithm to generate an approximation of sine and cosine.

  • carrier_mixer_xs (RCC)

Example Application

<?xml version="1.0"?>
<application done="file_write">
  <instance component="ocpi.core.file_read" connect="carrier_mixer_xs" to="input">
    <property name="filename" value="input.bin"/>
  </instance>
  <instance component="ocpi.core.file_read" connect="carrier_mixer_cs_cs" to="instep">
    <property name="filename" value="instep.bin"/>
  </instance>
  <instance component="ocpi.comp.sdr.dsp.carrier_mixer_xs" connect="file_write">
    <property name="carrier_amplitude" value="14060"/>
  </instance>
  <instance component="ocpi.core.file_write">
    <property name="filename" value="output.bin"/>
  </instance>
</application>

Dependencies

The dependencies to other elements in OpenCPI are:

There is also a dependency on:

  • ieee.std_logic_1164

  • ieee.numeric_std

  • ieee.math_real

Limitations

Limitations of carrier_mixer_xs are:

  • Setting carrier_amplitude above 14,060 requires users to ensure the combination of samples on input and instep ports do not cause an overflow.

Testing

Tested platforms: None

Component testing not completed.