GPSDO/GNSSDO: STM32G4 + u-blox ZED-F9T + TDC7200 - Page 1
Forum section: electronics / projects

author: Carsten
author_rank: Contributor
timestamp: August 05, 2022, 04:31:26 pm
content: Hello everyone,I'm in need of a GNSSDO for accurate timesynchronization of moving vehiclesdistributed over a few (dozen) square km. I've been professionally using the James Miller (G3RUH)Ministd, Jackson LabsLC_XO, and SRSFS740, but none of these deliver satisfactory results when used on the move. That's certainly not a flaw of these devices, because presumably they were not designed with a non-stationary use case in mind. Therefore, I decided to build a suitable GNSSDO myself. This isnot a low-cost project. Development priorities are performance, simplicity, and value for money in that order.I have positive experience with the u-blox ZED-F9PRTKGNSS receivers. As the F9P can achieve <5cm position accuracy with RTK correction data, its timing receiver sibling (ZED-F9T) should enable sub-nanosecond timing accuracy. The F9T supportsdifferential timingvia the same correction data used for RTK positioning. I'm not aware of any other GNSS timing receivers supporting this feature. The F9T also exhibitsexcellent Allan deviation(~5e-11 @ 10s). Therefore, the F9T is the center piece of my design, relying on theRCB-F9Tboard for prototyping.Design aspects/goals:ZED-F9T timing GNSS receiver with RTK correction data10 MHz OCXO as local reference oscillator (special OCXOs with low g-sensitivity for non-stationary use exist)TDC7200 for ~50 ps measurement of GNSS timepulse vs. OCXOSTM32 32-bit timer capture (~6ns resolution) to resolve aliasing/ambiguity of TDC measurement<10ns relative accuracy within 10 km radius while on the move (preferably <1ns)stabilized pulse output derived from OCXO (not directly from GNSS receiver)configurable pulse properties (not only 1PPS) with fine-tunable delay (~200ps resolution via STM32G4x4 high resolution timers)integrated distribution amplifier for 10 MHz and 1PPS outputs (capable of driving 50 Ohm loads)part and manufacturing costs preferably <500€ per device (excl. OCXO)My architecture is inspired (among others) by thinkfat'sDIY GPSDO project w/ STM32, TDC7200. However, I hope to improve on these aspects:Minimize digital processing of OCXO output. Feed 10 MHz directly to TDC7200 without division via 74HC390 to minimizetemperature dependence.Only use low-jitter clock ICs (e.g., LMK1C110x for fanout). No 74-type components, which AFAIK do not have jitter or phase noise specs.Active 1 Hz low-pass filter after tuning DAC to a) minimize noise (from supply, voltage reference, and DAC) fed to OCXO control voltage input and to b) enable finer than 16-bit tuning resolution via PWM. Assuming a 2 ppm tuning range, 16 bit yields 30 ppt frequency tuning resolution. At 10 seconds, that's already 300 ps, which is higher than the TDC7200's ~50 ps resolution. Hence, a finer tuning resolutionmaycome in handy, of course depending on the actual stability of OCXO and GNSS.My next step is to build a prototype PCB to put my ideas to the test. I've devised the preliminary architecture and put it into a schematic. The layout is in progress.I've attached the schematic and would appreciate constructive feedback, prior to having it produced.

