Electronics

Phase Noise in a 10 MHz Amplifier

Published 5 Nov 2026. By Jakob Kastelic.

These are some notes I’ve taken when creating a circuit that takes a 10 MHz sine-wave input and outputs several copies of the same, with a minimum of added phase noise or distortion. First, select a topology and simulate it. Then, build the circuit and measure the key specs: noise, crosstalk, distortion.

Basic Idea

The goal is simple, 10 MHz in, 10 MHz out. Many approaches have been explored:

Of these, I have chosen the version that I find easiest to explain to myself: an inverting buffer drives several non-inverting output drivers. This is shown in the image below.

A straightforward transient LTspice simulation (.tran 0 1.5u 0.5u 25p) shows that the output amplitude is 1Vrms. In other words, the circuit should work as shown.

In the simulation I used the spice model for the LMH6609 op-amp provided by Texas Instruments (original model by National Semiconductor). It works just fine in LTspice except for commenting out a comment. Apparently PSPICE supports the / symbol as comment in addition to the * used by LTspice.

Crosstalk and Pulling

A key spec on any multi-channel instrument is crosstalk: if a signal is injected in one output, does it show up in the other output?

Notice the V4 signal source in the LTspice schematic shown above. If we disable the main signal source V3 to AC 0 and enable V4 as AC 1, then an AC simulation (.ac dec 200 1k 1G) shows about 10μV of crosstalk at out1. Including a rough estimate for layout-dependent capacitive coupling between two outputs directly (e.g. 10fF at C7), this rises to 17μV, or about -95 dB.

Assuming the op-amp model is accurate, we can use this result to estimate the phase pulling between the two outputs. Assume one of the outputs is connected to an unterminated cable such that the full signal strength—all 1Vrms or +13dBm of it—comes back in quadrature. The peak amplitude is 2.82 × 17 μV = 48μV.

Adding a small phasor a at angle φ to a carrier A gives a resultant phase shift Δφ ≈ (a/A)·sin φ. The angle φ is set by the cable’s round-trip delay plus the coupling path’s fixed phase—and since the user can present any length, the worst case is φ = 90° (quadrature), where the interferer is pure phase: Δφ = 48 µV / 1.38 V = 35 µrad.

At 10MHz one period is 100ns spanning 2π rad, so Δt = Δφ/(2πf) = 34e-6 / (6.28e7) ≈ 0.55 ps. The reflection on Ch-2 will cause Ch-1 to move in phase by less than a picosecond. Pretty good!

Additive Phase Noise

There are many mechanisms that contribute to the phase noise at our outputs. Let us immediately ignore the noise of the 10 MHz source and instead focus on what adds to the source’s phase noise.

At large offsets away from carrier, the noise floor is set by op-amp voltage noise, resistor Johnson noise, and current noise. The same LTspice model from above (remember to disable V4 and re-enable V3!) can be used to calculate the voltage noise density at the output, by means of a .noise V(out1) V3 lin 401 9.9Meg 10.1Meg simulation directive. At 10 MHz, it reads 9.7 nV/rtHz. Relative to the 1 Vrms output amplitude, this is a phase noise floor of

L = 20 log10(9.7e-9 / 1.00) − 3.01 = −163 dBc/Hz.

Note the 3 dB subtracted, due to the fact that the noise decomposes into components in phase and in quadrature with the carrier phasor. The in-phase part wiggles the amplitude; the quadrature part wiggles the phase. For additive noise these are equal in power, so exactly half the noise power becomes phase modulation.

Convective Air Currents

Any air moving across the board, whether forced or natural convection, can cause the temperature of PCB components to fluctuate. Ferrite inductors, such as the 1.5 μH seen in our tank circuit, might have as much as 500 ppm/K of temperature coefficient. We can step the inductance value in the LTspice simulation to find about 0.45° of phase change due to 1% change in inductance.

Putting the numbers together, the phase sensitivity is 3.9e-4 rad/K, or, in time units, about 6.3 ps/K. If we estimate the inductors temperature noise at 1 Hz to be about 1.5 mK/rtHz, then the phase noise would be

L = 20 log10(3.9e-4 * 1.5e-3) - 3.01 = -127 dBc @ 1 Hz offset.

