+++
title = "Mimas Spartan 6 FPGA - New firmware, driver and PC-FPGA interface"
tags = ["Driver", "Embedded", "Firmware", "FPGA"]
date = "2022-03-17"
+++

[View project on github](https://github.com/Jojojoppe/MimasV1Firmware)

The [Numato Lab Mimas Spartan 6 FPGA development board](https://numato.com/product/mimas-spartan-6-fpga-development-board/) is a simple FPGA development board with a Xilinx Spartan 6 (xc6slx9) on it with a usb interface for programming the on-board flash. The flash is a 16 Mb SPI flash connected to both the FPGA an a Microchip PIC (18f14k50). The PIC runs firmware which presents itself as serial port to the connected PC and uses a python script to upload the generated bit-file.

Since the original firmware used a 9600 baud serial connection, the uploading of the bitfile it takes quite some time to upload. And next to that communication between the FPGA and the USB port is not implemented even though the PIC has connections to the FPGA. This was the reason to develop new firmware which could program the SPI flash faster and has an FPGA-USB interface for serial communication and/or datalogging purposes (like a logic analyzer).

The repository for this project contains the firmware for the PIC (in the `firmware` folder), the driver for programming and comunicating with the PIC (in the `driver` folder) and some usefull VHDL blocks for communication between the PIC and the FPGA. Information specific for the firmware, driver of hardware are located in their folders.

### FPGA-PIC Interface

The full schematics of the Mimas board can be found [here](https://numato.com/blog/wp-content/uploads/2016/08/MimasSpartan6ModuleSch.pdf) (which are published by Numato Lab under the CC BY-SA licence). The relevant parts are shown below. As can be seen, 7 lines are directly connected to the FPGA (`D[0..3]`, `CLK`, `RD` and `WR`) next to the SPI bus which both the FPGA and the MCU use to communicate to the SPI flash. The SPI bus is used for the communication between the FPGA and the MCU (while keeping the SPI flash disabled). Next to the SPI bus the CLK line from the mentioned signals is used as reset line to reset the FPGA from the MCU.

| ![PIC side of the FPGA-PIC interface](/images/blog/mimas/picside.png) |
|:--:| 
| *PIC side of the interface* |

| ![FPGA side of the FPGA-PIC interface](/images/blog/mimas/fpgaside.png) |
|:--:| 
| *FPGA side of the interface* |

| ![Hardware-firmware interface pinout of the IP block](/images/blog/mimas/HFinterface.png) |
|:--:| 
| *Interface IP block pinout* |

The project also provides an IP block written in VHDL which can be used together with this interface. It translates the serial data into 6 general purpose ports and two 8 bit channels. Each time a serial transfer takes place the IP block sends out the status of the 6 general purpose inputs and the internal buffer for channel 0 and 1 while it receives the values for the 6 general purpose outputs and the data for channels 0 and 1. When the transfer is complete the GPIO data and the channel data are clocked to the output and the valid line for the channel is held high for one clock period.

The transfer message consist out of 3 bytes: one status byte with GPIO values and a byte for each channel. The status byte has the 6 GPIO bits and a bit for both channels indicating if the corresponding byte contains valid data. If this bit is low it means that there is no data transfered over that channel. All data is sent MSB first.

| ![Serial transfer layout](/images/blog/mimas/signals.png) |
|:--:| 
| *Serial transfer layout* |

With the current SPI settings on the MCU the communication happens at roughly 272 kB per second over SPI if all the SPI transfers are spaced like in the captured image below. Unfortunately due to the path the data takes (PC->USB->MCU->SPI and back) the spacing between consecutive 'packets' are much larger and results in roughly 15 kB per second (or 5000 transfers per second/bps over one endpoint).

| ![Signals captured with a logic analyzer](/images/blog/mimas/logicanalyzer.png) |
|:--:| 
| *Signals captured with a logic analyzer* |

### USB Message Format

The PIC registers itself as a classless USB device with device ID `0000:0001`. It serves one endpoint on interface 0 which is used for all communication. The commands and other data are done with bulk writes/reads and the message layout is as stated in the table below.

> **NOTE:** The USB device ID is not a registered and valid VID-PID pair! Feel free to change the pair (which should be done in `firmware/usb_descriptors.c` line 14-15 and `driver/mimasdriver`/`mimas_interface.py` line 6-7).

| Command group | Command         | Arguments      | Extra info                                                                             |
|---------------|-----------------|----------------|----------------------------------------------------------------------------------------|
| NOP (0x00)    |                 |                | Does nothing                                                                           |
| FLASH (0x01)  | NOP (0x00)      |                | Does nothing                                                                           |
| FLASH (0x01)  | PROGRAM (0x01)  | `llllaaaa`     | Write a sector starting from `a` for `l` bytes                                         |
| FLASH (0x01)  | READ (0x02)     | `llllaaaa`     | Read a sector from flash starting from `a` for `l` bytes. Perform `l/64` bulk reads. |
| FLASH (0x01)  | GETID (0x03)    |                | Get the flash ID. Perform 1 bulk read.                                                 |
| HF (0x02)     | NOP (0x00)      |                | Does nothing                                                                           |
| HF (0x02)     | TRANSFER (0x01) | `GAB`          | Transfer one message to the FPGA. `G` contains the GPIO bits and the status bits and `A` and `B` contain the channel data. Perform 1 bulk read to get a message back (in the same format). |
| HF (0x02)     | HRST (0x02)     |                | Assert reset line                                                                      |
| HF (0x02)     | LRST (0x03)     |                | Deassert reset line                                                                    |

### Why not…

-   **Why not adding a simple serial link between the FPGA and the PIC instead of the SPI interface with two channels?**
    Well… I wish I could have done that. As can be seen in the schematic the RX line is used as SPI chip select for the flash so using the hardware UART in the PIC is not an option, hence this bit-banged solution.

-   **Why not using USB-CDC for the communication instead of this custom protocol?**
    To be honest, I wanted to do that! Unfortunately I couldn't get the combination of custom endpoint for programming and CDC class interface for communication working correctly so I switched it to the current setup. This does not mean that it wont be implented forever though. Next to that I really want to design some on-chip logic analyzers which is easier with the current setup than to do that over UART.