HackRF clock converter, 3

26.06.2021 10:48

I modified my HackRF with a small board based around the LPC6957 clock buffer. This allows me to connect a wider range of clock sources to its CLKIN input for a 10 MHz reference clock. Among other things, I can now synchronize HackRF to the ERASynth Micro I use in my vector network analyzer. In my last blog post I said I will share some more measurements on how the modified HackRF performs, so here are a few initial observations.

HackRF connected to the ERASynth Micro.

The measurements I talk about below were done with the HackRF antenna input connected to the RF output of the ERASynth Micro through a short piece of a RG-316 coaxial cable and a 20 dB attenuator. ERASynth Micro was set up to output a CW signal at various frequencies at -20 dBm level. I also had the REF OUT from the ERASynth Micro connected to CLKIN on the HackRF. For measurements where I didn't want ERASynth Micro and HackRF running from the same clock source I left the cable attached to CLKIN and disabled the CLKIN input using hackrf_clock --clkin 0.

The first thing I noticed when testing the clock converter modification was the fact that at some frequencies the phase noise appears higher at around 100 kHz offset when HackRF is running from an external clock. As I mentioned in my last post this was already noticeable in the waterfall plot of the spectrum analyzer application. Difference is even more obvious in the following plot of the apparent phase noise of the signal at 2420 MHz.

Apparent phase noise in digital baseband at 2420 MHz.

The plot shows spectral density calculated using the Welch's method from a 10 s long recording of digital I/Q samples from the HackRF at 8 MHz sampling frequency. This plot does not show phase noise of the actual signal on the wire. I have no instruments available to directly measure that (however the spec for ERASynth Micro phase noise is much lower than what I measured - I show the comparison in this post). The plot shows the apparent phase noise of the sine wave in the digital domain, including the contributions of both HackRF and ERASynth Micro.

A signal at 1000 MHz doesn't show a significant increase when CLKIN is enabled, however the interesting part at around 100 kHz offset it is obscured by some spurs:

Apparent phase noise in digital baseband at 1000 MHz.

My understanding is that at these offset frequencies the phase noise is largely defined by the various PLLs in HackRF. The synchronization itself shouldn't matter. As I said last time, I suspect the difference is because of different PLL settings in HackRF. When CLKIN is disabled, HackRF derives all internal clocks from a 25 MHz quartz oscillator. When CLKIN is enabled, it uses the 10 MHz reference, hence requiring a different multiplier in the first stage PLL that converts the reference to a 800 MHz clock.


For my specific application in the vector network analyzer the far-off phase noise is less important than the stability of the signal over periods of time in the range of 1 to 10 ms. This is because I use a time multiplex to compare the phase of the reference and measured signals. The assumption in this type of measurement is that the reference signal has a stable phase over one period of the time multiplex.

On the phase noise plots above, stability over this range of time intervals is shown beyond the left edge of the graph. However it's difficult to show this in the frequency domain since it requires Fourier transforms over a very large number of samples and at least my naive approaches ran out of computer memory. Hence I rather explored this in the time domain.

Setup for measuring phase stability.

This is the block diagram of the setup. The 10 MHz TCXO in the ERASynth Micro is the single reference frequency source. Two PLLs in the ERASynth Micro convert this reference into the 2420 MHz RF signal on the coax. HackRF then uses a complicated circuit that involves multiple PLLs, frequency conversions and an analog-to-digital conversion to convert the RF signal to a 2 MHz digital intermediate frequency. I then use a digital LO on the computer to convert the signal to DC and measure its phase angle.

A typical plot of the detected phase angle in degrees over a course of 100 ms looks like this. The plot is similar for other RF frequencies:

Phase stability of the received CW signal.

I was somewhat surprised that I still get this kind of random walk in signal phase, even when everything is running from a single clock source. I've seen it sometimes drift up to ±30 degrees. My understanding was that at these time scales the PLLs should largely track their reference clock and not contribute to the stability of the signal, so I'm not sure where this is coming from.

On the other hand, the whole system is very complicated and I find it hard to understand all the parts. Especially HackRF is internally much more complicated than I initially thought. It includes many nested layers of PLLs distributed through different chips and so far I failed to get a good high-level picture of how various parts affect could phase stability.

In conclusion, the clock converter board seems to work, but it has some side effects I didn't anticipate, like the unusual increase in phase noise at 100 kHz offset. The clock synchronization itself also didn't help as much as I thought it would in improving the accuracy of my vector measurements. However it did lead me to better explore the properties of the whole system and I found some other improvements I can make.

Posted by Tomaž | Categories: Analog | Comments »

HackRF clock converter, 2

18.06.2021 20:18

Last time I was writing about making a small modification for the HackRF to expand the range of signals that can be fed into the external 10 MHz reference input. My initial motivation for it was to sync the ERASynth Micro frequency synthesizer and HackRF in my home-made vector network analyzer. However I thought it might be more broadly useful, so I designed the PCB to fit nicely into off-the-shelf HackRF enclosures. I've now assembled a prototype, verified that it works and written the necessary HackRF firmware and host tools code to support the clock converter circuit.