That’s a significant amount of phase noise, but easily fixed by reducing the air currents or increasing thermal insulation. The inductor temperature changes are heavily low-pass filtered by means of the part’s thermal inertia. In other words, above the thermal pole the response falls as f^{-2}, so lowering the corner buys 20 dB per decade of shift.

Microphonics

Any sound or mechanical vibration modulates the electrical characteristics of the circuit. Non-NP0 capacitors are particularly affected, so it’s important to verify there’s none in the critical signal path.

Inductors are also prone to microphonics, via magnetostrictive modulation of inductance. The datasheet will most likely not specify it, so instead we take a wild guess, say 1.5e-4 inductance change per “g” of acceleration.

Reusing the 0.45° per 1% coefficient from the previous section, the phase sensitivity is 1.2e-4 rad/g, or about 1.9 ps/g. A fan blade-pass tone at 120 Hz depositing 0.01 g peak gives a peak phase deviation of 1.2 μrad, and a sinusoidal modulation of peak deviation Δφ produces sidebands at

20 log10(1.2e-6 / 2) = -124 dBc.
Theology

Seeing God and the Pretentiousness of Purity

Published 5 Nov 2026. By Jakob Kastelic.

Disclaimer: I’m not a theologian, proceed at your own risk.

An astute reader of the Notes on Cassian noticed a wild claim of mine, that “being dead to the wold” means afterlife, when examining Cassian’s thoughts on divine contemplation and “seeing God”, in Conf. 1, Ch. XV. Let’s take a closer look.

I don’t think you can “see God”, no matter how “pure” or “dead to the world” you are. To be fair, Cassian only makes the converse claim: if, any carnal affections survive in you, then you cannot lastingly contemplate God. Am I going too far by assuming Cassian implied the reverse claim: you could lastingly contemplate God if only no carnal affections survive in you?

A parallel set of claims arises from his scriptural quote. Exodus states that if you see God, then you cannot live. Cassian elaborates: you cannot live to “this world and to earthly affection” (mundo huic affectibusque terrenis). The implied reverse statement in this case is, if you’re “dead to the world”, then you may be able to see God. Again, did Cassian intend this implication or am I reading into it too far?

There’s only two options, either he did mean it or he did not. If he did not mean it, then we could discuss whether carnal affections (carnalis affectus) prevent you from contemplating God “lastingly” (perpetuo), or from seeing God. Since I’m not at this point interested in studying perpetuity, i.e., eternity or afterlife, so let’s pass on to the other option: Cassian did mean the “reversed claim”: purify your heart and you’ll be able to see God now and forever.

Agents

Same Input, Different Outputs

Published 4 Nov 2026. By Jakob Kastelic.

Some time ago, models used to take a widely variable time to complete a task, ususally between ten seconds and ten minutes. This kept me glued to the screen, mostly just waiting for it to be done. Then I got the idea to tell Claude that when it’s done, it should print a big “DONE” banner so I can see it from the other side of the room. I ended up collecting several different versions of this banner as they came out of the model.

