Sunday, November 15, 2015

Prj141 - Digital Down Converter Signal Block (Part2)

The signal block of the FPGA (overview here) is a simple digital down converter.  You could just use a Xilinx core, however, since this was my first project with VHDL I wanted to assemble the pieces myself (and I wasn't sure I could correctly use the generated core as are geared to multi-channel and much more complicated applications, besides that, it is more interesting and instructive to walk through a full DDC on your own at least once).  A block diagram of the signal block is shown below.
Single Channel Digital Down Converter Block Diagram
The VHDL source is here.  The signal processing block is a single channel digital down converter using separate Xilinx cores.  The 12 bit ADC signal comes in at the left and is formatted (unsigned to signed conversion). There is a mux which selects the ADC stream or an internally generated test pattern to be sent to separate I and Q multipliers (S_s12 in the block diagram).  The multipliers are driven by the sin and cos outputs of a Xilinx DDS generated core.  The DDS frequency is controlled by its phase increment register.  This register is written by a FSM in the AXI register block.  It takes a 16 bit wide set of discretes, buffers them and when they change writes the new value to the DDS core.

The output of the multipliers is fed into a CIC filter generated core.  The CIC is on the order of N=4 while the decimation is on the order of 50 to 300.  (the exact parameters depend on both the sample clock rate populated on the board and the detailed design of the filters downstream).

The CIC outputs are sent to a compensation FIR filter generated core.  The FIR filter is designed to compensate for the droop in the pass band of the CIC filter as well as to provide antialiasing for a decimate by 2 at this stage.  There are several good applications notes from both Xilinx and Altera on balancing the tradeoffs with CIC filters and FIR filters and decimation.

The low rate signal data from the I and Q chains is taken from the CFIRS by the IQ writer block and written to the FIFO a pair of samples at a time.  This block is implemented as a FSM which waits until both I and Q samples are ready and then writes both values to the FIFO.  Care needs to be taken at this step since the FIFO data can easily be shifted by 1 during starts/stops/resets.  If this happens the consumer of the data ends up reading I(n),Q(n+1) as a complex sample which represents a phase shift and results in not truly quadrature signals.  For this reason the FSM includes special logic to write a pair of samples or none at all.

Lastly, there is a mux which selects which data is presented to the FIFO write signals.  Based on the FSS (Fifo Source Select) discretes, samples from any point in the processing string can be sent to the FIFO. The FS designator on the block diagram shows the setting to select data from that point in the chain.  This capability might sound like a nicety, but is absolutely essential to developing, debugging, and integrating the software and firmware.

Similarly, the test pattern generator is immensely useful for a couple of reasons.  First it allows the use of clean known digital signals.  These can be specified at a precise frequency and amplitude.  Second, it serves as a reference for down stream software development without having to have a physical signal generator attached to the system.

There are a couple of other important aspects not shown on the block diagram for brevity and clarity. The entire signal processing block is driven by the ADC sample clock and is designed to work from 10MHz to 66MHz.  There is an internal reset used to reset the filters (i.e. ensure they all start on the same sample and have no residual samples from previous operations).  This is driven by the FIFO reset from the control section.

Related:
Prj141 Schematic
Prj141 Overview
Prj141 Digital Down Converter
Prj141 Digital Interface
Prj141 Software
Prj141 Filter Design
Prj141 Filter Evaluation
Prj141 LX9 Utilization
Prj141 Higher Sampling Rates

Friday, October 30, 2015

Prj 141 - Spartan6 LX9, ADC, and BBB (Part1)

With some work on the VHDL another unit was constructed with an ADC.  One of the advantages of using an FPGA assembly like the XuLA2 is that it can be moved from one carrier application board to another.  The schematic is shown in the previous post.  A picture of the final assembly is shown below.
Prj 141 Unit #2.  BeagleBoneBlack with SPI interface board at left.  Right hand side is ADC carrier (purple) with XuLA2 including a Spartan6 LX9 (green).
The one white wire shown is a regulator enable that I decided at the last minute to statically pull up rather than drive from the FPGA.

The VHDL was developed incrementally from the base digital/SPI interface into a single channel digital down converter.  All of the VHDL is available here.  The summary block diagram is shown below.
Block Diagram of Digital Down Converter for Spartan LX9 with SPI Interface
The inputs to the FPGA (Spartan6 LX9) are a 12 bit ADC input with sample clock, a 12MHZ digital clock input and a SPI interface.  The outputs are 4 LEDs for testing and a SPI output.  The sample clock is designed to be 10MHz to 100MHz.  All IO pins and timing constraints are specified in the UCF file.  The top level break down includes a digital block for interfacing to the processor, a signal block for interfacing with the ADC and processing the signal.  A 4k x16 bit FIFO buffers the data from the signal processing to the control block and processor.  The control block gets a digital clock which is multiplied up by 4 using a DCM to interface with the processor SPI.  It also receives a copy of the ADC sample clock for testing and diagnostic purposes.  The control block receives a status set of discretes from the signal block and provides to the signal block a set of control discretes.  The TPG discretes control the internal generation of test patterns, the FSS (Fifo Source Select) determines which internal signals are placed in the sample FIFO between the signal processing and digital interface and the PINC (Phase increment) determines the frequency setting of the signal block DDS or NCO that gets mixed with the ADC input.

There are two major clock domains within the part: the sample clock and the digital clock.  The signal processing block is driven entirely by the sample clock while the control block is driven completely by the digital clock (from the DCM).  All information between the blocks is through a FIFO with separate clocks or via discretes that are re-clock synchronized at the destination.

A couple follow on posts walk through some of the details.

Related:
Prj141 Schematic
Prj141 Overview
Prj141 Digital Down Converter
Prj141 Digital Interface
Prj141 Software
Prj141 Filter Design
Prj141 Filter Evaluation
Prj141 LX9 Utilization
Prj141 Higher Sampling Rates

Tuesday, September 29, 2015

FPGAs and VHDL on a budget

The Beagle Bone Black (BBB) and its PRU go a long way to building non-trivial projects (e.g. all of the boards in gallery1 and gallery2 including a  Level controlled RF synthesizer, 10MSPS ADC, and multistage SDRs.)  Having a simple, flexible, low-cost FPGA available started to become very appealing.  In looking around at various FPGA boards the XuLA2 Spartan6 LX9 caught my attention for several reasons. First the pin out is extremely simple (40 pin DIN at 900x100 mil spacing), second it has enough IO pins to be usable with ADCs, DACs, and an SPI but not so many as to be cumbersome, third it includes an SDRAM which could come in handy, and finally the cost is low enough that I could afford to purchase multiples and not worry about loosing one due to mistakes on the bench.
The near term goal was to interface the FPGA to an ADC and a BBB and the longer term goal being to eventually incorporate an NCO, digital mixer and filters.  I am also not a VHDL expert so things needed to progress incrementally.  Given this, I created a simple board as a carrier for the XuLA2 that included an SPI interface, LEDs and an ADC.  The schematic of that board is below.
XuLA2 and ADC carrier board schematic.
The idea is that there is enough on the board to develop and test an SPI interface and then populate the rest of the board with a 12 bit ADC.  The ADC and sample clock oscillator are pin compatible from 10MSPS up to 66MSPS (depending on how much you want to spend and can use).  Below is a picture of the first unit partially populated with only LEDs, SPI interface, and XuLA2. It is connected to a BBB via an SPI interface using the GPIOs through an Beagle Bone Black interface board.
Beagle Bone Black with interface cape at left.  XuLA2 w/ Spartan 6 LX9 on ADC carrier on right.

The first FPGA image developed included an SPI interface with an internal control register and a couple of counters (block diagram below).
Block diagram of VHDL for LX9 digital interface.

The SPI block serializes data into SI and out from SO.  The port controller is a finite state machine that uses the SI as a 16 bit command. The low 4 bits specify whether the transaction is a read or write and which port to read and write from while the upper 12 bits serve as the data.  Reads and writes with port 0 always go to register 0 (R0).  This is the primary control register which includes settings for the LEDS, ADC sampling enable and selecting what hardware is multiplexed to port 1.  Reads and writes with port 1 can be to a secondary set of control registers (R1 and R2), a set of counters, or a FIFO which crosses the system clock and ADC sample clock domains.  The overall programming model then becomes writing a command (and reading the results from the previous command since the serial data is clocked out concurrent with clocking in the write data).  For streaming operations, the port 1 selector is first configured to connect to the FIFO and then a stream of read-port-1 commands are issued.

This approach worked well.  It has enough complexity to serve as a non-trivial, applied learning exercise yet is simple enough to be tractable to debug without lots of test equipment and tools.  The SPI programming can be easily driven by and changed in the BBB user space C code. This means you can slow down transactions to seconds and verify things on the target hardware with the LEDs. The counters allow pattern verification of reads at all speeds and check the integrity of the interface.

Related:
Prj141 Schematic
Prj141 Overview
Prj141 Digital Down Converter
Prj141 Digital Interface
Prj141 Software
Prj141 Filter Design
Prj141 Filter Evaluation
Prj141 LX9 Utilization
Prj141 Higher Sampling Rates

HTML5 Canvas Experiment

After having completed the simple html/css/javascript synthesizer application (described in Part1, Part2, Part3, Part4) I wanted to evaluate using an HTML5 canvas for an instrumentation like display.  There are lots of good graphic packages available, however, I did not find one that seemed to offer basic and simple xy plots suitable for what I wanted to do with a browser based instrument.  For me the real keys were: a) simplicity where I could understand the code and tailor it, b) ability to graph 500 – 2k work of xy points every 50mS or so, c) basic measurement things like envelopes, memories, peak picking, a cursor, and markers.  Given this and the desire to spend a little more time advancing my javascript comfort level with non-trivial examples I decided to build a simple version of a similar Java display I have used (illustrated in the posts on ADC and spectrum analyzer experiments).

