Our design takes an audio signal and modulates it to a higher carrier frequency, using FM modulation. The modulator in our design is based on a numerically controlled oscillator (NCO) with several modifications.
The frequency control word, which increments the phase accumulator, is being added with the audio signal. This results in the phase increments proportional to the current audio sample level. The variation directly determines the actual shift of the output signal frequency. For the conversion of phase to a harmonic signal (sine wave) NCOs usually use look-up tables or CORDIC algorithm. However, both of these methods are resource-heavy, therefore the design adopts a very rough, piecewise linearized approximation of the sine function. The main upside of this approach is the lightweight implementation, which utilizes only simple bit-shifting and addition operations.
Since the output digital-to-analog converter suggested below is not followed by a reconstruction filter, the output signal will not be present only on a single frequency but also on several higher ones, sometimes called mirrors (as they appear on frequencies mirrored by the sampling frequency and its multiples). Thanks to this, it is possible to get the signal in the range of FM broadcast band, even with the sampling frequency lower than the carrier frequency.
Disclaimer! Our design is not intended for real on air use. Any signals generated by our design are far from ideal and require proper filtering. Improper use will most probably violate your local regulations. Use only at your own risk!
For testing the design you need to provide an audio source using the I2S bus interface. You can use for example Raspberry Pi. For the output, you need to build a DAC. A simple R–2R resistor ladder network should be enough for testing. The schematic is provided in our GitHub repository.
4-bit R-2R DAC, I2S source, SPI (optional)
# | Input | Output | Bidirectional |
---|---|---|---|
0 | i2s_clk | dac[0] (LSB) | |
1 | i2s_din | dac[1] | |
2 | i2s_ws | dac[2] | |
3 | i2s_ws_align_pin | dac[3] (MSB) | |
4 | audio_chan_sel_pin | spi_clk (in) | |
5 | multiply_sel_pin | spi_csn (in) | |
6 | dith_disable_pin | spi_mosi (in) | |
7 | spi_miso (inout) |