██████   ██████  ███    ██ ███████
██   ██ ██    ██ ████   ██ ██
██   ██ ██    ██ ██ ██  ██ █████
██   ██ ██    ██ ██  ██ ██ ██
██████   ██████  ██   ████ ███████
█████   ██████  ███    ██ ███████
██   ██ ██    ██ ██    ██ ██
██   ██ ██    ██ ██ ██  ██ █████
██   ██ ██    ██ ██  ██ ██ ██
█████   ██████  ██   ████ ███████
█████   ██████  ███    ██ ███████
█   ██ ██    ██ ██    ██ ██
█   ██ ██    ██ ██ ██  ██ █████
█   ██ ██    ██ ██  ██ ██ ██
████   ██████  ██   ████ ███████
█████   ██████  ███    ██ ███████
██   ██ ██    ██ ███    ██ ██
██   ██ ██    ██ ██ ██  ██ █████
██   ██ ██    ██ ██  ██ ██ ██
█████   ██████  ██   ████ ███████
█████   ██████  ███    ██ ███████
██   ██ ██    ██ ██    ██ ██
██   ██ ██    ██ ██ ██  ██ █████
██   ██ ██    ██ ██  ██ ██ ██
█████   ██████  ██   ████ ███████
█████    ██████   █    █   █████
█    █  █      █  ██   █   █
█    █  █      █  █ █  █   █████
█    █  █      █  █ █  █   █████
█    █  █      █  █  █ █   █
█████    ██████   █    █   █████
█████    ██████   █    █   █████
█    █  █      █  ██   █   █
█    █  █      █  █ █  █   █████
█    █  █      █  █  █ █   █
█    █  █      █  █   ██   █
█████    ██████   █    █   █████
█████   █████  █   █ █████
█   █  █   █  ██  █ █
█   █  █   █  █ █ █ ████
█   █  █   █  █  ██ █
█████   █████  █   █ █████
█████   ████  █   █ █████
█   █  █    █ ██  █ █
█   █  █    █ █ █ █ ███
█   █  █    █ █  ██ █
█████   ████  █   █ █████
████  ████  █   █ █████
█   █ █   █ ██  █ █
█   █ █   █ █ █ █ ███
█   █ █   █ █  ██ █
████  ████  █   █ █████
████  ████  █   █ █████
█  █  █  █  ██  █ █
█  █  █  █  █ █ █ ███
█  █  █  █  █  ██ █
████  ████  █   █ █████
███  ███  ██ █ █ ████
█ █  █ █  █ █ ██ █
█ █  █ █  █ █ ██ ███
█ █  █ █  █ █ █ █ █
███  ███  █ █ █ █ ████
DSP

Stream Data Into ADSP-2156

Published 3 Nov 2026, modified 5 Nov 2026. By Jakob Kastelic.

The ADSP-21569, as demonstrated on the EV-21569-SOM and EV-SOMCRR-EZLITE boards, appears to be optimized for streaming lots of audio channels. What if we instead need to stream fewer channels at faster sample rates? In this article, we will try out several possible pathways.

UART

The first step after “blink” works is to have a debug input/output and UART is always the easiest. Of course we already had to set it out previously to enable automated agentic code development and testing.

QSPI: From USB into DSP using FT4222

We can test mass data ingestion without any additional wiring via the QSPI interface, since the EZLITE board includes a USB-to-SPI adapter FT4222HQ-D-T. (Make sure to follow the QSPI setup instructions in the previous article to make sure that FT4222-as-master works.)

With DSP in slave mode, we can write a little test program that ingests the data using DMA into two buffers, “ping-ponging” between them: DMA writes into one buffer while we read from the other, and when the first one is full, DMA starts to write into the second one. If we process the data fast enough, this guarantees there’ll be no contention between the CPU and DMA without requiring any other synchronization.

In this case, all we are interested in is whether the data is received correctly. As a simple test, we can write a couple bytes and then read them out via UART, but then we cannot test the data transfer speed. Instead, we can tell the CPU to consume the data when DMA buffer fills up and calculate a running checksum (e.g., XOR all words into a single accumulator).

The data rates from USB into FT4222 and thence into the DSP are as shown in the table:

LanesSCKMbps actualMbps theoretical% peak
110 MHz4.41044 %
120 MHz5.82029 %
140 MHz6.84017 %
210 MHz16.12081 %
220 MHz27.14068 %
240 MHz40.78051 %
410 MHz27.14068 %
420 MHz41.18051 %
440 MHz53.916034 %

“Up to 53.8Mbps data transfer rate in SPI master with quad mode transfer” says the bullet point on FT4222 datasheet front page. Later on, in Table 4.1 on page 11, the “Max Throughput” is stated as 52.8Mbps. “It also depends on the USB bus transfer condition.”

The quad-lane theoretical maximum takes into account that at most 64K bytes can be transmitted at once, the clock rate is 40 MHz, and there’s an extra 6.65 ms (or is it 6.47 ms?) of library/USB overhead.

FT4222 Silicon bug: need 0x00 first byte

Using SPI2 in the 1-lane mode (regular four-wire SPI), the transfer works as expected. In Python, simply import ft4222 and then make use of the spiMaster_SingleWrite() function to write the data.