The package was developed as a standalone file with a couple of test drivers.  The tests themselves run in the browser and require no back end server to drive them.  The source code is at BREC/Js and a browser executable demo is here.  An image of one of the unit tests is below.

Example of HTML Canvas used to graph signals.  Browser demo available here.
The example has several buttons along the bottom.  The "run" button causes internal updates to the XY sequence displayed.  In the default case this is just a sinusoid with a up and down chirping frequency.

The "marker" button displays 10 markers.  These start out as predefined values on a sinusoid.  If you click anywhere on the canvas, marker 9 moves to that position.

The "peaks" button toggles peak picking.  When peak picking is on, markers 0 - 8 are taken over and assigned automatically to peaks found.  Marker 9 still follows the last canvas clicked location.

The "memshow" button toggles the display of a XY sequence in memory.  This is shown in light blue. The "mem" button captures the currently displayed sequence into the memory.

The "envelope" button toggles an envelope history.  When enabled the envelope is initialized and displayed.  When toggled off the envelope is hidden and not active.

The "function" button toggles between two internally generated XY series.  The first is the chirped sinusoid, the second is a spectrum like signal with two peaks and some random noise.

Saturday, September 12, 2015

Browser controlled synthesizer (Part4)

The fourth step in constructing a simple webpage controlled RF synthesizer is the mechanical assembly and packaging. (The previous steps are described in  part3, part2, and part1)