Clock converter board mounted onto the HackRF.

I installed the clock converter into my HackRF as I described in my previous post. I cut the PCB trace on the HackRF that connects the center pin of the CLKIN SMA connector and the pin 2 of the P22 header. I then soldered three thin wires between the SMA connector and the input on the clock converter board. Two outer wires are ground and the center wire carries the 10 MHz signal. They are quite short. I could use a short coax for this, but wires were simpler and I think that the impedance mismatch of this length won't matter much at 10 MHz.

HackRF with the clock converter modification installed.

I've put a footprint for an extra edge-mount SMA connector on the clock converter board. This way it can be used without any destructive modifications to the HackRF. However cutting the trace makes it possible to use the existing connector for connecting the HackRF to an external reference, same as before the modification. This way the modified HackRF fits into cheap off-the-shelf enclosures that provide some extra vertical space above the base PCB. The original molded plastic enclosure is too low unfortunately.

HackRF mounted in a metal enclosure.

The LTC6957 chip on the clock converter is turned on and configured through spare GPIOs on the HackRF's ARM CPU. It is disabled by default using some pull ups. Hence the HackRF should work as before if the converter board is plugged in but the firmware doesn't know about it. To actually use it, a patched firmware must be uploaded to the HackRF's MCU.

The firmware modifications are largely just boiler plate code that is needed to toggle GPIO pins based on requests over USB. Most of the new code is in clock_conv.c file.

The original README has instructions on how to build and upload the firmware. I didn't have any problems with that on a stock Debian Buster system. Remember to reset the MCU after uploading new firmware using hackrf_spiflash -R.

The only thing that was slightly confusing was the firmware version string that is reported by hackrf_info. The version string is made automatically from the current git tag, or commit SHA1 if tag doesn't exist. However, it only seems to get refreshed when making a new build directory with cmake, not when merely running the build with make.

For the host tools side of things, I patched the new hackrf_clock tool. I added two new command-line arguments: --clkin can be used to enable or disable the LTC6957 and hence the CLKIN input. --clkin-filt can be used to adjust the LTC6957 input filter bandwidth.

You can verify that the HackRF's PLL has locked onto the external reference using hackrf_debug as described in the wiki:

external reference disabled
$ hackrf_clock --clkin 0
$ hackrf_debug --si5351c -n 0 -r
[ 0] -> 0x51

external reference enabled
$ hackrf_clock --clkin 1
$ hackrf_debug --si5351c -n 0 -r
[ 0] -> 0x01

I will post some more detailed measurements of the performance of the modified HackRF later. For now, the simplest way to see the effect of the external clock is to check the frequency offset between HackRF and another device. Here are two screenshots of HackRF Spectrum Analyzer. In both cases I had the antenna input of the HackRF connected to ERASynth Micro via a coaxial cable and some attenuators. ERASynth Micro was set to output a 2420.000 MHz signal. Also, the REF OUT of ERASynth Micro was connected to CLKIN on the HackRF:

Spectrum of a 2.420 GHz signal with CLKIN disabled.

This is with the CLKIN disabled (--clkin 0). The signal appears on the spectrum display with an approximately 22 kHz offset, since the ERASynth Micro and the HackRF use their internal quartz references which have slightly different frequency offsets.

Spectrum of a 2.420 GHz signal with CLKIN enabled.

This is with the CLKIN enabled (--clkin 1). Now the signal appears exactly at 2420.000 MHz since both devices are synchronized to the common 10 MHz reference (in this case, the TCXO in the ERASynth Micro). Of course, that doesn't mean that the signal is really exactly at 2420.000 MHz, just that both devices now exactly agree on what 2420.000 MHz is.

One interesting thing to note is that the lower screenshot also shows a slightly increased level of phase noise around the signal peak. As far as I can see, this is not due to the clock converter board. Even when CLKIN is used on an unmodified HackRF, received signals seem to exhibit slightly increased phase noise compared to when the internal quartz oscillator is used. I also tried this with a different 10 MHz source, so it's not due to ERASynth Micro either.

I didn't investigate this further. It might be that all my 10 MHz sources are noisy. Another possible cause could be different settings in HackRF's SI5351C. The SI5351C uses a PLL to convert either 25 MHz from the internal quartz or 10 MHz from the CLKIN into a 800 MHz clock. This 800 MHz signal is then used to generate all other clock signals in the HackRF. It might be that the higher PLL divider value (80 versus 32) contributes to this effect.

If you want to modify your HackRF like this, you can find the hardware design files in my hackrf-clock-conv GitHub repository. The modified firmware can be found in my fork of the HackRF repository. If you don't want to bother with making and soldering the PCB yourself, I'm also still collecting interest for a small production run of these boards. Send me an email if you are interested.

Posted by Tomaž | Categories: Analog | Comments »

HackRF clock converter

06.06.2021 10:24

