Firmware Design - dawsonjon/OpenXcvr GitHub Wiki
Firmware Design
The FPGA firmware consists of 2 main parts. The RF rate section works at a sample rate of 300MS/s with a clock speed of 150MHz, and the audio rate section works at a sampling rate of 100KS/s and a clock speed of 50MHz.
In the RF rate section, two samples must be processed in each clock cycle. In general, this is achieved by duplicating logic. This section includes a Numerically Controlled Oscillator (NCO) and the transmitter modulator.
In the audio rate section, things are a bit more relaxed, we have up to 500 clock cycles to generate each sample. The audio section includes the TX modulator, RX demodulator, RX AGC, DC removal, and digital filter which is used in both the transmit and receive paths.
Receiver
Numerically Controlled Oscillator
A 32-bit phase counter forms the basis of the NCO. At 300MS/s this gives a frequency resolution of ~0.07 Hz. Normally, an NCO would be a simple counter representing the phase, each clock cycle the change in phase (better known as the frequency) is added to the phase. If the frequency value is large, the phase counter overflows quickly giving a high frequency. If the frequency value is small the phase counter takes a long time to overflow and the frequency is low.
In this system, we need to generate 2 samples per clock cycle. To achieve this we add twice the phase to the counter each clock cycle. Even-numbered samples are then derived directly from the counter, and odd samples are derived from the phase counter added to the frequency. Thus in cycle 0, the samples are 0 and 1x frequency, in cycle 1 the outputs are 2x frequency and 3x frequency, and so on. The NCO can only update the phase once per clock cycle, this results in jitter of 3.333ns, but over a long period the average frequency averages out to the programmed value precisely.
The I and Q outputs supplying the Quadrature Sampling Mixer (QSD) must be 90 degrees out of phase, a phase delayed version of the phase accumulator is generated by adding a 90 degree offset. The I and Q square wave outputs are generated by tapping the most significant bits from the accumulator and phase delayed accumulator. This is equivalent to a phase < 0
function.
Downconverter
The I and Q outputs from the PCM1802 ADC are received at a sample rate of approximately 100kHz. The receiver hardware does not pass signals at DC, and in any case, self-mixing of the local oscillator and other sources of noise make it desirable to use a small Intermediate Frequency (IF) within the bandwidth of the ADC. The IF signal is then down-converted to DC digitally using a complex mixer. When receiving, therefore, the frequency of the NCO is set to the frequency of the received signal minus the IF frequency. The IF frequency is chosen to be exactly one-quarter of the sampling frequency (FS/4). At this frequency, the I and Q components of the IF oscillator are either 0, 1, or -1. This greatly simplifies the design of the mixer which can then be built without using multipliers.
Digital Filter
To simplify the design of the filter, we can achieve the effect of an adjustable bandwidth filter by varying the sample rate in the Audio ADC. The Audio ADC includes oversampling and antialiasing, we can, therefore, rely on the ADC to strongly attenuate signals that fall outside the first Nyquist frequency range. The sample rate can simply be changed by adjusting the clock divide ratio in the prescaler supplying the ADC clock.
The filter uses a Finite Impulse Response (FIR) design. The filter uses two memories, one implements a complex circular buffer for the filter data, and the other implements a complex circular buffer for the filter kernel. A 127 pole filter is used to give a steep transition from the stopband to the passband. Each output sample is generated by multiplying each of the previous 127 input samples by the corresponding value in the filter kernel. All 127 products are accumulated into a single sum. In the audio section (assuming a maximum sample rate of 100kHz which is the maximum the ADC supports), 500 clock cycles are available to calculate each sample, so it is possible to calculate and accumulate 1 of the 127 products each clock cycle.
To provide an even greater range of filter bandwidths, the filter allows 4 possible frequency responses to be selected. This is achieved by increasing the size of the filter kernel RAM so that 4 filter kernels can be accommodated. The 2 MSBs of the kernel RAM address select between the available filter kernels.
MODE | Fs (kHz) | Filter Bandwidth (normalised) | Filter Bandwidth (kHz) |
---|---|---|---|
AM | 24.4 | Fs/4 | ~+/-3 |
NFM | 39.0 | Fs/4 | ~+/-5 |
FM | 65.2 | Fs/4 | ~+/-8 |
USB | 24.4 | Fs/8 | ~+/-1.5 |
LSB | 24.4 | Fs/8 | ~+/-1.5 |
CW | 24.4 | Fs/80 | ~+/-0.15 (300Hz) |
Demodulator
The demodulator converts the I and Q outputs of the filter into a single real audio output to supply the speaker.
To demodulate AM and FM signals, the I and Q components are first converted into a magnitude and phase representation. An efficient way to implement this is by using the CORDIC algorithm. The magnitude output of the CORDIC provides a demodulated AM signal which still contains a large DC component. The phase output is used to demodulate FM signals. Since the frequency of a signal is the change in phase, the frequency can be calculated by subtracting the phase of the previous sample from the phase of the current signal.
In single-sideband mode, the NCO is set to the centre of the desired sideband, while the width of the filter is sized to allow only the desired sideband through. This means that half of the frequencies are negative and half are positive. The frequencies need to be shifted up or down (depending on whether we are working with the upper or lower sideband) to leave a signal which contains all negative or all positive frequencies. After the frequency shift, the imaginary part of the signal is discarded (which effectively mirrors the sideband about DC). This leaves a real-only signal that can be supplied to the microphone. In SSB mode, the sampling frequency and decimation are chosen so that the up or downshift can be realised using an FS/4 frequency shift. We have already seen that this frequency shift is trivial to implement. In this case, however, since we are discarding the imaginary component, there is no need for the frequency shifter to generate it in the first place.
In CW mode, the filter is chosen to give a very narrow bandwidth around DC. This leaves a sub-audio frequency signal. To move this signal into the audio range another frequency shift is needed. In this case, Fs/8 gives a ~750Hz which is a reasonable sidetone frequency. This is more complex than an Fs/4 tone, a lookup table and multiplier are used. One improvement to consider would be to implement an NCO to drive the lookup table. This would allow a programmable sidetone frequency.
DC removal
A demodulated AM signal contains a large DC component which needs to be removed. The DC removal block uses a first-order IIR low-pass filter. In this design, filter coefficients are chosen so that the multiplications can be implemented with a single shift. This eliminates the need for multipliers. The low-pass filter provides an estimate of the DC present in the signal. The DC is removed by simply subtracting this value from the signal.
Automatic Gain Control (AGC)
The loudness of an AM or SSB signal is dependent on the strength of the received signal. Very weak signals are tiny compared to strong signals. The amplitude of FM signals is dependent not on the strength of the signal, but the frequency deviation. Thus wideband FM signals will sound louder than narrowband FM signals. In all cases, the AGC scales the output to give a similar loudness regardless of the signal strength or bandwidth.
This can be a little tricky, in speech, there are gaps between words. If the AGC were to react too quickly, then the gain would be adjusted to amplify the noise during the gaps. Conversely, if the AGC reacts too slowly, then sudden increases in volume will cause the output to saturate. The UHSDR project has a good description, and the OpenXCVR design is based on similar principles.
The first stage of the AGC is to estimate the average magnitude of the signal. This is achieved using a leaky max hold circuit. When the input signal is larger than the magnitude estimate, the circuit reacts by quickly increasing the magnitude estimate (attack). When the input is smaller than the magnitude estimate waits for a period (the hang period) before responding. After the hang period has expired, the circuit responds by slowly reducing the magnitude estimate (decay). The attack period is always quite fast, but the hang and delay periods are programmable and are controlled by the AGC rate setting. The diagram shows, how the magnitude estimate responds to a changing input magnitude.
Having estimated the magnitude, the gain is calculated by dividing the desired magnitude by the estimated magnitude. We have plenty of clock cycles to calculate this so a slow (and small) non-restoring divide algorithm is used to calculate 1 bit of the gain per clock cycle.
Having calculated the gain, we simply multiply the signal by the gain to give an appropriately scaled output. on those occasions where the magnitude of the signal increases rapidly and the AGC does not have time to react, we need to prevent the signal from overflowing. This is achieved using a combination of soft and hard clipping. Signals above the soft clipping threshold are gradually reduced in size, signals above the hard clipping limit are clamped to the limit value.
Transmitter
Modulator
The modulator converts a signal from the microphone and converts it into a baseband signal feeding the RF section. The RF section of the firmware requires a signal in polar (magnitude and phase) rather than rectangular (I and Q) format.
AM and FM modulation are reasonably simple. In AM modulation, the microphone signal drives the magnitude amplifier directly, while the phase is held at zero. FM modulation is only slightly more complicated. In this mode, the phase difference between samples (AKA frequency) is taken from the microphone. In other words, the microphone signal is integrated by adding each microphone to an accumulator. The accumulator is the phase output. In FM mode, the amplitude is held at the maximum value.
While AM and FM modulation only affects either the phase or magnitude of the signal, SSB modulation requires both the phase and frequency components to be modulated. The SSB signal is first generated in rectangular representation and then converted to phase and magnitude representation using a CORDIC component. The microphone input consists only of real samples. The I component is taken directly from the microphone input while the Q component is set to zero. Since the imaginary part of the signal is zero, it follows that the frequency spectrum is symmetrical and includes both positive and negative frequency components.
The positive frequency component is the upper sideband, and the negative frequency component is the lower sideband. One method of achieving this is to use a Hilbert transform. An ideal Hilbert transform is a filter that passes all positive frequency components but removes all negative ones.
A reasonable approximation of a Hilbert transform can be made using an FIR filter. This approach was used in earlier versions of this project. The main downside of this approach is that the filter has an asymmetrical frequency response. This means that the filter kernel has real and imaginary components. The filter must, therefore, be constructed from complex multipliers and adders. This requires twice as many multiplications and additions as a filter with a symmetrical response.
A more efficient method of generating a SSB signal is to up-shift the frequency by Fs/4 using a complex multiplier, filter the signal using a symmetrical half-band filter retaining only the negative frequency components. The frequency is then down-shifted by Fs/4 leaving only the lower sideband.
Fs/4 is chosen because it can be implemented efficiently. A complex sine wave with a frequency of Fs/4 consists of only 0,1 and -1. Multiplication by 0, 1, or -1 can be implemented using trivial arithmetic operations.
Choosing a half-band filter -Fs/4 to Fs/4 allows further improvements in efficiency. The kernel of a half-band filter is symmetrical, potentially this can approximately halve the number of multiplication operations, or halve the number of kernel values that need to be stored. In addition to this about half of the kernel values are 0, again approximately halving the number of multiplications. Overall, this filtering operation reduces the number of multiplications needed by an approximate factor of 8.
The structure as shown leaves the lower sideband part of the signal. An upper sideband signal could be generated by first down-shifting the frequency, and then up-shifting. Since the upper and lower sidebands are mirror images, an easier way to switch between upper and lower sidebands is to change the direction of rotation at the output of the modulator by switching the I and Q components for example.
NCO
In the transmit system, the NCO works slightly differently. The Transmitter uses a polar phase/magnitude representation. The phase component of the signal modulates the phase of the NCO. The I component of the NCO forms the RF output to the RF transmitter. The phase modulation is achieved by adding an additional phase offset to the phase accumulator. In transmit mode, the duty cycle of the RF output can also be controlled, this gives some level of control over the output voltage and can be used to achieve a better between the RF amplifier and the load.
GPS Frequency Calibration
GPS modules can be obtained very cheaply, and provide an extremely accurate frequency reference. OpenXCVR can use the 1 pulse per second (1PPS) output from a GPS module to accurately calibrate the frequency. The firmware counts (using a 150MHz clock) the number of clock cycles between rising edges of the 1PPS input. If the oscillator were perfectly accurate we would expect 150,000,000 clocks. If the number is greater or smaller than this, the control software can work out how much faster or slower the oscillator is running. The software can then apply a correction to the frequency setting in the NCO.
Self Test
One objective of this project is to enable the transceiver to be built with minimal test equipment. It is unlikely that a hobbyist builder will be able to get hold of a spectrum/network analyser. While it is possible to measure the frequency response of a filter using more basic equipment, this can be a time consuming and difficult task.
To simplify the process, OpenXCVR is capable of generating a test tone in the receiver's passband. With simple software, it is then possible to use the OpenXCVR as a "poor man's" network analyser. The following measurements of the band-pass filter response were made using the prototype.