Tuesday, May 17, 2016

Prj145 - BBB LX9 C++ and VHDL (Part5)

With a FPGA board and JTAG tools to load an image, the next step is to actually develop and use a VHDL application.  Since much of the VHDL is custom to the daughter board I focused on trying to get a basic digital control interface (BDC) that I could use with different daughter cards.  This has the added benefit of testing out the BBB-Fboard SPI and providing another set of GPIO ports.  The effort includes both the C++ and VHDL sides.  The following is a conceptual organization of the software.
C++ and VHDL Organization
The Fboard software primarily provides an interface to read and write the SPI interface to the Fboard hardware.  There are different flavors of SPI access including 8 and 16 bit accesses.  A device tree is installed and determines how the SPI interface is access – via the BBB sysfs interface or a PRU0 image.  The PRU0 is significantly faster and drives the SPI at multiple MHz while the sysfs version is on the order of kilohertz and is easier to start debug and test with.  The intent is that PRU1 can be used to issue SPI commands to PRU0 for application specific streaming of high speed data.

The basic digital control block (BDC) can be included in any FPGA image and provides a register interface via the SPI link between the BBB and the Fboard.  The control block is based on previous efforts and looks a lot like the Prj 141 digital interface.  The difference is that I wanted to simplify the programming model and allow each access to specify the register rather than needing a register access to control a selector for the next access to get to the target register.  A basic block diagram is below.
VHDL ControlBlock Implementing Basic Digital Control Interface
Each control block contains a set of 8 bit read/write registers, some 16 bit counters, and two GPIO units.  Registers/counters can be added with each bit or set of bits interfacing with other application specific VHDL logic. Each GPIO unit has three registers (one for input, output, and direction of pins). The GPIO units connect directly with each of the 10 pin ports on the Fboard. Each of these registers has its data and read/write valid signals muxed based on a register id from a finite state machine.
This state machine conducts the read/write of a register based on an SPI command.  The finite state machine has a register fifo with a 16 bit SPI slave.  The state machine to process SPI commands operates at 96MHz (8x the XO on the F board using a DCM) and takes multiple clocks to read or write a register.

The SPI interface timing is specified to support a 20MHz SPI clock (for FPGA timing and layout only, the BBB even with the PRU will not exceed 16MHz with 9MHz being more realistic).  The software is designed to clock 16 bits into the SPI register at the same time 16 bits are clocked out.  The format of a SPI word is below.
         -- Bit position
         -- 1111 1100 0000 0000
         -- 5432 1098 7654 3210
         -- RWNN NNNN VVVV VVVV
         -- Where:
         -- R = 1 => read
         -- W = 1 => write
         -- N = register selector
         -- V = 8 bit write value
The upper two bits select whether a read or write is conducted.  In both cases the next 6 bits identify the register to be operated on.  In the case of writes, the following 8 bits of value are written to the specified register.  In the case of a read, these 8 bits are ignored, and the specified register is read (16bits) and saved in an internal register.  On the next SPI access, while the new commands bits are being shifted in these 16 bits are being shifted out.

This might seem a bit counter intuitive, however, it keeps the finite state machine simple and extensible, focuses on single operation writes (8 bits of which is sufficient for my purposes) and allows streaming 16 bit reads with little overhead (e.g. for ADCs).  It also allows 2^6 = 64 registers to be defined. The first 15 registers are dedicated to common operations like: a) FPGA image and version identification, b) Debug counters, c) LED control/signaling, and d) the two GPIO ports.  The second set of 15 registers is dedicated to the application specific basics (for example the DDS frequency value).  A 16 bit read fifo is used as the last register available.

Related:

1 comment: