top of page

Create a MicroBlaze, Test the UART in SDK, and Boot Linux using 2019.1 Vivado and PetaLinux Tools

Updated: May 14, 2023

This post contains everything needed to create a MicroBlaze design and boot Linux on it over JTAG. It also contains links to all the IP documentation and how to smoke-test a design before using it.

Versions Used

2019.1 Vivado, PetaLinux Tools, and XSDK

VMWare Workstation 14 Player running Ubuntu 16.04.5 LTS running on Windows 10

Update Vivado 2019.1


I needed this patch to build the bitstream.


Step #1: Download the patch at:,will%20not%20generate%20a%20response.

Step #2: Exit Vivado 2019.1

Note: commands assume Vivado is installed at:


Step #3: Run

mkdir /tools/Xilinx/Vivado/2019.1/patches
mkdir /tools/Xilinx/Vivado/2019.1/patches/AR72956
pushd /tools/Xilinx/Vivado/2019.1/patches/AR72956
unzip ~/Downloads/

Step #4: Restart Vivado 2019.1

Step #5: Check that the Patch Applied

Enter in the Design


For Linux to boot on MicroBlaze

Page 19 of lists the requirements to run Linux on a MicroBlaze. I've left out both the Non-volatile memory and Ethernet in this design. Also, I use an AXI Timer, not a Dual channel timer.


Step #1: Run Vivado 2019.1

Step #2: File > Project > New

Step #3: Click Next on the Create New Vivado Project window

Step # 3.1: Click Next in the Project Name window

Step #3.2: (A) Click RTL Project and (B) click Next

Step # 3.3: (A) Click Boards, (B) enter zcu102, (C) click on the line, and (D) click Next

Step #3.4: Click Finish

Create the Block Design


Step #1: Click Create Block Design

Step #1.1: Click OK

Step #2: (A) Click Board, (B) Pull DDR4 SDRAM to the Diagram, and (C) click OK

Step #3: Click Run Connection Automation

Step #3.1: (A) Check all checkboxes and (B) click OK

You should see:

Step #4: (A) Click +, (B) type micro, and (C) double-click MicroBlaze

Step #5: Click Run Block Automation

Step #6: (A) Check the Interrupt Controller checkbox and (B) click OK

Note: we select Linux with MMU later during IP customization

Note 2: this ^^^ step is how you get microblaze_0_local_memory

Step #7: Click Run Connection Automation

Step #7.1: (A) Select all checkboxes and (B) click OK

You should see:

Step #7.2: (A) Click Board, (B) click and drag UART, (C) click OK, and (D) click Run Connection Automation

Step #7.3: Click OK

You should see:

Step #8: (A) Click +, (B) Type AXI Timer, and (C) click AXI Timer

Step #8.1: Click Run Connection Automation

Step # 8.2: Click OK

You should see:

Step #9: Connect the axi_timer_0 interrupt and the axi_uartlite_0 interrupt pins to the microblaze_0_xlconcat

Note: you will still see the UART output in XSDK without this, and Linux will run, but you won't see any UART output.

Customize the MicroBlaze IP


Step #1: Double click on the microblaze_0 instance of the MicroBlaze

Step #1.1: (A) Select Linux with MMU and (B) click OK

You only need to set Linux with MMU. Here are the other pages as a reference.

Page 1

Page 2

Page 3

Page 4

Page 5

Page 6

Page 7

Get Ready to Create the Bitstream


Step #1: Check the Board

Step #2: Check the full design

Step #2.1: Zoom into the left side

Step #2.2: Zoom into the right side

Step #3: Check the Address Editor

Step #4: Check the Project Summary

Step #4.1: Click PROJECT MANAGER to get the Project Summary

You should see something like:

Create the Bitstream


Step #1: Create the HDL Wrapper

Step #1.1: (A) Click Sources, (B) right-click design_1 (design_1_hd), and (C) click Create HDL Wrapper...

Step #1.2: Leave Let Vivado manage wrapper and auto-update selected and click OK

You should see:

Step #2: Click Generate Bitstream

Step #2.1: Click Save

Step #2.2: Click Yes on the No Implementation Results Available notification box

Step #2.3: Select as many cores as you can and click OK

Note: this can take 1 to 2 hours to run

Note 2: You should see a status indicator in the upper right-hand corner

Program the Bitstream


Step #1: (A) Select Open Hardware Manager and (B) click OK

Step #2: Plug the UART and JTAG USB cables into the board...

Step #2.1: ...and into a hub...

Step #2.2: ...which is plugged into the computer

Important note: using a hub is a good way to connect the JTAG and UART USB devices to a VM. It has worked for VMWare and VirtualBox.

Step #3: Make sure the SW6 is set to JTAG boot the ZCU102

Step #4: Turn on the ZCU102