HackRF can use an external 10 MHz reference clock instead of the built-in crystal oscillator. The CLKIN input accepts a DC coupled, CMOS-level, 3.3V square wave signal since it's connected directly to the digital input pin on the SI5351C PLL chip. I want to run my HackRF from the 10 MHz reference signal generated by my ERASynth Micro. Unfortunately, the TCXO output from the ERASynth Micro is an AC coupled, sinewave-ish signal and hence not directly compatible with the HackRF's CLKIN. While I've seen reports that sine wave signals on CLKIN also tend to work, I wanted to make a proper interface that didn't drive the SI5351 input outside of its rated signal levels.

HackRF CLKIN input line highlighted on the schematic.

In the future I might also want to synchronize the HackRF to other clock sources and I think a DC coupled, CMOS-level output is quite rare on instruments. Hence modifying the HackRF to accept a wider range of signals on the CLKIN connector seems useful to me.

I very much copied the idea for the circuit design from the Osmocom project's osmo-clock-conv. osmo-clock-conv is a stand-alone board that uses an Analog Devices LTC6957 clock buffer to convert a wide range of clock signals into a CMOS-level square wave. The LTC6957 is a specialized chip for this purpose that introduces very little additional phase noise and jitter into the signal during conversion. It should perform much better than, for example, a diode and a Schmitt trigger "self-biasing clock squarer" circuit with a similar function in the osmo-clock-gen.

I could have just used osmo-clock-conv board directly, or in fact I could just order the LTC6957 evaluation board and connect it via a coax to CLKIN. However I felt like making a more elegant solution that would be more tightly integrated with the HackRF. HackRF offers quite a lot of possibilities through various extension headers on its circuit board. The header P22 is connected to CLKIN and can be used to add add a custom circuit that supplies the reference clock signal. Adding a small TCXO board to P22 is quite popular and there are HackRF enclosures readily available that leave enough space for the TCXO mod. Hence adding a small clock converter circuit in place of the TCXO should be relatively straightforward and I could get a nice enclosure off-the-shelf that would nicely fit my modified HackRF.

3D render of the HackRF clock converter circuit board.

The circuit required to support the LTC6957 is quite minimal, so it wasn't hard to cram it all into a small two-layer board that will sit in the corner between P22 and P20 headers. Compared to the typical TCXO mod that only mounts onto the P22 I decided to also use the P20 header. This both makes it a bit more mechanically stable as well as gives me access to some unused GPIO lines on the HackRF's LPC4320 CPU.

I designed the input circuit to be 50 Ω terminated and hence work best with 50 Ω sources. The input is AC coupled and should work with AC or DC coupled sources. The converter should work with square wave signals with amplitudes between 0.8 V and 8 V peak-to-peak (when measured without a 50 Ω load) and sine wave signals with levels between -4 dBm and +16 dBm.

The LTC6957 has some digital inputs that affect its operation. This includes setting filter bandwidth (useful for adjusting for a sine wave or a square wave input) and turning the clock conversion on and off. osmo-clock-conv uses jumpers to configure those, but since I had GPIO lines available I simply used those. This makes the LTC6957 configurable from software. I also wanted to make sure I can power down the LTC6957 on request - LTC6957 with a floating input will likely produce a random clock signal and I don't want the SI5351 to lock onto that if I leave CLKIN unconnected. With the LTC6957 output disabled, the SI5351 should automatically switch back to its own crystal oscillator.

The LTC6957 has two identical outputs. The second one isn't used on the board, but I wired it to an AUX header in case it later turns out to be useful.

Position of the clock converter board on the HackRF.

The only hairy part of this design is the fact that the HackRF offers no clean way for an extension board to sit between CLKIN and the SI5351 clock input. The P22 header only allows a board to be connected in parallel to the clock line (see the schematic at the top of the post). There is also no series element on the clock line that can be desoldered to isolate the CLKIN from the SI5351.

What I plan to do is cut the trace on the HackRF PCB going from the CLKIN connector to the SI5351 right before it connects to the P22 header. I then plan to use a short piece of coax, or simply a pair of thin wires, to connect the original CLKIN SMA connector to the input of my clock converter board. This way the external clock signal will enter through the original CLKIN connector, go through a wire jumper to the clock converter board. After conversion the signal will then go back onto the HackRF board through P22.

I also left a footprint for an edge-mount SMA connector on the clock converter board. This makes it possible to use it without modifying the HackRF PCB by having a separate SMA connector for the clock converter input. I probably won't be using that since the additional connector will not fit in existing HackRF enclosures.

I'm currently waiting for the PCBs, which should arrive any day now. I was lucky to get what appears to be the last two LTC6957-3 chips on the market, so I should be able to assemble the board and test its design shortly. I also still have to write the software. Unfortunately, the HackRF firmware doesn't provide a general way of controlling the spare GPIOs so I will have to modify and recompile it. I did some quick tests and I don't think that will be much of a problem. The latest firmware release also introduces a new hackrf_clock utility and I'm hoping I can integrate with that.

I'll be publishing the designs and the firmware patch after I verify that it works as intended. If you're also interested in modifying your HackRF like this, please drop me a mail. I might do a small production run of the clock converter board after the current component shortage passes if I see enough interest.

Posted by Tomaž | Categories: Analog | Comments »