element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Path to Programmable 3
  • Challenges & Projects
  • Design Challenges
  • Path to Programmable 3
  • More
  • Cancel
Path to Programmable 3
Blog P2P3 AMD Vitis portability and reuse. Migrating a Microblaze bare metal environmental monitor App to the Zynq architecture.
  • Blog
  • Forum
  • Documents
  • Leaderboard
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Path to Programmable 3 to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: javagoza
  • Date Created: 10 Jun 2023 6:16 PM Date Created
  • Views 3005 views
  • Likes 12 likes
  • Comments 5 comments
  • Environmental Monitor
  • AMD XILINX
  • avnet
  • artix-7
  • pathtoprogrammableIII
  • zynq
  • portability
  • fpga
  • vivado
  • digilent
  • blog 2
  • amd
  • vitis
  • microblaze
  • minized
Related
Recommended

P2P3 AMD Vitis portability and reuse. Migrating a Microblaze bare metal environmental monitor App to the Zynq architecture.

javagoza
javagoza
10 Jun 2023
Minized Zynq Environmental Monitor

Introduction

In the current exercise, I want to evaluate the portability and reusability features provided by the Vitis Unified Software Platform environment to migrate an application I developed with a Spartan-7 FPGA, implementing a MicroBlaze soft processor, to the MiniZed architecture, a single-core Zynq.

A few months ago, I explored the possibilities of AMD Vitis and Vivado tools for rapid prototyping. To explore those possibilities, I built a simple environmental monitor that reported ambient temperature and relative humidity on a small OLED display. For that development, I used a MicroBlaze soft processor created within AMD's Spartan-7 FPGA from the 7 series of FPGAs.

Let's see how complicated it is to migrate the solution based on the Microblaze soft processor to the Minized with a Zynq SoC.

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

Table of Contents

  • Introduction
  • Comparing Microblaze to Zynq based solutions
    • AMD SP701 development board
    • Avnet Minized AMD Zynq-7Z007S
  • Spartan-7 FPGA Microblaze Original Design
    • Digilent Arty S7-50 AMD Spartan-7
  • Migrating the system between two differents Spartan-7 development boards
  • Migrating from the MicroBlaze/Spartan-7 to the Zynq/Artix-7
  • The Pmod Sensor and Actuator Modules
    • Digilent PmodHYGRO
    • Digilent PmodOLED
  • Designing the new hardware with the Zynq
    • Original Microblaze Based Version Block Design
    • New Zynq Based Version Block Design
    • Importing Digilent Vivado IPs
    • Makefile for PMOD Hygro C Driver
    • Makefile for the PMOD OLED C Driver
  • IP Catalog
  • Configuring the Zynq Processing System
  • Finding package PINs from the schematics
  • Programming the software from AMD Vitis
  • Plug and Program the Device
  • Summary
  • References
  • Path to Programmable III Training Blog Series

Comparing Microblaze to Zynq based solutions

First a little comparison between the two architectures.

The MicroBlaze CPU is a family of drop-in, modifiable preset 32-bit/64-bit RISC microprocessor configurations designed by AMD for their FPGAs. It offers flexibility and can be tailored to meet specific application requirements. Programmed with high-level languages such as C/C++, it provides a cost-effective solution for software-centric designs. It is fully implemented within the FPGA fabric, making it a compact and efficient option.

The AMD SP701 development board, as depicted in the picture, serves as an excellent example of a development board suitable for designing projects based on the MicroBlaze soft processor. The board provides a robust and versatile platform for implementing FPGA designs utilizing the MicroBlaze processor. The Spartan-7 does not integrate an Arm processor subsystem. The board implements an on-board system controller MSP430 not included in the Spartan-7 chip.

The Spartan 7 FPGAs are designed for I/O optimization with the highest performance-per-watt.

AMD SP701 development board

AMD SP701 Spartan-7 Development Board

