Monday, February 13, 2017

An FPGA SDR HF Transceiver, Part 1 -- An Overview

 
(The final destination of this blog series)

Introduction:

This post is the first in a planned series of posts describing an FPGA SDR HF transceiver.

This series will describe both the FPGA internal logic and the external hardware used to create a fully functioning, stand-alone HF transceiver.  No PC is required to drive it (after the FPGA's configuration EEPROM has been programmed, of course).

Also, there is no DSP chip.  All signal processing (including modulation/demodulation) is done by the FPGA.

Audio and RF are digitized with Analog-to-Digital Converters (ADCs) and provide the digitized signal inputs for a single FPGA (Xilinx XC3S500E).  In turn, Digital-to-Analog Converters (DACs) convert the FPGA's digital outputs back to analog RF and Audio.


Dick Benson, W1QG, has designed this radio's FPGA logic using Simulink software (from The Mathworks, Inc, and it is this software which defines the software part of "SDR" in this design), based upon an earlier CW/SSB Transceiver design of his that used both an FPGA and a DSP (and which, if the link still works, is described here). 

This new design uses a single FPGA and no DSP.  In Dick's own words, enhancements to that earlier design include:

1)   Elimination of DC offset in the processing chain which causes a tone at the BFO freq. with very low RX input levels.
2)   Loadable Information (i.e. passband) Filters.
3)  Hang AGC.
4)  Read back of FPGA Version.  This has saved my butt more than once!
5)  TX Demodulated Signal Monitor.
6)  Loadable TX Audio EQ Filter. 
7)  Loadable RX Audio EQ Filter.
8)  AM Modulation and Demodulation.
9)  TX Audio Monitor:  Monitor, during transmit, how the TX Audio EQ Filter and the Information Filter affect the quality of the Transmit Audio signal.

