One-Pin FPGA FM Receiver: How Much Radio Do You Actually Need?

April 22, 2026

FM radio recovered from one digital input pin.

Real RF crosses a digital threshold and becomes audio without the conventional receiver front end. This page preserves the demonstrated path: input threshold behavior, four-phase sampling, XOR-based frequency translation, rectangular integrate-and-dump filtering, cross-product FM demodulation, and sigma-delta audio output.

The result is not a smaller radio for its own sake. It is a working FM proof of mechanism rebuilt around threshold-crossing timing.

one input pin, one FPGA, real FM in, real sound out.

Proof of mechanismThis page delivers the one-pin FM audio-recovery result and its Verilog follow-up. Calibrated carrier detection and receiver performance remain the next result.

Included: the FPGA input threshold, RF transition stream, four-phase sampling, XOR mixing, an 80-sample integrate-and-dump window, cross-product FM discriminator, sigma-delta audio output, video link, source paths, and build notes.

Not yet established: calibrated sensitivity, measured selectivity or bandwidth, probability of detection, false-alarm rate, blocker rejection, or a terminal decision among no detected signal, CW, and modulated RF.

Waveforms, radio hardware prototype, and received spectrum
Waveforms, prototype hardware, and received RF structure from the one-pin radio work.
Thumbnail for the one-pin FPGA FM receiver video
Watch the one-pin FPGA FM receiver video
Hand-drawn one-pin FPGA receiver architecture
Broader receiver architecture, not the selected public build. The sketch includes LC preselection, an LNA, AGC, an offset DAC, three tuner paths, and CIC-plus-FIR filtering. The selected fm_radio_nov15.sv snapshot implements one thresholded input path, one tuner, rectangular integrate-and-dump filtering, cross-product FM recovery, and sigma-delta output.

The Conventional Receiver Brings A Lot Of Apparatus

I started where people usually start. Weak RF comes in. A low-noise amplifier boosts it. A mixer multiplies it against a local oscillator. The design produces IF or baseband. An ADC samples that. Later digital stages recover the audio.

That architecture works. It also brings work of its own.

The local oscillator has to be strong. Once it gets strong, it leaks into everything. It radiates. It pollutes the board. The receiver stops being a clean signal-recovery problem and turns into a containment problem for the machinery you introduced to solve it.

Then comes the ADC. It wants clean analog amplitude. It wants drive. It wants the front end to preserve explicit values faithfully enough that the later receiver path can recover what the analog chain made expensive. Then come lookup tables, multipliers, trigonometric mixing, atan2 phase extraction, and the ordinary arithmetic cost of that representation.

That whole path works. The experiment here asks which parts are necessary for this FM receiver.

So I cut the first burden out:

I hid the local oscillator action inside the FPGA.

That removed the loudest periodic signal from the outside world. It also forced the next question.

If I do not preserve analog amplitude with a conventional mixer-plus-ADC chain, what exactly do I preserve instead?

I Stopped Trying to Digitize Amplitude

The answer was not "a cheaper ADC." The answer was: stop treating amplitude as the thing that must survive first.

I let the FPGA input threshold the incoming RF around its midpoint.

When the signal crosses that midpoint, the pin sees a zero or a one.

That is the entire front edge of the receiver.

No multi-bit sample word. No explicit analog amplitude at the pin. Just transitions.

That step is destructive to absolute RF scale. For an ideal fixed midpoint threshold, sign(A cos(ωt)) = sign(cos(ωt)) for every A > 0: two clean sinusoids that differ only in amplitude produce the same bitstream.

It does not destroy every useful property of the signal. Crossing timing and pattern can retain phase and frequency structure. Known noise or dither, a nonzero threshold offset, hysteresis, or a swept threshold can break the scale ambiguity and support calibrated detection; calibrated front-end gain can then refer that result back to the RF input plane. FM makes the timing result especially direct because its information appears as changing instantaneous frequency.

So the first real reduction was this:

RF in, transition stream out.

That move killed a huge amount of inherited baggage in one shot.

I Did Not Get That Idea from Radio

That threshold idea came from somewhere else.

About a year and a half before this receiver, I was training neural networks to discover digital circuit layouts on multiplexer-based fabrics using backpropagation. Digital logic is brutally nonlinear, so people do not normally expect those systems to train well. But I found one trick that helped a lot: I introduced a 50-50 noise process that generated zeros and ones statistically at the weight generator. Once that noise was there, simple circuits, adders for example, became much more trainable.