On the other hand, the Zynq-7Z007S is an integrated system-on-chip (SoC) that combines a single-core ARM Cortex-A9 processor with an Artix 7 FPGA fabric on a single chip. It offers a balance between performance and resource utilization, making it suitable for various applications. The integration of an ARM processor with the FPGA fabric provides a seamless interaction between hardware and software.

Artix 7 FPGAs are designed for transceiver optimization and highest DSP bandwidth.

Avnet Minized AMD Zynq-7Z007S

Avnet Minized Zynq 7Z007S

While the MicroBlaze software processor provides flexibility and cost-effectiveness specifically for FPGA designs, the Zynq-7Z007S offers a more integrated solution with a dedicated ARM processor and FPGA fabric on a single chip.

Spartan-7 FPGA Microblaze Original Design

The original design, based on the Spartan-7 FPGA and MicroBlaze soft processor, was implemented using a Bare Metal application on the Digilent Arty S7-50 development board. Two external modules designed by Digilent, the PMOD Hygro and PMOD OLED modules, were utilized as shown in the image.

You can read the whole story in my participation in the "7 Ways to Leave Your Spartan-6 FPGA" program:  Arty S7 50 Rapid Prototyping - Environmental Monitor 

Digilent Arty S7-50 AMD Spartan-7

Environmental Monitor. Digilent Arty S7-50 Spartan 7 FPGA

In addition to the PMOD modules connected to the PMOD connectors on the Arty S7 board, the design incorporated twoLEDs to indicate whether the temperature is displayed in Celsius or Fahrenheit. A push button was used to toggle between displaying the temperature in one thermal scale to the other. The OLED display featured a two-line interface, showcasing the ambient temperature and relative humidity percentage.

Arty S7 -50 Environmental Monitor OLED Display

The program running on the MicroBlaze soft processor was developed in C, leveraging the drivers provided by Digilent. This allowed for seamless communication and control of the PMOD modules, enabling the display of temperature and humidity information on the OLED display.

Migrating the system between two differents Spartan-7 development boards

This design was easily ported to the AMD SP701 development board presented above, with a slight modification. Instead of using the PMOD OLED module, the HDMI output of the board was utilized, along with a design created in Vitis HLS (High-Level Synthesis). More on this in the following AMD SP701 - Experimenting with Sensor Fusion Design Challenge blog:   Sensor Fusion for Firefighters. Compass and Environmental HUD monitor with the Spartan-7 

The portability of the solution between two FPGAs of the same family was complete. There were no added problems when porting the solution from one board to another. In this case, both designs were supported by the Microblaze soft processor. Let's see what happens when we try to make the same application in a design that uses the Arm Cortex-A9 processor included in the Zynq.

Environmental Monitor on the AMD SP701 Spartan 7 FPGA

Migrating from the MicroBlaze/Spartan-7 to the Zynq/Artix-7

As shown in the diagram we want to convert the system on the left, an environmental monitor solution based on the MicroBlaze soft processor, into a solution based on the Minized Zynq's ARM Cortex-A9 processor.

In addition to the change of the processor we will have to take into account that the Minized board does not have the four pushbuttons that the Digilent Arty S7 50 board has nor the four indicator LEDs. We will complete that part of the hardware with the Programmable Logic Switch and the Programmable Logic Bi-element LED of the Minized

Environmental Monitor MicroBlaze to Zynq Migration

The Pmod Sensor and Actuator Modules

A brief overview of the Digilent Pmod modules that we are using. More about the modules in the blogs referred to above.


Digilent PmodHYGRO

The Digilent Pmod HYGRO is a relative humidity sensor with an integrated temperature sensor for highly accurate measurements at low power. With the TI HDC1080, we can determine the relative humidity of the environment with up to 14 bits of resolution.

image

References: 

  • Pmod HYGRO - Digilent Reference
  • Pmod HYGRO Reference Manual - Digilent Reference
{gallery}Digilent PmodHYGRO

Digilent PmodHYGRO - Digital humidity sensor with an integrated temperature sensor

Digilent PmodHYGRO - Unboxing

Digilent PmodHYGRO - Digital humidity sensor with an integrated temperature sensor

