XFM: A 32-Voice Polyphonic FM Synthesizer On An FPGA

There’s something about Frequency Modulation (FM) synthesizer chips that appeals to a large audience. That’s one of the reasons behind [René Ceballos]’s XFM project, aiming to duplicate on an FPGA the sound of pure-FM synthesizer chips of the past such as the Yamaha DX series, OPL chip series and TX81Z/802/816. The result is a polyphonic, 32-voice, 6-operator FM synthesizer stereo module.

The project page goes into a lot of detail about the design choices which ultimately led to XFM being implemented on an FPGA, instead of using a dedicated DSP or MCU. Coming from the world of virtual synthesizers running on PCs, [René ]’s first impulse was to implement something on a Raspberry Pi or equivalent. Unfortunately these boards require a lot of power (ruling out battery-powered operation) and can hardly be called real-time, which led [René ] to abandon this attempt.

The design choice against the use of an MCU is simple: though capable of real-time processing, they lack the necessary power to make them a good choice for audio-processing. Working through the calculations to determine what kind of processing power would be needed, it was found that around 650 MIPS would be needed, a figure which most MCUs struggle to achieve a fraction of.

As one of the further requirements for XFM was that it should be as cheap as possible, this ruled out as too expensive the DSP chips which do have the power and hardware features needed. The component chosen was a Xilinx Spartan 6 FPGA, which though somewhat infamous and shunned in FPGA circles turns out to be a very economical option for this project.

Picking the Mojo V3 with the Spartan 6 XC6SLX9 that has 16 DSP blocks as platform, [René ] then created an add-on board for the MIDI and SPDIF interfaces, along with an EEPROM for program memory and a dual sigma-delta 16-bit DAC implemented using discrete components.

The result is pretty impressive as you can hear for yourself in the below included video, with a brief look at the XFM system in action as well.

Being a mostly open design, the design files and software are available via the website for anyone who wants to build their own XFM system, assuming they can use the bit file for the currently supported FPGA boards. Unfortunately the Mojo V3 board has been phased out at this point, but [René ] has indicated in a response to us that he has ported the HDL to the Numato Mimas and CMOD A7 boards and will make the bit files for those platforms available in a few weeks.

There is talk of perhaps doing a crowdfunding campaign for a custom board or even an ASIC version in the future, which is the reason for not open sourcing the HDL.