Originally I had visions of constructing shields on the boards in RF sensitive areas and packaging the entire setup in a nice professional small case.  Let’s just say I’m learning…  Rather than getting hung up on the difficulties and errors in this regard I decided to forge ahead.  All I really needed was a dust cover.  The real concern is just protecting the electronics from having a tool fall on them or more likely a SMA connector brush across them as the cable flips over unexpectedly while reconfiguring a setup. To this end I decided to use some scrap plywood and acrylic.  The plywood provides enough mass that the instrument doesn’t get dragged around on the bench with cable tension and is sturdy enough that you can stack things on top of it.  Granted, it provides no shielding and I’m not entirely sure of the ESD properties.  Same for the acrylic face plate.  The face plate is thin enough that you can get the connectors through it and you can at least see the LEDs to know if it is powered on and should be working.  The following are a couple of pictures of the assembly. 
BBB Browser Controlled RF Synthesizer on Mounting Plate

Synthesizer with dust cover
The example below captures the control panel during a sweep along with the measured spectrum.
Browser based control panel.  Sweeps from 37MHz to 67MHz (1MHz steps) and from 0dBm to -30 dBm (1dBm steps).  At the time of capture the output at that steps was at 50MHz/-13dBm.

Spectrum of output.  There is a 30dB pad between the generator and the analyzer.  You can see the 3rd harmonic of the low frequency portion of the scan on the far right near 74MHz.
Similar sweeps and single frequency outputs are achievable through 2GHz.  Beyond this point the amplifiers used start to lose gain and the level drops and level control is reduced.  The following captures a sweep across 1.4GHz - 1.5GHz in 5MHz steps.
Constant level sweep from 1400MHz - 1500MHz in 5MHz steps.  Output at -5dBm with 30dB pad between analyzer and synthesizer.