Digilent PmodHYGRO - Unboxing

Digilent PmodHYGRO - Digital humidity sensor with an integrated temperature sensor

Digilent PmodHYGRO - Front

Digilent PmodHYGRO - Digital humidity sensor with an integrated temperature sensor

Digilent PmodHYGRO - BACK


Digilent PmodOLED

The Digilent Pmod OLED (Revision A) is an organic LED module with a 128×32 pixel display. Primary IC  SSD1306

image

References:

  • Pmod OLED - Digilent Reference
  • Pmod OLED Reference Manual - Digilent Reference
{gallery}Digilent PmodOLED

Digilent PmodOLED unboxing

Digilent PmodOLED unboxing

PmodOLED unboxing

Digilent PmodOLED unboxing

Digilent PmodOLED unboxing

Digilent PmodOLED Front

Digilent PmodOLED Back

Digilent PmodOLED Back


Designing the new hardware with the Zynq

To design the hardware to closely resemble the original design using the MicroBlaze, I will utilize the two Pmods connectors on the Avnet Minized.

Original Microblaze Based Version Block Design

Microblaze Environmental Monitor Block Design in Vivado

To replicate the design using the Zynq, I will utilize the same intellectual property (IP) blocks provided by Digilent for both the PMOD OLED and PMOD Hygro modules, which were used in the original design with MicroBlaze.

By incorporating the Digilent-provided IP blocks for both the PMOD OLED and PMOD Hygro modules, I will ensure that the Zynq replicates the same functionality as the original design with MicroBlaze. These IP blocks abstract the low-level communication details, making it easier to interface with the modules and achieve the desired functionality. Digilent provides software drivers compatible with both Microblaze and ARM Zynq processors.

For the PMOD OLED module, I will include the Digilent PMOD OLED IP block, which provides the necessary functionality for SPI communication with the OLED display. This IP block will handle the low-level details of the SPI protocol, allowing the Zynq to communicate with the OLED module seamlessly. By connecting it to the GPIO pins assigned to the PMOD OLED module, I will enable the Zynq to control the OLED display.

For the PMOD Hygro module, I will include the Digilent PMOD Hygro IP block, which facilitates I2C communication with the humidity and temperature sensors on the module. This IP block will handle the I2C protocol, including data transfer and address handling, simplifying the communication process. Additionally, I will configure the IP block to capture the I2C interrupt. By configuring the IP block and establishing the necessary connections, the Zynq will be able to communicate with the PMOD Hygro module via I2C and handle interrupts when required.

New Zynq Based Version Block Design

This will be the new design:

image

The new design incorporates an instance of the Zynq PS IP Block that allows us to configure all the necessary aspects of the Zynq, some of the features are dependent on the Avnet Zynq development board, so to facilitate our design we will start from the definitions of Minized dashboard specs created by Avnet for Vivado.

image

Importing Digilent Vivado IPs

Then we can download Digilent IP Blocks from Digilent's vivado-library repository: Digilent/vivado-library (github.com)

I found some problems with the Digilent drivers and Vivado 2022.2 under Windows 11. Examining the errors I found a problem with referencing wildcards in the drivers makefiles.

You can change the Makefie of the two drivers by the following ones:

Makefile for PMOD Hygro C Driver

COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxil.a

RELEASEDIR=../../../lib
INCLUDEDIR=../../../include
INCLUDES=-I./. -I${INCLUDEDIR}

INCLUDEFILES=*.h
LIBSOURCES=$(wildcard *.c)
OUTS = *.o
OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c)))
ASSEMBLY_OBJECTS = $(addsuffix .o, $(basename $(wildcard *.S)))

libs:
	@echo 'Compiling Pmod Hygro'
	$(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES)
	$(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} ${ASSEMBLY_OBJECTS}
	make clean

include:
	${CP} $(INCLUDEFILES) $(INCLUDEDIR)

clean:
	rm -rf ${OBJECTS} ${ASSEMBLY_OBJECTS}

Makefile for the PMOD OLED C Driver

COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxil.a

RELEASEDIR=../../../lib
INCLUDEDIR=../../../include
INCLUDES=-I./. -I${INCLUDEDIR}

INCLUDEFILES=*.h
LIBSOURCES=$(wildcard *.c)
OUTS = *.o
OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c)))
ASSEMBLY_OBJECTS = $(addsuffix .o, $(basename $(wildcard *.S)))

libs:
	@echo 'Compiling PMOD_oled'
	$(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES)
	$(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} ${ASSEMBLY_OBJECTS}
	make clean
include:
	${CP} $(INCLUDEFILES) $(INCLUDEDIR)

clean:
	rm -rf ${OBJECTS} ${ASSEMBLY_OBJECTS}

IP Catalog

Once imported they are referenced in the IP Catalog Settings ready to be instantiate.

The design uses the PmodHYGRO_v1.0 and the PmodOLED_v1.0

image

Configuring the Zynq Processing System

In the block diagram of the VIvado IP Integrator we can configure settings for our Zynq

We will enable de QUAD SPI Flash Memory Interface and the AXI Master Ports. And configure a clock for the Programmable Logic.

image

We will use the FCLK_CLK0 configured to 50 MHz to provide synchronization to the two PMOD modules interfaces.

We created and reserved the 100 MHz clock for future use, it will not be used in this design.

image

We enable the 2 UARTs, one will be used for debugging/printing to console.

image

As we are controlling the PMODs through AXI Lite interfaces we will need to enable a General purpose AXI Master Interface

image

Finding package PINs from the schematics

To configure the physical PMOD connectors, we can search for xdc files on Google or more easily find them in the schematics.

image

Starting with the PMOD connectors, we follow the diagram until we find the pins of the package to which they are connected.

image

Using the I/O Ports Editor form the Implemented Design section we can configure the needed ports to the package PINs

image

Finally we get an XDC constraints file with the configured ports

#######################################################################
# PL_SW_1
#######################################################################

set_property IOSTANDARD LVCMOS33 [get_ports {PL_SW_tri_i[0]}]
set_property PACKAGE_PIN E11 [get_ports {PL_SW_tri_i[0]}]

#######################################################################
# PL_LED_G
#######################################################################

set_property IOSTANDARD LVCMOS33 [get_ports {PL_LED_G_tri_o[0]}]
set_property PACKAGE_PIN E12 [get_ports {PL_LED_G_tri_o[0]}]

#######################################################################
# PL_LED_R
#######################################################################

set_property IOSTANDARD LVCMOS33 [get_ports {PL_LED_R_tri_o[0]}]
set_property PACKAGE_PIN E13 [get_ports {PL_LED_R_tri_o[0]}]

#######################################################################
# Pmod #2
#######################################################################

set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_pin1_io]
set_property PACKAGE_PIN L15 [get_ports PMOD1_pin1_io]

set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_pin2_io]
set_property PACKAGE_PIN M15 [get_ports PMOD1_pin2_io]

set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_pin3_io]
set_property PACKAGE_PIN L14 [get_ports PMOD1_pin3_io]

set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_pin4_io]
set_property PACKAGE_PIN M14 [get_ports PMOD1_pin4_io]

set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_pin7_io]
set_property PACKAGE_PIN K13 [get_ports PMOD1_pin7_io]

set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_pin8_io]
set_property PACKAGE_PIN L13 [get_ports PMOD1_pin8_io]

set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_pin9_io]
set_property PACKAGE_PIN N13 [get_ports PMOD1_pin9_io]

set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_pin10_io]
set_property PACKAGE_PIN N14 [get_ports PMOD1_pin10_io]


#######################################################################
# Pmod #2
#######################################################################

set_property IOSTANDARD LVCMOS33 [get_ports PMOD2_pin1_io]
set_property PACKAGE_PIN P13 [get_ports PMOD2_pin1_io]

set_property IOSTANDARD LVCMOS33 [get_ports PMOD2_pin2_io]
set_property PACKAGE_PIN P14 [get_ports PMOD2_pin2_io]

