Filter outputs to stop GPS interference [Maybe n00b verilog problem]


#1

This might be a bit left field, but I wasn’t sure where else to turn.

I have a project where I’m using a BX to read data and timing from a GPS module and output it to a little OLED screen. For weeks I’ve been plagued with the GPS struggling to get a satellite fix some days and getting it quickly other days. After lots of trial and error, I’ve traced it back to some fast switching outputs on the BX board (which is in close proximity). My tests haven’t always been repeatable and sometimes the GPS module survives for a while in the presence of noise which will eventually cause it to fail and sometimes it takes a while to get a fix even after I have turned off the noise.

The culprit is the clock signal for SPI data going to the screen. If I halve the frequency, it takes longer to fail. I started at 8MHz, but I am down to 250kHz and still getting occasional failures. It appears to be somewhat dependant on my breadboard layout - at one stage I moved the clock pin from one side of the BX to the other and it started working again. I got complacent and rearranged my breadboard again and now here we are again. It seems to be unrelated to whether the output is actually driving the clock pin on the screen or whether its unconnected.

I could lay it out differently again, but ultimately this will be going on a board where I’ll want to cram things in even tighter still so I’m after any advice about what I should be doing differently. I’ve tried some small capacitors to ground, but that didn’t help at all and I didn’t want to keep ramping up the size of the capacitor lest I be overloading the output.

I’ve stripped back the circuit so there’s only the BX board, the GPS module (powered from BX 5V with a capacitor) and a wire from the PPS pin to an input on the BX. Everything else is unconnected. I disable the clock when I lose satellite fix and re-enable it once I get a fix again (determined by the PPS pin starting up again). This way I can watch it fail and reestablish and get some rough idea of if I’m making it better or worse by the percentage time spent in failed state.

Is there something simple I’m missing?
Should an unconnected output switching at 8MHz interfere with a GPS module 2 inches away, which is trying to listen to data at ~1GHz? I presume its the harmonics generated by the edges of the signal rather than the fundamental tone.


#2

Almost certainly comes down to transmission line effects on the clock signal. Can be difficult to debug without decent test gear, :frowning: Take a look at this Things to try.

  1. Terminate clock line into a 100ohm resistor to Gnd at the display end. If needed add a 300ohm to 3v3 supply to pull up a bit.
  2. Series resistor on the way at the BX end.
  3. RC termination.

The problem is the edges of your 8MHz clock will have higher harmonic components. (Blame Mr Fourier).
You may also want to look at better decoupling on the power rails. Small value caps (1nF and below) for high freqs and large bulk decouplers too.
But generally getting to PCB should help especially if you have inner power layers.
On your final point, you clock may not be interfering with the incoming ~1GHz signal. It may be that it is interacing with the signal at the “mixed down” sampled signal. There are may ways that the demodulation of the signal can be upset, to the point where it can’t be sucessfully decoded. You may need to look at screening your GPS module. Remember, even if there is tin can screen on one side of th PCB, any signal passing through the otherside is liable to pick-up interference.

Hope this helps.


#3

It appears part of the problem is actually my code to detect when the GPS has failed. I do this by resetting a counter on each rising edge of the Pulse Per Second pin of the GPS module. If the counter counts too far, I flag it as failed. Now the problem is that my my gps_working bit is turning off even when the counter has not reached its timeout value.
Code:

module hardware (
	input clk_16mhz,
	output pin_1,
	output pin_2,
	output pin_3,
	output pin_5,
	output pin_6,
	output pin_7,
	input pin_24, // Pulse Per Second
	// onboard LED
	output user_led);
	
	wire clk = clk_16mhz;
	//GPS
	wire PPS; 
	assign PPS = pin_24;
	assign user_led = gps_working;
	reg gps_working;
	always @(posedge clk) begin
		if (PPS) begin
			gps_working <= 1'b1;
		end else begin
			if (clk_count[24]) begin
				gps_working <=1'b0;
			end else begin
				gps_working <= gps_working;
			end
		end	
	end
	assign pin_1 = gps_working;
	assign pin_2 = clk_count[23];
	assign pin_3 = clk_count[24];
	assign pin_5 = PPS_reg1;
	assign pin_6 = PPS_reg2;
	assign pin_7 = clk_count[4];
	//Clock counter
	reg [31:0] clk_count = 0;
	reg PPS_reg1, PPS_reg2;
	always @(posedge clk) begin
		PPS_reg1 <= PPS;
		PPS_reg2 <= PPS_reg1;
		if (PPS_reg1 & ~PPS_reg2) begin
			clk_count <=0;
		end else begin
			clk_count <= clk_count + 1;
		end
	end
endmodule

What I am seeing is that even though clk_count[24] never goes on, gps_working is going off occasionally (and seemingly irregularly). When it does happen it is on the falling edge of PPS.
Could it be some kind of race condition between the edges of clk and PPS?
I’m confident that I’m doing more than one thing wrong in my code. Making the jump from programming software to hardware has been, shall we say, humbling.