The Cortex-M1 is a 32-bit reduced instruction set computer (RISC) processor IP core from ARM that can be implemented on an FPGA as a soft processor. Loading the Cortex-M1 onto a Pynq Z2 FPGA board allows you to take advantage of the reconfigurable logic and processing power of the Zynq SoC while utilizing the flexibility and efficiency of the Cortex-M architecture. This guide will walk through the steps to generate the Cortex-M1 for the Pynq Z2, integrate it with the programmable logic, and get a simple “hello world” program running.
Overview of the Cortex-M1 Architecture
The Cortex-M1 processor implements the ARMv6-M architecture, which is optimized for microcontroller applications requiring low power consumption, reduced pin count, and low cost. The key features of the Cortex-M1 are:
- 32-bit RISC processor with Thumb-2 instruction set
- 3-stage pipeline to achieve high performance at low power
- Integrated nested vectored interrupt controller
- Optional memory protection unit
- Efficient branch predictor
- Operating frequencies up to 100 MHz
The Cortex-M1 is a simple yet high performance processor well suited for embedded and IoT applications. When implemented in an FPGA, it can be customized to target the specific needs of the application.
Generating the Cortex-M1 for the Pynq Z2
To generate the Cortex-M1 for the Pynq Z2 FPGA board, we will use the ARM DesignStartTM program which provides the IP needed to implement ARM cores. The steps are:
- Go to DesignStart and either sign up for a free account or login if you already have one.
- In the catalog, search for “Cortex-M1” and select the Cortex-M1 processor IP.
- On the next page, select the options for your Cortex-M1 configuration. For the Pynq Z2, set the ASIL (safety) level to “None” and choose the “Zynq UltraScale+ MPSoC EV Device” as the target device.
- Proceed through the rest of the options keeping the defaults. On the last page, accept the license agreement.
- Enter your email and click generate. The IP files will be emailed to you.
The generated IP will be specific to the Pynq Z2 FPGA you specified and will include the RTL source files, testbenches, and example software projects to help with integration.
Creating the Hardware Design
With the Cortex-M1 IP generated, the next step is creating a Vivado project and integrating the processor with the programmable logic of the Pynq Z2. Here are the steps:
- Open Vivado and create a new RTL project targeting the Pynq Z2’s device, such as the XCZU9EG-2FFVB1156E. Select “Do not specify sources at this time” to leave the design empty for now.
- In the IP catalog, select “Add Repository” and point to the directory containing the generated Cortex-M1 IP files.
- With the new Cortex-M1 IP added, customize and generate the instance with any parameters required for your design.
- Connect the Cortex-M1 interface signals to the PS-PL interface pins or any custom logic as needed.
- Add any additional logic or IP blocks in the PL region and connect them to the Cortex-M1.
- Validate the design by running synthesis and implementation. Review any timing reports or errors.
- Generate the bitstream to configure the FPGA with the Cortex-M1 soft processor.
With Vivado, we can build a complete hardware design integrating the Cortex-M1 with timers, memory interfaces, custom accelerators, and any other required peripherals or logic.
Creating and Loading Software
To test out the Cortex-M1 design, we need to create an example software application and load it onto the processor. This “hello world” example prints out a message over UART:
- In Vivado, export the hardware definition files for the Cortex-M1.
- Open the ARM Keil MDK toolkit and create a new project targeting the Cortex-M1.
- Select the “ Manage Run-Time Environment” option and point to the exported hardware definition files.
- Write a simple application in C that initializes the UART peripheral and prints “Hello World!” over the serial port.
- Build the application to generate a binary image file.
To load the program, connect to the Pynq Z2 board through JTAG and use Xilinx tools such as Vivado/SDK or ARM DS-5 to load the binary file onto the Cortex-M1 processor. This will start executing the code and print the hello world message. The program can be further debugged through the debugger connection.
Demo Program – Blinking an LED
Let’s look at a simple example that uses the Cortex-M1 soft processor to blink an LED on the Pynq Z2 board. This will demonstrate how to connect custom logic and use the processor to control it.
In the Vivado design, we will add:
- A GPIO block connected to an output pin on the PL interface
- An AXI Timer used to generate interrupts at fixed intervals
- Logic to sync the interrupt to the Cortex-M1 clock domain
The software program will:
- Initialize the GPIO and Timer peripherals
- Enable timer interrupts every 250ms
- Toggle the LED state on each timer tick
By generating this sample application, we can verify the Cortex-M1 is integrated correctly with the programmable logic and see how the processor can be used to control external signals.
Going Further with the Cortex-M1 Soft Processor
This guide covered the basics of loading the Cortex-M1 onto the Pynq Z2 FPGA board – generating the IP, creating a Vivado design, writing software, and running a simple demo. Here are some ways to take this project further:
- Add more complex peripherals like SPI, Ethernet, memory controllers etc.
- Attach custom logic and accelerators written in HDL.
- Experiment with different Cortex-M1 configurations and optimizations.
- Use the Cortex-M1 as a co-processor to the main application processor.
- Port over existing Cortex-M software projects over to run on the FPGA.
The Cortex-M1 soft processor opens up lots of possibilities for embedded designs using the low cost Pynq Z2 FPGA board. With the ability to customize the hardware and develop flexible software, many innovative applications can be created to leverage the full potential of the Pynq Z2 and Cortex-M1.