set_property IOSTANDARD LVCMOS33 [get_ports PMOD2_pin3_io]
set_property PACKAGE_PIN N11 [get_ports PMOD2_pin3_io]

set_property IOSTANDARD LVCMOS33 [get_ports PMOD2_pin4_io]
set_property PACKAGE_PIN N12 [get_ports PMOD2_pin4_io]

set_property IOSTANDARD LVCMOS33 [get_ports PMOD2_pin7_io]
set_property PACKAGE_PIN P15 [get_ports PMOD2_pin7_io]

set_property IOSTANDARD LVCMOS33 [get_ports PMOD2_pin8_io]
set_property PACKAGE_PIN R15 [get_ports PMOD2_pin8_io]

set_property IOSTANDARD LVCMOS33 [get_ports PMOD2_pin9_io]
set_property PACKAGE_PIN R12 [get_ports PMOD2_pin9_io]

set_property IOSTANDARD LVCMOS33 [get_ports PMOD2_pin10_io]
set_property PACKAGE_PIN R13 [get_ports PMOD2_pin10_io]

Then generate the bitstream programming file and export hardware (.xsa file) including the generated bitstream.

Programming the software from AMD Vitis

Now we can create a new platform project from the exported .xsa

image

Set the stdin and stdout variables to the uart1 of the PS for debugging purposes under the Board Support Package Settings

image

And create a new Empty Application Project using that Hardware Platform Project.

image

Then import the C Application code from the previous design and change only the references to the xparameters.h That's all!

// Get device IDs from xparameters.h
#define BTN_ID XPAR_AXI_GPIO_1_DEVICE_ID
#define LED_ID XPAR_AXI_GPIO_0_DEVICE_ID
#define BTN_CHANNEL 1
#define LED_CHANNEL 1

/******************************************************************************/
/*                                                                            */
/* env_monitor_main.c -- Environmental Monitor. Temperature / Humidity        */
/*  PmodOLED IP + PmodHYGRO                                                   */
/*                                                                            */
/******************************************************************************/
/* Author: Enrique Albertos                                                   */
/* 2022-2023 Public Domain                                                    */
/******************************************************************************/
/* File Description:                                                          */
/*                                                                            */
/* This project initializes and uses the PmodOLED and the PmodHYGRO to        */
/* display temperature and humidity values.                                   */
/* Temperature and humidity data are captured from the I2C connection and     */
/* displayed over the serial connection and on the OLED display once per      */
/* second.                                                                    */
/* This application configures UART 16550 to Baud rate 9600. PS7 UART (Zynq)  */
/* is not initialized by this application, since bootrom/bsp configures it to */
/* Baud rate 115200.                                                          */
/*                                                                            */
/*    UART TYPE   BAUD RATE                                                   */
/*    uartns550   9600                                                        */
/*    uartlite    Configurable only in HW design                              */
/*    ps7_uart    115200 (configured by bootrom/bsp)                          */
/*                                                                            */
/******************************************************************************/
/* Revision History:                                                          */
/*                                                                            */
/*    11/06/2022 Enrique Albertos:   Created w/ Vivado 2021.1                 */
/*    08/06/2023 Enrique Albertos:   Adapted to Avnet Minized Vivado 2022.2   */
/*                                                                            */
/******************************************************************************/
/* Baud Rates:                                                                */
/*                                                                            */
/*    Microblaze: 9600 or what was specified in UARTlite core                 */
/*    Zynq: 115200                                                            */
/*                                                                            */
/******************************************************************************/

/* ------------------------------------------------------------ */
/*                  Include File Definitions                    */
/* ------------------------------------------------------------ */

#include "PmodOLED.h"
#include "PmodHYGRO.h"
#include "sleep.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "xgpio.h"
#include "xil_types.h"

#ifdef __MICROBLAZE__
#define TIMER_FREQ_HZ XPAR_CPU_M_AXI_DP_FREQ_HZ
#else
#define TIMER_FREQ_HZ 100000000
#endif

