What is the KR260 and why use it
When you look at the documentation for the AMD KR260 Robotics Starter Kit it gives the description "The KR260 Robotics Starter Kit delivers a ROS-centric development experience, enabling a quick and easy workflow for roboticists and embedded developers to build their application on adaptive hardware."
You would read this as a beginner in robotics and it would be a great way to get started with building robots. But if you are just starting out with electronics or physical device programming in general, I would suggest staying with single board computers like the Raspberry Pi or Jetson Nano series or microcontrollers like the Arduino series first. The best way to get started with robotics is actually one of the cheap arduino kits you can find online. Adafruit in particular has great starter kits and documentation to get your first robots running. When you are done with that I highly recommend adding ROS or Robot Operating System to your kit robot. The documentation will usually not talk about ROS integration but a great source for integrating such kits with ROS this playlist from The Construct Robotics Institute. Episode 1 through 6 (index 23 to index 18 in the playlist) of the two wheel robot is what you need to go through. These videos are 7 years old and they do use ROS 1 which only had Python 2 support so you will need to adapt it a bit by reading the ROS documentation but the theory still applies. Note that ROS is not an actual operating system, its an application to allow communication between and across hardware mostly using pub/sub logic.
The KR260 is a much more advanced (and more expensive) device that combines the functionality of an Arduino and a Raspberry Pi and gives you the ability to customize a lot more of the hardware because it is internally running an FPGA(Field Programmable Gate Array) on top of a regular CPU. Basically an FPGA is a type of computer that can be programmed after manufacturing. This programming is not done in regular languages like Python or even C/C++. It is done using either Verilog or VHDL. But in order to use the Kria, you don't need to know these languages as AMD has visual programming tools that can allow you to pick and place parts and configure them on a UI and using that mapping to generate your FPGA code. The result of the generated code is referred to as "applications" in the AMD documentation for the Kria.
Why do you need to generate this code and the application? With the Pi or Arduino there is a fixed pinout which means a fixed number of PWM pins and fixed functions for communication pins like TX/RX or SDA/SCL. But with the Kria KR260, nothing comes preconfigured when you boot with the Linux image. Instead once you create your application, you can have as many or as few of whatever type of pins your robot requires. You also get access to two additional idle by default processors which you can use for real time control. All this customizability comes at the cost of significantly more complexity, starting with really finding out which documentation to even read first. With this tutorial I hope to demystify that a bit. The article ends with a handy glossary of terms (generated via Claude) that you may encounter in the docs usually without explanation.
Current Documentation and Tutorials
What I suggest is look briefly at the main page and then use the ubuntu 24.04 installation and then install Vivado on the host computer. Note that you will see this term repeated many times in the docs, it mean your computer/the computer you will be programming on as opposed to the Kria KR260 which is sometimes referenced as the device computer.
If you decide to use PetaLinux(the options listed as Embedded Linux on the page), there are additional steps but when you are just starting out, I personally recommend keeping the number of tools to a minimum which is why Ubuntu 24.04 is a good starting point in my opinion. PetaLinux just lets you create a custom bundle of Linux for your hardware application. It can be a good way to bundle things if you have multiple KR260 devices or are working with them across an organization but its not needed for this tutorial.
My Experience With The KR260:
Here is my issue with the documentation of the KR260. Normally as a software developer or even a hardware developer you might expect that a getting started page would immediately help you get to the important points. But when you look at the official documentation it is very much built for people who already have experience in FPGAs and it throws a lot of jargon at you without explaining where to really start. You will see two alternating paths when you read through the resources. "Vitis" and "Vivado". At a very basic level: Vitis is platform to allow you to program the real time processor on the KR260 and Vivado is the platform to allow you to customize the hardware.
For this reason when I was first working with the device for the competition I started on the Vitis Platform because the instructions said it was the software side and I wanted to get the image recognition and object detection working to find the starawberries. After the competition, I started looking at the documentation in more depth without the time pressure and I realized how important Vivado is and how it could have helped us remove a lot of the external controllers we were using and make the build a lot cleaner. But here is the issue with Vivado documentation. If you don't already know Verilog or some basics of FPGA programming you will quickly get lost in even more jargon and its really difficult to find proper getting started tutorials. The best resources for it are Whitney Knitter's series which is linked below. Unfortunately there is no ordered list I found so I am showing one below.
Before starting the tutorials you need to first install Vivado. The instructions change depending on the version but AMD should have the latest ones here so I won't be repeating those.
Tutorial order:
- Introduction to Vivado
- Direct continunation of previous
- Adding the connectors
- Adding the connectors to an actual robot
How to follow the above tutorials:
1 and 2 can be followed as is. They will lead you through the Vivado interface and help you create the first block diagram and resulting application. With 3, there are a few things you need to be careful about.
After you have added the 5 AXI GPIO IPs, rename them to kep track of what device is which. But because you renamed the devices and then possibly added pmod_pinout.xdc and rpi_pinout.xdc from the article you may need to look through and keep the names consistent. The pmods are named pmod1_io through pmod4_io in the code so they need those name in your diagram or you need to change the xdc file with the name you use. Later in the "Create HDL Wrapper" section, because you did some renaming already you need to allow for user edits. Then you need to look at the generated .v file and you need to rename pmodx_io and rpi_gpio pins based on the name you used in the diagram.
To keep track of these name changes, the tutorial mentions a spreadsheet linking the FPGA Pin names to the PMOD and RPi pin names. You can look through that but you don't need to create a spreadsheet for this when you just want to get a set of pins running. But you should know what each pin physically maps on to in the design when you start doing the wiring so read that part in more detail after you are done with 4.
When you are done with the block diagram and configuration, ignore the "Update PetaLinux with New XSA" part and skip to the "Generate Device Tree Overlay for PL Design" and complete the remaining tutorial. This is because instead of using PetaLinux, you will load the application using xmutil on the Kria, which is described in the 4th tutorial.
Before starting with tutorial 4, you should follow tutorial 3 and make sure to find the pin numbers which is shown under the section "Testing the GPIO". You gpio chip numbers may differ but the address of the PMOD1 will still start from where you find the result saying "80010000.gpio" and the addresses of your rpi pins will start from where you see the result "80050000.gpio" for the label command.
For the fourth tutorial, you probably don't have access to the lego hardware since Technic line has been discontinued and if you find one, it is likely more expensive than buying motors and a motor controllers yourself. So you can skim through the remaining tutorial but you mainly need to follow the Controlling Motors with the KR260 specifically for transferring the files and loading the application without using PetaLinux. After this you can ignore the DB3 PMod H-Bridge because the more common L298n will also work.
You didn't configure any PWM pins for this so you can connect a jumper to the ENA and ENB pins on the L298 to keep them at constant high. This means you loose any speed control but with the current configuration you can still turn your motors on and off and control direction using the IN1, IN2, IN3 and IN4 pins for testing. I will leave it as an exercise to configure add PWM pins to the PMODs on the Vivado platform.
As for wiring on the KR260 side, you can use the same configuration as in tutorial 3 for testing but instead of or in addition to LED lights, you can add your IN1 through 4 pins. I hooked mine up to the first 4 pins of PMOD1 and set my LEDs in the ascending order of pin number. That way you know when an LED is on, the corresponding pin on the L298n is also on. And because your pins are ordered, two LEDs next to each other should never be lit up at the same time, unless they are in the middle because that produces the 1,1 value for either IN1,IN2 pair or IN3,IN4 pair. But if they are in the middle and you have 2 motors hooked up that gives you a spinning motion or two motors driving at full speed in opposite directions.
Since the pin numbers and functionality are different, the python program in tutorial 4 will also not work. If you are using my L298 example you can configure all the required PMOD pins with a script like
sudo chown ubuntu:ubuntu -R /sys/class/gpio/*
echo 698 > /sys/class/gpio/export
sudo chown ubuntu:ubuntu -R /sys/class/gpio/gpio698/*
echo 699 > /sys/class/gpio/export
sudo chown ubuntu:ubuntu -R /sys/class/gpio/gpio699/*
echo 700 > /sys/class/gpio/export
sudo chown ubuntu:ubuntu -R /sys/class/gpio/gpio700/*
echo 701 > /sys/class/gpio/export
sudo chown ubuntu:ubuntu -R /sys/class/gpio/gpio701/*
echo 702 > /sys/class/gpio/export
sudo chown ubuntu:ubuntu -R /sys/class/gpio/gpio702/*
echo 703 > /sys/class/gpio/export
sudo chown ubuntu:ubuntu -R /sys/class/gpio/gpio703/*
echo 704 > /sys/class/gpio/export
sudo chown ubuntu:ubuntu -R /sys/class/gpio/gpio704/*
echo 705 > /sys/class/gpio/export
sudo chown ubuntu:ubuntu -R /sys/class/gpio/gpio705/*
echo out > /sys/class/gpio/gpio698/direction
echo out > /sys/class/gpio/gpio699/direction
echo out > /sys/class/gpio/gpio700/direction
echo out > /sys/class/gpio/gpio701/direction
echo out > /sys/class/gpio/gpio702/direction
echo out > /sys/class/gpio/gpio703/direction
echo out > /sys/class/gpio/gpio704/direction
echo out > /sys/class/gpio/gpio705/direction
for the above note that I am using 698 through 705 gpio pin numbers. This is because in my case, the address 80010000 was at 698 and the address 80020000 was at 706, meaning all pins between 698 to 705 belong to PMOD1 and all pins from 706 through the next 8 belong to PMOD2 and so on.
Once you have set up the pins with the above script, you can run the following python program to run the wheels for 5 seconds in forward and reverse direction
import os
import time
# both forward
os.system("echo 1 > /sys/class/gpio/gpio698/value")
os.system("echo 1 > /sys/class/gpio/gpio700/value")
# after 5 seconds reverse direction
time.sleep(5)
os.system("echo 0 > /sys/class/gpio/gpio698/value")
os.system("echo 0 > /sys/class/gpio/gpio700/value")
os.system("echo 1 > /sys/class/gpio/gpio699/value")
os.system("echo 1 > /sys/class/gpio/gpio701/value")
# after 5 more seconds stop
time.sleep(5)
os.system("echo 0 > /sys/class/gpio/gpio699/value")
os.system("echo 0 > /sys/class/gpio/gpio701/value")
Once this has been verified, you can easily turn these commands into python functions and create files for ROS2 to drive a robot the same way you would for an Arduino or Raspberry Pi based one.
Glossary of Terms
The chip
- FPGA — Field Programmable Gate Array. A chip full of generic logic cells and configurable interconnect that you wire into arbitrary digital circuits.
- Fabric — informal name for the FPGA's grid of logic. "In fabric" means "built out of reconfigurable logic" as opposed to fixed silicon.
- LUT — Lookup Table. The basic building block of the fabric. A small truth table that can implement any boolean function of its inputs. When Vivado reports "resource utilization," LUTs are one of the things it's counting.
- SoC / MPSoC — System on Chip. A Zynq UltraScale+ MPSoC puts ARM CPU cores and FPGA fabric on one die.
- PS — Processing System. The hard ARM side: the A53s, the R5Fs, memory controller, USB, Ethernet.
- PL — Programmable Logic. The FPGA fabric.
- APU — Application Processing Unit. The four Cortex-A53 cores. This is what runs Ubuntu.
- RPU — Real-time Processing Unit. The two Cortex-R5F cores. These run bare-metal or RTOS firmware and are idle unless you deliberately use them. You can ignore them entirely while learning.
- Hard vs soft — "hard" means physically fixed in silicon (the A53s are hard cores). "Soft" means built out of fabric (a MicroBlaze CPU is a soft core; so is every peripheral you place). Soft things are flexible and slower; hard things are fast and fixed.
- SOM / carrier card — System on Module. The K26 is a small module with the MPSoC, RAM, and flash on it. The KR260 is the carrier card it plugs into, providing the connectors, power, and headers. The point is that you can later design your own carrier and keep the module.
The build flow
- HDL — Hardware Description Language. Verilog and VHDL are the two common ones. You describe circuits, not instructions.
- RTL — Register Transfer Level. The abstraction HDL operates at: registers and the logic between them.
- Synthesis — turning your HDL or block design into a netlist of gates. The rough analogue of compiling.
- Implementation / place and route — deciding where each gate physically goes on the chip and routing wires between them. The slow step, and the one that fails on timing.
- Timing closure — getting signals to propagate between registers fast enough for your clock rate. The FPGA equivalent of a performance problem, except it's a build error rather than a slow program.
- Bitstream — the output file. Configuration data that physically reconfigures the fabric. On Kria under Ubuntu you'll see it packaged as .bit.bin.
- Constraints / XDC — a file that maps the logical ports of your design to specific physical package pins, sets voltage standards, and declares clock frequencies. Roughly, a linker script for pins. Getting these wrong is why your PMOD does nothing.
- Board files — vendor-supplied definitions that let Vivado know what a "KR260" is, so connector pins have sensible names instead of raw package coordinates.
Blocks and buses
- IP / IP core — a reusable, pre-built hardware module. The IP catalog is effectively a package registry. AXI GPIO, AXI UARTlite, AXI Timer are all IP.
- Block design — Vivado's schematic canvas where you place IP and connect it. Where most beginner work happens.
- AXI — ARM's on-chip bus protocol, how the PS talks to IP in the PL. Comes in flavors: AXI4-Lite for simple register reads and writes (most peripherals), AXI4 for bursty high-throughput transfers, AXI4-Stream for continuous unidirectional data with no addressing, which is what you use for video pipelines.
- Memory-mapped register — the interface you actually see. Your IP lives at an address; writing to it changes hardware state.
- AXI GPIO— the specific IP block that turns PL pins into readable and writable bits. The first thing you'll place.
- DMA — Direct Memory Access. An IP block that moves data between RAM and your fabric without the CPU copying it byte by byte.
- DPU — Deep-learning Processing Unit. A large AMD-supplied IP block, built in fabric, that executes quantized neural networks. This is what Vitis AI targets. Note that it lives in the PL, not on the R5 cores.
- HLS — High-Level Synthesis. A tool that takes annotated C or C++ and generates RTL, so you can build custom IP without writing Verilog. Useful for image processing pipelines.
Getting Linux to cooperate
- Device tree — a data structure describing what hardware exists, which the Linux kernel reads to decide which drivers to load.
- Device tree overlay (.dtbo) — a runtime patch to that description, needed because loading a bitstream creates hardware after boot.
- xmutil — the Kria command-line tool that loads a bitstream plus its overlay, making your PL design visible to Linux.
- UIO — Userspace I/O. A generic Linux driver that exposes an IP block's register space to userspace so you can mmap it and poke registers from Python or C, without writing a kernel driver.
- PMOD — Digilent's small peripheral connector standard, 6 or 12 pins. Common on FPGA boards for sensors and breakouts.
The tools
- Vivado — builds hardware. Block designs, synthesis, bitstreams. If your pins aren't working, you're here.
- Vitis — builds software and accelerated applications for the hardware Vivado produced, including R5 firmware.
- Vitis AI — the ML toolchain that quantizes models and compiles them for the DPU.
- PetaLinux — AMD's toolchain for building a custom embedded Linux image. Powerful, and one more thing to learn. Ubuntu 24.04 is the easier starting point.