Programming an ATtiny816 via UPDI using an FPGA.
The top-level module has two modules contained inside of it, updi_programmer and updi_phy.
The updi_programmer module is responsible for all of the logic involved in programming the UPDI-capable microcontroller.
The updi_phy module is responsible for taking the input/output bytes from the programmer module and converting it into a half-duplex UART stream (i.e., UPDI). In addition, this module is responsible for performing 'double breaks', which effectively reset the UPDI chip.
The two modules interface with each other via two FIFO interfaces. A block diagram showing the overall design is shown below:
Note that for the main simulation, the updi_phy module is substituted for an implementation in C++.
Verilator is used to simulate the design (note: version >5.x required which is not installable with apt, see installation directions here).
Libserial is used to interface with a connected USB to UART converter (sudo apt install libserial-dev).
In addition, intelhex is a required Python package (pip3 install intelhex or sudo apt install python3-intelhex).
All other dependencies should be installed during the installation process for these.
The main simulation simulates just the updi_programmer module and interfaces with a USB to UART converter to send bytes to a physically connected UPDI-capable device.
Run make sim to compile the simulation binary, or make sim_run to compile and run the simulation.
The assumptions of the simulation are that a USB to UART converter is plugged in on /dev/ttyUSB0, and a UART to UPDI cable is attached to the output of this.
Each individual test will be compiled to its own binary
Run make test to build the binaries, or make test_run to build and run all binaries.
For building/running individual tests, use make test_NAME and make test_run_NAME, respectively.
This project was tested with a Digilent Arty A7-100T development board.
The Vivado project file updi-fpga.xpr is included with all configurations needed for bitstream generation.
Currently, it is configured so that the UPDI signal is on IO1, the start button is BTN0, the 'busy' LED is LD4, and the 'error' LED is LD5. This can be modified in src/constraints/arty-a7-100t.xdc.
As of now, the design appears to be fully working in hardware :)
- Make it easier to adapt for other microcontrollers, which may have things mapped for different memory locations.
- Use Vivado's CLI tools to make it easier to build bitstreams.
- A smarter watchdog system that could perhaps just retry the last thing instead of fully resetting upon an error.
- Verify flashed program after programming is finished.
- Virtual UPDI-capable MCU for simulation (maybe overkill).