Friday, August 28, 2015

Browser controlled RF synthesizer (Part3)

The third step in constructing a simple webpage controlled RF synthesizer is the application level software. (The previous step was described here with the hardware described here)

Since all of the interfacing software is in C/C++, I wanted to use a light weight http server framework that I could build application specific C++ code into.  I did not want to use gateways or other scripts for performance reasons, not so much for this particular activity but for others which might require higher performance between the http command and the hardware.  There are a couple of good packages available for these purposes.  After a small amount of experimentation I decided to use libmicrohttpd.  It is pretty basic and doesn’t get in your way for simple servers like this.

Once you have the hardware control software and an http server framework, the next step is to decide on the building blocks for the actual user interface itself.  In support of this, there are a dizzying array of software packages including jQuery and Dojo.  For this particular application I wanted to start simple and use basic html, css, and javascript.

The browser component is structured as a simple table with a CSS defined border and cell entry formats.  The basic actions buttons with the numeric inputs being text box forms.  An example is shown below.
Browser Control Panel for Synthesizer

The buttons at the top allow the application software to be restarted, the BeagleBone Black to be rebooted, or the current configuration parameters to be saved persistently (and used at next power up).  The shutdown button is only for testing and is not required for use.  The box below that indicates if the browser is actually connected to the device, the time on the device (which should update every second if everything is working), the PLL lock status at the given frequency and the output level as currently read from the device.  The next set of control buttons allows the device to run, sweep, and continuously monitor the output power level.  The “run” actually will just power on or off the synthesizer boards allowing you to quiesce everything in case you are wondering where a certain signal is coming from.  The level monitoring allows an output level update, constant monitoring (~100Hz) or to be completely quiet – again in case there are questions about where a certain signal is coming from.  The final panel allows user inputs of various parameters and shows the currently in effect values.  These allow for a single constant frequency and level setting (start parameters), or a sweep in both frequency and level (from start to stop values) along with step sizes when sweeping for both level and frequency.  While sweeping the time at any given frequency and level can be configured from 0 (as fast as the device can step) to seconds using the “DwellTime” value.

This application is simple enough that it doesn’t merit a full MVC (model view controller) approach, however, a simplified variant is used – mostly to evaluate the approach.  The browser client code is here while the server code is here.

The state coming back from the server is expressed as a single JSON object.  This is easy to parse in javascript.  To keep things responsive the state is requested from the server using http query every 100mS.  The state variable contains all of the elements in the display.  The JSON object is then used to update all of the DIVS in the page.  This represents a single HTTP GET on the “getstate” URL and keeps the client parsing very simple along with the response construction. Each user input generates a HTTP GET on the “setstate” URL with the values being a name/value pair.  Again, this keeps the HTTPD server parsing simple and allows for easy testing with human synthesizable commands.  The network API is then simple enough that control can also be scripted using WGET. An external host can use bash scripts to control the device for automated test setups.