(I also made a few enhancements to Dick's design to better suit my preferences (e.g. AGC operation), and I found and fixed a couple of bugs that had crept into his design.)

To get a taste of the design, let's first take a look the Hardware which makes up the radio's core.


Hardware Overview:

The radio's core consists of four ICs, three to convert between the analog and digital realms, and the fourth to perform all radio processing functions digitally (e.g. passband filtering, demodulation/modulation, AGC, etc).  These four ICs are:
  • A single Xilinx XC3S500E FPGA
  • An LTC2206CUK 16-bit, 80 MHz ADC
  • An AD9744 14-bit RF DAC
  • A TI PCM3008 Audio Codec
Here is a block diagram of the radio core:

(Click on image to enlarge)

(In the diagram above /OVLD is an "overload" signal, and it is used to inform the operator if signals are too high at (for example) the RF or Audio ADC inputs.)


To simplify the design, Dick and I use pre-existing development boards for both the FPGA and the ADC.

The FPGA board is Waveshare's Core3S500E development board (circa $30):

The LTC2206 ADC is installed upon an LTC DC918C-C development board.  It is available from Digikey, but note -- it is quite expensive!


Here's my version of this radio-core:


And here is Dick's breadboard, with additional bells and whistles:



How might this radio-core be incorporated into a transceiver design?  Here is one possibility:

(Click on image to enlarge)

Note that because the RF ADC is clocked at 80 MHz, incoming RF must be frequency-limited to 40 MHz or below.

Future posts will add further detail to both the Core and Transceiver hardware, including schematics.


A quick mention of hardware tools:

In addition to the usual suite of hardware test equipment, one needs a way to program the FPGA and some way to control it (for development and debug) via Dick's 4-wire serial Command Interface.

To program the FPGA I use Waveshare's Platform Cable USB:


And to control the radio I built a simplified Control Panel (using an Arduino Nano):


Dick's Control Panel is similar, but he uses a PIC processor on a PIC development board.  You can see both the board and the controls (the latter mounted on Plexiglas) on his radio breadboard, below:



Now let's take a quick look at the FPGA internal functions...


FPGA Functional Overview:

The FPGA contains both Receive and Transmit Functions, as well as other functions such as the Command Interface.  In short, there is quite a bit of functionality crammed into the single FPGA (in fact, its number of "occupied slices" stands at about 95% -- not much more can be squeezed in!)

Let's first look at the Receive side.  Here is a functional block diagram of the Receivers:

(Click on image to enlarge)

Notes on these receiver function blocks:
  • The digitized RF ADC signal comes into the FPGA as a "Real" (i.e. not Complex) 16-bit, two's complement value.
  • The High Frequency DDS down-converts this signal to an intermediate frequency in Complex (I/Q) format.  Note that the data, although down-converted, is still running at an 80 MHz clock rate.
  • The Decimation Filter filters and converts the Mixer data (running at at 80 MHz), down to data rate of 9,765.625 Hz (a Decimation ratio of 8192).
  • CW and SSB are demodulated with a Weaver Demodulator, which consists, in part, of the Information Filter and the Low Frequency DDS and Mixers.  The Weaver Modulator and Demodulator are particularly straight-forward to implement in an FPGA.  
  • The Information Filter is a low-pass filter than, when combined with the Weaver Demodulator (or Modulator) represents a passband filter whose passband is twice the bandwidth of the low-pass filter.  It also determines the AM signal's audio bandwidth -- each sideband of the AM signal will have a bandwidth equal to the passband of the low-pass filter.  This filter is a 128-tap symmetric FIR whose 64 coefficients can be loaded via the radio core's Command Interface (e.g. from my Arduino or from Dick's PIC), thus, the user can invoke any number of custom passbands.
  • The AM Demodulator consists of an Envelope Detector.  Note that for AM Demodulation the IF frequency is 0 Hz and the Weaver Demodulator is not used.
  • The AGC block amplifies the converted signal so that its peak amplitude is essentially between +/- 1.0 (well, actually +0.9999../-1.0), as represented by 16-bit signed, two's complement values, whose decimal point is at bit 15.  This AGC block has two values of decay, Fast and Slow, and it has a programmable "hang" (more details on AGC will follow in a later post).
  • The RX EQ filter can serve a variety of purposes.  It can filter out low level "hiss" noise (quantization noise amplified by the AGC when it boosts low-level signals).  It can remove key-clicks from the local side-tone signal.  It can be used as an EQ filter, etc.
  • Audio volume can be controlled digitally (attenuated) with the RX Level value.
  • The 16-bit two's complement digital audio (representing max values of +/-1.0) is converted into a serial stream for the PCM3008 Audio Codec.
  • Note that during Transmit, this codec will also convert the TX Monitor Audio signal to an analog output, thus allowing the operator to monitor how the transmitter's EQ and Information Filter (i.e. passband filter) affect the quality of the transmitted audio.

Now let's look at the Transmit side.  Here is a block diagram of the Transmitter:

(Click on image to enlarge)

Notes on these transmitter function blocks:
  • The serial data from the PCM3008 Audio codec (in 16-bit, two's complement format) is first converted to 16-bit parallel data.  Because the codec is stereo, this data can actually be from two sources: either a Mic or from, for example, a Line-Level audio source).
  • This data then passes through an TX EQ block to transform its spectrum, should that be required.  The EQ's filter coefficients can be downloaded from the Control Panel via the FPGA's Command Interface.
  • The AGC block amplifies the audio and ensures that its max level is no greater than +/- 1.0 (when represented as a signed two-compliment 16-bit number whose decimal point is at bit 15).
  • At this point AM audio can be generated by adding a DC offset (Carrier Level) to the Audio signal.
  • The AM or SSB (or CW) audio is then attenuated via the TX Level value.  It is this level that controls TX output power.
  • The Audio then drives a Weaver Modulator, consisting, in part, of the DDS Low Frequency LO, two mixers (to create a Complex signal), and the Information Filter (which determines the bandwidth of the transmitted audio). Note that in AM mode the DDS Low Frequency LO is set to 0 Hz.
  • The Interpolation Filter converts (by interpolation) the Weaver Modulator's Complex (I/Q) output from its 9,765.625 Hz Audio sample rate to a complex signal whose sample rate is 80 MHz.
  • The complex output of the Interpolation filter is then mixed with the DDS High Frequency LO and up-converted to the desired RF frequency, creating a real, 14-bit, two's complement signal at an 80 MHz clock rate for the AD9744 DAC.  It is this High Frequency LO (and the summing stage following it) that, in CW and SSB modes, completes the Weaver Modulator.
  • TX Monitor Audio allows the operator, during transmit, to monitor how the TX EQ and Information Filter functions affect the quality of the transmitted audio.

To incorporate both the transmitter and receiver into a single FPGA, some sharing of functions is required.  The TX and RX functions share the following functional blocks:
  • High Frequency DDS oscillator and I/Q mixers.
  • Low Frequency DDS oscillator and I/Q mixers.
  • AGC (increase RX signal level, and level the Mic signal).
The other main function block within the FPGA is the Command Interface block, which allows the FPGA to be controlled by an external processor, such as a PIC or Arduino.  I will discuss this block in a future post.

Now, let's take a look at what software tools are needed for FPGA development...


FPGA Development Software Overview:

As I mentioned above, Dick developed the FPGA's logic using The MathWork's Simulink program.

Simulink not only simplifies the design process by allowing the designer to create a design using functional blocks (much like a schematic) in lieu of typing in a design with either VHDL or Verilog, but it also provides a powerful ability to simulate a design prior to implementation.  Ideas can be tested via simulation, and, if one has MatLab's "Fixed-Point Designer," then the actual effects of fixed-point arithmetic can be verified in a designs.

However, to create a design that can be downloaded into a Xilinx FPGA, you will need to use Xilinx "blocks" in the Simulink model, and these blocks are contained within the Xilinx "Blockset." This blockset is only available with the Xilinx System Generator software. Below is Xilinx's description of the System Generator:
System Generator is a DSP design tool from Xilinx that enables the use of the MathWorks model-based Simulink® design environment for FPGA design. Previous experience with Xilinx FPGAs or RTL design methodologies are not required when using System Generator. Designs are captured in the DSP friendly Simulink modeling environment using a Xilinx specific blockset. The System Generator design can then be imported into a Vivado IDE project using the IP Catalog.
Dick has the tools and did the majority of the design, and then we incorporated my changes into a revision for me.
An important caveat!  To create an FPGA using Simulink and the Xilinx System Generator, the version of MatLab (and Simulink) must be compatible with the version of Xilinx System Generator.  If you do not already have the tools and are considering their purchase, verify first their compatibility!
If you already have a copy of Xilinx System Generator, you can check which Matlab versions it is compatible with here.  If you have a version of Matlab and it is not compatible with your version of Xilinx System Generator, you might be able to download a compatible Matlab version, as long as it is an earlier Matlab version.  From Matlab Answers:
Visit http://www.mathworks.com/mwaccount and click on your license. Then over on the right hand side of the page that comes up, click on Download. That will bring up another page; on the right hand side of that, you will see "Download Earlier Release". Scroll down and pick out [an earlier matlab version] from there.
For those who do not have the these tools (and do not contemplate their purchase) but have the interest, skill, and time to implement an FPGA radio, they could use one of the inexpensive (if not free) HDL compilers and try to recreate the design in HDL from the Simulink model that I will present in this series of posts.

And so I will try to include as much detail of the FPGA design as possible, so that those who might want to recreate Dick's design in HDL will have a running start at doing that.  (Note: some Xilinx blocks, such as CIC and DDS blocks, contain Xilinx Intellectual Property, and, apart from a definition of high-level parameters, cannot be delved into).


Now let's discuss some features of a typical Xilinx Simulink Model, so that you might better understand what you will see later...


Notes on Xilinx Simulink Models:

Let's take a look at an example of one of the Simulink Subsystem blocks in the FPGA Simulink Model to get an idea of Xilinx/Simulink design nomenclature.

Here is the Clock Divider subsystem, which divides down the 80 MHz FPGA clock to 20, 10, and 5 MHz (for external applications, such as locking the radio-core's 80 MHz oscillator to an external time-base, as Dick has done).

(Click on image to enlarge)

In this image please note:
  • The blocks with a light-blue fill and a stylized "X" white shadow within them are Xilinx blocks available only through the Xilinx Blockset provided via their System Generator.
  • The output definition of the counter, UFix_4_0, means that this data is 4 bits wide, that these four bits represent an unsigned number (the U suffix), that this number is fixed-point (the Fix), and that the fixed-point number's Decimal Point is at bit 0. Thus, this example represents values between 0 and 15. 
  • In other instances, such as those blocks dealing with actual RF or audio signals, data will be passed as signed two's complement numbers.  For example, you might see a data format of Fix_16_15.  Note the absence of a U suffix -- the data is therefore signed two's complement.  And 16_15 means that the data word is 16 bits wide, and that it has a Decimal Point at bit 15.  So, in this case, values would range between +0.999...(i.e. the highest possible positive value, as represented by 0x7FFF) and -1.0.  (In other words, the 65,536 values represented by the 16 bit word would range, essentially, between +1.0 and -1.0.)
  • The "z-1" label in some blocks means that there is a register delay within this block (1 clock delay for z-1, but this delay could be longer, e.g. z-25 would represent a 25 clock delay within a block).
  • The "++" label within the counter means that it is an UP counter.  
If you could click on the counter block in the image above, you would see its parameter window:

(Click on image to enlarge)

Note that the last entry shows the counter's Sample Period as "1/Fs".  Fs is the frequency of the FPGA's system clock, which is 80 MHz in this application.

Another useful block, found in the subsystem above, is the "Slice" block.  The Slice block allows one to take a "slice" of data from a multi-bit wide data word.  For example, in the Clock Divider, I want to use three of the counter's output bits to create 20, 10, and 5 MHz clocks.  I do this by taking three 1-bit wide slices, each slice being a different bit of the counter's output.

If I click on the "Slice1" block, I will see the window below, which describes this slice as 1 bit wide and the MSB of the counter's 4-bit output (i.e. the 1-bit slice has a "0" offset from the top-bit of the value being sliced):

(Click on image to enlarge)

Per the image above, slices can also be referenced from the LSB bit location, and they can be of widths other than 1.

By the way, there is a complementary function to the Slice function which allows one to combine bits (or words) into larger words.  This function called "Concat" which allows you to concatenate any number of bits to form a wider word.

Here's another Simulink/Xilinx example.  Let's take a quick look at it.


Notes on this image:

1.  Note the "Bool" labels on some interconnects.  This stands for "Boolean", and it represents a logic value, rather than a signed/unsigned numerical value.

2.  You can have Constants.  These can represent multi-bit (or single-bit) signed/unsigned words, or Boolean values.

3.  This system takes data from one clock domain (whose clock is slower by a factor of 16), up-samples that data to the higher clock rate (this is the clock rate that the counter at the left is clocked at), and then down-samples it back to the slower clock rate.


OK, that was a very quick overview of the Simulink model's Xilinx nomenclature!  Finally, let's take a look at the Top Level of the FPGA Simulink Model...


Top Level of the FPGA Simulink Model:

Here's the Top Level Simulink Model of my version (rev. 1.1) of the FPGA:

(Click on image to enlarge)

Notes regarding this diagram:
"Subsystem" blocks are the blocks with white fill, such as the Serial Interface1 block, or the Audio_and_Mode_Control block.  Clicking on one of these blocks would open that subsystem into a new window to reveal the circuitry within that subsystem.  For example, if one were to click on the Clock_Divider subsystem block in the Simulink model, it would open up to reveal the image below (which you've already seen, above):



Delving deeper into the Top Level...

In the upper left hand corner of the Model's Top Level you see this:

(Click on image to enlarge)

In the image above:
You would click on the "System Generator" icon (which is one of the blocks available in the Xilinx Blockset) to generate a .XISE file.  The .XISE file is then transformed into a .BIT file by the Xilinx ISE Design Suite  (now the Vivado tool?).  The .BIT file, in turn, can be converted (using the Xilinx iMPACT program) into a .MCS file for loading into the FPGA board's EEPROM).
The icon labeled "DOC Text" is a document file in which I track my FPGA revision changes.
The Xilinx block named "Versionx10" is actually a "Constant" block (whose label has been renamed for convenience).  In this revision, it contains the value 10, representing a revision level of 1.0 (a value of 11 would represent a revision level of 1.1)
The yellow In blocks represent either individual FPGA input pins (in the case of the nRESET input), or groups of FPGA input pins (e.g. 16 pins for the hf_adc In block).  Clicking on this block in the actual model would bring up a window showing which actual       FPGA pin(s) are assigned to an In block.
Note that there are similar yellow block for FPGA output pins.  They are labeled Out.

I will note here, too, that not all FPGA I/O are shown on this top-level of the model (to keep Top Level complexity to a reasonable level).  Quite a few of the other I/O pins are buried within various subsystem blocks.

(You will note a number of Subsystem blogs, shown in  the image above, that are external to the FPGA itself (i.e. they drive FPGA input pins, etc.), such as the "RF Source" Subsystem and the other blocks connected to it.  Dick uses these to test/check his Simulink model, and you who are familiar with Simulink will know what they are.  I would like to be more informative, but I'm not (at this time) a Simulink user.)


That's my very brief description of Simulink's Xilinx nomenclature.  I'll add more details in future posts, as needed, when we examine more closely the Simulink Model.

More to follow in later posts!  Here's the link to Part 2:  FPGA Modulation and Demodulation

That's it for this post!

Background Notes:

SDR Notes:  Weaver Modulation and Demodulation
SDR Notes:  The Mixer Mathematics of Digital Down Conversion


Posts in this Series:

Part 1: Overview
Part 2: FPGA Modulation and Demodulation
Part 3: Interpolation and Decimation Filters
Part 5: Control Interface, Etc.
Part 9: 50 dB HF RF Power Amplifier
Part 10: 30 Amp DC Switching Power Supply
Part 11: Floobydust (and a pointer to the files!)


Resources:


Standard Caveat:

I or Dick might have made a mistake in our designs, equations, schematics, models, etc.  If anything looks confusing or wrong to you, please feel free to comment below or send me an email.

Also, I will note:

This design and any associated information is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

2 comments:

The radio maker said...

astounding , without a dsp chip! I'd like to make something with an ltc2246 25Ms that I have,only in RX for didactic pourposes.
It would be nyce to put a video on YouTube !

Les WB6ORZ said...

Nice work and report. Thanks.