/* ------------------------------------------------------------ */
/*                  Global Variables                            */
/* ------------------------------------------------------------ */

PmodOLED myOled;
PmodHYGRO myHygro;

/* ------------------------------------------------------------ */
/*                  Forward Declarations                        */
/* ------------------------------------------------------------ */

void DemoInitialize();
void DemoRun();
void DemoCleanup();
void EnableCaches();
void DisableCaches();
void OLED_putFloatVariable(PmodOLED *InstancePtr, int xch, int ych, char * head,
		float value, char * tail);

// To change between PmodOLED and OnBoardOLED is to change Orientation
const u8 orientation = 0x0; // Set up for Normal PmodOLED(false) vs normal
// Onboard OLED(true)
const u8 invert = 0x0; // true = whitebackground/black letters
// false = black background /white letters

#define BTN_MASK 0b1111
#define LED_MASK 0b1111
#define BTN1_MASK 0b0001
#define BTN2_MASK 0b0010
#define BTN3_MASK 0b0100
#define BTN4_MASK 0b1000
#define LED1_MASK 0b0001
#define LED2_MASK 0b0010
#define LED3_MASK 0b0100
#define LED4_MASK 0b1000
#define CELSIUS_LED LED1_MASK
#define FAHRENHEIT_LED LED1_MASK

// Get device IDs from xparameters.h
#define BTN_ID XPAR_AXI_GPIO_1_DEVICE_ID
#define LED_ID XPAR_AXI_GPIO_0_DEVICE_ID
#define BTN_CHANNEL 1
#define LED_CHANNEL 1

// can use a push button or an slide switch to toggle C/F
// #define __MINIZED__ 1

XGpio_Config *cfg_ptr;
XGpio led_device, btn_device;



/* ------------------------------------------------------------ */
/*                  Function Definitions                        */
/* ------------------------------------------------------------ */

int main() {
	DemoInitialize();
	DemoRun();
	DemoCleanup();

	return 0;
}

void DemoInitialize() {
	EnableCaches();

	xil_printf("HYGRO Init Started\n\r");
	HYGRO_begin(&myHygro,
	XPAR_PMODHYGRO_0_AXI_LITE_IIC_BASEADDR, 0x40, // Chip address of PmodHYGRO IIC
			XPAR_PMODHYGRO_0_AXI_LITE_TMR_BASEADDR,
			XPAR_PMODHYGRO_0_DEVICE_ID,
			TIMER_FREQ_HZ // Clock frequency of AXI bus, used to convert timer data
			);
	xil_printf("HYGRO Init Done\n\r");

	xil_printf("OLED Init Started\n\r");
	OLED_Begin(&myOled, XPAR_PMODOLED_0_AXI_LITE_GPIO_BASEADDR,
	XPAR_PMODOLED_0_AXI_LITE_SPI_BASEADDR, orientation, invert);
	xil_printf("OLED Init Done\n\r");

	// Initialize LED Device
	cfg_ptr = XGpio_LookupConfig(LED_ID);
	XGpio_CfgInitialize(&led_device, cfg_ptr, cfg_ptr->BaseAddress);

	// Initialize Button Device
	cfg_ptr = XGpio_LookupConfig(BTN_ID);
	XGpio_CfgInitialize(&btn_device, cfg_ptr, cfg_ptr->BaseAddress);

	// Set Button Tristate
	XGpio_SetDataDirection(&btn_device, BTN_CHANNEL, BTN_MASK);

	// Set Led Tristate
	XGpio_SetDataDirection(&led_device, LED_CHANNEL, 0);

}

/* ------------------------------------------------------------ */
/*** DemoRun()
 **
 **   Parameters:
 **      none
 **
 **   Return Value:
 **      none
 **
 **   Errors:
 **      If the demo is shut down without properly exiting, does not reinitialize
 **      properly.
 **
 **   Description:
 **      Displays Temperature each 1 second.
 **      Toggles temp units with button 1 pressed
 **      Exists when button 4 is pressed.
 **      Requires UART connection to terminal program on PC.
 */
