This project demonstrates how to create a simple PL design in Vivado to control the user-defined LEDs (DS7 and DS8) on the KR260 carrier board. The design uses an AXI GPIO IP core connected to the Zynq UltraScale+ Processing System (PS) via an AXI SmartConnect, enabling software control of the LEDs from Linux running on the APU.
This is a follow-up project to the Custom Yocto Linux & Network Boot for Xilinx KR260 post, which provides the foundation Linux environment with PYNQ, XRT, and network boot capabilities.
Problem StatementWhen developing FPGA applications on the KR260, you often need to:
- Create custom PL designs that interact with the PS
- Rapidly prototype and test hardware designs without lengthy compilation cycles
- Validate hardware functionality before integrating with more complex applications
- Prepare hardware designs for integration with RPU firmware or custom Linux drivers
Traditional FPGA development workflows require:
- Writing HDL code or using IP integrator
- Synthesizing and implementing the design
- Generating bitstreams
- Flashing SD cards or manually loading bitstreams
- Writing C/C++ applications to interact with hardware
This project simplifies this workflow by:
- Using Vivado's IP Integrator for visual design
- Leveraging PYNQ for Python-based hardware interaction
- Enabling rapid iteration through network boot and dynamic bitstream loading
The PL design consists of:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Zynq UltraScale+ PS β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β M_AXI_HPM0_LPD (Master AXI) β β
β βββββββββββββββ-βββββ¬βββββββββββββββββββββββββββββββββ-β β
ββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββ
β
β AXI4
β
ββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββ
β AXI SmartConnect (AXI SMC) β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β S00_AXI (Slave) βββββββββΊ M00_AXI (Master) β β
β ββββββββββββββ-ββββββ¬ββββββββββββββββββββββββββββββ-ββββ β
ββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββ
β
β AXI4-Lite
β
ββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββ
β AXI GPIO IP β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β GPIO Channel 1 (2-bit output) β β
β βββββββββββββββ-βββββ¬ββββββββββββββββββββββββββββ-ββββββ β
ββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββ
β
β GPIO[1:0]
β
ββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββ
β KR260 Carrier Board LEDs β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β LED0 (DS8) - Pin E8 (LVCMOS18) β β
β β LED1 (DS7) - Pin F8 (LVCMOS18) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββSoftware Architectureββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Linux APU (Yocto + PYNQ) β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Jupyter Notebook Server (:9090) β β
β β ββββββββββββββββββββββββββββββββββββββββββββββββ β β
β β β led_blink_pynq.ipynb β β β
β β β - Load bitstream via PYNQ β β β
β β β - Access AXI GPIO via Python β β β
β β β - Control LED patterns β β β
β β ββββββββββββββββββββββββββββββββββββββββββββββββ β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β PYNQ Runtime β β
β β - Bitstream loading β β
β β - Hardware description parsing (.hwh) β β
β β - IP register mapping β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β XRT (Xilinx Runtime) β β
β β - Device management β β
β β - Bitstream programming β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββDesign ComponentsZynq UltraScale+ PS: Processing System with ARM Cortex-A53 cores
- M_AXI_HPM0_LPD: Low Power Domain Master port for PL access
- PL_CLK0: 100 MHz clock output to PL
- PL_RESETN0: Reset signal to PL
AXI SmartConnect: Interconnect IP for AXI bus routing
- Connects PS master to PL slaves
- Handles protocol conversion and address mapping
AXI GPIO: General Purpose I/O IP core
- 2-bit output channel (GPIO[1:0])
- AXI4-Lite slave interface
- Base address: Assigned by Vivado (typically in LPD address space 0x80000000-0x9FFFFFFF)
Processor System Reset: Reset controller
- Synchronizes reset signals
- Provides reset to PL logic
This project assumes you have completed the Custom Yocto Linux & Network Boot project, which provides:
- Network-bootable Yocto Linux image
- PYNQ 3.1.2 runtime
- XRT and ZOCL support
- Jupyter Notebook server on port 9090
- NFS root filesystem mounted at
/nfsroot
- Launch Vivado and select Create Project
- Project Settings:Project name:
gpio_ledProject location: Choose your workspace directoryProject type: RTL Project (default) - Add Sources: Click Next (we'll create the design using IP Integrator)
- Add Constraints: Click Next (we'll add constraints later)
- Default Part:Select Boards tabSearch for KR260 and select KR260 Robotics Starter KitClick Next and Finish
- In the Flow Navigator, click Create Block DesignDesign name:
gpio_ledClick OK - Add Zynq UltraScale+ PS:Click + button in the diagramSearch for Zynq UltraScale+ PSDouble-click to add
zynq_ultra_ps_e_0
- Configure PS:Double-click the PS blockIn the PS Configuration window, navigate to PS-PL Configuration β GeneralEnable M_AXI_HPM0_LPD (Low Power Domain master port)Click Run Block AutomationThis will enable M_AXI_HPM0_LPD, PL_CLK0, and PL_RESETN0Click OK
- Add AXI GPIO:Click + buttonSearch for AXI GPIODouble-click to add
axi_gpio_0
- Configure AXI GPIO:Double-click the GPIO blockGPIO:Check All OutputsGPIO Width: 2Click OK
- Run Connection Automation:
- Click Run Connection Automation
- Select All Automation
- This will:Connect PS M_AXI_HPM0_LPD to AXI SmartConnectConnect AXI SmartConnect to AXI GPIOConnect clock and reset signals
- Click OK
- Create External Port:Right-click on
axi_gpio_0GPIO portSelect Make ExternalRename the port toled_output - Validate Design:Click Validate Design (F6)Ensure no errors or critical warnings
- Create HDL Wrapper:Right-click on
gpio_ledblock design in SourcesSelect Create HDL WrapperChoose Let Vivado manage wrapper and auto-updateClick OK
- Create Constraints File:In Sources, right-click Constraints β constrs_1Select Add Sources β Add or create constraintsClick Create FileFile name:
gpio_led.xdcClick OK and Finish
Add Pin Constraints: Open gpio_led.xdc and add:
# --- XDC for KR260 LED Demo ---
# KR260 carrier board D13/D14 connector:
# https://github.com/Xilinx/XilinxBoardStore/blob/2022.2/boards/Xilinx/kr260_carrier/1.0/board.xml#L221
# KR260-SoM for exact pin location:
# https://github.com/Xilinx/XilinxBoardStore/blob/2022.2/boards/Xilinx/kr260_som/1.1/part0_pins.xml#L64
# LED0 (DS8) - Pin E8 (HP Bank, using compatible LVCMOS18 standard)
set_property PACKAGE_PIN E8 [get_ports {led_output_tri_o[0]}]
set_property IOSTANDARD LVCMOS18 [get_ports {led_output_tri_o[0]}]
# LED1 (DS7) - Pin F8 (HP Bank, using compatible LVCMOS18 standard)
set_property PACKAGE_PIN F8 [get_ports {led_output_tri_o[1]}]
set_property IOSTANDARD LVCMOS18 [get_ports {led_output_tri_o[1]}]- Save the constraints file
- Run Synthesis:In Flow Navigator, click Run SynthesisWait for synthesis to complete (5-10 minutes depends on PC)
- Review Synthesis Results:Check for any errors or critical warningsVerify resource utilization is reasonable
- Run Implementation:Click Run ImplementationWait for implementation to complete (10-20 minutes depends on PC)
- Review Implementation Results:Check timing closureVerify no critical warnings
- Generate Bitstream:Click Generate BitstreamWait for bitstream generation (5-10 minutes depends on PC)
- Verify Output Files: After bitstream generation, verify these files exist:
gpio_led.runs/impl_1/gpio_led_wrapper.bit- Bitstream filegpio_led.gen/sources_1/bd/gpio_led/hw_handoff/gpio_led.hwh- Hardware description
- Export Hardware:In Flow Navigator, go to File β Export β Export HardwareSelect Include bitstreamClick NextExport location: Default (project directory)File name:
gpio_led.xsaClick FinishNote: The.xsafile will be used in the next project for RPU integration with Vitis.
- Locate Generated Files:Bitstream:
gpio_led.runs/impl_1/gpio_led_wrapper.bitHardware description:gpio_led.gen/sources_1/bd/gpio_led/hw_handoff/gpio_led.hwh - Copy to NFS Root: On your NFS server (where
/nfsrootis mounted):
# Copy bitstream (rename to gpio_led.bit)
cp gpio_led.runs/impl_1/gpio_led_wrapper.bit \
/nfsroot/home/xilinx/Notebook/gpio_led.bit
# Copy hardware description (rename to gpio_led.hwh)
cp gpio_led.gen/sources_1/bd/gpio_led/hw_handoff/gpio_led.hwh \
/nfsroot/home/xilinx/Notebook/gpio_led.hwh
# Set appropriate permissions
chmod 644 /nfsroot/home/xilinx/Notebook/gpio_led.bit
chmod 644 /nfsroot/home/xilinx/Notebook/gpio_led.hwh
Step 11: Create PYNQ Notebook- Create Notebook File: Create
led_blink_pynq.ipynbin/nfsroot/home/xilinx/Notebook/Or create it as a Python script and convert, or use Jupyter's web interface.
- Boot KR260:Ensure KR260 is network-booted (from previous project)Verify Jupyter is accessible at
http://172.20.1.1:9090 - Open Jupyter Notebook:Navigate to Jupyter in your browserOpen
led_blink_pynq.ipynb - Run the Notebook:Execute the first cell to reset the PLExecute the second cell to load the bitstream and run the LED patternObserve LEDs DS7 and DS8 on the KR260 board
Expected Behavior:
- Expected Behavior:LED0 (DS8) and LED1 (DS7) will blink in a walking pattern:Pattern 1: LED0 ON, LED1 OFF (0x1)Pattern 2: LED0 OFF, LED1 ON (0x2)Pattern 3: Both LEDs ON (0x3)Pattern 4: LED0 OFF, LED1 ON (0x2)Repeat 5 times with 0.5s pause between cycles
overlay = Overlay("gpio_led.bit")PYNQ's Overlay class:
- Loads the bitstream into the FPGA
- Parses the
.hwhfile to understand the hardware structure - Creates Python objects for each IP core (e.g.,
overlay.axi_gpio_0)
led_gpio = overlay.axi_gpio_0.channel1axi_gpio_0is the instance name from the Vivado block designchannel1is the GPIO channel (Channel 1 is the first channel)- The GPIO object provides
read()andwrite()methods
led_gpio.write(pattern, mask)pattern: Value to write (0x0 to 0x3 for 2 bits)mask: Bit mask indicating which bits to affect (0x3 = both bits)
- M_AXI_HPM0_LPD (Low Power Domain) is used instead of FPD (Full Power Domain)
- Rationale: GPIO control requires low bandwidth, making LPD ideal for power efficiency
- LPD provides sufficient performance for GPIO operations while consuming less power
- FPD ports are better reserved for high-bandwidth applications (video processing, DMA, etc.)
- PL clock: 100 MHz (from PS PL_CLK0)
- AXI bus clock: 100 MHz (synchronized with PL clock)
- GPIO update rate: Limited by Python loop speed (~4 Hz in this example)
- All Outputs: GPIO configured as output-only (no input capability)
- Width: 2 bits (matching two LEDs)
- I/O Standard: LVCMOS18 (compatible with KR260 HP bank)
- AXI GPIO base address:
0x80000000(LPD address space) - Address range: 64 KB (standard AXI4-Lite slave)
- Accessible from Linux userspace via PYNQ
- Note: LPD (Low Power Domain) uses the 0x80000000 address range, which is suitable for GPIO and other low-bandwidth peripherals
This project provides a foundation for more advanced PL development:
- Add More GPIO: Extend to control additional LEDs or read switches
- Custom IP Integration: Add custom AXI IP cores to the design
- Interrupt Support: Configure GPIO interrupts for event-driven control
- RPU Integration: Move LED control logic to RPU (see next project)
The next project in this series will demonstrate:
- Building FreeRTOS application for RPU using Xilinx Vitis Unified IDE
- Loading PL bitstream from APU using XRT
- Loading RPU firmware using remoteproc framework
- APU-RPU communication via libmetal and OpenAMP
- Shared memory between APU, RPU, and PL
- Real-time LED control from RPU while APU handles high-level tasks
This will showcase the full heterogeneous computing capabilities of the KR260, combining:
- APU: Linux for high-level control and networking
- RPU: FreeRTOS for real-time, deterministic tasks
- PL: Custom hardware accelerators and I/O
- Xilinx KR260 Documentation: Kria KR260 Documentation
- PYNQ Documentation: PYNQ.io
- Vivado Design Suite: Xilinx Vivado
- Previous Project: Custom Yocto Linux & Network Boot for KR260
This project demonstrated:
β Creating a PL design in Vivado using IP Integratorβ Configuring AXI GPIO for LED controlβ Adding pin constraints for KR260 boardβ Generating bitstream and hardware descriptionβ Loading bitstream dynamically using PYNQβ Controlling hardware from Python/Jupyterβ Rapid prototyping workflow for FPGA development
The combination of Vivado's visual design tools and PYNQ's Python interface creates a powerful, accessible platform for FPGA development on the KR260. This workflow enables rapid iteration and experimentation, making FPGA development more approachable for software engineers and embedded developers.







Comments