Hello World on Microblaze UART on PS in Zynq Processor

In this post we will show how to print a message from Microblaze to the built-in ARM UART on a Zynq SoC using Vivado. In academic boards with Zynq processor, UART hardware is not simply available to the programmable logic (PL). However, in the evaluation board, the UART physical port is permanently tied to PS MIO and it is not possible to interface it to a UART IP like axi_uartlite. So you don’t have access to RX TX pins (one dirty hack).

To show how to say “Hello World” from the Microblaze and send it to the UART on the PS via the PG port on the PS we first need to create the hardware design. In the Vivado add two elements in the IP Intgrator, namely “processing_system7_0” (this is the component interfaces between the ARM hard-logic and the PL) and also a Microblaze. Double click on the Zynq7 Processing System to enable the S AXI GP0 interface. Click on the green “32b GP AXI Slave Ports” box at the bottom towards the middle and on the window that opens, check the box next to “Enable S_AXI_GP0 interface”. (General purpose 32-bit AXI Slave Interface 0). The Microbalze communicates with Zymq PS through the S AXI GP0. Increase the local memormy of Microblaze to 64KB and uncheck the cache.

To connect the two processors together, we’ll use the GP AXI Slave Port. Switch to the “Zynq” tab and Notice that one of the arrows turns green back in the diagram. Switch back to the “Bus Interfaces” tab and expand the “processing_system7_0” component, notice that a new signal “S_AXI_GP0” is now visible. Connect this to the “microblaze_0_axi_periph” bus. This connection allows the MB to use the ARM resources like an AXI slave.

Run Block Automation and Connection Automation. Either uncheck the M AXI GP0 in Zynq configuration or simply connect the master and slave to each other. You will get the following design:

Block Design

Do the followings: Generate Output Products Create HDL Wrapper Generate Bitstream Export to SDK include bitstream and finally Launch SDK.

In the SDK, make a new Application Project. Name it as you want and let microblaze_0 be the default processor. Create a Hello World app and finish it. Open the helloworld.c in the src folder and replace it with the following code:

#include <stdio.h>
#include "platform.h"
#include "xil_io.h"

/* Write to memory location or register */
#define X_mWriteReg(BASE_ADDRESS, RegOffset, data) \
           *(unsigned int *)(BASE_ADDRESS + RegOffset) = ((unsigned int) data);
/* Read from memory location or register */
#define X_mReadReg(BASE_ADDRESS, RegOffset) \
           *(unsigned int *)(BASE_ADDRESS + RegOffset);

//void print(char *str);

#define XUartChanged_IsTransmitFull(BaseAddress)			 \
	((Xil_In32((BaseAddress) + 0x2C) & 	\
	 0x10) == 0x10)

void XUartChanged_SendByte(u32 BaseAddress, u8 Data)
{
		/*
		 * Wait until there is space in TX FIFO
		 */
		while (XUartChanged_IsTransmitFull(BaseAddress));

		/*
		 * Write the byte into the TX FIFO
		 */
		X_mWriteReg(BaseAddress, 0x30, Data);
}

void outbyte(char c) {
	 XUartChanged_SendByte(0xE0001000, c);
}

void ChangedPrint(char *ptr)
{
  while (*ptr) {
    outbyte (*ptr++);
  }
}


int main()
{

	ChangedPrint("Hello World from MicroBlaze\n\r");

    return 0;
}

Then go to Xilinx Tools and click Program FPGA. Then right click on your project and select run as -> Launch on Hardware (GDB). Open a serial port with 115200 as the baudrate in the SDK Terminal and wait until the Hello World message appears.

All the Vivado and SDK projects files are available in here .

P.S: It is also possible to instantiate a axi_uartlite in the PL based IP and then use a daughter card to be plugged in available pins on the board.

Borrowed partially from:

https://forums.xilinx.com/t5/Zynq-All-Programmable-SoC/UART-console-from-UART-IP-from-PL-region/m-p/687235/highlight/true#M11992

http://www.xilinx.com/support/documentation/application_notes/xapp1093-amp-bare-metal-microblaze.pdf

http://www.xilinx.com/support/answers/50869.html

Written on October 8, 2016