27 thoughts on “XFM: A 32-Voice Polyphonic FM Synthesizer On An FPGA

  1. Think I just stick to my DX7. If people ever learn to program a DX7 instead of just using the custom sounds that came with it. You would see there is a whole new world of sounds to the DX7. Plus a DX7 makes a great master keyboard too.

        1. I hate to necro-post but I am a huge fan of the Volca series(I have a Bass, NuBass, and Drum), and didn’t know this. Any chance you know if an FM2 will work or if it’s only the FM?

          1. I don’t have an FM2, but everyone says you just upload DX7 SysEx files to it and it works. FM2 has the full set of voices versus the original Volca FM. The patches themselves wouldn’t be any different, it only changes how many keys you can press at once.

  2. >The component chosen was a Xilinx Spartan 6 FPGA, which though somewhat infamous and shunned in FPGA circles turns out to be a very economical option for this project.

    Uhh, source/context for this statement? From my perspective, the Spartan 6 is/was one of the most economical and feature-packed FPGAs, a hobbyist’s dream.

    1. It’s also the last non-BGA FPGA sold by Xilinx. Spartan 7 and up only comes in BGA.

      It would be worthwhile to see if a similar design would work in the Lattice ICE40UP5K. It’s a smaller part, but it has DSP blocks and is supported by Icestorm.

      1. Yeah, this comment made no sense to me either. I’ve seen it in many commercial devices and while the ISE tools were less than awesome, it seemed like a perfectly capable device in my projects, and they went into several projects of mine at work, as well as hobby stuff.

  3. I’m working on a synthesizer on BlackIce (supported by IceStorm.) It uses a CS4344 with I2S protocol as a DAC. The FPGA outputs samples from a wavetable. The rate of sampling is controlled by a period register which itself can be driven by another wavetable. Ergo, FM synthesis!

    This is not particularly compute intensive. The wavetable is all integers, no sin functions are ever needed. (And if they were, they would use a lookup table or execute CORDIC in integer math.)

    The nice thing about the FPGA is that you can add more generators until all the gates are used up. An adding loop, over the output voices, executes in parallel to everything else, which is no overhead. The adder runs at 100MHz adding up numbers to output no faster than 256 KHz.

    Features yet to implement:

    Interpolation between samples in the wavetable
    Configure many modulation chains (like DX7)
    Compression of the output (prevent clipping, use full dynamic range) Simple PID algorithm.

    Using a wavetable, I can’t see why a microprocessor implementation would not be feasible. There are just a couple of lookups, pointer arithmetic, and multiply-adds per 256kHz cycle. All in integer math, because I2S samples are just 24 bit integers. A cheap 80MHz Arm Cortex M0 should have no problem.

    I welcome knowledge of how much DSP power others have thrown at such an implementation.

    1. Hi Erik,

      Thank you. I shared my estimations for this synthesizer in the page, and how I calculated and picked the XC6SLX9 (futur3soundz.com). An 80MHz CPU which calculates 32-voices at 48kHz (like XFM) will give you 52 clock cycles to calculate anything you want to calculate for a single sample: phase-counting, lookup, interpolation, gain staging, filtering or audio processing, envelope, lfo, etc. It sounds like it’s a lot, but once you stack plenty of voices at a high samplerate it is not.

    2. For a synthesizer that calculates 32 simultaneous voices such as XFM at 48,000 samples per second, an 80 MHz clock give you about 52 clock cycles to calculate your audio. This is, the phase accumulator, the lookup, the interpolation, the gain staging, the envelope generation, the lfo, etc. Moreover, some of the instructions you need to use are multi-clock (all instructions, in some platforms). There are very basic synthesizers that can be done with such polyphony/samplerate combo. With lower specs, an ATtiny85 will make sound :-)

      I have shared the full line of reasonin behind the estimation of calculation power in the XFM page, and some of the previous attempts (80MHz is exactly what the Propeller 8-core MCU I used previously to switch to FPGA).

      Your statement on “FPGA is just parallelizing” is somehow oversimplified. While you can replicate LUTs and registers, FPGAs have a very limited number of hard resources such as DSP blocks (16 in the case of XFM) and RAM (72kB). Expanding the limits using resource fabric will enormously expand the required FPGA size, moving the price range again out of competitiveness.

      1. Thank you for detailed reply. I have not done the MP calculations myself, as you have clearly done in detail. I was anchored on just 4 voices that I’m working with so I assumed plenty of cycles if I were to code it in assembly.

        I did not consider DSP blocks – I just built integer math to scale amplitude by 15 fixed decibel steps.

        Also, I am guilty of not looking ahead very far. I made 4 voices and 4 LFOs, using about 1500 cells out of the ICE40HX4K 7680 cells. (ICE40HX4K has 3520 in Lattice Diamond, but IceStorm unlocks the full 7680.) I will hit the wall before 32 voices.

        Block RAM will obviously run out at some point; I store 640 samples * 16 bits = 10Kbits per sample. I load sine, sawtooth, square, triangle, or substitute other 640-word single cycle samples. That’s half the 80Kbit block RAM (though IceStorm/Yosys will find 128Kbits.) That’s what I’m using so far, anticipating switching samples in and out from EEPROM.

        Overall, I have a lower target and trying to work with underdog tools like IceStorm. You are right that what you have done would overload a cheap microcontroller.

        Just checked: the ICE40HX4K is $6.31 (7680 cells usable). Upgrading to the ECP5 with 24000 cells the chip is $10. The top of that range is $30 for 84000 cells. I think that’s the upper limit for IceStorm based projects. Of course dev boards add a lot to the cost.

        I’ll go study your page now.

      2. 32 voice 6-op synthesis may be a little extreme for an MCU but it’s not far off, should be simple once MCUs start getting phone chip clocks. Let’s say there’s 60 cpu cycles to get a sine with no assembly (determined experimentally with a tuned polynomial series by me) and all the overhead of a function call, and you’ve got a cortex m4 at 180mhz. You ought to be able to do 2 ops and an envelope a million times a second. divide that by 3 for 6-op to get 330k and that by 10 finger polyphony to get 33k. Sure you won’t get the top octave of harmonics but it’s more than enough for music. And with some actual hand optimization to assembly you ought to be able to be able to get back above 44k samples.

        1. 10-voice, 6-op is very easily done at 180MHz on hardware with multipliers. Actually, I have a 16-voice, 2-op synthesizer on a Propeller chip @ 80MHz. The need of upping the frequency goes against the power consumption, meaning battery-unfriendliness. The FPGA way is horrendous in terms of “rapid development” terms, yet this little project serves well as proof-of-concept of projects that can’t be achieved using MCU dev boards, noteven high clocked or floating-point enabled (Teensy, etc.).

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.