That left me with a useful lesson:

information can survive as binary stochastic structure.

It does not always need to survive as a clean explicit value.

I was also studying sigma-delta ADCs and DACs around that time. I had their waveforms and oscillograms printed out and kept staring at them. Sigma-delta teaches a similar lesson from another angle: a smooth analog signal can live inside a digital pulse stream far more efficiently than people assume. You do not need an explicit analog word every time you touch the signal. Transitions can carry much more structure than the ordinary sampled-amplitude mindset admits.

That did not mean I wanted a sigma-delta RF front end. In a real sigma-delta converter, the digital output feeds back into the analog side and shifts the midpoint dynamically. That feedback creates the very kind of pulsing front-end activity I was trying to avoid. I had already removed the strong external local oscillator. I did not want to solve that problem and then recreate it in another form.

So I kept the insight and rejected the architecture.

The insight said:

the one-pin input is not starved of information. It is rich in transitions.

That was enough.

What the Pin Preserves, and What It Does Not

Once I thresholded the RF at the FPGA input, I stopped asking for explicit amplitude and started asking for crossings.

That turns out to be enough for the result shown here: recovering FM structure and intelligible audio.

A fixed midpoint threshold discards absolute RF scale. In the noise-dominated region, however, coherent statistics of the one-bit stream vary with signal-to-noise ratio, allowing signal presence and relative strength to be recovered after calibration.

The I/Q plots are evidence for structure recovery, not an absolute RF voltmeter. I can generate a sawtooth in the transmitter, send it over RF, receive it through one pin, and recover its internal I/Q behavior. Absolute volts or dBm would require a calibrated input gain, threshold, and noise reference, or a measurement mode that deliberately varies the threshold.

That is the core result of this design: threshold crossings preserved enough phase and frequency structure for this FM path, even though the fixed threshold did not preserve absolute amplitude.

Four-Phase Sampling Gives Me the Signal Back

Inside the FPGA, I sample the thresholded bitstream in four phases.

That matters. I do not just oversample more and hope for the best. I sample in quadrature, with 90-degree offsets, so I preserve direct and quadrature structure explicitly. In effect, I sample at 2F in quadrature: two samples per carrier cycle, but with the quadrature timing preserved. Those four phases carry the full signal content I need.

That gives me:

Once I have that, the rest of the receiver simplifies aggressively.

I Do Not Multiply by Sines and Cosines

A conventional digital receiver path often reaches for trigonometric machinery: sine tables, cosine tables, multipliers, and explicit oscillators.

I do not need any of that here.

The signal is already in thresholded quadrature form. My digital Weaver stage just flips bits in the right pattern. In practice, that means XOR operations, controlled inversion of the ones-and-zeros stream. That is enough to perform the mixing and frequency translation I need.

So the digital mixing stage becomes logic, not a sine/cosine multiplier chain.

That cut matters because it keeps the receiver aligned with the representation it actually has.

I Do Not Use atan2 Either

The usual FM-demodulation answer is to recover explicit phase with atan2 and then differentiate it. That is expensive. It also never matched how I was already thinking.

I had been working on a DQPSK demodulator, and that had already trained me to think in relative phase change between successive I/Q vectors, not in absolute phase extraction.

So when I reached post-accumulator baseband I and Q in this receiver, I went straight to the geometric relation that mattered:

Xn = In-1Qn - Qn-1In = |zn||zn-1| sin(φn - φn-1)

That is the 2D cross product of successive I/Q vectors in the operand order used by the selected source. Reversing the operands changes only the output polarity.

Small-angle approximation for phase difference from vector components
A working note from the same no-atan2 demodulation thread: estimate phase movement from vector components instead of extracting absolute phase.

For small phase steps, it gives a magnitude-weighted sine of the relative rotation directly. FM can use that rotation. So instead of computing atan2, then differentiating, then carrying all that arithmetic around, I compute the cross product.

Two multiplications. One subtraction. Done.

That stage fits the FM audio path, but it is not a calibrated carrier detector. A centered CW has approximately zero phase step and therefore approximately zero cross product. No-signal noise also has approximately zero mean cross product. An offset CW appears approximately as DC, while FM produces a changing output. The exposed sigma-delta audio output provides no calibrated, unambiguous decision statistic for distinguishing no detected signal from a centered CW.