Step #5: Ensure that the Cygnal Integrated CP2108 Quad USB to UART Bridge Controller is enabled and Future Devices Digilent USB Device is enabled.

Step #6: Click Open target

Step #7: Click Auto Connect

Step #8: Click Program device

Step #9: Click Program

You should see:

Export the Design for UART Smoke Test with XSDK and Creating a Linux Build with PetaLinux


Step #1: (A) Click File, (B) Export, and (C) Export Hardware...

Step #1.1: Click OK

Create a Hello World test App to Test the UART Works Before Creating a Linux Build


Step #1: (A) Click File and (B) click Launch SDK

Step #1.1: Click OK

Step #2: (A) Click the drop-down and (B) click Application Project

Step #2.1: (A) Use Hello_world for the Project name: and (B) click Next

Important Note: never use spaces; the SDK cannot handle spaces

Step #2.2: (A) Click Hello World and (B) Finish

Step #3: Open a terminal and start screen using:

screen /dev/ttyUSB2 9600

Note 1: Type Ctrl-a d to detach, Ctrl-a k to kill

Note 2: After detaching, reattached with:

screen -r 

Note 3: if someone else has attached, reattach with:

screen -x

Note 4: to clear what's in a screen, type Ctrl-a C. To get more commands, type Ctrl-a ?

Step #4: (A) Right-click on Hello_world, (B) click Debug As, and (C) click Launch on Hardware (System Debugger)

Step #5: Click Yes to Confirm Perspective Switch

You will likely not see anything because the target is stuck at:

void XUartLite_SendByte(UINTPTR BaseAddress, u8 Data)
 while (XUartLite_IsTransmitFull(BaseAddress));   /* <<<<< stuck */

 XUartLite_WriteReg(BaseAddress, XUL_TX_FIFO_OFFSET, Data);

...and the memory load from the UART returned:

xsct% mrd 0x40600000

xsct% Memory read error at 0x40600000. Memory access exception


We'll fix that next by ensuring we click the Reset entire system check box in the Debug configuration.

Step #6: (A) Click the debug drop down and (B) click Debug Configurations....

Step #6.1: (A) Check the Reset entire system checkbox, (B) click Apply, and (C) click Debug

Step #6.2: Click OK

Step #7:Click Step Over

Step #7.1: Click Step Over again

Step #7.2: ...and one more time observing Hello World on your screen session

Note: To restart debugging, click the Bug...

...and click OK...

Create and Build MicroBlaze Linux


Step #1: Type the following to create a PetaLinux project and build it

cd plxprjs/
source ~/petalinux/2019.1/
petalinux-create --type project --template microblaze --name zcu102mb
cd zcu102mb
petalinux-config --get-hw-description=/home/demo/project_3/project_3.sdk
# Accept defaults and exit (just select Exit in the autoconfig)

Step #2: Reset the ZCU102

Step #3: Download the FPGA using xsct

cd /home/demo/petalinux/2019.1/tools/xsct/bin/
 connect -url tcp:localhost:3121
 # Select the PL
 targets 3
 fpga -no-revision-check /home/demo/plxprjs/zcu102mb/images/linux/system.bit

Note 1:

I needed to use xsct flow because I got a

WARNING: [Xicom 50-99] Incorrect bitstream assigned to device. Bitstream was generated for part xczu9eg-ffvb1156-2-e, target device (with IDCODE revision 1) is compatible with es2 revision bitstreams.

Note 2: You can download the bit file using HARDWARE MANAGER by running:

set_param xicom.use_bitstream_version_check false Vivado

Step #4: Back in PetaLinux type:

petalinux-boot --jtag --kernel -v

Note: Consider always using -v to see what the command actually does

Step #5: Examine build output:

INFO: sourcing build tools
XSDB Script:
INFO: Launching XSDB for file download and boot.
INFO: This may take a few minutes, depending on the size of your image.

