Assembled my first NanoPi FPGA board today! The NanoPi is a variation of my existing Nano6 Xilinx Spartan6 2 layer FPGA breakout board but designed specifically to connect mechanically and electrically with a RaspberryPi A+ or B+ Linux single board computer. Purpose of the project is to greatly enhance the low cost Linux SBC infrastructure provided by the Pi with fully flexible and custom real time hardware control and high speed IO of a low cost FPGA.
Connected together they make up a 32bit ARM Linux workstation with USB,Ethernet, HDMI video and a software reconfigurable FPGA providing 250K gates of logic, 512Kbits of RAM and 32 configurable LVCMOS or LVDS high speed IO. Very small package for only $50 BOM cost with tremendous amount of capabilities.
What I found most intriguing about this project is that I can configure Linux on the Pi ( Raspian , derived from Debian ) to boot and automatically login in and execute a predetermined Python script of my choosing. Python on the Pi has full access to video and GPIO ports. The Pi provides a 125 MHz SPI serial port that I have connected directly to my Nano FPGA. Now all I need to do is write the Verilog for the SPI interface to LocalBus bridge inside the FPGA and a simple Backdoor library of calls in Python for doing low level bus writes and reads to the FPGA. At 125 MHz and sending binary this FPGA Backdoor interface will be 200x faster than my Windows FTDI 921,600 baud UART interface I currently use sending ASCII. In the past, if I wanted a hardware project with any kind of low power and small form factor, I would have to turn to an ARM7 chip or Arduino and write and compile C code – a time consuming process. With this platform, I can script everything in Python ( much faster to develop in ) and initially store all the files on my Synology NAS network drive as the Pi easily mounts my filesystem thanks to Samba. Tremendous improvement in productivity over writing embedded C. The Pi can also run completely headless and the serial port can be used for remote shell login for using Vi to edit and test software.
Now for technical details of the project: The FPGA is a 45nm Xilinx Spartan6 XC6SLX9 that I buy onesie-twosie from Digikey for $15 ( probably $5-$7 in volume ). The FPGA is powered from 5V supplied either by the RaspberryPi or the FTDI header. Two diodes prevent the Pi from trying to power a computer plugged into the FTDI cable or vice versa. Two SOIC8 LDOs regulate the 5V down to 3.3V IO and 1.2V core voltages the FPGA requires. A 40 MHz reference oscillator provides a clock that the FPGA can PLL any internal core clock frequency it needs. Finally, an 8Mbit SPI PROM provides 2x the capacity needed for a single FPGA bitstream. The total BOM for the design is about $30 including misc Caps, Resistors, LEDs , Diodes and connectors. FYI – for them same price I also purchased the RaspberryPi SBC – manufactured in millions, quite the bargain. The FPGA has 2 x16 Nano Bus Connectors, a 1×6 FTDI serial port connector and dedicated traces going to the Pi’s GPIO connector for UART Serial, SPI Serial and a hand full of GPIOs. A x8 expansion connector ( currently not populated ) is shared between the Pi and the FPGA and could potentially be used for an add on board for switches, knobs, LEDs, etc.
[ Board Design ]
Board design was very straight forward. I took my 2 layer ExpressPCB design files from my original Nano6 skinny and widened the design to match the Pi’s width and allow for 2 x16 Nano bus connectors instead of the single x16 of the Nano6 skinny and routed all the signals I could from the Pi’s 2×20 GPIO connector to the FPGA’s unused pins. Board cost was $15, about 2x my normal FPGA breakout board cost for a 2 layer PCB from OSH-Park.
[ Board Bringup ]
Step-1 : Initial bringup of the FPGA board post assembly always starts out with applying 5V from my linear bench supply and making sure excess current isn’t flowing due to any solder shorts or just plain wrong design errors. Around 10mA is typical. I always visually inspect the FPGA under a microscope at 30x, so shorts usually don’t exist by the time I apply power.
Step-2 : Loading Bootloader bitstream via JTAG. The FPGA wants to configure itself on powerup from the SPI PROM, but the SPI PROM is empty initially so I use the Xilinx JTAG programmer along with Impact application on Windows to load my bootloader bitstream into the FPGA. Normally I include the Digilent HS2 JTAG footprint ( 1×6 0.100″ ) for quick JTAG access on a board. For this design I didn’t have the PCB area available around the FPGA so I instead did a 2×2 0.100″ grid with only TMS,TCK,TDI,TDO signals. GND and 3V VREF are available on the Nano x16 bus headers. I never actually solder headers into my JTAG vias as I use JTAG usually just once on bringup. Instead of solder header, I insert the header pins on the flying lead wires and apply pressure against the vias to establish a good contact during the download process. It takes two hands, but installing headers would be extra effort, extra cost and also ruin the overall appearance of the finished design. With the bitstream loaded over JTAG – if the FPGA is functioning, my 1Hz heartbeat LED will flash and I can continue to the next step of loading the PROM.
Step-3 : Loading the PROM can be done using Xilinx SW – but it doesn’t work always using an HS2 JTAG adapter, so instead I rely on my own bootloader design and BD_SHELL.exe application. My bootloader design is a simple “BSP” FPGA design that provides Backdoor LocalBus access via FTDI to a SPI PROM interface and some control registers. BD_SHELL.exe has built in command for loading SPI proms from bitfiles into multiple “slots” of a SPI PROM. The 1st Slot-0 is where my bootloader design is placed. For the XC6SLX9 FPGA, the 8Mbit PROM has room for 2 slots. My bootloader design on startup checks the logic level of an external jumper pin, if the jumper is open, the design initiates an ICAP reconfigure to Slot-1. If the jumper is closed, the bootloader design in Slot-0 stays resident, allowing the PCB to always be reconfigured over USB even if a bad user design is loaded into Slot-1. Loading the PROM takes three steps from BD_SHELL.
1) prom_root : this unlocks slot-0 which is normally locked and unable to be written to.
2) prom_load slot0.bit 0 : this loads slot0.bit into slot-0 ( the bootloader )
3) prom_load slot1.bit 1 : this loads final user design into slot-1
Once the PROM is correctly programmed, I should never have to use JTAG again ( Yes! ) as a simple jumper will guarantee the bootloader design stays resident, allowing BD_SHELL.exe to program Slot-1 of the PROM via USB FTDI interface. The Pi will also have access to the PROM interface, allowing for network FPGA firmware updates over Wifi or Ethernet. Last I checked – trying to do this from Arduino was more than just an afternoon project.
Step-4 : Board Level Test : The bootloader design has 2 purposes, 1) a guaranteed way of reconfiguring the FPGA PROM even if a bad user design is loaded and 2) provide a built in self test feature for testing that a board has been assembled correctly. Typing “prom_bist” from BD_SHELL will enable the BIST feature of the bootloader design. When BIST is enabled, the IOs of the x16 Nano bus connectors that are normally tristated will be actively driven by an 8bit counter. Board level test is performed by taking a scope probe ( or a Saleae 8bit lead ) to all the IO pins and confirming they are toggling as expected.
Whats Next? As I mentioned, I need to write a bunch of Verilog for the SPI interface to LocalBus bridge and then some Python. I have plans to have the FTDI connector to the FPGA wait for 30 seconds ( how long Linux takes to boot ) and if the FPGA’s backdoor hasn’t been opened by an external PC ( Windows running BD_SHELL ) then the FTDI connector will get redirected from the 921,600 Backdoor FPGA interface to the 115,200 RaspberryPi terminal login interface instead. This will allow a user to run the Pi headless and use a standard FTDI cable for remote login from an external PC. I supposed I could have included 2 FTDI headers, but this seems cleaner. Regarding applications – the NanoPi can be used for all sorts of stuff potentially. It provides the power and flexibility of the Python scripting language with the high speed IO capabilities and real time logic functions of an FPGA. By designing PIT timers into FPGA logic, Python scripts may be interrupted to perform time sensitive actions that usually wouldn’t be possible in a scripting environment. Potentially the NanoPi could be used for things like chip testing and board testing, running tests written in Python that interface to external hardware via the FPGA and then generating reports that are either sent off over ethernet, serial or stored locally on a USB flash drive. Its a platform with huge potential in the size of a pack of cigarettes ( do people still say that ? ).
Looking forward to the next stage of this project – writing Python and Verilog to make the combination come alive. Stay tuned!