The Rest of the Chain Is Simple

In the selected source snapshot, an 80-sample rectangular integrate-and-dump window filters the quadrature signal, followed by one transfer/reset clock. That keeps the rate conversion cheap, but its selectivity is limited and must not be confused with the CIC-plus-FIR path in the broader sketch.

Then the cross-product demodulator recovers the FM baseband.

Then a sigma-delta output stage turns the recovered signal into audio that can drive a speaker.

So the full chain is this:

That is the published FM audio-recovery path.

The Verilog Follow-Up

The added source snapshot is now in one-pin-RF/README.md. The selected receiver file for this article is fm_radio_demo_2026/fm_radio_nov15.sv, because build.sh is wired to synthesize that file for an iCE40 UP5K build. The nearby fm_radio_2026_pin_4_3.sv file is a near-identical retuned variant, not the build target.

The intended build path is explicit: Yosys reads the SystemVerilog, nextpnr targets UP5K SG48 with the pin constraints, IceStorm packs the bitstream, and dfu-util downloads it. The archived source currently uses an unresolved identifier n in both sample-shift ranges, and build.sh supplies no definition. This page therefore treats it as the selected historical source snapshot, not as a freshly reproduced build; that typo or missing definition and a clean build log must be resolved before claiming source-level reproducibility.

read_verilog -sv ./fm_radio_nov15.sv
synth_ice40 -top top -json ./build/fm_radio.json
nextpnr-ice40 --ignore-loops --pre-pack ./timing.py --freq 336 --up5k --package sg48
icepack ./build/fm_radio.txt ./build/fm_radio.bin

The relevant pin boundary is one RF input and one sigma-delta audio output. The constraint file maps DIFF_PINS_4P_3N to package pin 4 and PIN2 to package pin 2.

input DIFF_PINS_4P_3N,
output PIN2,

wire [1:0] RF4X_SAMPLES;

SB_IO #(
    .PIN_TYPE(6'b000000),
    .IO_STANDARD("SB_LVDS_INPUT")
) ddr_sampler_2 (
    .PACKAGE_PIN(DIFF_PINS_4P_3N),
    .INPUT_CLK(CLK_168_MHZ),
    .D_IN_0(RF4X_SAMPLES[0]),
    .D_IN_1(RF4X_SAMPLES[1])
);

The sampler is not a metaphor. The comments in the source call the DDR samplers the heart of the radio: they sample binary RF values at the four-times-LO clock. The code then folds the even and odd samples into two 16-bit quadrature words.

samples_even <= {samples_even[n-1:0], RF4X_SAMPLES[0]};
samples_odd  <= {samples_odd [n-1:0], RF4X_SAMPLES[1]};

samples_i <= {
  samples_even[7],  samples_odd[7],
 ~samples_even[6], ~samples_odd[6],
  samples_even[5],  samples_odd[5],
  // same alternating pattern continues through bit 0
};

samples_q <= {
 ~samples_even[7],  samples_odd[7],
  samples_even[6], ~samples_odd[6],
 ~samples_even[5],  samples_odd[5],
  // same quadrature pattern continues through bit 0
};

The digital mixer is controlled inversion. The repeated accumulation blocks XOR each one-bit sample against the DDS sign bit, then sum the results into the baseband accumulators.