targets -set -nocase -filter {name =~ "microblaze*#0"}
puts stderr "INFO: Downloading ELF file: /home/demo/plxprjs/zcu102mb/images/linux/image.elf to the target."
dow "/home/demo/plxprjs/zcu102mb/images/linux/image.elf"
after 2000
rlwrap: warning: your $TERM is 'xterm-256color' but rlwrap couldn't find it in the terminfo database. Expect some problems.: Inappropriate ioctl for device
INFO: Downloading ELF file: /home/demo/plxprjs/zcu102mb/images/linux/image.elf to the target.
Downloading Program -- /home/demo/plxprjs/zcu102mb/images/linux/image.elf
 section, .text: 0xc0000000 - 0xc043d427
 section, __fdt_blob: 0xc043d428 - 0xc044d427
 section, .rodata: 0xc044e000 - 0xc0565adf
 section, .pci_fixup: 0xc0565ae0 - 0xc056767f
 section, __ksymtab: 0xc0567680 - 0xc056ddbf
 section, __ksymtab_gpl: 0xc056ddc0 - 0xc0572717
 section, __ksymtab_strings: 0xc0572718 - 0xc058bf6c
 section, __param: 0xc058bf70 - 0xc058c537
 section, __modver: 0xc058c538 - 0xc058cfff
 section, __ex_table: 0xc058d000 - 0xc058e53f
 section, .notes: 0xc058e540 - 0xc058e57b
 section, .sdata2: 0xc058e57c - 0xc058efff
 section, .data: 0xc058f000 - 0xc05b557f
 section, .init.text: 0xc05b6000 - 0xc05d9c1f
 section, 0xc05d9c20 - 0xc05db6b3
 section, .init.ivt: 0xc05db6b4 - 0xc05db6db
 section, .init.setup: 0xc05db6dc - 0xc05dba8f
 section, .initcall.init: 0xc05dba90 - 0xc05dbe07
 section, .con_initcall.init: 0xc05dbe08 - 0xc05dbe0b
 section, .init.ramfs: 0xc05dbe0c - 0xc1283013
 section, .bss: 0xc1284000 - 0xc1310533
100% 18MB 0.2MB/s 01:52 
Setting PC to Program Start Address 0x80000000
Successfully downloaded /home/demo/plxprjs/zcu102mb/images/linux/image.elf

Step #6: Examine console output

Note 1: it looks like the console hangs, but it eventually came up (after a few minutes)

Note 2: Use root for the username and root for the password

Ramdisk addr 0x00000000,
Compiled-in FDT at (ptrval)
Linux version 4.19.0-xilinx-v2019.1 (oe-user@oe-host) (gcc version 8.2.0 (GCC)) #1 Sun Mar 7 18:29:2
2 UTC 2021
setup_memory: max_mapnr: 0x20000
setup_memory: min_low_pfn: 0x80000
setup_memory: max_low_pfn: 0xa0000
setup_memory: max_pfn: 0xa0000
Zone ranges:
 DMA [mem 0x0000000080000000-0x000000009fffffff]
 Normal empty
 HighMem empty
Movable zone start for each node
Early memory node ranges
 node 0: [mem 0x0000000080000000-0x000000009fffffff]
Initmem setup node 0 [mem 0x0000000080000000-0x000000009fffffff]
On node 0 totalpages: 131072
 DMA zone: 1024 pages used for memmap
 DMA zone: 0 pages reserved
 DMA zone: 131072 pages, LIFO batch:31
setup_cpuinfo: initialising
setup_cpuinfo: Using full CPU PVR support
pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
pcpu-alloc: [0] 0
Built 1 zonelists, mobility grouping on. Total pages: 130048
Kernel command line: console=ttyUL0,9600 earlyprintk
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
Memory: 499716K/524288K available (4341K kernel code, 153K rwdata, 1276K rodata, 13108K init, 561K b
ss, 24572K reserved, 0K cma-reserved, 0K highmem)
Kernel virtual memory layout:
 * 0xfffea000..0xfffff000 : fixmap
 * 0xff800000..0xffc00000 : highmem PTEs
 * 0xff800000..0xff800000 : early ioremap
 * 0xf0000000..0xff800000 : vmalloc & ioremap
NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
irq-xilinx: /amba_pl/interrupt-controller@41200000: num_irq=2, edge=0x1
/amba_pl/timer@41c00000: irq=1
clocksource: xilinx_clocksource: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 6370868154 ns
sched_clock: 32 bits at 300MHz, resolution 3ns, wraps every 7158278654ns
Calibrating delay loop... 49.35 BogoMIPS (lpj=246784)
pid_max: default: 4096 minimum: 301
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
devtmpfs: initialized
random: get_random_u32 called from bucket_table_alloc+0xa0/0x23c with crng_init=0
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
futex hash table entries: 16 (order: -4, 448 bytes)
NET: Registered protocol family 16
audit: initializing netlink subsys (disabled)
PCI: Probing PCI hardware
audit: type=2000 audit(0.200:1): state=initialized audit_enabled=0 res=1
vgaarb: loaded
clocksource: Switched to clocksource xilinx_clocksource
NET: Registered protocol family 2
tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 6144 bytes)
TCP established hash table entries: 4096 (order: 2, 16384 bytes)
TCP bind hash table entries: 4096 (order: 4, 81920 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
UDP hash table entries: 256 (order: 1, 12288 bytes)
UDP-Lite hash table entries: 256 (order: 1, 12288 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
PCI: CLS 0 bytes, default 32
random: fast init done
Skipping unavailable RESET gpio -2 (reset)
workingset: timestamp_bits=30 max_order=17 bucket_order=0
romfs: ROMFS MTD (C) 2007 Red Hat, Inc.
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
io scheduler mq-deadline registered
io scheduler kyber registered
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
40600000.serial: ttyUL0 at MMIO 0x40600000 (irq = 2, base_baud = 0) is a uartlite
console [ttyUL0] enabled
brd: module loaded
libphy: Fixed MDIO Bus: probed
NET: Registered protocol family 17
Key type encrypted registered
Warning: unable to open an initial console.
Freeing unused kernel memory: 13108K
This architecture does not have kernel memory protection.
Run /init as init process
random: dd: uninitialized urandom read (512 bytes read)
random: dropbearkey: uninitialized urandom read (32 bytes read)
random: dropbearkey: uninitialized urandom read (32 bytes read)
random: crng init done
PetaLinux 2019.1 zcu102mb /dev/ttyUL0

zcu102mb login:

Example of Checking the Pins and How the Pins Map to a Part

Once the bitstream has completed, check package pins

To get to the Package Pins

Step #1: Click Open Implemented Design

Step #2: A) Click Window, B) click I/O Ports

Step #3: Turn off Group by Interface and Bus to get a linear tale

Package Pins:







Ref Des: U42

Device: Oscillator

Package: SI570

Value: 10MHZ_TO_810MHZ

Voltage: N/A

Tolerance: 50PPM

Dielectric: N/A

Power: N/A


Manf P/N: 570BAB001614DG

Dist: Silicon Labs

Dist P/N: 570BAB001614DG

Alternate P/N: N/A

Barcode: 600047








Item#: 268

Qty: 1

Ref Des: U40

Device: IC Bridge

Package: 64_VFQFN

Value: CP2108

Voltage: 3.3V

Tolerance: N/A

Dielectric: N/A

Power: N/A


Manf P/N: CP2108-B02-GM

Dist: Digikey

Dist P/N: 336-3020-ND

Alternate P/N: N/A

Barcode: 500404


Core Docs


MicroBlaze Debug Module (MDM) (3.2)

MicroBlaze Debug Module v3.2 LogiCORE IP Product Guide Vivado Design Suite

PG115 (v3.2) January 21, 2021


DDR4 SDRAM (MIG) (2.2)


MicroBlaze (11.0)


Processor System Reset (5.0)

Processor System Reset Module v5.0 LogiCORE IP Product Guide PG164 November 18, 2015


AXI Uartlite (2.0)

AXI UART Lite v2.0 LogiCORE IP Product Guide Vivado Design Suite PG142 April 5, 2017


AXI SmartConnect (1.0)

SmartConnect v1.0 LogiCORE IP Product Guide Vivado Design Suite PG247 February 3, 2020


Processor System Reset

Processor System Reset (5.0)

Processor System Reset Module v5.0 LogiCORE IP Product Guide PG164 November 18, 2015


AXI Interconnect

AXI Interconnect (2.1)

AXI Interconnect v2.1 LogiCORE IP Product Guide Vivado Design Suite PG059 December 20, 2017



Concat (2.1)


AXI Interrupt Controller

AXI Interrupt Controller (4.1)

AXI Interrupt Controller (INTC) v4.1 LogiCORE IP Product Guide Vivado Design Suite PG099 June 24, 2020



Local Memory Bus (LMB) 1.0

Local Memory Bus (LMB) v3.0 LogiCORE IP Product Guide Vivado Design Suite PG113 April 6, 2016


LMB BRAM Controller

LMB BRAM Controller (4.0)

LMB BRAM Interface Controller v4.0 LogiCORE IP Product Guide Vivado Design Suite PG112 January 21, 2021


Block Memory Generator

Block Memory Generator (8.4)

Block Memory Generator v8.4 LogiCORE IP Product Guide Vivado Design Suite PG058 December 9, 2019


Zynq UltraScale+ MPSoC ZCU102 Evaluation Kit

PetaLinux Tools Documentation Reference Guide UG1144 (v2019.1) May 22, 2019

MicroBlaze Processor Reference Guide UG984 (v2019.1) May 22, 2019:

MicroZed Chronicles: Building PetaLinux for MicroBlaze — Part One

MicroZed Chronicles: Building PetaLinux for MicroBlaze — Part 2

Running Hello World on Microblaze + ZCU102

Utilizing PS memory to execute Microblaze application on Zynq Ultrascale

Vivado Design Suite User Guide Embedded Processor Hardware Design UG898 (v2019.1) June 4, 2019

Vivado Design Suite User Guide Designing IP Subsystems Using IP Integrator UG994 (v2019.1) May 22, 2019

Generating Basic Software Platforms Reference Guide

UG1138 (v2018.2) July 16, 2018

UG1138 (v2019.2) October 30, 2019

Xilinx logo from [link]

bottom of page