Soft AVR Core + Interfaces
This package is a full-stack implementation of the AVR 2-stage pipeline, featuring synthesis for AVR2 (classic core), AVR2.5 (classic plus), AVR3 (with extended program memory), AVR4 (enhanced core) and AVR5 (enhanced core with extended program memory). Interrupts are supported with customized number of IRQ vector width.
The project comes with some example peripherals, such as UART, SPI, a basic timer, output port and SysTick timer.
Synthetized and tested using various tools, including free & open source packages:
- iCE40HX8K-BG121 and iCE40HX8K-CT256 (on ICE40HX8K-B-EVN and custom design boards): Project IceStorm: yosys-0.9, nextpnr-ice40 and icestorm utilities;
- iCE40HX8K-BG121 and iCE40HX8K-CT256 (on ICE40HX8K-B-EVN and custom design boards): Lattice iCEcube2; and
- XA7A100T-1CSG324 (on a Digilent Nexys A7 board): Xilinx Vivado 2019.1.
Software run by the core can seamlessly be built with the AVR-GCC toolchain. This bundle includes utilities aiding the conversion from ELF output to BRAM initializations (designed for iCE40 EBRs) or generic synchronous ROM interface to set up the initial program memory. A configurable startup code (crt0.s) is included in the package with options to be matched to the synthetized core architecture.
This package is available from https://szofi.net/pub/verilog/softavrcore/. Select the softavrcore-latest.tar.gz file for the latest version. Comments are welcomed! Contact information: see ./core/avr_core.v.
On a Linux system, install the following toolchains and utilities:
make in the main directory. This will compile the example C code (found in ./build) and then run the synthesis and place-and-route targeted for the ICE40HX8K-B-EVN board. This step is automatically followed by the generation of the FPGA configuration bitstream for iCE40HX8K-CT256 (see the file top.bin).
On another operating systems and/or for non-Lattice FPGA targets:
- use the corresponding AVR toolchain port to compile the source and create the main.bin file. A working bash/awk is needed to automatically create the *.v files containing the flash interface for this virtual MCU. These are available on MacOS by default. On Windows, you may need to install additional components (e.g. Cygwin).
- Collect the source *.v files, including the core (avrcore.v), peripherals (avrio.v), flash interface (main.v), data memory (ram.v) and the top module (top.v) into a single directory if your operating system does not support symlinks.
- Import the top.v to your synthesis toolchain (icecube2, vivado, ...). You can use the shipped *.pcf files for Lattice tools (such as icecube2) without any further modifications. For Xilinx, you may use the file top-digilentnexysa7-cx7a100t.xdc as a starting point, or use it without any modifications for the Digilent Nexys A7 board.
By default, the example code (./build/main.c) sends the following series of messages via the built-in secondary UART interface of the ICE40HX8K-B-EVN board at 115200 baud:
[x] 0 => 0
[x] 1 => 1
[x] 2 => 4
[x] 3 => 9
[x] 4 => 16
[x] 5 => 25
[x] 6 => 36
Here the cadence is one message per second. The cores and the C code expect a 12MHz clock input for baud rate configuration and during the computation of the timer delay.
You may change the contents of the main() function to switch to another examples. Note also that the example is fitted for 1024 words of program code (i.e. 2048 bytes of program flash memory). Change top.v and ./build/Makefile accordingly for larger (or smaller) program memory configurations.
- LD/ST operations work only on data memory interface, not on the I/O port and the register file. GCC is not known to generate such code unless register mappings are explicitly indexed with the X, Y or Z pointer registers. Since registers are not available directly for C code and I/O ports are defined to be constants for all of the relevant peripherals, it is not expected at all and access to those areas are seamlessly translated by GCC to the faster MOV, IN and OUT instructions instead of LD/ST.
- SPM instruction is not supported, however, equivalent self-programming interfaces can be synthetized by custom peripherals.
- Watchdog is not supported, however, equivalent functionality can be synthetized by custom peripherals.
- Automatic interrupt acknowledgement is not supported at the moment.
- Fuse bits and in-system programming are not supported. These are, in practice, nearly meaningless on such an FPGA-based CPU/MCU implementation.
- This soft AVR CPU is cycle compatible with the exception of the store operations (ST, STS, STD, PUSH). These store operations runs faster by 1 cycle compared to the AVR hardware. Use a preceding or following NOP to be cycle compatible with off-the-shelf AVR hardware.
- I2C peripheral
- CAN bus interface
- An implementation of the AVR architecture using a 4-stage pipeline
- FreeRTOS port
- some more detailed documentation