Whilst the frequency of the FPGA and Electron sound output matched, there was still something not quite right with the sound. A subtle difference between the two that I couldn’t quite put my finger on.
After hooking the oscilloscope up to both with the Electron’s speaker still connected, it became rather obvious.
Whilst the Electron ULA and FPGA ULA both output a square wave on the o_sound_op pin of varying frequency, that’s only part of the story as the Electron has a little additional hardware:
Ignoring the amplification transistors, the additional Electron hardware shapes the ULA’s 265Hz square wave as the following comparison shows:
The capacitor C11 is key to this. Beyond blocking DC it didn’t change the waveform noticeably in my original measurements. However, I’d taken those with the speaker disconnected and a probe hooked up to the exposed header pins. Yet as the schematic shows, the speaker has a resistance equivalent to 16Ohm. That combined with C11 forms a high pass filter which quite dramatically changes the waveform at low frequencies.
Simulating this circuit in LTSpice with the speaker replaced with a simple 16Ohm resistor gives a rough idea of how much impact C11 has. Original square wave in green and the result of the high pass filter in blue.
This clearly needs to be accounted for as the difference between the square wave and the filtered version from the spice simulation is pretty easy to hear.
The replay library includes an rc_bypass component that allows simulation of a low pass filter in VHDL but no similar high pass filter component. It was however pointed out that subtracting the low pass filtered signal from the original signal will give the same result as a high pass filter.
After configuring the component to simulate a low pass filter comprising a 10uF capacitor and 16Ohm resistor (a simplification of a real speaker circuit), the resulting waveform (in cyan) looks reasonably close to the previous LTSpice simulation image.
It also sounds a lot closer to the Electron but comparing the Electron (yellow) and FPGA (cyan) waveforms does still betray a difference.
The amplitude of the Electron is half that of FPGA output and the fall off more gradual. This is caused by R61, a 47Ohm resistor that is in series with C11 and increases the time C11 will take to charge as LTSpice shows
By adding in an extra low pass filter stage with a 47Ohm resistor and 10uF capacitor and dropping the signal amplitude by half, the resulting waveform, whilst not an exact match, is a close enough approximation of the Electron. This holds through both low and high frequency tests.
Comparing game music between the two, I really can’t hear any difference now. I didn’t go as far as an A/B or blind test as I’d have to setup a matching speaker for that to be of any use. It sounds close enough that I’m happy to call it done and move onto fixing a few display quirks.