MicroZed Chronicles: Implementing an Arm Cortex-M1 Processor Solution From Scratch
How to implement an Arm Cortex-M1 controller in your FPGA.
One of the more popular online and in-person classes I present at conferences and in webinars discusses how to implement Arm Cortex-M1 and Cortex-M3 processors in Xilinx programmable logic devices.
In this class, we start with an existing reference design, learn about the tool flow, and implement an application based on the provided reference design. While providing an excellent introduction to working with the Cortex-M1 and Cortex-M3 processors, it does not show how to create Cortex-M1 and Cortex-M3 solutions from scratch.
Over the next few blogs, I am going to explain this beginning with how to implement an Arm Cortex-M1 processor within the programmable logic.
The first thing we need to do is download the DesignStart FPGA files from the Arm website. This will provide the Arm reference designs along with the IP cores for both the processor and the necessary software APIs.
Once the download is extracted, the first step is to open Vivado Design Suite and add the Arm Cortex-M1 processor to the IP repository.
You can find the IP repository containing the Arm Cortex-M1 core under the AT472-BU-98000-r0p1-00rel0\vivado\Arm_ipi_repository directory in the download.
With the IP available for use, the next step is to create a new project and block diagram. For this project, I am going to be targeting the Arty S7-50 Spartan-7 FPGA board from Digilent.
With the Arm Cortex-M1 processor available for our design, the next stage is to add this into the block diagram.
The first thing we need to do once the Arm Cortex-M1 is included within the design is to configure it as we desire. In this case, I am going to implement the processor core with no debugging and with 32KB of instruction and data memory.
Now we need to connect the Cortex-M1 processor to a UART so I can send a “hello world” message. To do this, we need to be able to provide the Corex-M1 with a clock and reset.
Adding the clock and reset is straightforward. We can drag and drop the system clock onto the block diagram. This will instantiate a clock wizard. The input clock frequency is 12 MHz, with the output clock set at 100MHz. To be able to use the external reset, we need to inform the Clock Wizard the reset input is active low.
We add in the UART in the same manner by dragging and dropping it from the board view onto the block diagram. This will instantiate a LogiCORE IP AXI UART Lite interface, and we can run the connection automation wizard to connect the AXI UART Lite into the Cortex-M1 processor’s address map.
The final step is to connect the IRQ, NMI and CFGITCMEN inputs correctly. The first two interrupt requests, the IRQ and Non Maskable Interrupt (NMI), can be tied low.
The third input, CFGITCMEN, controls the location of the instruction tightly coupled memory. In this instance, it is set to 0x03. Setting to other values allows us to use Block RAM connected to the AXI interface to hold the application.
See below for the complete hardware design in Vivado.
Now that we have the hardware, we can then implement the design and export the design to the Xilinx Software Development Kit (SDK). However, we will look at that in the next blog as the software side is a little more complicated and requires the use of SDK and the Arm Keil Microcontroller Development Kit (MDK).
See My FPGA / SoC Projects: Adam Taylor on Hackster.io
Get the Code: ATaylorCEngFIET (Adam Taylor)
Access the MicroZed Chronicles Archives with over 300 articles on the FPGA / Zynq / Zynq MpSoC updated weekly at MicroZed Chronicles.