EMI under control: spreading a PWM line with a Fibonacci LFSR

Elektronik Projekte

Sharp spectral line above the EMI limit. No room for extra inductors. Fix: a Fibonacci LFSR in the CPLD and a single register.

The starting point

A classical relay pulls in at around 12 V and holds at around 5 V. Instead of generating two supplies, you PWM the hold voltage on the full rail and let the coil inductance do the averaging. We sit at 16.25 kHz: above the audible band, slow enough for the freewheel diode, and a clean divisor of the 4.16 MHz internal oscillator inside the Lattice® MachXO2® CPLD (4.16 MHz / 256 = 16.25 kHz).

In practice it is not one relay but sixteen channels. For the explanation one is enough. What the EMI scan shows is a sharp line at 16.25 kHz and the odd harmonics: 49, 81, 113, 146, 178 kHz and so on. The conducted-EMI regulated band starts at 150 kHz, and the 146 and 178 kHz lines walk right into it. A single narrow spike is much harder to pass than the same total energy smeared across 1 kHz of bandwidth.

So we spread the spectrum.

Fibonacci, in the CPLD

The idea: vary the duty cycle by a small amount every PWM period. The fundamental no longer sits on a single spectrum bin, it walks across a narrow range. Peak goes down, energy stays the same.

For the random source you do not need true noise, that would be overkill. A deterministic-looking pseudo-random sequence that visits every value in a range evenly is enough. The classical tool of choice is the linear-feedback shift register in Fibonacci form.

The name comes from the structure. A Fibonacci LFSR computes each new bit as the XOR of several selected bits from the shift register, shifts the whole content by one place, and feeds the fresh bit into the input. Just like Leonardo of Pisa’s famous sequence Fn=Fn−1+Fn−2F_n = F_{n-1} + F_{n-2}, every new value is built from earlier ones, only that the addition is replaced by an XOR and the choice of positions by a polynomial.

The math behind it is the theory of finite fields. An n-bit register corresponds to a polynomial over F2\mathbb{F}_2. If the feedback taps are chosen so that the associated polynomial is primitive, the LFSR visits every non-zero state of the 2n−12^n - 1 possible states exactly once before repeating. That sequence is called a maximum length sequence or m-sequence, and it has pleasant properties: evenly distributed bits, a wide flat spectrum, and an autocorrelation that is almost a delta function.

For 8 bits x^8 + x^6 + x^5 + x^4 + 1 is a primitive polynomial. That gives the taps {7, 5, 4, 3} and a period of 255. Exactly what the spread needs.

The Verilog, annotated

localparam [7:0] PWM_DUTY = 8'h66;       // 40 % hold duty (102/256)

reg [7:0] pwm_cnt;        // free-running 0..255, wraps at 16.25 kHz
reg [7:0] lfsr;           // 8-bit Fibonacci LFSR, 255 states
reg [7:0] duty_latched;   // dithered duty, held for one full period

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        pwm_cnt      <= 8'h00;
        lfsr         <= 8'h01;
        duty_latched <= PWM_DUTY;
    end else begin
        pwm_cnt <= pwm_cnt + 8'd1;

        // Fibonacci LFSR, taps {7,5,4,3}, full 255-cycle
        lfsr <= {lfsr[6:0], lfsr[7] ^ lfsr[5] ^ lfsr[4] ^ lfsr[3]};
        if (lfsr == 8'h00) lfsr <= 8'h01;     // zero-lock guard

        // Sample a fresh dithered duty once per PWM period
        if (pwm_cnt == 8'h00)
            duty_latched <= PWM_DUTY + {4'h0, lfsr[3:0]};
    end
end

assign pwm_active = (pwm_cnt < duty_latched);

Only the low four bits of the LFSR are used. That gives 16 duty values: 0x66 (40.0 %) through 0x75 (45.7 %). The effective fundamental walks across roughly 750 Hz per PWM period.

The zero-lock guard is a safety net. From a non-zero state the LFSR cannot mathematically reach the all-zero state. But a glitched power-on could land it there, the guard costs one comparator and guarantees that the LFSR never sits on the all-zero line.

One pitfall: the latch

The crucial piece is duty_latched. The LFSR shifts on the system clock, not on the PWM period. If the comparator looked directly at the raw LFSR output, the threshold would wobble 256 times within one PWM period. Right where the falling edge should sit, the output would flicker.

With the latch, the threshold is constant inside one period, the edge is clean, and the next period starts with a fresh value. The pattern is generally useful: when a slowly varying control is fed by a fast source, latch it at the boundary where the consumer wraps.

Is 750 Hz of spread enough?

The resolution bandwidths (RBW) used for conducted emission testing are fixed by CISPR 16-1-1:

BandFrequency rangeRBW
A9 kHz to 150 kHz200 Hz
B150 kHz to 30 MHz9 kHz

Spreading only helps when it is significantly wider than the RBW. Otherwise all the spread energy lands back in one resolution bin and the peak detector sees no difference.

What saves us is that the spread scales linearly with the harmonic index. If the fundamental walks 750 Hz, the N-th harmonic walks N × 750 Hz:

FrequencyBandRBWSpreadEffective?
16.25 kHz (fundamental)A200 Hz750 Hzclearly effective
178 kHz (11th harmonic)B9 kHz8.3 kHzborderline
1 MHzB9 kHz46 kHzclearly effective
10 MHzB9 kHz460 kHzfar over-dimensioned

In the typical EMI problem zone (above 1 MHz) the measure is most effective exactly where the peak is high. Right at the lower band boundary around 178 kHz it is just barely effective. If you need more margin there, use more LFSR bits (e.g. 6 instead of 4 for 64 values and roughly 3 kHz fundamental spread), at the cost of more current ripple on the coil.

What the spectrum analyser sees

Before: sharp 16.25 kHz line, odd harmonics at 49, 81, 113, 146, 178 kHz and so on, each a narrow spike. The regulated range starts at 150 kHz, so the 178 kHz line and every higher harmonic falls into it.

After: the fundamental is cleanly smeared within Band A’s 200 Hz RBW. In Band B above 150 kHz the spread becomes more effective with every harmonic. Where the peaks usually fight the limit (the high harmonics), the smearing is wide compared to the 9 kHz RBW and the peak detector sees a markedly smaller maximum. The energy delivered to the coil is identical.

Margin shifts from “marginal” to “comfortable”, BoM stays untouched: no extra inductor, no extra capacitor, no separate clock generator.

What ten flip-flops bought us

ResourceCountPurpose
pwm_cnt8 FFFree-running PWM counter, 256-tick period
lfsr8 FF8-bit Fibonacci LFSR
duty_latched8 FFPeriod-stable dithered duty
LFSR taps4 inputs, 1 XORThe actual feedback

24 flip-flops shared across all channels. Each channel only adds the registered output FF on top. The MachXO2-640HC has 640 LUT4 and matching FFs, the whole PWM block fits in well under 5 % of the chip.

The math behind the spread:

That is the whole story. One 8-bit Fibonacci LFSR, one comparator, one latch. EMI passes.

Sources

Keywords: PWM spread spectrum, Fibonacci LFSR, MachXO2 CPLD, save EMC filters, CISPR 16, Verilog LFSR, conducted emissions, EMC optimisation consulting, Lattice CPLD design, EMI reduction, electronics engineering Switzerland, swissEmbedded FPGA Zurich

EMI measurement just over the limit and the BoM does not allow extra filters? We look at schematic, layout and FPGA code together and find the cheap levers that already sit in the silicon.

Contact us →