author: vk3jpk
author_rank: Newbie
timestamp: August 06, 2022, 12:12:24 am
content: Hi Carsten,I had a quick look at your circuit and notice that you are attempting to directly measure the time between the GNSS PPS and the next 10MHz OCXO rising clock edge using the TDC7200. Unfortunately this will not work as the TDC7200 has a minimum measurement interval of 12ns (according to the data sheet). In practise the time difference between the GNSS PPS and the next 10MHz clock edge will be in the range of 0ns through 100ns so you could be in trouble up to 12% of the time.This is explained in some detail in the TAPR TICC Operation Manual (seehttps://web.tapr.org/~n8ur/TICC_Manual.pdf) along with the solution TAPR used to work around this issue in their situation which was also constrained by a relatively slow Arduino.So you need to find a way to derive the time difference indirectly.One method that I have personally used is to feed the GNSS PPS into a chain of D flip flops clocked by the 10MHz clock to create a synchroniser and use the TDC7200 to measure the difference between the GNSS PPS and the output of the synchroniser and then use this synchronised output with your microcontroller counter (assuming your microcontroller counter is also synchronous to the same 10MHz clock used by the TDC7200).If you look at the equations for how the TDC7200 result is calculated you can eliminate the temperature variance in the synchroniser flip flop propagation delay by calculating directly from the TDC7200 measurements the time from the GNSS PPS rising edge to the 10MHz rising edge AFTER the rising edge at the output of the synchroniser. By happy coincidence this is the same rising edge your microcontroller counter will use (assuming it counts the output of the synchroniser and has a clock synchronous to the 10MHz clock used by the TDC7200).James

author: Carsten
author_rank: Contributor
timestamp: August 06, 2022, 07:11:32 am
content: Hi James, thank you for taking the time to look at the schematic.Quote from: vk3jpk on August 06, 2022, 12:12:24 amMy idea to circumvent the TDC7200's dead time is to exploit the 10 MHz signal's periodicity. When it doesn't measure 0 to 12 ns, it should measure 100 to 112 ns. I haven't read anything in the datasheet that indicates the TDC7200 would be negatively affected from a stop pulse within its dead time (other than not measuring that stop pulse, of course). The way I understand the data sheet,early stop pulses are simply ignored:QuoteThinkfat also didn't have any issues with feeding continous 10 MHz stop pulses to the TDC.Even if the first stop pulse falls into the dead time and/or the first measurement is flawed, using the TDC's feature to measure multiple consecutive stop pulses could be used to filter out nonsensical measurement values.Quote from: vk3jpk on August 06, 2022, 12:12:24 amThanks for the suggestion. Using the TDC's CLOCK_CNTR_STOP_MASK to wait one 10 MHz clock period after the start pulse before processing stop pulses should have the same effect without relying on external circuitry. That's my plan B if above plan A fails.

author: iMo
author_rank: Super Contributor
timestamp: August 06, 2022, 07:30:42 am
content: Also mind the 7200's resolution is 55ps with "35ps std dev" (rms)..PS: Figure 15 of the DS shows the std dev vs. int clock dependency..

author: Carsten
author_rank: Contributor
timestamp: August 06, 2022, 01:03:22 pm
content: My design use the 10 MHz OCXO for clocking the TDC7200. A faster clock will only bring marginal std dev improvement (~5 ps as per Fig. 15).Fig. 17is also quite interesting. In timing mode 1, which I plan to use, the standard deviation deteriorates to ~100 ps at a 500 ns interval. Originally, I wanted to measure and average 5 stop pulses, but without appropriate weighting that could actually be detrimental compared to just using the first measurement.

author: iMo
author_rank: Super Contributor
timestamp: August 06, 2022, 03:16:24 pm
content: Read the entire thread with thinkfat's elaboration of his design - he did elaborate with many aspects of the 7200 application.. Also TI's forum contains some hints and measurements (see below - I downloaded them from TI's forum in past when I messed with the 7200 in my reciprocal counter exercise).

author: Carsten
author_rank: Contributor
timestamp: August 07, 2022, 12:38:09 pm
content: Thanks. I quickly went through the TDC7200-related part of thinkfat's thread (and found I'm missing a pullup on the TDC's INTB). The temperature dependency issues were my motivation to minimize any processing of the 10 MHz and 1PPS signals to the bare minimum before feeding them to the TDC. That minimum is the LMK1C1103, which is transparent in terms of (temperature-dependent) propagation delay, as it equally applies to the output ports.For now I really want to finalize the design and layout. I'll consult that thread again when I start implementing the TDC7200 measurement.

author: Carsten
author_rank: Contributor
timestamp: August 11, 2022, 06:50:17 am
content: I've updated the schematic. Added an IMU (TDK InvenSense IIM-42652 on a separate breakout board) and pushed the active low-pass filter cutoff frequency to 10 Hz. Also preliminarily finished the layout. BOM is still open, so maybe a few capacitor/resistor footprints will change (to minimize assembly costs by picking parts without setup cost), but apart from that I consider the prototype design finalized. Will let it sit for a few days to review everything with some distance.The board outline (including SMA connector base) is 100x100 mm, so it'll fit into a typical aluminum PCB enclosure, should the need arise. For unhoused use, I've place the OCXO under a plastic cover (Hammond 1551P) to shield it from airflow.

author: thinkfat
author_rank: Unknown
timestamp: August 14, 2022, 11:30:15 am
content: Carsten,I remember I shared a little circuit with a 74HC74 to delay the stop pulse by 100ns (one 10MHz clock cycle). That circumvents the problem with the dead time in mode 1. Also, if you search the time-nuts archive, you'll find a similar design by member Tobias Pluess. He shared his full schematics on the mailing list as well. It is sure worth a look.PS: I'd add an air pressure sensor as well. It is something I missed in my design, the next revision will have it.

author: Carsten
author_rank: Contributor
timestamp: August 14, 2022, 03:44:45 pm
content: Quote from: thinkfat on August 14, 2022, 11:30:15 amWhat's the advantage of delaying the stop pulse compared to relying on the 10 MHz stop signal's periodicity as I intend to do it? Values within the dead time (0 to 12 ns) should simply map to 100 to 112 ns. Do you see any reason that's not gonna work? The systematic error should be non-measurable, as the difference between sucessive 10 MHz edges is given by the phase noise floor (offset >1 MHz).I have two reasons against using a synchronizer based on 74-type logic:Temperature dependency: The 74HC74 adds too much uncertainty in terms of potential temperature dependence ofpropagation delay(14/~40 ns typ./max. @ 5V). Even the high-speed CMOS variant74AHC74, which I would recommend over the regular 74HC74, still fields a propagation delay of typically 3.7 ns at 25°C and min/max from 1.0 to 8.5 ns over the -40°C to +85°C temperature range. That's simply too much uncertainty (i.e., potential temperature dependence) between the edge measured by the TDC7200 and the edge output on the SMA connectors. The LMK1C1103 I'm using as a fanout buffer hasmax. 50 ps skew between channelsover its entire -40°C to 125°C temperature range.Rise/fall times: TheTDC7200 datasheetspecifies theMaximum rise, fall time for START, STOP signalsandMaximum rise, fall time for external CLOCKas nominally 1 ns. The 74HC74's transition time is substantially higher (7/19 ns typ./max.). Unfortunately, no rise time is given in Nexperia's 74AHC74 datasheet. The LMK1C110x specifies max. 0.7 ns rise/fall time.Quote from: thinkfat on August 14, 2022, 11:30:15 amDo you also recommend that for OCXOs or just for your LPRO? AFAIK, OCXOs should be insenstive to air pressure due to hermetically sealed cases.

author: 0xFFF0
author_rank: Regular Contributor
timestamp: August 14, 2022, 04:12:01 pm
content: Use LVC types. They have 1 or 2 ns rise time.

author: Carsten
author_rank: Contributor
timestamp: August 14, 2022, 04:24:55 pm
content: Thanks for the suggestion. That rise time does sound better. Also, the 74LVC74'spropagation delayis lower (1.0 to 5.2 ns in the -40°C to +85°C temperature range). However, I still don't see a reason to use an additional discrete component if I can achieve the same result via configuring the TDC7200 (CLOCK_CNTR_STOP_MASK = 1) and/or post-processing its measurements.

author: 0xFFF0
author_rank: Regular Contributor
timestamp: August 14, 2022, 04:30:11 pm
content: In order to use the 7200 correctly, I can recommend this paper. Finest stuff.https://github.com/TAPR/TICC/blob/master/docs/TAPR%20TICC%20User%20Manual.pdf

author: Carsten
author_rank: Contributor
timestamp: August 14, 2022, 05:12:11 pm
content: I've read all official and unofficial documents on the TDC7200 that I could find, including the TICC docs. While many designs use dividers and/or synchronizers for the STOP signal, the TDC7200 datasheet gives no indication that STOP signals within the dead time or preceding the START signal have an adverse affect on subsequent measurements. thinkfat also conlcluded that Feeding the 10MHz into a counter and directly to the TDC7200 works:Quote from: thinkfat on April 16, 2022, 03:42:28 pmI do not want to add a synchronizer, unless there's a absolutely solid technical reason for it.As there's obivously some doubt about my approach, should I first verify that the TDC7200 works the way I intend to use it before having the GNSSDO manufactured?

author: iMo
author_rank: Super Contributor
timestamp: August 14, 2022, 05:23:59 pm
content: Quote from: Carsten on August 14, 2022, 05:12:11 pmI would do it..

author: Theboel
author_rank: Frequent Contributor
timestamp: August 15, 2022, 02:02:04 am
content: Hi Carsten,I just curious how You measure the performance of GPSDO in Your application.

author: mino-fm
author_rank: Regular Contributor
timestamp: August 15, 2022, 09:38:42 am
content: Quote from: Carsten on August 14, 2022, 05:12:11 pmYou can leave any delay circuit if you are sure your time difference is always >= 12 ns all of the time.I wouldn't do so.Quote from: Carsten on August 06, 2022, 01:03:22 pmI wonder how five stop pulses could improve your results. Pulsdifferences 2 - 5 should be exactly 100 ns.TDC7200 compared to AS6500 is very noisy.

author: Carsten
author_rank: Contributor
timestamp: August 15, 2022, 11:45:12 am
content: Quote from: Theboel on August 15, 2022, 02:02:04 amWe conducted an automotive measurement with the Jackson Labs LC_XO GPSDOs (part of USRP X310) about 3 years ago. Boils down to packing them in a car, using separate antennas for each one (preferably with different orientation) to maximize the difference between each signal, and directly comparing the output signals of each GPSDO while driving.Results are published behind an IEEE paywall, sorry. Measuring between different vehicles is difficult. We only did that in a stationary scenario between buildings. Doing it on the move is complex and error prone as it requires a radio link with ideal line-of-sight conditions between participating nodes. While probably feasible, not worth the effort.

author: Carsten
author_rank: Contributor
timestamp: August 15, 2022, 12:24:09 pm
content: Quote from: mino-fm on August 15, 2022, 09:38:42 amIt isn't. But time differences 0 < t < 12 ns should just wrap to 100 < t < 112 ns due to the periodic 10 MHz stop signal.Quote from: mino-fm on August 15, 2022, 09:38:42 amAveraging to reduce noise. No idea whether that would have a positive effect with the TDC7200.Quote from: mino-fm on August 15, 2022, 09:38:42 amThanks for the hint with the AS6500. I think I have looked at it before, because I distinctly recall the color scheme of the ScioSense website, but I must have discarded it because the QFN package scared me off or sth.Honestly, now the specs blow my mind. I'll have to think how to proceed from here.

author: WatchfulEye
author_rank: Regular Contributor
timestamp: August 15, 2022, 07:46:18 pm
content: There's quite a nice set of experiments documented here:https://hamsci.org/sites/default/files/publications/2020_TAPR_DCC/N8UR_GPS_Evaluation_August2020.pdfMy take from this is that the noise from the ZED-F9T is orders of magnitude higher than the noise from the TDC7200 at relevant loop bandwidths.Also there is a possibility to "misuse" mode 2 if you are measuring phase offset to a clock edge. You just discard the "TIME2" measure, and only count clocks and use the TIME1 fractional measure. This avoids the additive noise which comes from summing what is effectively 2 measures. This is how I did it in my TDC7200 based GNSSDO.

author: Carsten
author_rank: Contributor
timestamp: August 15, 2022, 08:04:31 pm
content: Quote from: WatchfulEye on August 15, 2022, 07:46:18 pmThat's an informative paper, indeed. I already cited it in my initial postQuote from: WatchfulEye on August 15, 2022, 07:46:18 pmHaven't thought of that. That's a nice idea.

author: thinkfat
author_rank: Unknown
timestamp: August 15, 2022, 09:06:16 pm
content: Quote from: Carsten on August 14, 2022, 03:44:45 pmLets just say I see behavior in the DAC output of my GPSDO that is clearly not only temperature related. It sure won't hurt to have more input data, and the next easy target after temperature is air pressure. Also I'm not so sure if OCXO are totally immune to air pressure, I remember some discussions on the topic on the time-nuts mailing list that suggest otherwise. It cannot hurt, IMHO.Regarding delaying the stop signal, I really like your idea of using the mask function to ignore early stop events. I hadn't thought of that, I'll have to consider that.

author: thinkfat
author_rank: Unknown
timestamp: August 15, 2022, 09:14:02 pm
content: Regarding the AS6500 - it's an expensive part and probably not worth the expense. Just how accurately do you want to sample the noise of the GNSS time pulse? Even with the F9T, the time uncertainty is still in the nanoseconds range.

author: mino-fm
author_rank: Regular Contributor
timestamp: August 16, 2022, 08:49:23 am
content: Quote from: thinkfat on August 15, 2022, 09:14:02 pmDid you ever use it?I think: no.

author: thinkfat
author_rank: Unknown
timestamp: August 16, 2022, 10:18:12 am
content: Quote from: mino-fm on August 16, 2022, 08:49:23 amI haven't used it. And I likely won't, looking at the spec sheet and the price it's listed for at Mouser (around. 24€ in single quantities). You don't need 20ps single shot resolution for a GNSSDO. 55ps is already plenty. The one-second uncertainty for the time signal of the F9T is at least two orders of magnitude worse. So, again, how accurately do you need to sample that noise?

author: thinkfat
author_rank: Unknown
timestamp: August 16, 2022, 10:21:47 am
content: Quote from: thinkfat on August 15, 2022, 09:06:16 pmAlright. Looks like you cannot use the stop mask in mode 1 because the clock counter is not running. That was what you intended to do, right?

author: Carsten
author_rank: Contributor
timestamp: August 16, 2022, 05:53:29 pm
content: The resolution/noise of both AS6500 and TDC7200 are certainly more than sufficient for the typical GNSS timpulse jitter, including the ZED-F9T's. What struck me about the AS6500 was its feature set. Basically, it's half aMulti TICCon steroids in a single IC. Very tempting for a general purpose TIC device. I briefly considered it, because it would enable straightforward time-tagging of an externally provided time pulse (#featuritis) and obviate the need for the additional MCU timer capture measurement to resolve the 10 MHz period ambiguity. However, then I'd have to separately synchronize an MCU timer for generation of a stabilized 1PPS output. So I'm sticking with TDC7200 for now.Quote from: thinkfat on August 16, 2022, 10:21:47 amThat was my plan B in case plan A (rely on the 10 MHz stop signal periodicity and the TDC7200 to not trip over a stop pulse in mode 1's dead time) fails.I will spin a breakout board for the TDC7200 and try out whether my approach works. See attached quick'n'dirty schematic. Using the (high-resolution) timers of the STM32G474 to dynamically generate start and stop signals should faciliate rapid generation of a large dataset to derive stochastically significant conclusions from.

author: MIS42N
author_rank: Frequent Contributor
timestamp: August 18, 2022, 11:48:18 am
content: You may be interested in my approach to providing a control voltage to the OCXO. Instead of a DAC I use just the 10-bit resolution PWM output of a PIC processor. This is dithered on a pulse by pulse basis to effectively provide 24-bit resolution. The PWM (in my design) is buffered through a FET pair supplied by a precision voltage source. This is followed by a passive filter, most OCXOs have a high input impedance, the filter is effectively 12kohm in series so usually provides better than 90% of the full voltage swing (which even old OCXOs don't seem to go near).The PIC is clocked by the 10MHz, internally has a x 4 PLL to provide a 40MHz clock to the PWM. The PWM is set to provide 1000 bit frames at 40kHz. For a 0 to 5V control the dithering and filtering produces a control voltage with better than 1µV granularity. The filter removes all PWM artifacts.There isn't much to get wrong. The 2N7000/BS250 FETs are not optimal as their on resistance are not matched and may vary differently. If the two 10kΩ resistors are matched then any change in them is balanced out. The PIC processors are reputed to have low jitter output, I have not tested the assertion.Link to the whole circuit, the PWM processing is near the bottom.https://www.eevblog.com/forum/projects/budget-gpsdo-a-work-in-progress/?action=dlattach;attach=1553218;imageThe dithering is done in an interrupt routine invoked by the Timer 2 interrupt - quite short so doesn't hog the processor. The PIC could be a slave to something more sophisticated, just send the desired 24 bit control voltage across a serial connection, write it to the location I call PWM.This may be cheaper and better than a DAC.This is the dither routine.Code:; Timer 2 determines the length of each PWM output. The duty cycle of; each pulse is dithered each interrupt. In software, the PWM value is; held as 24 bits. The most significant 10 bits are loaded into the PWM; duty cycle register. The least significant 14 bits of the 3 byte PWM; value are repeatedly added to the value Dithr. If Dithr overflows to; the 15th bit then the duty cycle is increased by 1 bit for the next; PWM pulse.BANKSEL PWMMOVF PWM,W ; Add the least significantADDWF Dithr,F ; 14 bits of PWM to DithrMOVF PWM+1,WANDLW 0x3F ; truncate to top 6 of 14 bitsADDWFCDithr+1,WMOVWFDithr+1ANDLW0x40 ; isolate possible carry outXORWFDithr+1,F ; remove it from DithrADDWFPWM+1,W ; now the most significant 10 bitsMOVWF PWM2DCL ; bits 0-5 ignoredCLRWADDWFCPWM+2,WMOVWF PWM2DCH ; and store it as top 8 bits of next pulse width

author: Carsten
author_rank: Contributor
timestamp: August 19, 2022, 02:29:08 pm
content: Thank you for the suggestion. I believe sth. similar could be realized using the STM32G4's (high-resolution) timers and DMA requests triggered automatically by roll-over events to synchronously update the compare registers. For the first iteration I wanted to keep the hardware straightforward, so I went for a low-noise 16-bit DAC. If more resolution becomes necessary, I can similarly use circular DMA with the DAC to implement PAM/PWM.Quote from: MIS42N on August 18, 2022, 11:48:18 amHave you considered the noise contribution of the resistor? At 300 Kelvin it would generate 14 nV/√Hz of thermal noise, which is significantly above the output noise of the OPA189 I chose for active filtering my DAC output. While the OCXO control voltage inputs are high impedance, I'd assume their input noise cannot be modeled resistively. I haven't calculated/simulated which control voltage noise level is negligible compared to the OCXO's uncontrolled phase noise, but to err on the side of caution I picked a 100 Ohm resistor for my second, passive filter stage.

author: 0xFFF0
author_rank: Regular Contributor
timestamp: August 19, 2022, 03:02:10 pm
content: A noise density of 14 nV/√Hz wont't be your enemy, but the 20ns jitter from the gps.

author: MIS42N
author_rank: Frequent Contributor
timestamp: August 20, 2022, 11:14:03 am
content: Quote from: Carsten on August 19, 2022, 02:29:08 pmThe time constant of the filter is measured in seconds, every resistor in the filter is bypassed by a capacitor (in the circuit I just use electrolytics, but I'm not looking for a low noise solution). I don't think resistor noise would be an issue. Without doing a lot of calculation, I would assume the last resistor in the chain would contribute most noise, it is 1K. The preceding capacitors in the filter chain would disappear the contribution of the other resistors. The bandwidth for argument is 1Hz. I think that says noise is something less than 150nV. The granularity of the pseudo 24 bits is around 350nV so noise is less than minimum step. Not an issue IMHO. In contrast using a 16-bit DAC over 5V gives steps of 75µV.I didn't use 24 bits because I needed it. You could say it comes for free (2 instructions in the interrupt routine, 1 byte of memory). I committed to the idea of using dithering to eliminate the need for a DAC. Because the control voltage doesn't vary much, a long bit stream can be used - in this case 16M bits, generated at a 40MHz rate, so the pattern repeats more than twice a second. Granularity is no longer an issue, one less variable to deal with.I don't understand the need for such precise timing. If your vehicles are moving at 300kph, then in 1µs they move less than 0.1mm. That is a lot less than the accuracy of the GPS location. If your aim was value for money, don't bother with an OCXO, just use the output of the ZED-F9T directly. Messing with nanoseconds is messing with dollars.Quote from: 0xFFF0 on August 19, 2022, 03:02:10 pmManufacturer's figure Time pulse jitter ±4 ns. I believe the internal TCXO is steered to be synchronous with the generated timing pulses. Any disciplining algorithm will average over a period of seconds, random jitter disappears.

author: WatchfulEye
author_rank: Regular Contributor
timestamp: August 23, 2022, 02:47:34 pm
content: Resistor noise is essentially negligible, indeed, unless you have an oscillator with a particularly large tuning range, you need only minimal filtering of the DAC output.Using narrow band modulation theory, it is straightforward to calculate the phase noise attributable to Vc input noise. Conveniently in the narrow band regime, the infinite sum of Bessel J functions simplifies considerably and gives the following approximation.Np(f) ~= 20 log10( S * Nv(f) / 2f ).Where Np(f) is the phase noise at offset frequency f in dbc/√Hz, Nv(f) is voltage input noise at frequency f (V/√Hz) and S is tuning sensitivity (Hz/V).As a worked example, I used a cheap AliX 10 MHz OCXO with pull range of +/-2 ppm over a 0-4V range, giving S=10 Hz/V. A 0.5 Hz square wave with 1 LSB p-p is used to modulate the OCXO. Considering the fundamental only for now, the amplitude is 0.5 LSB = 30 uV. This gives an expression:20 log (10 * 3e-5 / 1) = -70 dbc/√Hz at 0.5 Hz offset.Taking into account the harmonic sequence of the square wave, and frequency dependence of phase noise, it can be seen that the phase noise attributable to harmonics decreases at a rate of 40dB/decade. So, to estimate phase noise in the region of 10 Hz offset, we apply the factor of 40dB/decade, to reach a phase noise @ 10 Hz (approx) of -122 dbc/√Hz, which is far below the specified phase noise of many budget OCXOs - so you could reasonably omit filtering all together.

author: Carsten
author_rank: Contributor
timestamp: August 23, 2022, 03:05:19 pm
content: Quote from: MIS42N on August 20, 2022, 11:14:03 amThe actual jitter is in the order of500 ps rms vs. a Cesium.Quote from: MIS42N on August 20, 2022, 11:14:03 amThe relevant speed is not the speed of the vehicles, but the speed of light. While with RTK you can get positions down to a few cm or even mm, inaccurate time dilutes this position accuracy substantially (30 cm per 1 ns) wrt the radio wave, which is what I want to measure.(Ab)using the ZED-F9T's time pulse outputs as a frequency reference is not an option ifphase noise is a concern.Quote from: MIS42N on August 20, 2022, 11:14:03 amWhat's your filter's cutoff frequency? With such a long period, don't you get some residual wobble at the filter output even with 1 Hz 3 dB cutoff?

author: Carsten
author_rank: Contributor
timestamp: August 23, 2022, 03:21:17 pm
content: Quote from: WatchfulEye on August 23, 2022, 02:47:34 pmSo I did err way on the side of caution, like I hopedThanks for the formula and example calculation. I haven't had the time to dig into the theory on this. I'll have a look at the numbers.

author: MIS42N
author_rank: Frequent Contributor
timestamp: August 24, 2022, 12:20:29 pm
content: Quote from: Carsten on August 23, 2022, 03:05:19 pmI don't know if there is some misunderstanding about PWM and dithering. WatchfulEye talks about an 0.5Hz wave of 30µV. Not sure where that comes from. The basic PWM is 0V and 5V alternating at a 40kHz rate. The filter has to get rid of the 40kHz to produce an average voltage. The processor I work with has a 10-bit PWM so can produce a duration of the 0V (and consequently the 5V) that is varied to produce averaged voltages in steps of 5mV. Dithering is simply increasing the length of some pulses by 1 bit so some pulses are 25ns longer than others. If all the longer pulses were lumped at the start of the 16,000 pulses required to get a pseudo 24-bit then yes there would be 2.4Hz wave riding on top of the 40kHz wave, about 5mV p-p. But the method of dithering doesn't do that, it intersperses the longer and shorter pulses optimally to give the filter the least amount of work to do.I modeled the filter in LTspice. I looked at getting a variation of less than 300nV at the oscillator control pin (that being the granularity of the dithered PWM). I didn't worry about the time constant, it is probably in the seconds range. An adjustment to the averaged PWM is usually quite small (typically less than 1mV) and it doesn't matter if it takes a few seconds to take effect. And yes, the filtering may be more than is required, but it does the job.

author: Carsten
author_rank: Contributor
timestamp: August 28, 2022, 03:04:02 pm
content: Quote from: MIS42N on August 24, 2022, 12:20:29 pmWatchfulEye approximated the control voltage noise with 1 LSB. Lacking detailed information on the source, I'd say that's a decent, conservative placeholder number for calculations.Thanks for the explanation of your dithering algorithm.

author: iMo
author_rank: Super Contributor
timestamp: August 28, 2022, 03:45:51 pm
content: Quote from: MIS42N on August 18, 2022, 11:48:18 amDouble-check that as it could easily be the assertion is not valid for an internal clock made by its PLL..

author: Carsten
author_rank: Contributor
timestamp: August 28, 2022, 04:38:29 pm
content: Quote from: imo on August 14, 2022, 05:23:59 pmQuote from: Carsten on August 16, 2022, 05:53:29 pmGot the PCBs. Photo and schematic attached. It's a straightforward breakout board for the TDC7200 (and some additional components to recycle the PCB) as an STM Nucleo-64 shield. The board supports two modes of operation (changable via JP1):Generation of START and STOP pulse pairs with arbitrary delays in multiples of 5.88 ns (the STM32G474's timer resolution at the maximum 170 MHz clock frequency) via TIM2 channels 3 and 4. Alternatively, the G474's high-resolution timer (HRTIM) could be used for ~200 ps resolution by changing the pin assignment.Re-use of TDC_CLOCK as continuous, periodic STOP signal and generation of arbitrary START pulse via TIM2 or HRTIM. That's the mode of operation I plan to use for my GNSSDO, with the START pulse coming the GNSS Rx, of course.TDC_CLOCK is generated via the STM's RCC_MCO pin (master clock output), configured to divide an external 24 MHz crystal down to 12 MHz (the TDC7200 requires 1 to 16 MHz).I've written a quick'n'dirty firmware for the STM to measure configurable delays between START and STOP signal:Code:for (uint32_t n = 0; n < config.iterations; n++) {// start measurementtdc_start_measurement(1);// measured 92 TIM2 clock cycles (~541 ns) from start command to TRIGG//while (!tdc_read_trigg()) {}// configure TIM2 to generate rising edges in in ~1000 TIM2 clock cyclesuint32_t tim2 = TIM2->CNT;TIM2->CCMR2 = 0x3030;TIM2->CCR4 = tim2 + 1000;TIM2->CCR3 = tim2 + 1000 + config.pulse_delay;// wait for measurement to complete, then reset start and stop signalswhile (tdc_read_intb()) {}TIM2->CCMR2 = 0x4040;// read measurement results from TDC7200uint8_t int_status = tdc_read8(TDC_REG_INT_STATUS);uint32_t time1 = tdc_read24(TDC_REG_TIME1);uint32_t calib1 = tdc_read24(TDC_REG_CALIB1);uint32_t calib2 = tdc_read24(TDC_REG_CALIB2);tdc_clear_interrupts();// write results to LPUARTlen = sprintf((char *) buf, "0x%02x,%lu,%lu,%lu\n",int_status, time1, calib1, calib2);if (HAL_UART_Transmit(&hlpuart1, buf, len, 100) != HAL_OK)Error_Handler();}Preliminary goal is to verify my assumption that the TDC7200 isn't bothered by premature STOP signals (<12 ns after or even before the START signal). The following table illustrates the results for the TDC7200's measurement mode 1. Negative delays indicate that the STOP signal precedes the START signal. A measurement result is assumed to be valid and included into the average if theINT_STATUSregister equals 0x19, while 0x0a indicates an overflow error (due to missing STOP signal). Results using 10 periods for calibration 2:Code:START STOP | TDC7200 MODE 1 TOF | VALID |TIMER DELAY | AVERAGE +- STDEV | TOFs | ERRORS------------|----------------------|--------|--------117.65 ns | nan +- nan ns | 0 | 10000-88.24 ns | nan +- nan ns | 0 | 10000-58.82 ns | nan +- nan ns | 0 | 10000-29.41 ns | nan +- nan ns | 0 | 10000-23.53 ns | nan +- nan ns | 0 | 10000-17.65 ns | nan +- nan ns | 0 | 10000-11.76 ns | nan +- nan ns | 0 | 10000-5.88 ns | nan +- nan ns | 0 | 100000.00 ns | nan +- nan ns | 0 | 100005.88 ns | 6.71 +- 0.010 ns | 99833 | 16711.76 ns | 12.54 +- 0.013 ns | 100000 | 017.65 ns | 18.47 +- 0.028 ns | 100000 | 023.53 ns | 24.31 +- 0.022 ns | 100000 | 029.41 ns | 30.14 +- 0.026 ns | 100000 | 035.29 ns | 36.05 +- 0.032 ns | 100000 | 041.18 ns | 41.92 +- 0.035 ns | 100000 | 047.06 ns | 47.77 +- 0.040 ns | 100000 | 052.94 ns | 53.68 +- 0.043 ns | 100000 | 058.82 ns | 59.57 +- 0.047 ns | 100000 | 070.59 ns | 71.34 +- 0.053 ns | 100000 | 082.35 ns | 83.08 +- 0.057 ns | 100000 | 094.12 ns | 94.84 +- 0.064 ns | 100000 | 0105.88 ns | 106.59 +- 0.071 ns | 100000 | 0117.65 ns | 118.37 +- 0.080 ns | 100000 | 0147.06 ns | 147.86 +- 0.096 ns | 100000 | 0176.47 ns | 177.31 +- 0.117 ns | 100000 | 0205.88 ns | 206.68 +- 0.136 ns | 100000 | 0235.29 ns | 236.14 +- 0.159 ns | 100000 | 0264.71 ns | 265.53 +- 0.178 ns | 100000 | 0294.12 ns | 294.94 +- 0.205 ns | 100000 | 0352.94 ns | 353.80 +- 0.260 ns | 100000 | 0411.76 ns | 412.64 +- 0.311 ns | 100000 | 0470.59 ns | 471.39 +- 0.370 ns | 100000 | 0529.41 ns | 530.29 +- 0.425 ns | 100000 | 0588.24 ns | 589.12 +- 0.481 ns | 100000 | 0647.06 ns | 647.95 +- 0.537 ns | 100000 | 0705.88 ns | 706.81 +- 0.588 ns | 100000 | 0764.71 ns | 765.66 +- 0.648 ns | 100000 | 0823.53 ns | 824.37 +- 0.703 ns | 100000 | 0882.35 ns | 883.24 +- 0.761 ns | 100000 | 0941.18 ns | 942.11 +- 0.826 ns | 100000 | 01000.00 ns | 1000.94 +- 0.872 ns | 100000 | 01058.82 ns | 1059.80 +- 0.917 ns | 100000 | 01117.65 ns | 1118.67 +- 0.967 ns | 100000 | 01176.47 ns | 1177.35 +- 1.013 ns | 100000 | 0As far as I can tell, the TDC7200 works as expected with delays <12 ns. Premature STOP pulses are simply ignored. I didn't see any erroneous measurement results. Will dive a little deeper and report more in the coming days/weeks.

author: iMo
author_rank: Super Contributor
timestamp: August 28, 2022, 07:33:49 pm
content: Nice board! Btw, why your stddev is rising proportionally with the TOF?

author: vk3jpk
author_rank: Newbie
timestamp: August 29, 2022, 04:41:51 am
content: Quote from: imo on August 28, 2022, 07:33:49 pmFigure 17 in the TDC7200 data sheet might partly explain the increasing stddev. This is probably why they decided to put mode 2 in the TDC7200 for measuring longer TOF.You may also just be observing the noise of the microcontroller 170MHz PLL ...A histogram of the TOF distribution at a few of the delay times may provide more insight than the stddev alone.James

author: Carsten
author_rank: Contributor
timestamp: August 29, 2022, 05:08:00 pm
content: Quote from: vk3jpk on August 29, 2022, 04:41:51 amInterestingly, my stdev is substantially higher than the one in Fig. 17. Unfortunately, the number ofcalibration 2 periodsis not given for that figure. I used the default of 10 (added that info to my previous post).A linear dependency between delay and standard deviation seems logical to me. All ring oscillator calibration measurements should exhibit a similar average error, which is then scaled by the actual delay between start and stop signals. Therefore, 40 calibration cycles (instead of the default 10) should bring the standard deviation down. I'll give that a shot for comparison. I'll also add some additional illustrations of the measurement data.Quote from: vk3jpk on August 29, 2022, 04:41:51 amThe STM32G474 datasheet puts the PLL jitter at approx. +- 25 ps. Assuming that also applies to the MCU timers, the impact on the TDC measurement should be negligible. Also, since MCU and TDC effectively rely on the same clock, I wouldn't expect a quasi-linear dependency.

author: thinkfat
author_rank: Unknown
timestamp: August 30, 2022, 07:09:45 am
content: For a complete characterization, what results to you get if you send two 100ns spaced stop edges? This is your intended use case, right? The linearity of the region across the crossover point would be interesting to see.

author: WatchfulEye
author_rank: Regular Contributor
timestamp: August 31, 2022, 09:49:32 pm
content: It's worth mentioning that MCUs may demonstrate some jitter on their outputs, not just from their PLLs.I was using an adafruit arduino clone with a microchip SAMD51, and found that the on-chip PLL had lots of jitter (about 5 ns at maximum ref clock), but even if I ran the entire MCU (and it's peripherals) synchronously directly from the same 10 MHz OCXO driving the TDC7200, there was still up to 1 ns of jitter from the waveform generators. I suspect that some of this was ground bounce or similar noise due to poor decoupling on the dev board I was using.It you have the option to try to characterise the jitter of the MCU with various PLL configurations, it might prove informative. For info, this is what I found with my experiments with the SAMD51 (different lines represent different PLL ref clock frequencies - note that 5 MHz is out of spec for this MCU, max is 3 MHz).

author: Carsten
author_rank: Contributor
timestamp: September 01, 2022, 06:11:38 am
content: Quote from: thinkfat on August 30, 2022, 07:09:45 amI'll have a look at that when I use the continuous 10 MHz stop signal. Examining the cross-over point in detail is a good idea. I'll put that on the list. The STM32G4x4's high-resolution timers (HRTIM) should prove useful for that.Quote from: WatchfulEye on August 31, 2022, 09:49:32 pmThanks for the hint. I already played around with the PLL and MCO configs, using 160 MHz as main PLL frequency, which is divided by 16 for the MCO pin that drives the TDC clock input, but the measured delay stdev didn't change substantially.Next I'll use the HRTIM for comparison with TIM2, which I'm using now. As the HRTIM advertises 184 ps resolution, I'm hoping its jitter should be lower than that.

author: iMo
author_rank: Super Contributor
timestamp: September 02, 2022, 02:50:47 pm
content: I think those high resolution timers with stm32 are made of temperature compensated "delay lines" (it means they are not generated by PLL at GHz frequency)..PS: basically the same principle as in the 7200..

author: Carsten
author_rank: Contributor
timestamp: September 03, 2022, 05:10:03 pm
content: Managed to substantially decrease the delay measurements' standard deviation. Initially, I used the GPIO output speedvery highas the TDC7200 specifies nominal 1 ns rise times for START/STOP/CLOCK signals. Playing around with the GPIO output speeds, I noticed thatvery highsignificantly affects the standard deviation, see attached plot. The plot includes values from the datasheet's Fig. 17, which is still better than my measurement results. I've also attached the raw measurement data.Haven't had a chance to investigate with a probe and scope yet, but I'll use speed settinghighfor now.TDC7200+MCU signal configuration:Code:* START, STOP, and CLOCK signals generated by STM32G474 (on Nucleo-G474RE board)* TDC7200 mounted on Nucleo-G474RE via minimal breakout board* STM32 PLL clock (160 MHz) generated from external 24 MHz crystal (via HSE input)* TDC7200 CLOCK frequency is 10 MHz (160 MHz PLL clock divided by 16 and output on MCO pin)* START and STOP generated by 32-bit timer (TIM2) running at 160 MHz, i.e., 6.25 ns resolution* measured 100000 iterations for each combinations of configured TIM2 delay between start and stop signals (see file names; delay in multiples of TIM2 clock cycle)Raw measurement results:Code:delay(ns), gpio_ospeed, mu(ns), sigma(ns), num_errors, num_valid, num_3sigma, num_5sigma12.50, 0, 12.81, 0.217, 0, 100000, 0, 012.50, 1, 13.30, 0.075, 0, 100000, 5746, 012.50, 2, 13.27, 0.054, 0, 100000, 5228, 112.50, 3, 13.26, 0.042, 0, 100000, 3660, 018.75, 0, 19.16, 0.208, 0, 100000, 0, 018.75, 1, 19.55, 0.054, 0, 100000, 3886, 2918.75, 2, 19.55, 0.059, 0, 100000, 3491, 018.75, 3, 19.54, 0.045, 0, 100000, 3438, 050.00, 0, 50.37, 0.227, 0, 100000, 0, 050.00, 1, 50.72, 0.064, 0, 100000, 2821, 150.00, 2, 50.71, 0.055, 0, 100000, 1896, 050.00, 3, 50.71, 0.047, 0, 100000, 359, 0150.00, 0, 150.47, 0.233, 0, 100000, 22, 0150.00, 1, 150.77, 0.115, 0, 100000, 549, 0150.00, 2, 150.75, 0.101, 0, 100000, 572, 0150.00, 3, 150.78, 0.114, 0, 100000, 29, 0250.00, 0, 250.40, 0.242, 0, 100000, 131, 0250.00, 1, 250.74, 0.132, 0, 100000, 929, 3250.00, 2, 250.73, 0.130, 0, 100000, 998, 0250.00, 3, 250.81, 0.192, 0, 100000, 0, 0500.00, 0, 500.16, 0.258, 0, 100000, 1793, 16500.00, 1, 500.52, 0.240, 0, 100000, 2278, 16500.00, 2, 500.49, 0.241, 0, 100000, 2287, 10500.00, 3, 500.74, 0.426, 0, 100000, 0, 0750.00, 0, 750.14, 0.398, 0, 100000, 1596, 11750.00, 1, 750.48, 0.326, 0, 100000, 2480, 141750.00, 2, 750.46, 0.324, 0, 100000, 2477, 126750.00, 3, 750.82, 0.655, 0, 100000, 0, 02000.00, 0, 1999.79, 0.547, 0, 100000, 586, 1622000.00, 1, 2000.11, 0.520, 0, 100000, 561, 1962000.00, 2, 2000.09, 0.520, 0, 100000, 594, 1902000.00, 3, 2000.36, 1.209, 0, 100000, 3406, 1