The use of HTTP GET is not in line with network security and best practices, however, there is nothing secure about this device.  It was intended for use on a dedicated and isolated network with other instruments.  There is no login to prevent conflicts among users/sessions. The server will server up any file on the BBB.  I am sure there are numerous other security holes within the configuration of the BBB Linux configuration as I have it setup.  The whole point of this is simplicity and experimentation.

The one final interesting portion to note is the persistent configuration saving feature.  Once you get things setup for a particular measurement it is exceedingly useful to be able to save it and then later just power on the device and have it start working like you wanted to without even having to attach to it with an Ethernet or  browser.  The BBB file system is mounted read only for robustness.  The state parameters are read from a file on startup.  When the server receives a save configuration command, the file system is re-mounted read/write, the configuration file with the current parameters written and then the root file system re-mounted read only.  This produces a small window in time during which the device root file system may be vulnerable to interruptions.  In practice, this has not proven to be a problem as the entire re-mount, write 200 bytes, re-mount operation occurs within milliseconds.  If you are prepared to re-partition the eMMC on the BBB one could create a small spare partition and read/write the configuration file through a raw block device.  This side steps any file system checks and integrity concerns.  

Saturday, August 15, 2015

Browser controlled RF synthesizer (Part2)

The second step in assembling the synthesizer (based on this hardware) is configuring the BBB Linux distribution.

An older rev B BeagleBone Black is used as the primary control board.  This uses Angstrom Linux. I cannot speak to the differences between this and rev C with Debian distributions.  I will say that I find the Angstrom distribution slightly more difficult to work with as I am accustomed to the standard unix utilities and configuration approach.  Angstrom’s use of select packages such as connman and busybox help resource footprint but often send me to the web searching for how to do basic system administration and configuration actions I have done for years.  Said differently, I believe you can do all of these and at least as easily with Debian on a rev C board.

The following steps are in the notes.txt file in the  BREC/SynHttpd software. The text here provides a little more background and narrative beyond the terse command notes.

The first step is to disable a set of default services that are not used and that use the http default port 80.  There are plenty of good tutorials on the web and all boil down to “systemctl disable <svc>”, where <svc> is cloud9.service, gateone.service, bonescript.service, bonescript.socket, bonescript-autorun.service, avahi-daemon.service, gdm.service, and mpd.service.

The next step is to setup the synthesizer application to start automatically at boot time.  Again, there are plenty of good tutorials on the web and there are examples in the BREC/Scripts directory of the software.  I configured a service to start a bash script via systemd.  The main script is placed in /home/root with the rest of the executables and the script launches the actual applications.  To me, systemd has quirks like crond, you don’t have the exact same environment as your normal shell (just enough to throw things off) and the configuration files take some getting used to.  You can use “systemctl status <service you defined>” to check on the application and its children’s status and see any stdio.  It takes some getting used to.  There are items to be aware of like exiting with a good status or having your processes “cleaned up” for you.  You need to start the applications and get them in the background before a predefined time limit or the service process tree is killed as being hung.  All of these things can be adjusted in the configuration files or in your startup script – you just have to pick an approach and understand the subtleties of the configuration you have defined. There are also issues to be aware of with starting so quickly on boot.  One of particular importance is “/dev/uio0” not being present for a brief period of time.  This is the special file the libpru code uses to access the PRU.  I found that startup services I created would randomly seem to not start.  It turned out that sometimes by the time they went to open the pru the special file was available and sometimes not.  By just checking for the existence of the special file in the startup of the service script the service reliably starts every time.

So at this point you have a BBB that lets you start your own web service on startup.  The next step is to safely allow shutdowns without other action.  To do this the root disk is mounted as read only. There are several examples on the web as well as a sample /etc/fstab in the BREC/SynHttpd/fstab-ro file.  To make root writeable you just issue “mount –o remount,rw /” and everything is back to a standard writeable file system. I have to admit this works really well and consider using this on normal development boards where I write to the root partition.  A read only root file system speeds the boot time but also helps when working with a new board and linux gets powered down without warning.  There are posts and comments on the web regarding early perceived issues with a read only file system on BBB (e.g. applications could not access the gpio pins through sysfs), however, I experienced no issues – everything works as expected including all device interfacing and other system services.