sum <=
    { 4'd0, samples_i[ 0] ^ dds_ch1[CH1_MSB] }
  + { 4'd0, samples_i[ 1] ^ dds_ch1[CH1_MSB] }
  + { 4'd0, samples_i[ 2] ^ dds_ch1[CH1_MSB] };

sum_qq <=
    { 4'd0, samples_q[ 0] ^ dds_ch1_90[CH1_MSB] }
  + { 4'd0, samples_q[ 1] ^ dds_ch1_90[CH1_MSB] }
  + { 4'd0, samples_q[ 2] ^ dds_ch1_90[CH1_MSB] };

The FM recovery stage is the same direct relative-phase calculation described above. The implementation multiplies the current and previous baseband I/Q values in the cross-product form, then feeds that into the sigma-delta output path. It does not compute or expose a parallel I/Q energy or coherent-carrier statistic.

phase_delta <= decimator[DECIMATOR_MSB] ? (
  samples_bb[25:10] * samples_q_bb[25:10]
  -
  samples_bb_q[25:10] * samples[25:10]
) : phase_delta;

sd_dac <= {2'd0, phase_delta, 16'd0} + 34'd6442450944 +
  (dac_out ? 34'd8589934592 : 34'd8589934591);

dac_out <= sd_dac[SD_DAC_MSB];
assign PIN2 = ~dac_out;

That is the promised Verilog follow-up in miniature: thresholded RF enters one FPGA pin, the iCE40 DDR input primitive samples it, the logic builds I/Q by timing and inversion, the baseband path uses the cross product instead of atan2, and the recovered signal leaves as a sigma-delta bitstream.

What the Selected Snapshot Predicts, and What It Does Not Measure

The selected source is simpler than the broader architecture sketch. Its 21 MHz processing clock accumulates 80 rectangular samples, then spends one clock transferring and resetting the accumulator. The resulting I/Q update rate is 21 MHz / 81 = 259.26 kS/s.

For the 80-sample rectangular window alone, the calculated digital response is:

The 259.26 kS/s output has a 129.63 kHz Nyquist frequency, where the rectangular window is already approximately −3.82 dB. Responses outside that range alias into the output, so aliases are part of the receiver measurement, not a detail to omit.

Those are source-derived filter calculations, not measured receiver selectivity. Thresholding happens before the digital filter, so a strong off-channel signal can dominate and severely corrupt the crossing stream before the wanted channel reaches the integrate-and-dump window. A one-tone frequency sweep cannot establish blocking performance; that requires holding a wanted signal near sensitivity while raising a second, adjacent signal.

The RTL calls one logical port DIFF_PINS_4P_3N and configures it as SB_LVDS_INPUT. Physically, that mode uses the pin-4/pin-3 differential comparator pair; Lattice documents that the tool automatically assigns the complementary pin. The RF-bearing input and its companion reference/bias pin are therefore both part of the receiver boundary. The current iCE40 UltraPlus data sheet specifies guaranteed comparator HIGH and LOW regions at differential inputs of at least +250 mV and at most −250 mV for 2.5 V VCCIO; it does not specify radio sensitivity. The public artifact does not yet document the voltage and bias network on both pins, so it cannot support an absolute dBm claim.

What I Removed

I removed the parts people normally assume are untouchable:

I did not remove them out of ideology. I removed them because the demonstrated FM audio-recovery path still worked without them.

That is the whole point of the project.

A serious hardware project does more than show that something works. It shows what can disappear without breaking the thing.

Why This Receiver Matters

This is not about making radio smaller as a trick. The useful result is the receiver boundary: thresholded RF enters one digital pin, and the later path still recovers audio.

That is what this receiver exposed.

It showed that this constrained FM audio-recovery path can omit much of the conventional apparatus. It did not establish that the same path matches a conventional receiver's sensitivity, selectivity, dynamic range, calibration, or blocker tolerance.

Much later I found an obscure old Xilinx publication from roughly twenty years earlier describing an FM receiver along related lines, quiet input biasing, direct threshold behavior, no front-end sigma-delta feedback. That did not weaken the result. It strengthened it. It showed this direction was real, not fantasy, even if the mainstream story of radio ignored it.

So the one-pin FPGA FM receiver answered the only question that mattered:

How much radio do you actually need?

Less than the conventional receiver path suggests.

And that is exactly why I built it.

The Next Receiver Result

This page proves that threshold crossings preserve enough information to recover FM audio. The next result must establish a detector and a calibrated receiver boundary:

From the same thresholded RF pin, distinguish no detected signal, CW, and modulated RF at a selected frequency, with stated bandwidth, sensitivity, probability of detection, false-alarm rate, and blocker rejection.

That requires a quiet capture path for signed post-filter I/Q, raw one-density, transition count, and discriminator output; a conducted and shielded 50 Ω fixture; a frozen detector rule; terminated-input calibration; CW power and frequency sweeps; two-tone blocker tests; and FM SINAD, distortion, and deviation-linearity measurements.

The defensible absence statement will have the form: No signal of the tested class was detected within B Hz of f during T. At or above X dBm, that class was detected with PD at least 0.90 at PFA = Y per stated dwell and searched bin.

The follow-up article will be Can One Bit Tell What Is There? It will be published when those fields contain measurements rather than predictions.