Software apps and online services
The Arty A7 board is a development board for Xilinx's Artix-7 FPGA chip. It comes in two sizes in terms of the amount of programmable logic available in the FPGA: the Arty A7-35T and the Arty A7-100T. It is also one of the more affordable options for FPGA development boards with the Arty A7-35T available for $129.
The Artix is does not have any hardware peripherals built into it like its Zynq counterparts. So in order to have a processor available in the design like the Arm in the Zynq, we must instantiate a soft processor in the programmable logic of the Artix. Xilinx offers their own soft processor solution with the MicroBlaze CPU IP. This also means that any other desired peripherals, such as UART, GPIO, SPI, I2C, and so on, must be manually instantiated.
This project will walk through how to set up the Arty A7-35T with the MicroBlaze CPU with a UART serial console and GPIO control for LEDs on the board.
If you haven't already, install the board preset files for the Arty A7. Digilent has an up-to-date guide here on how to do that along with the links of where to get the board files.
Once the board files have been installed, relaunch Vivado and create a new project in Vivado targeting the Arty A7-35 board:
The first step in any new Vivado project is to create a block design. The option for creating a new block design can be found in the Flow Navigator menu on the left under IP Integrator.
A blank window will pop up where you can use the '+' button to start adding IP blocks to the design. The first of which will be the MicroBlaze CPU itself. Start typing 'MicroBlaze' in the search box at the top of the menu that pops up when you click the '+' button, and you'll see it filter down to the MicroBlaze IP blocks. The one just titled 'MicroBlaze' is the CPU IP block. Double-click on 'MicroBlaze' and you'll see it appear in the blank block design window along with a green banner at the top with an option for 'Run Block Automation'.
The block automation option will appear whenever Vivado detects something in a block design with a very common or preset design available. In this case, part of what is in the board preset files for the Arty A7 board is the configuration for the MicroBlaze. Click on the 'Run Block Automation' option and check the box for the Interrupt Controller (even though I forgot it in the screenshot below) so the block automation will include it when it applies the rest of the board preset IP blocks, but leave everything else at its default value.
Once block automation completes, another green banner will appear at the top of the block design window with the prompt to 'Run Connection Automation'. Again, click on the hyperlinked button and a window will appear summarizing the options for the connection automation to run. In this instance it is wanting to add the master clock wizard and reset controller IP blocks for the design. Check the box for 'All Automation' and click OK.
Everything for the MicroBlaze CPU is now instantiated, so it's time to add peripherals to the design. For this project, I decided to add just the basics: GPIO for the onboard LEDs, and a UART to be able to send/receive via a serial console.
Again, click the '+' button and search for 'GPIO' and double-click on the 'AXI GPIO' option to add it to the block design. The Run Connection Automation option will appear after the GPIO block is added and check the box for 'All Automation'. If you click on GPIO in the menu, the window will show you the preset options you can connect the GPIO to. For the Arty board, this includes regular LEDs, RGB LEDs, push buttons, and toggle switches. I chose the regular LEDs for this project.
One of the most useful peripherals for FPGA development in my opinion is a serial console interface. To add this to the Arty's design, add an instance of the UART 16650 IP to the block design and run the connection automation when it appears.
When the interrupt controller is added to the design and the block automation hooks everything up, it assumes that two interrupts will be connected to the interrupt controller. Since we only have one coming from the UART IP block, the concat block connected to the interrupt controller IP needs to be modified to only have one port. Double-click on the Concat IP block to bring up the customization window for it and change the number of ports from 2 to 1 and click OK.
After editing the concat block, connect the interrupt output of the UART IP to the input of the concat block to the interrupt controller as shown below:
The connection automation for the Arty board in Vivado 2019.2 has a glitch where it creates an extra reset line and port that needs to be removed. Delete the port named reset_0 and connect the port for the inverter block to the port titled reset:
Now that the block design is complete, run a design validation on it prior to moving on to verify there are no major design flaws thus far. Click on the icon that looks like a box with a checkmark in it to run validation.
Once validated with no critical warnings or errors (don't worry about regular warnings, many of them are simply due to the fact that some manual overrides were applied) save the block design and create an HDL wrapper for it. This top level HDL wrapper is what instantiates the block design itself in the programmable logic of the FPGA. Right-click on the block design in the Sources menu and select the option 'Create HDL Wrapper...".
In the window that pops up, select the option to allow Vivado to manage and auto-update the wrapper and click OK.
Once the HDL wrapper has been completed, run synthesis by clicking on 'Run Synthesis' from the Flow Navigator or pressing F11.
Once completed, select the option to open the synthesized design from the prompt that appears. Navigate to the I/O ports menu at the bottom of the window and find the line for 'diff_clock_rtl_clk_p' (this is the input for the system clock from the oscillator on the Arty board). In the 'Package Pin' field enter 'E3', then select 'DIFF_HSTL_II_18' from the drop down for the 'I/O Std' field and click the save button in the upper left corner.
A prompt will appear asking for a new constraints file to be created to save these new constraint options to, type in your desired name for the file and click OK.
Rerun synthesis, then run implementation and generate a bitstream (a prompt will pop up at the end of end run to ask if you want to go ahead and run the next task). Once the bitstream has been successfully generated, export the entire hardware platform by selecting File > Export > Export Hardware. Be sure to check the box to include the bitstream, and be sure the file path is for the top level of the Vivado project directory (which should be the default option). This will export the hardware platform as an.xsa file.
With the hardware design for the Arty completed, the C code to run on the MicroBlaze needs to be generated and compiled. We need to switch over to Vitis to do this, launch the Vitis IDE from the Tools menu in Vivado.
Unlike it's predecessor, XSDK, Vitis does not automatically pull in the hardware platform, so the first step in Vitis is to create a new platform project.
After naming the new platform project and clicking 'Next', browse to the.xsa file in the Vivado local project directory exported in the previous steps. Leave the option for operating system set to standalone and the processor set to MicroBlaze and click 'Finish'.
The platform project creates all of the hooks for the software and firmware that needs to run on the MicroBlaze. It is at this point that the actual application project for 'Hello World' can be created. Click the icon in the toolbar right below the File menu and select New Application Project. Name the new application and leave the default option to create a new system project, then click 'Next'.
The prompt will then ask what hardware platform to use for the application, be sure to select the custom platform we just exported from Vivado and click 'Next'.
Since this will be a bare-metal application, the domain will be standalone (the default option). Then you can select your desire programming language.
Finally, select the 'Hello World' application template and click 'Finish'.
The main function in the 'Hello World' application template is located in hello world.c under the src folder of the application in the Explorer menu. It already has a basic structure where it initializes the hardware, prints "Hello World" once, then cleans up the platform in preparation for power down. I personally like to add a while loop where "Hello World" is infinitely printed with a slight delay between prints so that I have the time to connect to the UART with a serial terminal application like Putty or TeraTerm.
I edited the main function to look like the following:
Save the file and build the whole project with the shortcut control+B.
Plug in the Arty board to your PC and right-click on the application system project in the Explorer menu, select 'Debug As...' and the 'Launch on Hardware' option.
Vitis will switch perspectives into debug mode at stop at the program entry where you can either let the program run as normal or you can step through it line by line.
It will stop at the init_platform function as an entry point.
Connect to the Arty's UART via a serial console app such at Putty or TeraTerm. Vitis also has a built in serial console that I like to use just to keep everything in a single window. You can pull up the serial console in Vitis by selecting Window > Show View... > Xilinx > Vitis Serial Terminal.
The baud rate is set to the default 9600, and you'll be able to see the "Hello World" print out by pressing F8 to let the program run as normal.
With this complete overview, you can go back to add any new logic in Vivado to the design and/or C code in Vitis to expand on the design.