void DemoRun() {
	long timeCounterMillis;
	u32 buttonsState;
	int button1State;
	int lastbutton1State;
	float temp_degc, hum_perrh, temp_degf;
	u8 bDegreesCelsius = 1;

	xil_printf("UART, I2C and SPI opened for Environment Monitor\n\r");
	XGpio_DiscreteWrite(&led_device, LED_CHANNEL, LED1_MASK);
	while (1) {
        // read buttons
		buttonsState = XGpio_DiscreteRead(&btn_device, BTN_CHANNEL);

        //if button 4 is pressed exit
        if(buttonsState & BTN4_MASK ) {
        	xil_printf("exiting\r\n");
        	// exit
        	break;
        }

        // check button for toggling temperature units
        button1State = buttonsState & BTN1_MASK;
		//if button 1 low to high edge
        if((button1State != lastbutton1State) && button1State && timeCounterMillis > 100) {
        	xil_printf("toggle units\r\n");
        	// toggle temp units mode

        	bDegreesCelsius = !bDegreesCelsius;

        	// change led indicator
        	if (bDegreesCelsius ) {
        		XGpio_DiscreteWrite(&led_device, LED_CHANNEL, LED1_MASK);
        	} else {
        		XGpio_DiscreteWrite(&led_device, LED_CHANNEL, LED2_MASK);
        	}
        	// force environmental data update
        	timeCounterMillis = 1001;
        }
		lastbutton1State = button1State;

        if( timeCounterMillis > 1000) {
        	timeCounterMillis = 0;
			temp_degc = HYGRO_getTemperature(&myHygro);
			temp_degf = HYGRO_tempC2F(temp_degc);
			hum_perrh = HYGRO_getHumidity(&myHygro);
			xil_printf("Temperature: %d.%02d deg F  Humidity: %d.%02d RH\n\r",
					(int) temp_degf, ((int) (temp_degf * 100)) % 100,
					(int) hum_perrh, ((int) (hum_perrh * 100)) % 100);

			// Turn automatic updating off
			OLED_SetCharUpdate(&myOled, 0);

			if(bDegreesCelsius) {
				// Display Temperature Value in Degrees Celsius
				OLED_putFloatVariable(&myOled, 1, 1, "T: ", temp_degc, " C");
			} else {
				// Display Temperature Value in Degrees Fahrenheit
				OLED_putFloatVariable(&myOled, 1, 1, "T: ", temp_degf, " F");
			}
			// Display Relative Humidity Percentage
			OLED_putFloatVariable(&myOled, 1, 3, "H: ", hum_perrh, " %RH");
			// Update display
			OLED_Update(&myOled);
        }

		usleep(1000);
		timeCounterMillis++;
	}
	xil_printf("Exiting PmodOLED Demo\n\r");
}

/*
 * Displays on the OLED a float variable with a header and a tail
 * ie T: 12.67 C
 * OLED_putFloatVariable(&myOled, 1, 1, "T: ", temp_degc, " C");
 */
void OLED_putFloatVariable(PmodOLED *InstancePtr, int xch, int ych, char * head,
		float value, char * tail) {
	OLED_SetCursor(InstancePtr, xch, ych);
	OLED_PutString(InstancePtr, head);
	OLED_PutChar(InstancePtr, ((int) value / 10) % 10 + 48);
	OLED_PutChar(InstancePtr, ((int) value) % 10 + 48);
	OLED_PutString(InstancePtr, ".");
	OLED_PutChar(InstancePtr, ((int) (value * 10)) % 10 + 48);
	OLED_PutChar(InstancePtr, ((int) (value * 100)) % 10 + 48);
	OLED_PutString(InstancePtr, tail);
}

void DemoCleanup() {
	OLED_End(&myOled);
	DisableCaches();
}

void EnableCaches() {
#ifdef __MICROBLAZE__
#ifdef XPAR_MICROBLAZE_USE_ICACHE
	Xil_ICacheEnable();
#endif
#ifdef XPAR_MICROBLAZE_USE_DCACHE
	Xil_DCacheEnable();
#endif
#endif
}