The dual and quad SPI modes, however, are more tricky. First of all, the spiMaster_SingleWrite() refuses to send data outside the single-lane mode. The library provides spiMaster_MultiReadWrite() which does transmit data but sometimes all but the first byte is transmitted incorrectly: the bit corresponding to D1 stays stuck at 0.

There’s a hint in the “User Guide for LibFT4222” (FTDI App Note AN_329), in a section on using the FT4222 in slave mode:

For some reasons, support lib will append a dummy byte (0x00) at the first byte automatically.

We’re using the FT4222 in master mode, but it seems that the library author knew something that the app note writer did not: the chip has a quirk, or perhaps an undocumented in-band command depending on the contents of the first byte transmitted.

For example, if the first word transmitted is 0x0d4416c4, then all subsequent data will be corrupted. However, many other first words do not trigger the bug (e.g. 0x00000000, 0xFFFFFFFF, 0xc8ad14e5).

The workaround is as indicated in the above quote: always send 0x00 as the first byte. Annoying, but irrelevant in this instance since all we care about is to measure what is the maximum reliable data rate.

I have not been able to find this bug documented either in the datasheet or in the Technical Note TN_161, “FT4222H Errata”.

QSPI out of DSP

Getting the data output of the DSP is just a little bit more tricky. We do not want to switch the FT4222 into slave mode, because then we need to physically move the S5 jumper on the EZLITE board, which would be annoying to automate. Moreover, the FT4222 only supports the single-bit data transfer in slave mode, while the master supports all three bit widths, both data directions.

GPIO loopback

Some of the tests in the future will require wiring SPI and SPORT ports between each other as “external loopback”. To verify wiring continuity, it is helpful to set up a GPIO example code that verifies which pins are connected to which pins.

On the EZLITE board, connector P13 breaks out the DAI pins that are used for the SPORT interface. Note that the pins’ presence on the board does not mean they are connected to anything! (They may be used with other SOM boards.)

P13 pinP13 signalNotes
7DAI0_PIN13absent both packages
9DAI0_PIN14absent both packages
19DAI0_PIN15absent both packages
21DAI0_PIN16absent both packages
31DAI0_PIN17absent both packages
33DAI0_PIN18absent both packages
2DAI1_PIN01
4DAI1_PIN02
6DAI1_PIN03
8DAI1_PIN04
10DAI1_PIN05
12DAI1_PIN06
14DAI1_PIN07
16DAI1_PIN08
18DAI1_PIN09
20DAI1_PIN10
22DAI1_PIN11absent 120-lead LQFP
24DAI1_PIN12absent 120-lead LQFP
26DAI1_PIN13absent both packages
28DAI1_PIN14absent both packages
30DAI1_PIN15absent both packages
32DAI1_PIN16absent both packages
34DAI1_PIN17absent both packages
36DAI1_PIN18absent both packages
38DAI1_PIN19
40DAI1_PIN20

On the P14 header, we get access to the I2C and two SPI ports. These are highly multiplexed. For example, the PA_06 and PA_07 are UART0_TX and UART0_RX, respectively.

P14 pinP14 signalP14 functionMultiplexed
25PA_14TWI2_SCLFn 0
27PA_15TWI2_SDAFn 0
2PA_06SPI0_CLKFn 0
4PA_07SPI0_MISOFn 0
6PA_08SPI0_MOSIFn 0
8PA_09SPI0_SSBInput Tap
10PB_05SPI0_SEL2*Fn 2
12PA_10SPI1_CLKFn 1
14PA_11SPI1_MISOFn 1
16PA_12SPI1_MOSIFn 1
18PA_13SPI1_SEL1*Fn 1
20PB_10SPI1_SEL2*Fn 1
Incoherent Thoughts

The Power of Unconscious Intentions

Published 2 Nov 2026. By Jakob Kastelic.

Consciously, I can only focus on one thing at a time, and hold only a few in working memory. But the unconscious part of the psyche can hold a tremendous amount of memories, skills, goals, and intentions.

When a lot needs to be done, it’s best to banish it all from the conscious mind and merely set unconscious intentions, then let things arise one by one as appropriate until the goal is achieved. Holding awareness of multiple tasks is like carrying ten full cups of tea: I’d get nowhere or spill them all.

By trusting your unconscious, you free your conscious attention for the one action in front of you.