void DisableCaches() {
#ifdef __MICROBLAZE__
#ifdef XPAR_MICROBLAZE_USE_DCACHE
	Xil_DCacheDisable();
#endif
#ifdef XPAR_MICROBLAZE_USE_ICACHE
	Xil_ICacheDisable();
#endif
#endif
}

Plug and Program the Device

Without further changes to those due to the numbering of the AXI Lite control interfaces, the system works first time.

Avnet Minized Environmental Monitor

Use the DIP switch to change from Fahrenheit to Celsius scale visualization.

Avnet Minized Environmental Monitor

By connecting to the UART we can receive the debug lines sent by the application.

image

Summary

I was curious to know the degree of portability of the solutions created under the Vitis Unified Software Platform environment. I was already aware of the possibility of porting solutions between boards based on FPGAs of the same family, but I had my doubts about what would happen when migrating a development made for the Microblaze soft processor to the Zynq. I have been pleasantly surprised at how easy it has been. In the next blog we will go a step further by testing the portability of solutions that use more resources from the PL fabric.

References

  • Minized Technical Documents: MiniZed - Boards - Avnet Boards Community
  • My participation in the: 7 Ways to Leave Your Spartan-6 FPGA
  • My participation in; AMD SP701 - Experimenting with Sensor Fusion Design Challenge
  • ds190-Zynq-7000-Overview.pdf
  • ds187-XC7Z010-XC7Z020-Data-Sheet.pdf

Path to Programmable III Training Blog Series

  1. BLOG 1: P2P3 Getting Started. Clockless Hardware Blinky on the Avnet Minized 
  2. BLOG 2:  P2P3 AMD Vitis portability and reuse. Migrating a Microblaze bare metal environmental monitor App to the Zynq architecture. 
  3. BLOG 3:  P2P3 AMD Zynq-7000 SoC XADC. External Multiplexer Mode. 
  4. BLOG 4:  P2P3 AMD Vivado Cascaded Integrator Comb (CIC) Compiler. PDM Microphone to PCM Decimation 
  5. BLOG 5:  P2P3 Wireless sensors on the Avnet Minized. Getting Started with PetaLinux 
  6. FINAL PROJECT:  AMD Zynq SoC MIDI Vintage Sound Synthesizer - Final 
  • Sign in to reply
  • javagoza
    javagoza over 2 years ago in reply to guillengap

    Like  flyingbean, I have encountered the same situation when it comes to updating Vivado projects from an older version to a newer one.

    My approach involves initially opening a duplicate of the old version project in the new version, without performing any updates, in read-only mode. This allows me to analyze the IP Block Diagram and the IP versions. Subsequently, I open another duplicate of the project, this time updating it to the new version and following the provided update instructions. In cases where certain new IP versions are not backward compatible, I compare and study both versions in order to manually carry out the necessary updates.

    When it comes to Vitis IDE projects, I prefer to recreate the Platform App using the .xsa file and create a new application project by importing the source files.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • flyingbean
    flyingbean over 2 years ago in reply to guillengap

    The short answer is More Yes than No. Vivado IP version update could be one of the biggest challenges to update from older Vivado version into newer version. Sometimes, Vivdao can do the updating automatically. However, if the version number jumps too big, Vivado will ask the user to update IPs manually. Another challenge is from MAKEFILE, which was covered by javagoza in this blog. IP driver updating can be very tricky. I am still in the middle of learning that. Hopefully, there will have more blogs on that in the community.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • guillengap
    guillengap over 2 years ago

    Good presentation! My question is the migration using different versions of Vivado and Vitis. Is there a problem or not?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • javagoza
    javagoza over 2 years ago in reply to flyingbean

    flyingbean , thanks for your kind words.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • flyingbean
    flyingbean over 2 years ago

    Very good blog on how to integrate Digilent IPs into Vivado tool chain. One of the best HOWTO blogs on this topic I read so far.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube