Embedded Design Handbook
1. Introduction
The Embedded Design Handbook complements the primary documentation for the Intel tools for embedded system development. It describes how to most effectively use the tools, and recommends design styles and practices for developing, debugging, and optimizing embedded systems using Intel-provided tools. The handbook introduces concepts to new users of Intel’s embedded solutions, and helps to increase the design efficiency of the experienced user.
1.1. Document Revision History for Embedded Design Handbook
Document Version | Changes |
---|---|
2020.07.22 | Updated the following chapters:
|
2020.04.25 | Updated the Software System Design with a Nios® II Processor chapter. |
2020.01.13 | Updated the Software System Design with a Nios® II Processor chapter. |
2018.11.12 | Updated the following chapters:
|
2017.11.06 | Updated the following chapters:
|
2017.06.12 | Updated the following chapters:
|
2016.12.19 | Updated the following chapters:
|
2015.12.18 | Updated the following chapters:
|
Refer to the individual chapter's revision history section for more details about the changes and previous revision history.
2. First Time Designer's Guide
The First Time Designer’s Guide is a basic overview of Intel embedded development process and tools for the first time user. The chapter provides information about the design flow and development tools, interactions, and describes the differences between the Nios® II processor flow and a typical discrete microcontroller design flow.
This guide does not replace the basic reference material for the first time designer. It references other documents that provide detailed information about the individual tools and procedures. It contains resources and sections to help the first-time user of Intel’s embedded development tools for hardware and software development. For more information, refer to the related information links.
2.1. FPGAs and Soft-Core Processors
FPGAs can implement logic that functions as a complete microprocessor while providing many flexibility options.
An important difference between discrete microprocessors and FPGAs is that an FPGA contains no logic when it powers up. Before you run software on a Nios® II based system, you must configure the FPGA with a hardware design that contains a Nios® II processor. To configure an FPGA is to electronically program the FPGA with a specific logic design. The Nios® II processor is a true soft-core processor: it can be placed anywhere on the FPGA, depending on the other requirements of the design. Two different variants of the processor are available for Nios® II Gen2, each with flexible features.1
To enable your FPGA-based embedded system to behave as a discrete microprocessor-based system, your system should include the following:
- A JTAG interface to support FPGA configuration and hardware and software debugging
- A power-up FPGA configuration mechanism
If your system has these capabilities, you can begin refining your design from a pretested hardware design loaded in the FPGA. Using an FPGA also allows you to modify your design quickly to address problems or to add new functionality. You can test these new hardware designs easily by reconfiguring the FPGA using your system's JTAG interface.
The JTAG interface supports hardware and software development. You can perform the following tasks using the JTAG interface:
- Configure the FPGA
- Download and debug software
- Communicate with the FPGA through a UART-like interface (JTAG UART)
- Debug hardware (with the Signal Tap II embedded logic analyzer)
- Program flash memory
After you configure the FPGA with your Nios® II processor-based design, the software development flow is similar to the flow for discrete microcontroller designs.
2.2. Embedded System Design
Whether you are a hardware designer or a software designer, read the Nios® II Hardware Development Tutorial to start learning about designing embedded systems on an Intel FPGA. The “ Nios® II System Development Flow” section is particularly useful in helping you to decide how to approach system design using Intel's embedded hardware and software development tools. Intel recommends that you read this tutorial before starting your first design project. The tutorial teaches you the basic hardware and software flow for developing Nios® II processor-based systems.
Designing with FPGAs gives you the flexibility to implement some functionality in discrete system components, some in software, and some in FPGA-based hardware. This flexibility makes the design process more complex. The Platform Designer system design tool helps to manage this complexity. Even if you decide a soft-core processor does not meet your application's needs, Platform Designer can still play a vital role in your system by providing mechanisms for peripheral expansion or processor offload.
The figure below illustrates the overall Nios® II system design flow, including both hardware and software development. This illustration is greatly simplified. There are numerous correct ways to use the Intel tools to create a Nios® II system.
2.3. Embedded Design Resources
This section contains a list of resources to help you find design help. Your resource options include traditional Intel-based support such as online documentation, training, and My Support, as well as web-based forums and Wikis. The best option depends on your requirements and your current stage in the design cycle.
2.3.1. Intel Embedded Support
Intel recommends that you seek support in the following order:
- Look for relevant literature on the Intel Documentation page, especially on the Documentation: Nios® II Processor page.
- For reference, see the related design examples in the Intel FPGA Design Store.
- Consult one of the following community-owned resources:
- The Nios Forum, available on the Intel® FPGA Community website.
- The Intel® FPGA Wiki website
- Rocketboards for Linux support
Note: Intel is not responsible for the contents of the Nios Forum and Intel® FPGA Wiki websites, which are maintained by public authors and experts outside of Intel. - Contact technical support through the My Intel page of the Intel website to get support directly from Intel.
- Contact your local Intel sales office or sales representative, or your field application engineer (FAE).
2.3.2. Intel Embedded Training
To learn how the tools work together and how to use them in an online or instructor-led environment, register for training. Several training options are available. For information about general training, refer to the Training page of the Intel FPGA website.
For detailed information about available courses and their locations, visit the Embedded SW Designer Curriculum page of the Intel FPGA website. This page contains information about both online and instructor-led training.
2.3.3. Intel Embedded Documentation
You can access documentation about the Nios® II processor and embedded design from your Nios® II EDS installation directory at < Nios® II EDS install dir> \documents\index.htm. To access this page directly on Windows platforms, on the Start menu, click All Programs. On the All Programs menu, on the Intel submenu, on the Nios® II EDS <version> submenu, click Nios® II <version> Documentation. This web page contains links to the latest Nios® II documentation.
The Documentation: Nios® II Processor page of the Intel website includes a list and links to available documentation. At the bottom of this page, you can find links to various product pages that include Nios® II processor online demonstrations and embedded design information.
The other chapters in the Embedded Design Handbook are a valuable source of information about embedded hardware and software design, verification, and debugging. Each chapter contains links to the relevant overview documentation.
2.3.4. Third Party Intellectual Property
Many third parties have participated in developing solutions for embedded designs with Intel FPGAs through the Intel DSN Program. For up-to-date information about the third-party solutions available for the Nios® II processor, visit the Nios® II Processor page of the Intel website, and select the Ecosystem tab; or run a search on the Intellectual Property Find IP web page..
Several community forums are also available. These forums are not controlled by Intel. The Intel FPGA Forum's Marketplace provides third-party hard and soft embedded systems-related IP. The forum also includes an unsupported projects repository of useful example designs. You are welcome to contribute to these forum pages.
For Linux support, you can also refer to Rocketboards.
Traditional support is available from the Support Center or through your local Field Application Engineer (FAE). You can obtain more informal support by visiting the Nios Forum section of the Intel FPGA Forum or by browsing the information contained on the Intel FPGA Wiki. Many experienced developers, from Intel and elsewhere, contribute regularly to Wiki content and answer questions on the Nios Forum.
2.4. Intel Embedded Glossary
The following definitions explain some of the unique terminology for describing Platform Designer and Nios II processor-based systems:
- Component—A named module in Platform Designer that contains the hardware and software necessary to access a corresponding hardware peripheral.
- Custom instruction—Custom hardware processing integrated with the Nios® II processor's ALU. The programmable nature of the Nios® II processor and Platform Designer-based design supports this implementation of software algorithms in custom hardware. Custom instructions accelerate common operations. (The Nios® II processor floating-point instructions are implemented as custom instructions).
- Custom peripheral—An accelerator implemented in hardware. Unlike custom instructions, custom peripherals are not connected to the CPU's ALU. They are accessed through the system interconnect fabric. (See System interconnect fabric). Custom peripherals offload data transfer operations from the processor in data streaming applications.
- ELF (Executable and Linking Format)—The executable format used by the Nios® II processor. This format is arguably the most common of the available executable formats. It is used in most of today's popular Linux/BSD operating systems.
- HAL (Hardware Abstraction Layer)—A lightweight runtime environment that provides a simple device driver interface for programs to communicate with the underlying hardware. It provides a POSIX-like software layer and wrapper to the newlib C library.
-
Nios® II Command Shell—The command shell you use to
access
Nios® II and Platform Designer command-line utilities.
- On Windows platforms, a Nios® II Command Shell is a Cygwin bash with the environment properly configured to access command-line utilities.
- On Linux platforms, to run a properly configured bash, type < Nios® II EDS install path>/nios2_command_shell.sh
- Nios® II Embedded Development Suite (EDS)—The complete software environment required to build and debug software applications for the Nios® II processor.
- Nios® II Software Build Tools (SBT)—Software that allows you to create Nios® II software projects, with detailed control over the software build process.
- Nios® II Software Build Tools for Eclipse—An Eclipse-based development environment for Nios® II embedded designs, using the SBT for project creation and detailed control over the software build process. The SBT for Eclipse provides software project management, build, and debugging capabilities.
- Platform Designer —Software that provides a GUI-based system builder and related build tools for the creation of FPGA-based subsystems, with or without a processor.
- System interconnect fabric—An interface through which the Nios® II processor communicates to on- and off-chip peripherals. This fabric provides many convenience and performance-enhancing features.
2.5. First Time Designer's Guide Revision History
Document Version | Changes |
---|---|
2016.12.19 |
|
2015.12.18 |
|
Date | Version | Changes |
---|---|---|
July 2011 | 2.3 |
|
March 2010 | 2.2 | Updated for the SBT for Eclipse. |
January 2009 | 2.1 | Updated Nios Wiki hyperlink. |
November 2008 | 2.0 | Added System Console. |
March 2008 | 1.0 | Initial release. |
3. Hardware System Design with Intel Quartus Prime and Platform Designer
This chapter provides information on the hardware system design flow, designing with Platform Designer, and interfacing an external processor to an FPGA. Also included are useful configurations available with a Nios® II processor, timing constraints and requirements, and how to customize the FPGA to your design needs.
The Platform Designer system integration tool saves significant time and effort in the FPGA design process by automatically generating interconnect logic to connect intellectual property (IP) functions and subsystems. The following sections explains how to connect signals in Platform Designer.
3.1. FPGA Hardware Design
Although you develop your FPGA-based design in Platform Designer, you must perform the following tasks in other tools:
- Connect signals from your FPGA-based design to your board level design
- Connect signals from your Platform Designer system to other signals in the FPGA logic
- Constrain your design
3.1.1. Connecting Your FPGA Design to Your Hardware
To connect your FPGA-based design to your board-level design, perform the following two tasks:
- Identify the top level of your FPGA design.
- Assign signals in the top level of your FPGA design to pins on your FPGA using any of the methods mentioned in the Intel I/O Management, Board Development Support, and Signal Integrity Analysis Resource Center page of the Intel FPGA website.
3.1.2. Connecting Signals to your Platform Designer System
You must define the clock and reset pins for your Platform Designer system. You must also define each I/O signal that is required for proper system operation. The figure below shows the top-level block diagram of a Platform Designer system that includes a Nios® II processor. The large symbol in this top-level diagram, labeled std_1s40, represents the Platform Designer system. The flag-shaped pin symbols in this diagram represent off-chip (off-FPGA) connections.

For more information about connecting your FPGA design pins, refer to the Intel I/O Management, Board Development Support, and Signal Integrity Analysis Resource Center page of the Intel website.
3.1.3. Constraining Your FPGA-Based Design
To ensure your design meets timing and other requirements, you must constrain the design to meet these requirements explicitly using tools provided in the Quartus® Prime software or by a third party EDA provider. The Intel® Quartus® Prime software uses your constraint information during design compilation to achieve Intel’s best possible results.
3.2. System Design with Platform Designer
Platform Designer simplifies the task of building complex hardware systems on an FPGA. Platform Designer allows you to describe the topology of your system using a graphical user interface (GUI) and then generate the hardware description language (HDL) files for that system. The Intel® Quartus® Prime software compiles the HDL files to create an SRAM Object File (.sof). For additional information about Platform Designer, refer to the Intel® Quartus® Prime Handbook.
Platform Designer allows you to choose the processor core type and the level of cache, debugging, and custom functionality for each Nios® II processor. Your design can use on-chip resources such as memory, PLLs, DSP functions, and high-speed transceivers. You can construct the optimal processor for your design using Platform Designer.
After you construct your system using Platform Designer, and after you add any required custom logic to complete your top-level design, you must create pin assignments using the Intel® Quartus® Prime software. The FPGA’s external pins have flexible functionality, and a range of pins are available to connect to clocks, control signals, and I/O signals.
For information about how to create pin assignments, refer to Intel® Quartus® Prime Help and to the I/O Management chapter in Volume 2: Design Implementation and Optimization of the Intel® Quartus® Prime Handbook.
Intel recommends that you start your design from a small pretested project and build it incrementally. Start with one of the many Platform Designer example designs available from the All Design Examples web page of the Intel website, or with an example design from the Nios® II Hardware Development Tutorial.
Platform Designer allows you to create your own custom components using the component editor. In the component editor you can import your own source files, assign signals to various interfaces, and set various component and parameter properties.
Before designing a custom component, you should become familiar with the interface and signal types that are available in Platform Designer.
You should use dynamic addressing for slave interfaces on all new components. Dynamically addressable slave ports include byte enables to qualify which byte lanes are accessed during read and write cycles. Dynamically addressable slave interfaces have the added benefit of being accessible by masters of any data width without data truncation or side effects.
To learn about the interface and signal types that you can use in Platform Designer, refer to Avalon Interface Specifications. To learn about using the component editor, refer to the Component Editor chapter in the Intel® Quartus® Prime Handbook.
As you add each hardware component to the system, test it with software. If you do not know how to develop software to test new hardware components, Intel recommends that you work with a software engineer to test the components.
The Nios® II EDS includes several software examples, located in your Nios® II EDS installation directory (nios2eds), at < Nios® II EDS install dir>\examples\software. After you run a simple software design—such as the simplest example, Hello World Small—build individual systems based on this design to test the additional interfaces or custom options that your system requires. Intel recommends that you start with a simple system that includes a processor with a JTAG debug module, an on-chip memory component, and a JTAG UART component, and create a new system for each new untested component, rather than adding in new untested components incrementally.
After you verify that each new hardware component functions correctly in its own separate system, you can combine the new components incrementally in a single Platform Designer system. Platform Designer supports this design methodology well, by allowing you to add components and regenerate the project easily.
For detailed information about how to implement the recommended incremental design process, refer to the Verification and Board Bring-Up chapter of the Embedded Design Handbook.
3.2.1. Intel System on a Programmable Chip (Platform Designer) Solutions
To understand the Nios® II software development process, you must understand the definition of a Platform Designer system. Platform Designer is a system development tool for creating systems including processors, peripherals, and memories. The tool enables you to define and generate a complete Platform Designer very efficiently. Platform Designer does not require that your system contain a Nios® II processor, although it provides complete support for integrating Nios® II processors with your system.
A Platform Designer system is similar in many ways to a conventional embedded system; however, the two kinds of system are not identical. An in-depth understanding of the differences increases your efficiency when designing your Platform Designer system.
In Intel Platform Designer solutions, the hardware design is implemented in an Intel FPGA device. An Intel FPGA device is volatile—contents are lost when the power is turned off— and reprogrammable. When an Intel FPGA is programmed, the logic cells inside it are configured and connected to create a Platform Designer system, which can contain Nios® II processors, memories, peripherals, and other structures. The system components are connected with Avalon® interfaces. After the FPGA is programmed to implement a Nios® II processor, you can download, run, and debug your system software on the system.
Understanding the following basic characteristics of FPGAs and Nios® II processors is critical for developing your Nios® II software application efficiently:
- FPGA devices and Platform Designer—basic properties:
- Volatility—The FPGA is functional only after it is configured, and it can be reconfigured at any time.
- Design—Many Intel Platform Designer systems are designed using Platform Designer and the Intel® Quartus® Prime software, and may include multiple peripherals and processors.
- Configuration—FPGA configuration can be performed through a programming cable, such as the Intel® FPGA Download Cable , which is also used for Nios® II software debugging operations.
- Peripherals—Peripherals are created from FPGA resources and can appear anywhere in the Avalon memory space. Most of these peripherals are internally parameterizable.
-
Nios® II processor—basic properties:
- Volatility—The Nios® II processor is volatile and is only present after the FPGA is configured. It must be implemented in the FPGA as a system component, and, like the other system components, it does not exist in the FPGA unless it is implemented explicitly.
- Parameterization—Many properties of the Nios® II processor are parameterizable in Platform Designer, including core type, cache memory support, and custom instructions, among others.
- Processor Memory—The Nios® II processor must boot from and run code loaded in an internal or external memory device.
- Debug support—To enable software debug support, you must configure the Nios® II processor with a debug core. Debug communication is performed through a programming cable, such as the Intel® FPGA Download Cable.
- Reset vector—The reset vector address can be configured to any memory location.
- Exception vector—The exception vector address can be configured to any memory location.
3.2.2. Platform Designer Design
The recommended design flow requires that you maintain several small Platform Designer systems, each with its Intel® Quartus® Prime project and the software you use to test the new hardware. A Platform Designer design requires the following files and folders:
- Intel® Quartus® Prime Project File (.qpf)
-
Intel®
Quartus® Prime Settings File (.qsf)
The .qsf file contains all of the device, pin, timing, and compilation settings for the Intel® Quartus® Prime project.
- One of the following types of top-level design file:
- Block Design File (.bdf)
- Verilog Design File (.v)
- VHDL Design File (.vhd)
Platform Designer generates most of the HDL files for your system, so you do not need to maintain them when preserving a project. You need only preserve the HDL files that you add to the design directly.
For details about the design file types, refer to the Intel® Quartus® Prime Help.
- Platform Designer Design File (.qsys)
-
Platform Designer Information File (.sopcinfo)
This file contains an XML description of your Platform Designer system. Platform Designer and downstream tools, including the Nios® II Software Build Tools (SBT), derive information about your system from this file.
- Your software application source files
To replicate an entire project (both hardware and software), simply copy the required files to a separate directory. You can create a script to automate the copying process. After the files are copied, you can proceed to modify the new project in the appropriate tools: the Intel® Quartus® Prime software, Platform Designer, the SBT for Eclipse, the SBT in the command shell, or the Nios® II Integrated Development Environment (IDE).
For more information about all of these files, refer to the "Archiving Projects" chapter in the Intel® Quartus® Prime Handbook Volume 1: Design and Synthesis.
3.3. Interfacing an External Processor to an Intel FPGA
Intel provides options to connect an external processor to an Intel FPGA. These interface options include the PCI Express* , PCI, RapidIO™, serial peripheral interface (SPI) interface or a simple custom bridge that you can design yourself.
By including both an FPGA and a commercially available processor in your system, you can partition your design to optimize performance and cost in the following ways:
- Offload pre- or post- processing of data to the external processor
- Create dedicated FPGA resources for co-processing data
- Reduce design time by using IP from Intel’s library of components to implement peripheral expansion for industry standard functionality
- Expand the I/O capability of your external processor
You can instantiate the PCI Express* , PCI, and RapidIO Intel® FPGA IP functions using either the Parameter Editor or Platform Designer design flow. The PCI Lite and SPI cores are only available in the Platform Designer design flow. Platform Designer automatically generates the HDL design files that include all of the specified components and system connectivity. Alternatively, you can use the IP Toolbench with the Parameter Editor to generate a stand-alone component outside of Platform Designer. The figure below shows the steps you take to instantiate a component in both design flows.
The remainder of this section provides an overview of the Intel® FPGA IP functions that you can use to interface an Intel FPGA to an external processor. It covers the following topics:
- Configuration Options
- RapidIO Interface
- PCI Express* Interface
- PCI Interface
- Serial Protocol Interface (SPI)
- Custom Bridge Interfaces
3.3.1. Configuration Options
The figure below illustrates a Platform Designer system design that includes a high-performance external bus or switch to connect an industry-standard processor to an external interface of an IP core inside the FPGA. This IP core also includes an Avalon® -MM master port that connects to the Platform Designer system interconnect fabric. As the figure illustrates, Intel provides a library of components, typically Avalon® -MM slave devices, that connect seamlessly to the Platform Designer system interconnect fabric.

The design below includes an external processor that interfaces to a PCI Express endpoint inside the FPGA. The system interconnect fabric inside the implements a partial crossbar switch between the endpoint that connects to the external processor and two additional PCI Express root ports that interface to an Ethernet card and a marking engine. In addition, the system includes some custom logic, a memory controller to interface to external DDR SDRAM memory, a USB interface port, and an interface to external flash memory. Platform Designer automatically generates the system interconnect fabric to connect the components in the system.

Alternatively, you can also implement your logic in Verilog HDL or VHDL without using Platform Designer. Below the figure illustrates a modular design that uses the FPGA for co-processing with a second module to implement the interface to the processor. If you choose this option, you must write all of the HDL to connect the modules in your system.
The table below summarizes the components Intel provides to connect an Intel FPGA device to an external processor. As this table indicates, three of the components are also available for use in the Parameter Editor design flow in addition to Platform Designer. Alternative implementations of these components are also available through the Intel IP Core Partners Program (DSN) partners. The partners offer a broad portfolio of IP cores optimized for Intel devices.
For a complete list of third-party IP for Intel FPGAs, refer to the Intellectual Property: Find IP web page of the Intel website.
Protocol | Available in Platform Designer | Available In Parameter Editor | Third-Party Solution | Intel® FPGA IP Evaluation Mode Available |
---|---|---|---|---|
RapidIO | Yes | Yes | Yes | Yes |
PCI Express | Yes | Yes | Yes | Yes |
PCI Lite | Yes | — | — | License not required |
SPI | Yes | — | — |
The table below summarizes the most popular options for peripheral expansion in Platform Designer systems that include an industry-standard processor. All of these are available in Platform Designer. Some are also available using the Parameter Editor.
Protocol | Available in Platform Designer | Available In Parameter Editor | Third-Party Solution | Intel® FPGA IP Evaluation Mode Available |
---|---|---|---|---|
CAN | Yes | — | Yes | Yes |
I2C | Yes | — | Yes | Yes |
Ethernet | Yes | Yes | Yes | Yes |
PIO | Yes | — | — | Not required |
POS-PHY Level 4 (SPI 4.2) | — | Yes | — | Yes |
SPI | Yes | — | Yes | Not required |
UART | Yes | — | Yes | Yes |
USB | Yes | — | Yes | Yes |
For detailed information about the components available in Platform Designer refer to the Embedded Peripherals IP User Guide and the Intellectual Property: Find IP page.
The following sections discuss the high-performance interfaces that you can use to interface to an external processor.
3.3.2. RapidIO Interface
RapidIO is a high-performance packet-switched protocol that transports data and control information between processors, memories, and peripheral devices. The RapidIO Intel® FPGA IP function is available in Platform Designer includes Avalon® -MM ports that translate Serial RapidIO transactions into Avalon® -MM transactions. The Intel® FPGA IP function also includes an optional Avalon® Streaming ( Avalon® -ST) interface that you can use to send transactions directly from the transport layer to the system interconnect fabric. When you select all optional features, the core includes the following ports:
- Avalon® -MM I/O write master
- Avalon® -MM I/O read master
- Avalon® -MM I/O write slave
- Avalon® -MM I/O read slave
- Avalon® -MM maintenance master
- Avalon® -MM system maintenance slave
- Avalon® Streaming sink pass-through TX
- Avalon® -ST source pass-through RX
Using the Platform Designer design flow, you can integrate a RapidIO endpoint in a Platform Designer system. You connect the ports using the Platform Designer System Contents tab and Platform Designer automatically generates the system interconnect fabric. The figure below illustrates a Platform Designer system that includes a processor and a RapidIO Intel® FPGA IP function.

Refer to the RapidIO trade association web site's product list at rapidio.org for a list of processors that support a RapidIO interface.
Refer to the following documents for a complete description of the RapidIO Intel® FPGA IP function: RapidIO Intel® FPGA IP Function User Guide and AN513: RapidIO Interoperability With TI 6482 DSP Reference Design.
3.3.3. PCI Express Interface
The Intel IP Compiler for PCI Express* configured using the Platform Designer design flow uses the IP Compiler for PCI Express* 's Avalon-MM bridge module to connect the IP Compiler for PCI Express* component to the system interconnect fabric. The bridge facilitates the design of PCI Express* systems that use the Avalon-MM interface to access Platform Designer components. The figure below illustrates a design that links an external processor to an Platform Designer system using the IP Compiler for PCI Express* .
You can also implement the IP Compiler for PCI Express* using the Parameter Editor design flow. The configuration options for the two design flows are different. The IP Compiler for PCI Express* is available in Intel FPGA devices as a hard IP implementation and can be used as a root port or end point. I

The figure shows an example system in which an external processor communicates with an Intel FPGA through a PCI Express* link.
For more information about using the IP Compiler for PCI Express* refer to the following reference documents:
3.3.4. PCI Interface
Intel offers a wide range of PCI local bus solutions that you can use to connect a host processor to an FPGA. You can implement the PCI Intel® FPGA IP function using the Parameter Editor or Platform Designer design flow.
The PCI Platform Designer flow is an easy way to implement a complete Avalon-MM system which includes peripherals to expand system functionality without having to be well-acquainted with the Avalon-MM protocol. The figure below illustrates a Platform Designer system using the PCI Intel® FPGA IP function. You can parameterize the PCI Intel® FPGA IP function with a 32- or 64-bit interface.

For more information refer to the PCI Compiler User Guide.
3.3.5. Serial Protocol Interface (SPI)
The SPI Slave to Avalon® Master Bridge component provides a simple connection between processors and Platform Designer systems through a four-wire industry standard serial interface. Host systems can initiate Avalon® -MM transactions by sending encoded streams of bytes through the core's serial interface. The core supports read and write transactions to the Platform Designer system for memory access and peripheral expansion.
The SPI Slave to Avalon® Master Bridge is an Platform Designer-ready component that integrates easily into any Platform Designer system. Processors that include an SPI interface can easily encapsulate Avalon® -MM transactions for reads and writes using the protocols outlined in the SPI Slave/JTAG to Avalon® Master Bridge Cores chapter of the Embedded Peripherals IP User Guide.

Details of each protocol layer can be found in the following chapters of the Embedded Peripherals IP User Guide:
SPI Slave/JTAG to Avalon® Master Bridge Cores—Provide a connection from an external host system to an Platform Designer system. Allow an SPI master to initiate Avalon® -MM transactions.
Avalon® -ST Bytes to Packets and Packets to Bytes Converter Cores—Provide a connection from an external host system to an Platform Designer system. Allow an SPI master to initiate Avalon® -ST transactions.
Avalon® Packets to Transactions Converter Core—Receives streaming data from upstream components and initiates Avalon® -MM transactions. Returns Avalon® -MM transaction responses to requesting components.
The SPI Slave to Avalon® Master Bridge Design Example demonstrates SPI transactions between an Avalon® -MM host system and a remote SPI system.
3.3.6. Custom Bridge Interfaces
Many bus protocols can be mapped to the system interconnect fabric either directly or with some custom bridge interface logic to compensate for differences between the interface standards. The Avalon® -MM interface standard, which Platform Designer supports, is a synchronous, memory-mapped interface that is easy to create custom bridges for.
If required, you can use the component editor available in Platform Designer to quickly define a custom bridge component to adapt the external processor bus to the Avalon® -MM interface or any other standard interface that is defined in the Avalon® Interfaces Specifications. The Templates menu available in the component editor includes menu items to add any of the standard Avalon® interfaces to your custom bridge. You can then use the Interfaces tab of the component editor to modify timing parameters including: Setup, Read Wait, Write Wait, and Hold timing parameters, if required.
For more information about the component editor, refer to the Creating Platform Designer Components chapter of the Intel® Quartus® Prime Handbook Volume 1: Design and Synthesis.
The Avalon® -MM protocol requires that all masters provide byte addresses. Consequently, it may be necessary for your custom bridge component to add address wires when translating from the external processor bus interface to the Avalon® -MM interface. For example, if your processor bus has a 16-bit word address, you must add one additional low-order address bit. If processor bus drives 32-bit word addresses, you must add two additional, low-order address bits. In both cases, the extra bits should be tied to 0. The external processor accesses individual byte lanes using the byte enable signals.
Consider the following points when designing a custom bridge to interface between an external processor and the Avalon® -MM interface:
- The processor bus signals must comply or be adapted with logic to comply with the signals used for transactions, as described in the Avalon® Interfaces Specifications.
- The external processor must support the Avalon® waitrequest signal that inserts wait-state cycles for slave components
- The system bus must have a bus reference clock to drive Platform Designer interface logic in the FPGA.
- No time-out mechanism is available if you are using the Avalon® -MM interface.
- You must analyze the timing requirements of the system. You should perform a
timing analysis to guarantee that all synchronous timing requirements for the
external processor and
Avalon®
-MM interface are met. Examine the following timing
characteristics:
- Data tSU, tH , and tCO times to the bus reference clock
- fMAX of the system matches the performance of the bus reference clock
- Turn-around time for a read-to-write transfer or a write-to-read transfer for the processor is well understood
If your processor has dedicated read and write buses, you can map them to the Avalon® -MM readdata and writedata signals. If your processor uses a bidirectional data bus, the bridge component can implement the tristate logic controlled by the processor’s output enable signal to merge the readdata and writedata signals into a bidirectional data bus at the pins of the FPGA. Most of the other processor signals can pass through the bridge component if they adhere to the Avalon® -MM protocol. The figure below illustrates the use of a bridge component with a 32-bit external processor.

For more information about designing with the Avalon® -MM interface refer to the Avalon® Interfaces Specifications.
3.4. Avalon-MM Byte Ordering
This section describes Avalon® Memory-Mapped (Avalon-MM) interface bus byte ordering and provides recommendations for representing data in your system. Understanding byte ordering in both hardware and software is important when using intellectual property (IP) cores that interpret data differently.
Intel recommends understanding the following documents before proceeding:
- Platform Designer Interconnect chapter of the Intel® Quartus® Prime Handbook Volume 1: Design and Synthesis
- The Avalon Interface Specifications
3.4.1. Endianness
The term endian describes data byte ordering in both hardware and software. The two most common forms of data byte ordering are little endian and big endian. Little endian means that the least significant portion of a value is presented first and stored at the lowest address in memory. Big endian means the most significant portion of a value is presented first and stored at the lowest address in memory. For example, consider the value 0x1234. In little endian format, the 4 is the first digit presented or stored. In big endian format, the 1 is the first digit presented or stored.
Endianness typically refers only to byte ordering. Bit ordering within each byte is a separate subject covered in “PowerPC Bus Byte Ordering” and “ARM BE-32 Bus Byte Ordering”.
3.4.1.1. Hardware Endianness
Hardware developers can map the data bits of an interface in any order. There must be coordination and agreement among developers so that the data bits of an interface correctly map to address offsets for any master or slave interface connected to the interconnect. Consistent hardware endianness or bus byte ordering is especially important in systems that contain IP interfaces of varying data widths because the interconnect performs the data width conversion between the master and slave interfaces. The key to simplifying bus byte ordering is to be consistent system-wide when connecting IP cores to the interconnect. For example, if all but one IP core in your system use little endian bus byte ordering, modify the interface of the one big endian IP core to conform to the rest of the system.
The way an IP core presents data to the interconnect is not dependent on the internal representation of the data within the core. IP cores can map the data interface to match the bus data byte ordering specification independent of the internal arithmetic byte ordering.
3.4.1.2. Software Endianness
Software endianness or arithmetic byte ordering is the internal representation of data within an IP core, software compiler, and peripheral drivers. Processors can treat byte offset 0 of a variable as the most or least significant byte of a multibyte word. For example, the value 0x0A0B0C0D, which spans multiple bytes, can be represented different ways. A little endian processor considers the byte 0x0D of the value to be located at the lowest byte offset in memory, whereas a big endian processor considers the byte 0x0A of the value to be located at the lowest byte offset in memory.
The example below shows a C code fragment that illustrates the difference between the little endian and big endian arithmetic byte ordering used by most processors.
Reading Byte Offset 0 of a 32-Bit Word
long * long_ptr; char byte_value; *long_ptr = 0x0A0B0C0D; // 32-bit store to 'long_ptr' byte_value = *((char *)long_ptr); // 8-bit read from 'long_ptr'
In the example, the processor writes the 32-bit value 0x0A0B0C0D to memory, then reads the first byte of the value back. A little endian processor such as the Nios II processor, which considers memory byte offset 0 to be the least significant byte of a word, stores byte 0x0D to byte offset 0 of pointer location long_ptr. A processor such as a PowerPC®, which considers memory byte offset 0 to be the most significant byte of a word, stores byte 0x0A to byte offset 0 of pointer location long_ptr. As a result, the variable byte_value is loaded with 0x0D if this code executes on a little endian Nios® II processor and 0x0A if this code executes on a big endian PowerPC processor.
Arithmetic byte ordering is not dependent on the bus byte ordering used by the processor data master that accesses memory. However, word and halfword accesses sometimes require byte swapping in software to correctly interpret the data internally by the processor.
For more information, refer to “Arithmetic Byte Reordering” and “System-Wide Arithmetic Byte Reordering in Software”.
3.4.2. Avalon -MM Interface Ordering
To ensure correct data communication, the Avalon® -MM interface specification requires that each master or slave port of all components in your system pass data in descending bit order with data bits 7 down to 0 representing byte offset 0. This bus byte ordering is a little endian ordering. Any IP core that you add to your system must comply with the Avalon® -MM interface specification. This ordering ensures that when any master accesses a particular byte of any slave port, the same physical byte lanes are accessed using a consistent bit ordering. For more information, refer to the Avalon® Interface Specifications.
The interconnect handles dynamic bus sizing for narrow to wide and wide to narrow transfers when the master and slave port widths connected together do not match. When a wide master accesses a narrow slave, the interconnect serializes the data by presenting the lower bytes to the slave first. When a narrow master accesses a wide slave, the interconnect performs byte lane realignment to ensure that the master accesses the appropriate byte lanes of the slave.
For more information, refer to the Platform Designer Interconnect chapter of the Intel® Quartus® Prime Handbook Volume 1: Design and Synthesis
3.4.2.1. Dynamic Bus Sizing DMA Examples
A direct memory access (DMA) engine moves memory contents from a source location to a destination location. Because Platform Designer supports dynamic bus sizing, the data widths of the source and destination memory in the examples do not need to match the width of the DMA engine. The DMA engine reads data from a source base address and sequentially increases the address until the last read completes. The DMA engine also writes data to a destination base address and sequentially increases the address until the last write completes.
The following three figures illustrate example DMA transfers to and from memory of differing data widths. The source memory is populated with an increasing sequential pattern starting with the value 0 at base address 0. The DMA engine begins transferring data starting from the base address of the source memory to the base address of the destination memory. The interconnect always transfers the lower bytes first when any width adaptation takes place. The width adaptation occurs automatically within the interconnect.
3.4.3. Nios II Processor Data Accesses
In the Nios® II processor, the internal arithmetic byte ordering and the bus byte ordering are both little endian. Internally, the processor and its compiler map the least significant byte of a value to the lowest byte offset in memory.
For example, the figure below shows storing the 32-bit value 0x0A0B0C0D to the variable Y. The action maps the least significant byte 0x0D to offset 0 of the memory used to store the variable.

The Nios® II processor is a 32-bit processor. For data larger than 32 bits, the same mapping of the least significant byte to lowest offset occurs. For example, if the value 0x0807060504030201 is stored to a 64-bit variable, the least significant byte 0x01 of the variable is stored to byte offset 0 of the variable in memory. The most significant byte 0x08 of the variable is stored to byte offset 7 of the variable in memory. The processor writes the least significant four bytes 0x04030201 of the variable to memory first, followed by the most significant four bytes 0x08070605.
The master interfaces of the Nios® II processor comply with Avalon® -MM bus byte ordering by providing read and write data to the interconnect in descending bit order with bits 7 down to 0 representing byte offset 0. Because the Nios® II processor uses a 32-bit data path, the processor can access the interconnect with seven different aligned accesses. The table below shows the seven valid write accesses that the Nios® II processor can present to the interconnect.
Access Size (Bits) | Offset (Bytes) | Value | Byte Enable (Bits 3:0) | Write Data (Bits 31:24) | Write Data (Bits 23:16) | Write Data (Bits 15:8) | Write Data (Bits 7:0) |
---|---|---|---|---|---|---|---|
8 | 0 | 0x0A | 0001 | — | — | — | 0x0A |
8 | 1 | 0x0A | 0010 | — | — | 0x0A | — |
8 | 2 | 0x0A | 0100 | — | 0x0A | — | — |
8 | 3 | 0x0A | 1000 | 0x0A | — | — | — |
16 | 0 | 0x0A0B | 0011 | — | — | 0x0A | 0x0B |
16 | 2 | 0x0A0B | 1100 | 0x0A | 0x0B | — | — |
32 | 0 | 0x0A0B0C0D | 1111 | 0x0A | 0x0B | 0x0C | 0x0D |
The code fragment shown in the example generates all seven of the accesses described in the table in the order presented in the table, where BASE is a location in memory aligned to a four-byte boundary.
Nios® II Write Data Byte Mapping Code
IOWR_8DIRECT(BASE, 0, 0x0A); IOWR_8DIRECT(BASE, 1, 0x0A); IOWR_8DIRECT(BASE, 2, 0x0A); IOWR_8DIRECT(BASE, 3, 0x0A); IOWR_16DIRECT(BASE, 0, 0x0A0B); IOWR_16DIRECT(BASE, 2, 0x0A0B); IOWR_32DIRECT(BASE, 0, 0x0A0B0C0D);
3.4.4. Adapting Processor Masters to be Avalon-MM Compliant
Because the way the Nios® II processor presents data to the interconnect is Avalon-MM compliant, no extra effort is required to connect the processor to the interconnect. This section describes how to modify non-Avalon-MM compliant processor masters to achieve Avalon-MM compliance.
Some processors use a different arithmetic byte ordering than the Nios® II processor uses, and as a result, typically use a different bus byte ordering than the Avalon-MM interface specification supports. When connecting one of these processors directly to the interconnect in a system containing other masters such as a Nios® II processor, accesses to the same address result in accessing different physical byte lanes of the slave port. Mixing masters and slaves that conform to different bus byte ordering becomes nearly impossible to manage at a system level. These mixed bus byte ordering systems are difficult to maintain and debug. Intel requires that the master interfaces of any processors you add to your system are Avalon-MM compliant.
Processors that use a big endian arithmetic byte ordering, which is opposite to what the Nios® II processor implements, map the most significant byte of the variable to the lowest byte offset of the variable in memory. For example, the figure below shows how a PowerPC processor core stores the 32-bit value 0x0A0B0C0D to the memory containing the variable Y. The PowerPC stores the most significant byte, 0x0A, to offset 0 of the memory containing the variable.

This arithmetic byte ordering is the opposite of the ordering shown in “ Nios® II Processor Data Accesses”. Because the arithmetic byte ordering internal to the processor is independent of data bus byte ordering external to the processor, you can adapt processor masters with non-Avalon-MM compliant bus byte ordering to present Avalon-MM compliant data to the interconnect.
The following sections describe the bus byte ordering for the two most common processors that are not Avalon-MM complaint:
- “PowerPC Bus Byte Ordering”
- “ARM BE-32 Bus Byte Ordering”
3.4.4.1. PowerPC Bus Byte Ordering
The byte positions of the PowerPC bus byte ordering are aligned with the byte positions of the Avalon® -MM interface specification; however, the bits within each byte are misaligned. PowerPC processor cores use an ascending bit ordering when the masters are connected to the interconnect. For example, a 32-bit PowerPC core labels the bus data bits 0 up to 31. A PowerPC core considers bits 0 up to 7 as byte offset 0. This layout differs from the Avalon® -MM interface specification, which defines byte offset 0 as data bits 7 down to 0. To connect a PowerPC processor to the interconnect, you must rename the bits in each byte lane as shown below.

In the figure above, bit 0 is renamed to bit 7, bit 1 is renamed to bit 6, bit 2 is renamed to bit 5, and so on. By renaming the bits in each byte lane, byte offset 0 remains in the lower eight data bits. You must rename the bits in each byte lane separately. Renaming the bits by reversing all 32 bits creates a result that is not Avalon® -MM compliant. For example, byte offset 0 would shift to data bits 31 down to 24, not 7 down to 0 as required.
3.4.4.2. ARM BE-32 Bus Byte Ordering
Some ARM cores use a bus byte ordering commonly referred to as big endian 32 (BE-32). BE-32 processor cores use a descending bit ordering when the masters are connected to the interconnect. For example, an ARM BE-32 processor core labels the data bits 31 down to 0. Such a processor core considers bits 31 down to 24 as byte offset 0. This layout differs from the Avalon® -MM specification, which defines byte 0 as data bits 7 down to 0.
A BE-32 processor core accesses memory using the bus mapping shown below.
Access Size (Bits) | Offset (Bytes) | Value | Byte Enable (Bits 3:0) | Write Data (Bits 31:24) | Write Data (Bits 23:16) | Write Data (Bits 15:8) | Write Data (Bits 7:0) |
---|---|---|---|---|---|---|---|
8 | 0 | 0x0A | 1000 | 0x0A | — | — | — |
8 | 1 | 0x0A | 0100 | — | 0x0A | — | — |
8 | 2 | 0x0A | 0010 | — | — | 0x0A | — |
8 | 3 | 0x0A | 0001 | — | — | — | 0x0A |
16 | 0 | 0x0A0B | 1100 | 0x0A | 0x0B | — | — |
16 | 2 | 0x0A0B | 0011 | — | — | 0x0A | 0x0B |
32 | 0 | 0x0A0B0C0D | 1111 | 0x0A | 0x0B | 0x0C | 0x0D |
The write access behavior of the BE-32 processor shown in the table above differs greatly from the Nios® II processor behavior shown in Table 3. The only consistent access is the full 32-bit write access. In all the other cases, each processor accesses different byte lanes of the interconnect.
To connect a processor with BE-32 bus byte ordering to the interconnect, rename each byte lane as the figure below shows.

3.4.4.3. ARM BE-8 Bus Byte Ordering
Newer ARM processor cores offer a mode called big endian 8 (BE-8). BE-8 processor master interfaces are Avalon® -MM compliant. Internally, the BE-8 core uses a big endian arithmetic byte ordering; however, at the bus level, the core maps the data to the interconnect with the little endian orientation the Avalon® -MM interface specification requires.
3.4.4.4. Other Processor Bit and Byte Orders
There are numerous other ways to order the data leaving or entering a processor master interface. For those cases, the approach to achieving Avalon-MM compliance is the same. In general, apply the following three steps to any processor core to ensure Avalon-MM compliance:
- Identify the bit order.
- Identify the location of byte offset 0 of the master.
- Create a wrapper around the processor core that renames the data signals so that byte 0 is located on data 7 down to 0, byte 1 is located on data 15 down to 8, and so on.
3.4.4.5. Arithmetic Byte Reordering
Altering your system to conform to Avalon® -MM byte ordering modifies the internal arithmetic byte ordering of multibyte values as seen by the software. For example, an Avalon® -MM compliant big endian processor core such as an ARM BE-8 processor accesses memory using the bus mapping shown below.
Access Size (Bits) | Offset (Bytes) | Value | Byte Enable (Bits 3:0) | Write Data (Bits 31:24) | Write Data (Bits 23:16) | Write Data (Bits 15:8) | Write Data (Bits 7:0) |
---|---|---|---|---|---|---|---|
8 | 0 | 0x0A | 0001 | — | — | — | 0x0A |
8 | 1 | 0x0A | 0010 | — | — | 0x0A | — |
8 | 2 | 0x0A | 0100 | — | 0x0A | — | — |
8 | 3 | 0x0A | 1000 | 0x0A | — | — | — |
16 | 0 | 0x0A0B | 0011 | — | — | 0x0B | 0x0A |
16 | 2 | 0x0A0B | 1100 | 0x0B | 0x0A | — | — |
32 | 0 | 0x0A0B0C0D | 1111 | 0x0D | 0x0C | 0x0B | 0x0A |
The big endian ARM BE-8 mapping in the table above matches the little endian Nios® II processor mapping for all single byte accesses. If you ensure that your processor is Avalon® -MM compliant, you can easily share individual bytes of data between big and little endian processors and peripherals.
However, making sure that the processor data master is Avalon® -MM compliant only ensures that single byte accesses map to the same physical byte lanes of a slave port. In the case of multibyte accesses, the same byte lanes are accessed between the BE-8 and little endian processor; however, the value is not interpreted consistently. This mismatch is only important when the internal arithmetic byte ordering of the processor differs from other peripherals and processors in your system.
To correct the mismatch, you must perform arithmetic byte reordering in software for multibyte accesses. Interpretation of the data by the processor can vary based on the arithmetic byte ordering used by the processor and other processors and peripherals in the system.
For example, consider a 32-bit ARM BE-8 processor core that reads from a 16-bit little endian timer peripheral by performing a 16-bit read access. The ARM processor treats byte offset 0 as the most significant byte of any word. The timer treats byte offset 0 as the least significant byte of the 16-bit value. When the processor reads a value from the timer, the bytes of the value, as seen by software, are swapped. The figure below shows the swapping. A timer counter value of 0x0800 (2,048 clock ticks) is interpreted by the processor as 0x0008 (8 clock ticks) because the arithmetic byte ordering of the processor does not match the arithmetic byte ordering of the timer component.
For the values to be interpreted accurately, the processor must either read each byte lane individually and then combine the two byte reads into a single 16-bit value in software, or read the single 16-bit value and swap the bytes in software.
The same issue occurs when you apply a bus-level renaming wrapper to an ARM BE-32 or PowerPC core. Both processor cores treat byte offset 0 as the most significant byte of any value. As a result, you must handle any mismatch between arithmetic byte ordering of data used by the processor and peripherals in your system.
On the other hand, if the timer in the figure above were to treat the most significant byte of the 16-bit value as byte 0 (big endian ordering), the data would arrive at the processor master in the same arithmetic byte ordering used by the processor. If the processor and the component internally implement the same arithmetic byte ordering, no software swapping of bytes is necessary for multibyte accesses.
The figure below shows how the value 0x0800 of a big endian timer is read by the processor. The value is retained without the need to perform any byte swapping in software after the read completes.
3.4.5. System-Wide Design Recommendations
In the previous sections, we discussed arithmetic and bus byte ordering from a processor perspective. The same concepts directly apply to any component in your system. Any component containing Avalon-MM slave ports must also adhere to the Avalon-MM specification, which states that the data bits be defined in descending order with byte offset 0 positioned at bits 7 down to 0. As long as the component’s slave port is Avalon-MM compliant, you can use any arithmetic byte ordering within the component.
3.4.5.1. System-Wide Arithmetic Byte Ordering
Typically, the most convenient arithmetic byte ordering to use throughout a system is the ordering the processor uses, if one is present. If the processor uses a different arithmetic byte ordering than the rest of the system, you must write software that rearranges the ordering for all multibyte accesses.
The majority of the IP provided by Intel that contains an Avalon-MM master or slave port uses little endian arithmetic byte ordering. If your system consists primarily of components provided by Intel, it is much easier to make the remainder of your system use the same little endian arithmetic byte ordering. When the entire system uses components that use the same arithmetic byte ordering and Avalon-MM bus byte ordering, arithmetic byte reordering within the processor or any component performing data accesses is not necessary.
Intel recommends writing your driver code to handle both big and little endian arithmetic byte ordering. For example, if the peripheral is little endian, write the peripheral driver to execute on both big and little endian processors. For little endian processors, no byte swapping is necessary. For big endian processors, all multibyte accesses requires a byte swap. Driver code selection is controlled at compile time or run time depending on the application and the peripheral.
3.4.5.2. System-Wide Arithmetic Byte Reordering in Software
If you cannot modify your system so that all the components use the same arithmetic byte ordering, you must implement byte reordering in software for multibyte accesses. Many processors today include instructions to accelerate this operation. If your processor does not have dedicated byte-reordering instructions, the example below shows how you can implement byte reordering in software by leveraging the macros for 16-bit and 32-bit data.
Software Arithmetic Byte Reordering
/* Perform 16-bit byte reordering */ #define SW_16_BIT_ARITHMETIC_REORDERING (data) ( \ (((data) << 8) & 0xFF00) | \ (((data) >> 8) & 0x00FF) \ ) /* Perform 32-bit byte reordering */ #define SW_32_BIT_ARITHMETIC_REORDERING (data) ( \ (((data) << 24) & 0xFF000000) | \ (((data) << 8) & 0x00FF0000) | \ (((data) >> 8) & 0x0000FF00) | \ (((data) >> 24) & 0x000000FF) \
Choose the appropriate instruction or macro to perform the byte reordering based on the width of the value that requires arithmetic byte reordering. Because arithmetic byte ordering only applies to individual values stored in memory or peripherals, you must reverse the bytes of the value without disturbing the data stored in neighboring memory locations. For example, if you load a 16-bit value from a peripheral that uses a different arithmetic byte ordering, you must swap two bytes in software. If you attempt to load two 16-bit values as a packed 32-bit read access, you must swap the individual 16-bit values independently. If you attempt to swap all four bytes at once, the two individual 16-bit values are swapped, which is not the original intent of the software developer.
3.5. Memory System Design
This section describes the efficient use of memories in a Platform Designer embedded systems. Efficient memory use increases the performance of FPGA-based embedded systems. Embedded systems use memories for a range of tasks, such as the storage of software code and lookup tables (LUTs) for hardware accelerators.
3.5.1. Memory Types
Your system’s memory requirements depend heavily on the nature of the applications which you plan to run on the system. Memory performance and capacity requirements are small for simple, low cost systems. In contrast, memory throughput can be the most critical requirement in a complex, high performance system. The following general types of memories can be used in embedded systems.
3.5.1.1. Volatile Memory
A primary distinction in memory types is volatility. Volatile memories only hold their contents while power is applied to the memory device. As soon as power is removed, the memories lose their contents; consequently, volatile memories are unacceptable if data must be retained when the memory is switched off. Examples of volatile memories include static RAM (SRAM), synchronous static RAM (SSRAM), synchronous dynamic RAM (SDRAM), and FPGA on-chip memory.
3.5.1.2. Non-Volatile Memory
Non-volatile memories retain their contents when power is switched off, making them good choices for storing information that must be retrieved after a system power-cycle. Processor boot-code, persistent application settings, and FPGA configuration data are typically stored in non-volatile memory. Although non-volatile memory has the advantage of retaining its data when power is removed, it is typically much slower to write to than volatile memory, and often has more complex writing and erasing procedures. Non-volatile memory is also usually only guaranteed to be erasable a given number of times, after which it may fail. Examples of non-volatile memories include all types of flash, EPROM, and EEPROM. Most modern embedded systems use some type of flash memory for non-volatile storage.
Many embedded applications require both volatile and non-volatile memories because the two memory types serve unique and exclusive purposes. The following sections discuss the use of specific types of memory in embedded systems.
3.5.2. On-Chip Memory
On-chip memory is the simplest type of memory for use in an FPGA-based embedded system. The memory is implemented in the FPGA itself; consequently, no external connections are necessary on the circuit board. To implement on-chip memory in your design, simply select On-Chip Memory from the Component Library on the System Contents tab in Platform Designer. You can then specify the size, width, and type of on-chip memory, as well as special on-chip memory features such as dual-port access.
3.5.2.1. Advantages
On-chip memory is the highest throughput, lowest latency memory possible in an FPGA-based embedded system. It typically has a latency of only one clock cycle. Memory transactions can be pipelined, making a throughput of one transaction per clock cycle typical.
Some variations of on-chip memory can be accessed in dual-port mode, with separate ports for read and write transactions. Dual-port mode effectively doubles the potential bandwidth of the memory, allowing the memory to be written over one port, while simultaneously being read over the second port.
Another advantage of on-chip memory is that it requires no additional board space or circuit-board wiring because it is implemented on the FPGA directly. Using on-chip memory can often save development time and cost.
Finally, some variations of on-chip memory can be automatically initialized with custom content during FPGA configuration. This memory is useful for holding small bits of boot code or LUT data which needs to be present at reset.
3.5.2.2. Disadvantages
While on-chip memory is very fast, it is somewhat limited in capacity. The amount of on-chip memory available on an FPGA depends solely on the particular FPGA device being used, but capacities range from around 15 KBytes in the smallest Cyclone II device to just under 2 MBytes in the largest Stratix III device.
Because most on-chip memory is volatile, it loses its contents when power is disconnected. However, some types of on-chip memory can be initialized automatically when the FPGA is configured, essentially providing a kind of non-volatile function. For details, refer to the embedded memory chapter of the device handbook for the particular FPGA family you are using or Intel® Quartus® Prime Help.
3.5.2.3. Best Applications
The following sections describe the best uses of on-chip memory.
3.5.2.3.1. Cache
Because it is low latency, on-chip memory functions very well as cache memory for microprocessors. The Nios® II processor uses on-chip memory for its instruction and data caches. The limited capacity of on-chip memory is usually not an issue for caches because they are typically relatively small.
3.5.2.3.2. Tightly Coupled Memory
The low latency access of on-chip memory also makes it suitable for tightly coupled memories. Tightly coupled memories are memories which are mapped in the normal address space, but have a dedicated interface to the microprocessor, and possess the high speed, low latency properties of cache memory.
For more information regarding tightly-coupled memories, refer to the Using Tightly Coupled Memory with the Nios® II Processor Tutorial.
3.5.2.3.3. Look Up Tables
For some software programming functions, particularly mathematical functions, it is sometimes fastest to use a LUT to store all the possible outcomes of a function, rather than computing the function in software. On-chip memories work well for this purpose as long as the number of possible outcomes fits reasonably in the capacity of on-chip memory available.
3.5.2.3.4. FIFO
Embedded systems often need to regulate the flow of data from one system block to another. FIFOs can buffer data between processing blocks that run most efficiently at different speeds. Depending on the size of the FIFO your application requires, on-chip memory can serve as very fast and convenient FIFO storage.
For more information regarding FIFO buffers, refer to the On-Chip FIFO Memory Core chapter of the Embedded Peripheral IP User Guide.
3.5.2.4. Poor Applications
On-chip memory is poorly suited for applications which require large memory capacity. Because on-chip memory is relatively limited in capacity, avoid using it to store large amounts of data; however, some tasks can take better advantage of on-chip memory than others. If your application utilizes multiple small blocks of data, and not all of them fit in on-chip memory, you should carefully consider which blocks to implement in on-chip memory. If high system performance is your goal, place the data which is accessed most often in on-chip memory cache.
3.5.2.5. On-Chip Memory Types
Depending on the type of FPGA you are using, several types of on-chip memory are available. For details on the different types of on-chip memory available to you, refer to the device handbook for the particular FPGA family you are using.
3.5.2.6. Best Practices
To optimize the use of the on-chip memory in your system, follow these guidelines:
- Set the on-chip memory data width to match the data-width of its primary system master. For example, if you are connecting the on-chip memory to the data master of a Nios® II processor, you should set the data width of the on-chip memory to 32 bits, the same as the data-width of the Nios® II data master. Otherwise, the access latency could be longer than one cycle because the system interconnect fabric performs width translation.
- If more than one master connects to an on-chip memory component, consider enabling the dual-port feature of the on-chip memory. The dual-port feature removes the need for arbitration logic when two masters access the same on-chip memory. In addition, dual-ported memory allows concurrent access from both ports, which can dramatically increase efficiency and performance when the memory is accessed by two or more masters. However, writing to both slave ports of the RAM can result in data corruption if there is not careful coordination between the masters.
To minimize FPGA logic and memory utilization, follow these guidelines:
- Choose the best type of on-chip memory for your application. Some types are larger capacity; others support wider data-widths. The embedded memory section in the device handbook for the appropriate FPGA family provides details on the features of on-chip memories.
- Choose on-chip memory sizes that are a power of 2 bytes. Implementing memories with sizes that are not powers of 2 can result in inefficient memory and logic use.
3.5.3. External SRAM
The term external SRAM refers to any static RAM (SRAM) device that you connect externally to a FPGA. There are several varieties of external SRAM devices. The choice of external SRAM and its type depends on the nature of the application. Designing with SRAM memories presents both advantages and disadvantages.
3.5.3.1. Advantages
External SRAM devices provide larger storage capacities than on-chip memories, and are still quite fast, although not as fast as on-chip memories. Typical external SRAM devices have capacities ranging from around 128 KBytes to 10 MBytes. Specialty SRAM devices can even be found in smaller and larger capacities. SRAMs are typically very low latency and high throughput devices, slower than on-chip memory only because they connect to the FPGA over a shared, bidirectional bus. The SRAM interface is very simple, making connecting to an SRAM from an FPGA a simple design task. You can also share external SRAM buses with other external SRAM devices, or even with external memories of other types, such as flash or SDRAM.
3.5.3.2. Disadvantages
The primary disadvantages of external SRAM in an FPGA-based embedded system are cost and board real estate. SRAM devices are more expensive per MByte than other high-capacity memory types such as SDRAM. They also consume more board space per MByte than both SDRAM and FPGA on-chip memory, which consumes none.
3.5.3.3. Best Applications
External SRAM is quite effective as a fast buffer for medium-size blocks of data. You can use external SRAM to buffer data that does not fit in on-chip memory and requires lower latency than SDRAM provides. You can also group multiple SRAM memories to increase capacity.
SRAM is also optimal for accessing random data. Many SRAM devices can access data at non-sequential addresses with the same low latency as sequential addresses, an area where SDRAM performance suffers. SRAM is the ideal memory type for a large LUT holding the data for a color conversion algorithm that is too large to fit in on-chip memory, for example.
External SRAM performs relatively well when used as execution memory for a processor with no cache. The low latency properties of external SRAM help improve processor performance if the processor has no cache to mask the higher latency of other types of memory.
3.5.3.4. Poor Applications
Poor uses for external SRAM include systems which require large amounts of storage and systems which are cost-sensitive. If your system requires a block of memory larger than 10 MBytes, you may want to consider a different type of memory, such as SDRAM, which is less expensive.
3.5.3.5. External SRAM Types
There are several types of SRAM devices. The following types are the most popular:
- Asynchronous SRAM—This is the slowest type of SRAM because it is not dependent on a clock.
- Synchronous SRAM (SSRAM)—Synchronous SRAM operates synchronously to a clock. It is faster than asynchronous SRAM but also more expensive.
- Pseudo-SRAM—Pseudo-SRAM (PSRAM) is a type of dynamic RAM (DRAM) which has an SSRAM interface.
- ZBT SRAM—ZBT (zero bus turnaround) SRAM can switch from read to write transactions with zero turnaround cycles, making it very low latency. ZBT SRAM typically requires a special controller to take advantage of its low latency features.
3.5.3.6. Best Practices
To get the best performance from your external SRAM devices, follow these guidelines:
- Use SRAM interfaces which are the same data width as the data width of the primary system master that accesses the memory.
- If pin utilization or board real estate is a larger concern than the performance of your system, you can use SRAM devices with a smaller data width than the masters that accesses them to reduce the pin count of your FPGA and possibly the number of memory devices on the PCB. However, this change results in reduced performance of the SRAM interface.
3.5.4. Flash Memory
Flash memory is a non-volatile memory type used frequently in embedded systems. In FPGA-based embedded systems, flash memory is always external because FPGAs do not contain flash memory. Because flash memory retains its contents after power is removed, it is commonly used to hold microprocessor boot code as well as any data which needs to be preserved in the case of a power failure. Flash memories are available with either a parallel or a serial interface. The fundamental storage technology for parallel and serial flash devices is the same.
Unlike SRAM, flash memory cannot be updated with a simple write transaction. Every write to a flash device uses a write command consisting of a fixed sequence of consecutive read and write transactions. Before flash memory can be written, it must be erased. All flash devices are divided into some number of erase blocks, or sectors, which vary in size, depending on the flash vendor and device size. Entire sections of flash must be erased as a unit; individual words cannot be erased. These requirements sometimes make flash devices difficult to use.
3.5.4.1. Advantages
The primary advantage of flash memory is that is non-volatile. Modern embedded systems use flash memory extensively to store not only boot code and settings, but large blocks of data such as audio or video streams. Many embedded systems use flash memory as a low power, high reliability substitute for a hard drive.
Among other non-volatile types of memory, flash memory is the most popular for the following four reasons:
- It is durable.
- It is erasable.
- It permits a large number of erase cycles.
- It is low-cost.
You can share flash buses with other flash devices, or even with external memories of other types, such as external SRAM or SDRAM.
3.5.4.2. Disadvantages
A major disadvantage of flash is its write speed. Because you can only write to flash devices using special commands, multiple bus transactions are required for each flash write. Furthermore, the actual write time, after the write command is sent, can be several microseconds. Depending on clock speed, the actual write time can be in the hundreds of clock cycles. Because of the sector-erase restriction, if you need to change a data word in the flash, you must complete the following steps:
- Copy the entire contents of the sector into a temporary buffer.
- Erase the sector.
- Change the single data word in the temporary buffer.
- Write the temporary buffer back to the flash memory device.
This procedure contributes to the poor write speed of flash memory devices. Because of its poor write speed, flash memory is typically used only for storing data which must be preserved after power is turned off.
3.5.4.3. Typical Applications
Flash memory is effective for storing any data that you wish to preserve if power is removed from the system. Common uses of flash memory include storage of the following types of data:
- Microprocessor boot code
- Microprocessor application code to be copied to RAM at system startup
- Persistent system settings, including the following types of settings:
- Network MAC address
- Calibration data
- User preferences
- FPGA configuration images
- Media (audio, video)
3.5.4.4. Poor Applications
Because of flash memory's slow write speeds, you should not use it for anything that does not need to be preserved after power-off. SRAM is a much better alternative if volatile memory is an option. Systems that use flash memory usually also include some SRAM as well.
One particularly poor use of flash is direct execution of microprocessor application code. If any of the code's writable sections are located in flash memory, the software simply will not work, because flash memory cannot be written without using its special write commands. Systems that store application code in flash memory usually copy the application to SRAM before executing it.
3.5.4.5. Flash Types
There are several types of flash devices. The following types are the most popular:
- Serial flash – This flash has a serial interface to preserve device pins and
board space. Because many serial flash devices have their own specific interface
protocol, it is best to thoroughly read a serial flash device's datasheet before
choosing it. Intel EPCS configuration devices are a type of serial flash.
For more information about EPCS configuration devices, refer to the Documentation: Configuration Devices page on the Intel website.
- NAND flash – NAND flash can achieve very high capacities, up to multiple GBytes per device. The interface to NAND flash is a bit more complicated than that of CFI flash. It requires either a special controller or intelligent low-level driver software. You can use NAND Flash with Intel FPGAs; however, Intel does not provide any built-in support.
3.5.5. SDRAM
SDRAM is another type of volatile memory. It is similar to SRAM, except that it is dynamic and must be refreshed periodically to maintain its content. The dynamic memory cells in SDRAM are much smaller than the static memory cells used in SRAM. This difference in size translates into very high-capacity and low-cost memory devices.
In addition to the refresh requirement, SDRAM has other very specific interface requirements which typically necessitate the use of special controller hardware. Unlike SRAM, which has a static set of address lines, SDRAM divides up its memory space into banks, rows, and columns. Switching between banks and rows incurs some overhead, so that efficient use of SDRAM involves the careful ordering of accesses. SDRAM also multiplexes the row and column addresses over the same address lines, which reduces the pin count necessary to implement a given size of SDRAM. Higher speed varieties of SDRAM such as DDR, DDR2, and DDR3 also have strict signal integrity requirements which need to be carefully considered during the design of the PCB.
SDRAM devices are among the least expensive and largest-capacity types of RAM devices available, making them one of the most popular. Most modern embedded systems use SDRAM. A major part of an SDRAM interface is the SDRAM controller. The SDRAM controller manages all the address-multiplexing, refresh and row and bank switching tasks, allowing the rest of the system to access SDRAM without knowledge of its internal architecture.
For information about the SDRAM controllers available for use in Intel FPGAs, refer to the External Memory Interface Handbook.
3.5.5.1. Advantages
SDRAM's most significant advantages are its capacity and cost. No other type of RAM combines the low cost and large capacity of SDRAM, which makes it a very popular choice. SDRAM also makes efficient use of pins. Because row and column addresses are multiplexed over the same address pins, fewer pins are required to implement a given capacity of memory. Finally, SDRAM generally consumes less power than an equivalent SRAM device.
In some cases, you can also share SDRAM buses between multiple SDRAM devices, or even with external memories of other types, such as external SRAM or flash memory.
3.5.5.2. Disadvantages
Along with the high capacity and low cost of SDRAM, come additional complexity and latency. The complexity of the SDRAM interface requires that you always use an SDRAM controller to manage SDRAM refresh cycles, address multiplexing, and interface timing. Such a controller consumes FPGA logic elements that would normally be available for other logic.
SDRAM suffers from a significant amount of access latency. Most SDRAM controllers take measures to minimize the amount of latency, but SDRAM latency is always greater than that of regular external SRAM or FPGA on-chip memory. However, while first-access latency is high, SDRAM throughput can actually be quite high after the initial access latency is overcome, because consecutive accesses can be pipelined. Some types of SDRAM can achieve higher clock frequencies than SRAM, further improving throughput. The SDRAM interface specification also employs a burst feature to help improve overall throughput.
3.5.5.3. Best Applications
SDRAM is generally a good choice in the following circumstances:
- Storing large blocks of data—SDRAM's large capacity makes it the best choice for buffering large blocks of data such as network packets, video frame buffers, and audio data.
- Executing microprocessor code—SDRAM is commonly used to store instructions and data for microprocessor software, particularly when the program being executed is large. Instruction and data caches improve performance for large programs. Depending on the system topography and the SDRAM controller used, the sequential read patterns typical of cache line fills can potentially take advantage of SDRAM's pipeline and burst capabilities.
3.5.5.4. Poor Applications
SDRAM may not be the best choice in the following situations:
- Whenever low-latency memory access is required—Although high throughput is possible using SDRAM, its first-access latency is quite high. If low latency access to a particular block of data is a requirement of your application, SDRAM is probably not a good candidate to store that block of data.
- Small blocks of data—When only a small amount of storage is needed, SDRAM may be unnecessary. An on-chip memory may be able to meet your memory requirements without adding another memory device to the PCB.
- Small, simple embedded systems—If your system uses a small FPGA in which logic resources are scarce and your application does not require the capacity that SDRAM provides, you may prefer to use a small external SRAM or on-chip memory rather than devoting FPGA logic elements to an SDRAM controller.
3.5.5.5. SDRAM Types
There are a several types of SDRAM devices. The following types are the most common:
- SDR SDRAM—Single data rate (SDR) SDRAM is the original type of SDRAM. It is referred to as SDRAM or as SDR SDRAM to distinguish it from newer, double data rate (DDR) types. The name single data rate refers to the fact that a maximum of one word of data can be transferred per clock cycle. SDR SDRAM is still in wide use, although newer types of DDR SDRAM are becoming more common.
- DDR SDRAM—Double data rate (DDR) SDRAM is a newer type of SDRAM that supports higher data throughput by transferring a data word on both the rising and falling edge of the clock. DDR SDRAM uses 2.5 V SSTL signaling. The use of DDR SDRAM requires a custom memory controller.
- DDR2 SDRAM—DDR2 SDRAM is a newer variation of standard DDR SDRAM memory which builds on the success of DDR by implementing slightly improved interface requirements such as lower power 1.8 V SSTL signaling and on-chip signal termination.
- DDR3 SDRAM—DDR3 is another variant of DDR SDRAM which improves the potential bandwidth of the memory further by improving signal integrity and increasing clock frequencies.
- QDR, QDR II, and QDR II+ SRAM—Quad Data Rate (QDR) SRAM has independent read and write ports that run concurrently at double data rate. QDR SRAM is true dual-port (although the address bus is still shared), which gives this memory a high bandwidth, allowing back-to-back transactions without the contention issues that can occur when using a single bidirectional data bus. Write and read operations share address ports.
- RLDRAM II and RLDRAM 3—Reduced latency DRAM (RLDRAM) provides DRAM-based point-to-point memory devices designed for communications, imaging, server systems, networking, and cache applications requiring high density, high memory bandwidth, and low latency. The fast random access speeds in RLDRAM devices make them a viable alternative to SRAM devices at a lower cost.
- LPDDR2—LPDDR2-S is a high-speed SDRAM device internally configured as a 4- or 8-bank memory. All LPDDR2 devices use double data rate architecture on the address and command bus to reduce the number of input pins in the system. The 10-bit address and command bus contains command, address, and bank/row buffer information. Each command uses one clock cycle, during which command information is transferred on both the positive and negative edges of the clock.
- LPDDR3—LPDDR3-SDRAM is a high-speed synchronous DRAM device internally configured as an 8-bank memory. All LPDDR3 devices use double data rate architecture on the address and command bus to reduce the number of input pins in the system. The 10-bit address and command bus contains command, address, and bank buffer information. Each command uses one clock cycle, during which command information is transferred on both the positive and negative edges of the clock.
For more information about SDRAM types refer to the External Memory Interface Handbook Volume 2: Design Guidelines.
3.5.5.6. SDRAM Controller Types Available From Intel
The table below lists the SDRAM controllers that Intel provides. These SDRAM controllers are available without licenses.
Controller Name | Description |
---|---|
SDR SDRAM Controller |
This controller is the only SDR SDRAM controller Intel offers. It is a simple, easy-to-use controller that works with most available SDR SDRAM devices. |
DDR/DDR2 Controller Megacore Function | This controller is a legacy component which is maintained for existing designs only. Intel does not recommend it for new designs. |
High Performance DDR/DDR2 Controller | This controller is the DDR/DDR2 controller that Intel recommends for
new designs. It supports two primary clocking modes, full-rate and
half-rate.
|
High Performance DDR3 Controller | This controller is the DDR3 controller that Intel recommends for new designs. It is similar to the high performance DDR/DDR2 controller. It also supports full- and half-rate clocking modes. |
Hard Memory Controller (HMC) | The hard memory controller initializes, refreshes, manages, and communicates with the external memory device. The HMC supports all the popular and emerging memory standards including DDR4, DDR3, and LPDDR3. |
For more information about the available SDRAM controllers, refer to the External Memory Interface Handbook Volume 3: Reference Material.
3.5.5.7. Best Practices
When using the high performance DDR or DDR2 SDRAM controller, it is important to determine whether full-rate or half-rate clock mode is optimal for your application.
3.5.5.7.1. Half-Rate Mode
Half-rate mode is optimal in cases where you require the highest possible SDRAM clock frequency, or when the complexity of your system logic means that you are not able to achieve the clock frequency you need for the DDR SDRAM. In half-rate mode, the internal Avalon® interface to the SDRAM controller runs at half the external SDRAM frequency.
In half-rate mode, the local data width (the data width inside the Platform Designer system) of the SDRAM controller is four times the data width of the physical DDR SDRAM device. For example, if your SDRAM device is 8 bits wide, the internal Avalon® data port of the SDRAM controller is 32 bits. This design choice facilitates bursts of four accesses to the SDRAM device.
3.5.5.7.2. Full-Rate Mode
In full-rate mode, the internal Avalon interface to the SDRAM controller runs at the full external DDR SDRAM clock frequency. Use full-rate mode if your system logic is simple enough that it can easily achieve DDR SDRAM clock frequencies, or when running the system logic at half the clock rate of the SDRAM interface is too slow for your requirements.
When using full-rate mode, the local data width of the SDRAM controller is twice the data width of the physical DDR SDRAM. For example, if your SDRAM device is 16 bits wide, the internal Avalon data port of the SDRAM controller in full-rate mode is 32 bits wide. Again, this choice facilitate bursts to the SDRAM device.
3.5.5.7.3. Sequential Access
SDRAM performance benefits from sequential accesses. When access is sequential, data is written or read from consecutive addresses and it may be possible to increase throughput by using bursting. In addition, the SDRAM controller can optimize the accesses to reduce row and bank switching. Each row or bank change incurs a delay, so that reducing switching increases throughput.
3.5.5.7.4. Bursting
SDRAM devices employ bursting to improve throughput. Bursts group a number of transactions to sequential addresses, allowing data to be transferred back-to-back without incurring the overhead of requests for individual transactions. If you are using the high performance DDR/DDR2 SDRAM controller, you may be able to take advantage of bursting in the system interconnect fabric as well. Bursting is only useful if both the master and slave involved in the transaction are burst-enabled. Refer to the documentation for the master in question to check whether bursting is supported.
Selecting the burst size for the high performance DDR/DDR2 SDRAM controller depends on the mode in which you use the controller. In half-rate mode, the Avalon-MM data port is four times the width of the actual SDRAM device; consequently, four transactions are initiated to the SDRAM device for each single transfer in the system interconnect fabric. A burst size of four is used for those four transactions to SDRAM. This is the maximum size burst supported by the high performance DDR/DDR2 SDRAM controller. Consequently, using bursts for the high performance DDR/DDR2 SDRAM controller in half-rate mode does not increase performance because the system interconnect fabric is already using its maximum supported burst-size to carry out each single transaction.
However, in full-rate mode, you can use a burst size of two with the high performance DDR/DDR2 SDRAM controller. In full-rate mode, each Avalon transaction results in two SDRAM device transactions, so two Avalon transactions can be combined in a burst before the maximum supported SDRAM controller burst size of four is reached.
3.5.5.7.5. SDRAM Minimum Frequency
Many SDRAM devices, particularly DDR, DDR2, and DDR3 devices have minimum clock frequency requirements. The minimum clock rate depends on the particular SDRAM device. Refer to the datasheet of the SDRAM device you are using to find the device's minimum clock frequency.
3.5.5.7.6. SDRAM Device Speed
SDRAM devices, both SDR and DDR, come in several speed grades. When using SDRAM with FPGAs, the operating frequency of the FPGA system is usually lower than the maximum capability of the SDRAM device. Therefore, it is typically not worth the extra cost to use fast speed-grade SDRAM devices. Before committing to a specific SDRAM device, consider both the expected SDRAM frequency of your system, and the maximum and minimum operating frequency of the particular SDRAM device.
3.5.6. Case Study
This section describes the optimization of memory partitioning in a video processing application to illustrate the concepts discussed earlier.
3.5.6.1. Application Description
This video processing application employs an algorithm that operates on a full frame of video data, line by line. Other details of the algorithm do not impact design of the memory subsystem. The data flow includes the following steps:
- A dedicated DMA engine copies the input data from the video source to a buffer.
- A Nios® II processor operates on that buffer, performing the video processing algorithm and writing the result to another buffer.
- A second dedicated DMA engine copies the output from the processor result buffer to the video output device.
- The two DMAs provide an element of concurrency by copying input data to the next input buffer, and copying output data from the previous output buffer at the same time the processor is processing the current buffer, a technique commonly called ping-ponging.
3.5.6.2. Initial Memory Partitioning
As a starting point, the application uses SDRAM for all of its storage and buffering, a commonly used memory architecture. The input DMA copies data from the video source to an input buffer in SDRAM. The Nios® II processor reads from the SDRAM input buffer, processes the data, and writes the result to an output buffer, also located in SDRAM. In addition, the processor uses SDRAM for both its instruction and data memory, as shown below.
Functionally, there is nothing wrong with this implementation. It is a frequently used, traditional type of embedded system architecture. It is also relatively inexpensive, because it uses only one external memory device; however, it is somewhat inefficient, particularly regarding its use of SDRAM. As the figure above illustrates, six different channels of data are accessed in the SDRAM.
- Processor instruction channel
- Processor data channel
- Input data from DMA
- Input data to processor
- Output data from processor
- Output data to DMA
With these many channels moving in and out of SDRAM simultaneously, especially at the high data rates required by video applications, the SDRAM bandwidth is easily the most significant performance bottleneck in the design.
3.5.6.3. Optimized Memory Partitioning
This design can be optimized to operate more efficiently. These optimizations are described in the following sections.
3.5.6.3.1. Add an External SRAM for Input Buffers
The first optimization to improve efficiency is to move the input buffering from the SDRAM to an external SRAM device. This technique creates performance gains for the following three reasons:
- The input side of the application achieves higher throughput because it now uses its own dedicated external SRAM to bring in video data.
- Two of the high-bandwidth channels from the SDRAM are eliminated, allowing the remaining SDRAM channels to achieve higher throughput.
- Eliminating two channels reduces the number of accesses to the SDRAM memory, leading to fewer SDRAM row changes, leading to higher throughput.
The redesigned system processes data faster, at the expense of more complexity and higher cost. The figure below illustrates the redesigned system.
If the video frames are small enough to fit in FPGA on-chip memory, you can use on-chip memory for the input buffers, saving the expense and complexity of adding an external SRAM device.
Note that four channels remain connected to SDRAM:
- Processor instruction channel
- Processor data channel
- Output data from processor
- Output data to DMA
While we could probably achieve some additional performance benefit by adding a second external SRAM for the output channel, the benefit is not likely to be significant enough to outweigh the added cost and complexity. The reason is that only two of the four remaining channels require significant bandwidth from the SDRAM, the two video output channels. Assuming our Nios® II processor contains both instruction and data caches, the SDRAM bandwidth required by the processor is likely to be relatively small. Therefore, sharing the SDRAM for processor instructions, processor data, and the video output channel is probably acceptable. If necessary, increasing the processor cache sizes can further reduce the processor's reliance on SDRAM bandwidth.
3.5.6.3.2. Add On-Chip Memory for Video Line Buffers
The final optimization is to add small on-chip memory buffers for input and output video lines. Because the processing algorithm operates on the video input one line at a time, buffering entire lines of input data in an on-chip memory improves performance. This buffering enables the Nios® II processor to read all its input data from on-chip RAM—the fastest, lowest latency type of memory available.
The DMA fills these buffers ahead of the Nios® II processor in a ping-pong scheme, in a manner analogous to the input frame buffers used for the external SRAM. The same on-chip memory line buffering scheme is used for processor output. The Nios® II processor writes its output data to an on-chip memory line buffer, which is copied to the output frame buffer by a DMA after both the input and output ping-pong buffers flip, and the processor begins processing the next line. The figure below illustrates this memory architecture.
3.6. Nios II Hardware Development Tutorial
Using the Intel® Quartus® Prime software and the Nios® II Embedded Design Suite (EDS), you can:
- build a Nios® II hardware system design
- create a software program that runs on the Nios® II system and interfaces with components on Intel development boards
Building embedded systems in FPGAs involves system requirements analysis, hardware design tasks, and software design tasks. This tutorial guides you through the basics of each topic, with special focus on the hardware design steps.
3.6.1. Software and Hardware Requirements
The following are the software requirements for the tutorial:
- Intel® Quartus® Prime software version 14.0 or later—The software must be installed on a Windows or Linux computer that meets the Intel® Quartus® Prime minimum requirements.
- Nios® II EDS version 14.0 or later.
- Design files for the design example—Refer related information below for the design example file.
You can build the design example with any Intel development board or your own custom board that meets the following hardware requirements:
- The board must have either Intel® MAX® 10, Stratix series, Cyclone series, or Arria series FPGA.
- The FPGA must contain a minimum of 2800 logic elements (LE) or adaptive lookup tables (ALUT).
- The FPGA must contain a minimum of 40 M9K memory blocks.
- An oscillator must drive a constant clock frequency to an FPGA pin. The maximum frequency limit depends on the speed grade of the FPGA. Frequencies of 50 MHz or less should work for most boards; higher frequencies might work.
- FPGA I/O pins can optionally connect to eight or fewer LEDs to provide a visual indicator of processor activity.
- The board must have a JTAG connection to the FPGA that provides a programming interface and communication link to the Nios® II system. The JTAG connection can be a dedicated 10-pin JTAG header for an Intel FPGA USB Download Cable or a USB connection with Intel® FPGA Download Cable circuitry embedded on the board.
3.6.2. Intel FPGA IP Evaluation Mode
You can perform this tutorial on hardware without a license. With Intel® FPGA IP Evaluation Mode, you can perform the following actions:
- Simulate the behavior of a Nios® II processor within your system
- Verify the functionality of your design
- Evaluate the size and speed of your design quickly and easily
- Generate time-limited device programming files for designs that include Nios® II processors
- Program a device and verify your design in hardware
You need to purchase a license for the Nios® II processor only when you are completely satisfied with its functionality and performance, and want to use your design in production.
3.6.3. Nios II Design Example
The example Nios® II system contains the following components:
- Nios® II/f processor core
- On-chip memory
- Timer
- JTAG UART
- 8-bit parallel I/O (PIO) pins to control the LEDs
- System identification component
Other logic can exist within the FPGA alongside the Nios® II system. In fact, most FPGA designs with a Nios® II system also include other logic. A Nios® II system can interact with other on-chip logic, depending on the needs of the overall system. This design example does not include other logic in the FPGA.
3.6.4. Nios II System Development Flow
The Nios® II development flow consists of three types of development:
- hardware design steps
- software design steps
- system design steps, involving both hardware and software
The design steps in this tutorial focus on hardware development, and provide only a simple introduction to software development.
3.6.4.1. Analyzing System Requirements
The development flow begins with predesign activity which includes an analysis of the application requirements, such as the following questions:
- What computational performance does the application require?
- How much bandwidth or throughput does the application require?
- What types of interfaces does the application require?
- Does the application require multithreaded software?
Based on the answers to these questions, you can determine the concrete system requirements, such as:
- Which Nios® II processor core to use: smaller or faster.
- What components the design requires and how many of each kind.
- Which real-time operating system (RTOS) to use, if any.
- Where hardware acceleration logic can dramatically improve system performance.
For example:
- Could adding a DMA component eliminate wasted processor cycles copying data?
- Could a custom instruction replace the critical loop of a DSP algorithm?
Analyzing these topics involve both the hardware and software point of view.
3.6.4.2. Defining and Generating the System in Platform Designer
After analyzing the system hardware requirements, you use Platform Designer to specify the Nios® II processor core(s), memory, and other components your system requires. Platform Designer automatically generates the interconnect logic to integrate the components in the hardware system.
You can select from a list of standard processor cores and components provided with the Nios® II EDS. You can also add your own custom hardware to accelerate system performance. You can add custom instruction logic to the Nios® II core which accelerates CPU performance, or you can add a custom component which offloads tasks from the CPU. This tutorial covers adding standard processor and component cores, and does not cover adding custom logic to the system.
The primary outputs of Platform Designer are the following file types:
File Types | Description |
---|---|
Platform Designer Design File (.qsys) | Contains the hardware contents of the Platform Designer system |
SOPC Information File (.sopcinfo) | Contains a description of the contents of the .qsys file in Extensible Markup Language File (.xml) format. The Nios® II EDS uses the .sopcinfo file to create software for the target hardware. |
Hardware description language (HDL) files | Are the hardware design files that describe the Platform Designer system. The Intel® Quartus® Prime software uses the HDL files to compile the overall FPGA design into an SRAM Object File (.sof). |
3.6.4.3. Integrating the Platform Designer System into the Intel Quartus Prime Project
After generating the Nios® II system using Platform Designer, you integrate it into the Intel® Quartus® Prime project. Using the Intel® Quartus® Prime software, you perform all tasks required to create the final FPGA hardware design.
Using the Intel® Quartus® Prime software, you can:
- assign pin locations for I/O signals
- specify timing requirements
- apply other design constraints
- compile the Intel® Quartus® Prime project to produce a .sof to configure the FPGA
You download the .sof to the FPGA on the target board using an Intel download cable, such as the Intel FPGA USB Download Cable. After configuration, the FPGA behaves as specified by the hardware design, which in this case is a Nios® II processor system.
3.6.4.4. Developing Software with the Nios II Software Build Tools for Eclipse
You can perform all software development tasks for your Nios® II processor system using the Nios® II Software Build Tools (SBT) for Eclipse™.
After you generate the system with Platform Designer, you can begin designing your C/C++ application code immediately with the Nios® II SBT for Eclipse. Intel provides component drivers and a hardware abstraction layer (HAL) which allows you to write Nios® II programs quickly and independently of the low-level hardware details. In addition to your application code, you can design and reuse custom libraries in your Nios® II SBT for Eclipse projects.
To create a new Nios® II C/C++ application project, the Nios® II SBT for Eclipse uses information from the .sopcinfo file. You also need the .sof file to configure the FPGA before running and debugging the application project on target hardware.
The Nios® II SBT for Eclipse can produce several outputs, listed below. Not all projects require all of these outputs.
Output | Description |
---|---|
system.h file |
|
Executable and Linking Format File (.elf) | Is the result of compiling a C/C++ application project, that you can download directly to the Nios® II processor. |
Hexadecimal (Intel-Format) File (.hex) |
|
Flash memory programming data |
|
This tutorial focuses on downloading only the .elf directly to the Nios® II system.
3.6.4.5. Running and Debugging Software on the Target Board
The Nios® II SBT for Eclipse has the capability to download software to a target board, and run or debug the program on hardware. The Nios® II SBT for Eclipse debugger allows you to start and stop the processor, step through code, set breakpoints, and analyze variables as the program executes.
3.6.4.6. Varying the Development Flow
The development flow is not strictly linear. The following lost the common variations:
- Refining the Software and Hardware
- Iteratively Creating a Nios® II System
- Verifying the System with Hardware Simulation Tools
Refining the Software and Hardware
After running software on the target board, you might discover that the Nios® II system requires higher performance. In this case, you can:
- return to software design steps to make improvements to the software algorithm; or
- return to hardware design steps to add acceleration logic
If the system performs multiple mutually exclusive tasks, you might even decide to use two (or more) Nios® II processors that divide the workload and improve the performance of each individual processor.
Iteratively Creating a Nios® II System
A common technique for building a complex Nios® II system is to start with a simpler Platform Designer system, and iteratively add to it. At each iteration, you can verify that the system performs as expected. You might choose to verify the fundamental components of a system, such as the processor, memory, and communication channels, before adding more complex components. When developing a custom component or a custom instruction, first integrate the custom logic into a minimal system to verify that it works as expected; then integrate the custom logic into a more complex system.
Verifying the System with Hardware Simulation Tools
You can perform hardware simulation of software executing on the Nios® II system, using tools such as the ModelSim® RTL simulator. Hardware simulation is useful to meet certain needs, including the following cases:
- To verify the cycle-accurate performance of a Nios® II system before target hardware is available.
- To verify the functionality of a custom component or a Nios® II custom instruction before trying it on hardware.
If you are building a Nios® II system based on the standard components provided with the Nios® II EDS, the easiest way to verify functionality is to download the hardware and software directly to a development board.
3.6.5. Creating the Design Example
First, you must install the Intel® Quartus® Prime software and the Nios® II EDS. You must also download tutorial design files from the Intel web site. The design files provide a ready-made Intel® Quartus® Prime project to use as a starting point.
3.6.5.1. Install the Design Files
Perform the following steps to set up the design environment:
- Locate the zipped design files on the Intel web site.
-
Unzip the contents of the zip file to a directory on your computer. Do not use
spaces in the directory path name.
The remainder of this tutorial refers to this directory as the <design files directory>.
3.6.5.2. Analyze System Requirements
The system requirements are derived from the following goals of the tutorial design example:
- Demonstrate a simple Nios® II processor system that you can use for control applications.
- Build a practical, real-world system, while providing an educational experience.
- Demonstrate the most common and effective techniques to build practical, custom Nios® II systems.
- Build a Nios® II system that works on any board with an Intel FPGA. The entire system must use only on-chip resources, and not rely on the target board.
- The design should conserve on-chip logic and memory resources so it can fit in a wide range of target FPGAs.
These goals lead to the following design decisions:
- The
Nios® II system uses only the following inputs and outputs:
- One clock input, which can be any constant frequency.
- Eight optional outputs to control LEDs on the target board.
- The design uses the following components:
- Nios® II/f core with 2 KB of instruction cache with static branch prediction
- 20 KB of on-chip memory
- Timer
- JTAG UART
- Eight output-only parallel I/O (PIO) pins
- System ID component
3.6.5.3. Start the Intel Quartus Prime Software and Open the Example Project
- Start the Intel® Quartus® Prime software.
-
Click Open Existing Project on the splash screen, or, on the File menu, click Open
Project.
The Open Project dialog box appears.
- Browse to the <design files directory>.
- Select the file nios2_quartus2_project.qpf and click Open.
-
To display the Block Diagram File (.bdf) nios2_quartus2_project.bdf,
perform the following steps:
-
On the File menu, click Open.
The Open dialog box appears.
- Browse to the <design files directory>.
- Select nios2_quartus2_project.bdf and click Open.
The .bdf contains an input pin for the clock input and eight output pins to drive LEDs on the board. -
On the File menu, click Open.
3.6.5.4. Create a New Platform Designer System
You use Platform Designer to generate the Nios® II processor system, adding the desired components, and configuring how they connect together. To create a new Platform Designer system, click Platform Designer on the Tools menu in the Intel® Quartus® Prime software. Platform Designer starts and displays the System Contents tab.
3.6.5.5. Define the System in Platform Designer
You use Platform Designer to define the hardware characteristics of the Nios® II system, such as which Nios® II core to use, and what components to include in the system. Platform Designer does not define software behavior, such as where in memory to store instructions or where to send the stderr character stream.
The Platform Designer design process does not need to be linear. The design steps in this tutorial are presented in the most straightforward order for a new user to understand. However, you can perform Platform Designer design steps in a different order.
3.6.5.5.1. Specify Target FPGA and Clock Settings
To specify target FPGA and clock settings, perform the following steps:
-
On the Project Settings
tab, select the Device Family that matches
the Intel FPGA you are targeting.
If a warning appears stating the selected device family does not match the Quartus project settings, ignore the warning. You specify the device in the Quartus project settings later in this tutorial.
- In the documentation for your board, look up the clock frequency of the oscillator that drives the FPGA.
- On the Clock Settings tab, double-click the clock frequency in the MHz column for clk_0. clk_0 is the default clock input name for the Platform Designer system. The frequency you specify for clk_0 must match the oscillator that drives the FPGA.
- Type the clock frequency and press Enter.
3.6.5.5.2. Add the On-Chip Memory
Processor systems require at least one memory for data and instructions. This design example uses one 20 KB on-chip memory for both data and instructions. To add the memory, perform the following steps:
- On the IP Catalog tab (to the left of the System Contents tab), expand Basic Functions, expand On-Chip Memory, and then click On-Chip Memory (RAM or ROM).
-
Click Add.
The On-Chip Memory (RAM or ROM) parameter editor appears.
- In the Block type list, select Auto.
-
In the Total memory size box, type 20480 to specify a memory size of 20 KB.
Do not change any of the other default settings.
- Click Finish. You return to Platform Designer.
-
Click the System Contents tab.
An instance of the on-chip memory appears in the system contents table.
- In the Name column of the system contents table, right-click the on-chip memory and click Rename.
-
Type onchip_mem and press Enter.
You must type these tutorial component names exactly as specified. Otherwise, the tutorial programs written for this Nios® II system fail in later steps. In general, it is a good habit to give descriptive names to hardware components. Nios® II programs use these symbolic names to access the component hardware. Therefore, your choice of component names can make Nios® II programs easier to read and understand.
3.6.5.5.3. Add the Nios II Processor Core
You add the Nios® II/f core and configure it to use 2 KB of on-chip instruction cache memory, no data cache and use static branch prediction. For this tutorial, the Nios® II/f core is configured to provide a balanced trade-off between performance and resource utilization. To add a Nios® II/f core to the system, perform the following steps:
- On the IP Catalog tab, expand Processors and Peripherals, and then click Nios® II Gen2 Processor.
-
Click Add.
The Nios® II Processor parameter editor appears, displaying the Core Nios II tab.
- In the Main Tab under Select an Implementation, select Nios® II/f.
-
Click Finish and return to the
Platform Designer System Contents tab.
The Nios® II core instance appears in the system contents table. Ignore the exception and reset vector error messages. You resolve these errors in future steps.
- In the Name column, right-click the Nios® II processor and click Rename.
- Type cpu and press Enter.
- In the Connections column, connect the clk port of the clk_0 clock source to both the clk1 port of the on-chip memory and the clk port of the Nios® II processor by clicking the hollow dots on the connection line. The dots become solid indicating the ports are connected.
- Connect the clk_reset port of the clk_0 clock source to both the reset1 port of the on-chip memory and the reset_n port of the Nios® II processor.
- Connect the s1 port of the on-chip memory to both the data_master port and instruction_master port of the Nios® II processor.
- Double-click the Nios® II processor row of the system contents table to reopen the Nios® II Processor parameter editor.
- Under Reset Vector in Vectors tab, select onchip_mem.s1 in the Reset vector memory list and type 0x0 in the Reset vector offset box.
- Under Exception Vector, select onchip_mem.s1 in the Exception vector memory list and type 0x20 in the Exception vector offset box.
- Click the Caches and Memory Interfaces tab.
- In the Instruction cache list, select 2 Kbytes.
- Choose None for Data Cache size and do not change other default settings.
- In Advanced Features tab, select Static branch prediction type.
-
Click Finish. You
return
to the Platform Designer System Contents tab.
Do not change any settings on the MMU and MPU Settings and JTAG Debug tabs.
3.6.5.5.4. Add the JTAG UART
The JTAG UART provides a convenient way to communicate character data with the Nios® II processor through the Intel® FPGA Download Cable. To add the JTAG UART, perform the following steps:
- On the IP Catalog tab, expand Interface Protocols, expand Serial, and then click JTAG UART.
-
Click Add.
The JTAG UART parameter editor appears and do not change the default settings.
-
Click Finish and return to the
Platform Designer System Contents tab.
The JTAG UART instance appears in the system contents table.
- In the Name column, right-click the JTAG UART and click Rename.
- Type jtag_uart and press Enter.
- Connect the clk port of the clk_0 clock source to the clk port of the JTAG UART.
- Connect the clk_reset port of the clk_0 clock source to the reset port of the JTAG UART.
-
Connect the data_master port of the
Nios® II processor to the avalan_jtag_slave
port of the JTAG UART.
The instruction_master port of the Nios® II processor does not connect to the JTAG UART because the JTAG UART is not a memory device and cannot send instructions to the Nios® II processor.
3.6.5.5.5. Add the Interval Timer
Most control systems use a timer component to enable precise calculation of time. To provide a periodic system clock tick, the Nios® II HAL requires a timer. To add the timer, perform the following steps:
- On the IP Catalog tab, expand Processors and Peripherals, expand Peripherals, and then click Interval Timer.
-
Click Add.
The Interval Timer parameter editor appears.
-
Click Finish return to the
Platform Designer System Contents tab.
The interval timer instance appears in the system contents table.
- In the Name column, right-click the interval timer and click Rename.
- Type sys_clk_timer and press Enter.
- Connect the clk port of the clk_0 clock source to the clk port of the interval timer.
- Connect the clk_reset port of the clk_0 clock source to the reset port of the interval timer.
- Connect the data_master port of the Nios® II processor to the s1 port of the interval timer.
3.6.5.5.6. Add the System ID Peripheral
The system ID peripheral safeguards against accidentally downloading software compiled for a different Nios® II system. If the system includes the system ID peripheral, the Nios® II SBT for Eclipse can prevent you from downloading programs compiled for a different system. To add system ID peripheral, perform the following steps:
- On the IP Catalog tab, expand Basic Functions, expand Simulations; Debug and Verifications and then click System ID Peripheral.
-
Click Add.
The System ID Peripheral parameter editor appears and do not change the default setting.
-
Click Finish and return to the
Platform Designer System Contents tab.
The system ID peripheral instance appears in the system contents table.
- In the Name column, right-click the system ID peripheral and click Rename.
- Type sysid and press Enter.
- Connect the clk port of the clk_0 clock source to the clk port of the system ID peripheral.
- Connect the clk_reset port of the clk_0 clock source to the reset port of the system ID peripheral.
- Connect the data_master port of the Nios® II processor to the control_slave port of the system ID peripheral.
3.6.5.5.7. Add the PIO
PIO signals provide an easy method for Nios® II processor systems to receive input stimuli and drive output signals. Complex control applications might use hundreds of PIO signals which the Nios® II processor can monitor. This design example uses eight PIO signals to drive LEDs on the board. To add the PIO, perform the following steps:
- On the IP Catalog tab, expand Processors and Peripherals, expand Peripherals, and then click PIO .
-
Click Add.
The PIO (Parallel I/O) parameter editor appears and do not change the default settings.
-
Click Finish and return to the
Platform Designer System Contents tab.
The PIO instance appears in the system contents table.
- In the Name column, right-click the PIO and click Rename.
- Type led_pio and press Enter.
- Connect the clk port of the clk_0 clock source to the clk port of the PIO.
- Connect the clk_reset port of the clk_0 clock source to the reset port of the PIO.
- Connect the data_master port of the Nios® II processor to the s1 port of the PIO.
- In the external_connection row, click Click to export in the Export column to export the PIO ports.
3.6.5.5.8. Specify Base Addresses and Interrupt Request Priorities
To specify how the components added in the design to interact to form a system, you need assign base addresses for each slave component, and assign interrupt request (IRQ) priorities for the JTAG UART and the interval timer.
Platform Designer provides the Assign Base Addresses command which makes assigning component base addresses easy. For many systems, including this design example, Assign Base Addresses is adequate. However, you can adjust the base addresses to suit your needs. Below are some guidelines for assigning base addresses:
-
Nios® II processor cores can address a 31-bit address span. You must assign base
address between 0x00000000 and 0x7FFFFFFF. Note: The Use most-significant address bit in processor to bypass data cache option is enable by default. If disabled, the Nios® II processor cores supports full 32-bit address.
- Nios® II programs use symbolic constants to refer to addresses. You do not have to choose address values that are easy to remember.
- Address values that differentiate components with only a one-bit address difference produce more efficient hardware. You do not have to compact all base addresses into the smallest possible address range, because this can create less efficient hardware.
- Platform Designer does not attempt to align separate memory components in a contiguous memory range. For example, if you want an on-chip RAM and an off-chip RAM to be addressable as one contiguous memory range, you must explicitly assign base addresses.
Platform Designer also provides an Assign Interrupt Numbers command which connects IRQ signals to produce valid hardware results. However, assigning IRQs effectively requires an understanding of how software responds to them. Because Platform Designer does not know the software behavior, Platform Designer cannot make educated guesses about the best IRQ assignment.
The Nios® II HAL interprets low IRQ values as higher priority. The timer component must have the highest IRQ priority to maintain the accuracy of the system clock tick.
To assign appropriate base addresses and IRQs, perform the following steps:
- On the System menu, click Assign Base Addresses to make Platform Designer assign functional base addresses to each component in the system. Values in the Base and End columns might change, reflecting the addresses that Platform Designer reassigned.
- In the IRQ column, connect the Nios® II processor to the JTAG UART and interval timer.
- Click the IRQ value for the jtag_uart component to select it.
- Type 16 and press Enter to assign a new IRQ value.
- Click the IRQ value for the sys_clk_timer component to select it.
- Type 1 and press Enter to assign a new IRQ value.
3.6.5.5.9. Generate the Platform Designer System
To generate the Platform Designer system, perform the following steps:
- Click the Generation tab.
-
Select None in both the Create simulation model and Create testbench Platform Designer
system lists.
Because this tutorial does not cover the hardware simulation flow, you can select these settings to shorten generation time.
- Click Generate. Click Yes when the Save changes? dialog box appears.
-
Type first_nios2_system in the File name box and click Save.
The Generate dialog box appears and system generation process begins. The generation process can take several minutes. When generation completes, Platform Designer prompt: Create HDL design files for synthesis.
- Click Close to close the dialog box.
- On the File menu, click Exit to close Platform Designer and return to the Intel® Quartus® Prime software.
3.6.5.6. Integrate the Platform Designer System into the Intel Quartus Prime Project
To complete the hardware design, you need to perform the following tasks:
- Instantiate the Platform Designer system module in the Intel® Quartus® Prime project.
- Assign FPGA device and pin locations.
- Compile the Intel® Quartus® Prime project.
- Verify timing.
3.6.5.6.1. Instantiate the Platform Designer System Module in the Intel Quartus Prime Project
Platform Designer outputs a design entity called the system module. The tutorial design example uses the block diagram method of design entry, so you instantiate a system module symbol first_nios2_system into the .bdf.
To instantiate the system module in the .bdf, perform the following steps:
-
Double-click in the empty space to the right of the input and output wires.
The Symbol dialog box appears.
- Under Libraries, expand Project.
-
Click first_nios2_system.
The Symbol dialog box displays the first_nios2_system symbol.
- Click OK. You return to the .bdf schematic. The first_nios2_system symbol tracks with your mouse pointer.
- Position the symbol so the pins on the symbol align with the wires on the schematic.
- Click to anchor the symbol in place.
-
If your target board does not have LEDs that the
Nios® II system can drive, you
must delete the LEDG[7..0] pins. To delete the pins, perform the following steps:
- Click the output symbol LEDG[7..0] to select it.
- On your keyboard, press Delete.
- To save the completed .bdf, click Save on the File menu.
3.6.5.6.2. Add IP Variation File
You can add the Intel® Quartus® Prime IP File (.qip) to the your Intel® Quartus® Prime project by performing the following steps:
-
On the Assignments menu, click Settings.
The Settings dialog box appears.
-
Under Category, click Files.
The Files page appears.
- Next to File name, click the browse (...) button.
- In the Files of type list, select Script Files (*.tcl, *.sdc, *.qip).
- Browse to locate <design files directory>/first_nios2_system/synthesis/ first_nios2_system.qip and click Open to select the file.
- Click Add to include first_nios2_system.qip in the project.
- Click OK to close the Settings dialog box.
3.6.5.6.3. Assign FPGA Device
Before assigning FPGA pin locations to match the pinouts of your board, you need to first assign a specific target device. To assign the device, perform the following steps:
-
On the Assignments menu, click Device.
The Device dialog box appears.
-
In the Family list, select the FPGA family that matches your board.
If prompted to remove location assignments, do so.
- Under Target device, select Specific device selected in Available devices list.
-
Under Available devices, select the exact device that matches your board.
If prompted to remove location assignments, do so.
- Click OK to accept the device assignment.
3.6.5.6.4. Assign FPGA Pin Locations
Before assigning the FPGA pins, you must know the pin layout for the board. You also must know other requirements for using the board, refer to related information below. To assign the FPGA pin locations, perform the following steps:
-
On the Processing menu, point to Start, and click Start Analysis & Elaboration to
prepare for assigning pin locations.
The analysis starts by displaying a data not available message and can take several minutes. A confirmation message box appears when analysis and elaboration completes.
- Click OK.
-
On the Assignments menu, click Pin Planner.
The Intel® Quartus® Prime Pin Planner appears.
- In the Node Name column, locate PLD_CLOCKINPUT.
- In the PLD_CLOCKINPUT row, double-click in the Location cell to access a list of available pin locations.
-
Select the appropriate FPGA pin that connects to the oscillator on the board.
If your design fails to work, recheck your board documentation for this step first.
- In the PLD_CLOCKINPUT row, double-click in the I/O Standard cell to access a list of available I/O standards.
- Select the appropriate I/O standard that connects to the oscillator on the board.
- If you connected the LED pins in the board design schematic, repeat steps 4 to 8 for each of the LED output pins (LEDG[0], LEDG[1], LEDG[2], LEDG[3], LEDG[4], LEDG[5], LEDG[6], LEDG[7]) to assign appropriate pin locations.
- On the File menu, click Close to save the assignments.
-
On the Assignments menu, click Device.
The Device dialog box appears.
-
Click Device and Pin Options.
The Device and Pin Options dialog box appears.
- Click the Unused Pins page.
-
In the Reserve all unused pins list, select As input tri-stated with weak pull-up.
With this setting, all unused I/O pins on the FPGA enter a high-impedance state
after power-up.
Unused pins are set as input tri-stated with weak pull-up to remove contention which might damage the board. Depending on the board, you might have to make more assignments for the project to function correctly. You can damage the board if you fail to account for the board design. Consult with the maker of the board for specific contention information.
- Click OK to close the Device and Pin Options dialog box.
- Click OK to close the Device dialog box.
3.6.5.6.5. Set Timing
To ensure the design meets timing, perform the following steps:
- On the File menu, click Open.
- In the Files of type list, select Script Files (*.tcl, *.sdc, *.qip).
- Browse to locate <design files directory>/hw_dev_tutorial.sdc and click Open. The file opens in the text editor.
- Locate the following create_clock command:create_clock -name sopc_clk -period 20 [get_ports PLD_CLOCKINPUT]
- Change the period setting from 20 to the clock period (1/frequency) in nanoseconds of the oscillator driving the clock pin.
- On the File menu, click Save.
-
On the Assignments menu, click Settings.
The Settings dialog box appears.
- Under Category, click TimeQuest Timing Analyzer.
- Next to File name, click the browse (...) button.
- Browse to locate <design files directory>/hw_dev_tutorial.sdc and click Open to select the file.
- Click Add to include hw_dev_tutorial.sdc in the project.
- Turn on Enable multicorner timing analysis during compilation.
- Click OK.
3.6.5.6.6. Compile the Intel Quartus Prime Project and Verify Timing
To create a .sof file, you have to compile the hardware design and then it download to the board. After the compilation completes, you must analyze the timing performance of the FPGA design to verify that the design works in hardware. To compile the Intel® Quartus® Prime project, perform the following steps:
-
On the Processing menu, click Start Compilation.
The Tasks window and percentage and time counters in the lower-right corner display progress. The compilation process can take several minutes. When compilation completes, a dialog box displays the message "Full Compilation was successful."
- Click OK. The Quartus Prime software displays the Compilation Report tab.
- Expand the TimeQuest Timing Analyzer category in the compilation report.
- Click Multicorner Timing Analysis Summary.
-
Verify that the Worst-case Slack values are positive numbers for Setup, Hold,
Recovery, and Removal.
If any of these values are negative, the design might not operate properly in hardware. To meet timing, adjust Intel® Quartus® Prime assignments to optimize fitting, or reduce the oscillator frequency driving the FPGA.
3.6.5.7. Download the Hardware Design to the Target FPGA
To download the .sof to the target board, perform the following steps:
- Connect the board to the host computer with the download cable, and apply power to the board.
-
On the Tools menu in the
Intel®
Quartus® Prime software, click Programmer.
The Intel® Quartus® Prime Programmer appears and automatically displays the appropriate configuration file (nios2_quartus2_project.sof).
-
Click Hardware Setup in
the upper left corner of the
Intel®
Quartus® Prime Programmer to verify your download
cable settings.
The Hardware Setup dialog box appears.
-
Select the appropriate download cable in the Currently selected hardware list.
If the appropriate download cable does not appear in the list, you must first install drivers for the cable.
- Click Close.
- In the nios2_quartus2_project.sof row, turn on Program/Configure.
-
Click Start.
The Progress meter sweeps to 100% as the Intel® Quartus® Prime software configures the FPGA.
3.6.5.8. Develop Software Using the Nios II SBT for Eclipse
Developing software using the Nios® II SBT for Eclipse consists the following tasks:
- Create new Nios® II C/C++ application and BSP projects.
- Compile the projects.
To perform these steps, you must have the .sopcinfo file you created earlier in this tutorial. Refer to related information for more information.
3.6.5.8.1. Create a New Nios II Application and BSP from Template
To create new Nios® II C/C++ application and BSP projects, perform the following steps:
- Start the Nios® II SBT for Eclipse. On Windows computers, click Start, point to Programs, Nios® II EDS <version>, and then click Nios® II <version> Software Build Tools for Eclipse. On Linux computers, run the executable file < Nios® II EDS install path>/bin/eclipse-nios2.
- If the Workspace Launcher dialog box appears, click OK to accept the default workspace location.
- On the Window menu, point to Open Perspective, and then either click Nios® II , or click Other and then click Nios® II to ensure you are using the Nios® II perspective.
-
On the File menu, point to New, and then click
Nios® II Application and BSP from
Template.
The Nios II Application and BSP from Template wizard appears.
- Under Target hardware information, next to SOPC Information File name, browse to locate the <design files directory>.
-
Select first_nios2_system.sopcinfo and click Open.
Nios II Application and BSP from Template wizard shows the current information for the SOPC Information File name and CPU name fields.
- In the Project name box, type count_binary.
- In the Templates list, select Count Binary
- Click Finish.
- count_binary—Your C/C++ application project
- count_binary_bsp—A board support package that encapsulates the details of the Nios® II system hardware
3.6.5.8.2. Compile the Project
You have to compile the project to produce an executable software image. For the tutorial design example, you must first adjust the project settings to minimize the memory footprint of the software, because your Nios® II hardware system contains only 20 KB of memory. To adjust the project settings and compile the project, perform the following steps:
- In the Project Explorer view, right-click count_binary_bsp and click Properties. The Properties for count_binary_bsp dialog box appears.
-
Click the
Nios® II BSP Properties page. The
Nios® II BSP Properties page contains
basic software build settings.
Though not needed for this tutorial, note the BSP Editor button in the lower right corner of the dialog box. You use the Nios® II BSP Editor to access advanced BSP settings.
-
Adjust the following settings to reduce the size of the compiled executable:
- Turn on enable_reduced_device_drivers.
- Turn off enable_gprof.
- Turn on enable_small_c_library.
- Turn off enable_sim_optimize.
-
Click OK.
The BSP regenerates, the Properties dialog box closes, and you return to the Nios® II SBT for Eclipse.
- In the Project Explorer view, right-click the count_binary project and click Build Project.
3.6.5.9. Run the Program on Target Hardware
To download the software executable to the target board, perform the following steps:
-
Right-click the count_binary project, point to Run As, and then click
Nios® II
Hardware.
If the Run Configurations dialog box appears, verify that Project name and ELF file name contain relevant data, then click Run.The Nios® II SBT for Eclipse downloads the program to the FPGA on the target board and the program starts running. When the target hardware starts running the program, the Nios® II Console view displays character I/O output. If you connected LEDs to the Nios® II system in previous section, then the LEDs blink in a binary counting pattern.
-
Click the Terminate icon
(the red square) on the tool bar of the
Nios® II Console view to terminate the run session and the
Nios® II SBT for Eclipse
disconnects
from the target hardware.
You can edit the count_binary.c program in the Nios® II SBT for Eclipse text editor and repeat these two steps to witness your changes executing on the target board. If you rerun the program, buffered characters from the previous run session might display in the Console view before the program begins executing.
3.7. Platform Designer System Design Tutorial
This tutorial shows you how to design a system that uses various test patterns to test an external memory device. It guides you through system requirement analysis, hardware design tasks, and evaluation of the system performance, with emphasis on system architecture.
In this tutorial, you create a memory tester system that tests a synchronous dynamic random access memory (SDRAM) device. The final system contains the SDRAM controller and instantiates a Nios® II processor and embedded peripherals in a hierarchical subsystem. The final design includes various Platform Designer components that generate test data, access memory, and verify the returned data.
The memory tester components for the design are Verilog HDL components with an accompanying Hardware Component Description File (_hw.tcl) that describes the interfaces and parameterization of each component. The _hw.tcl files are located in the tt_qsys_design\memory_tester_ip directory.
The final system contains the following components:
- Processor subsystem based on the Nios® II/e core, which includes an on-chip RAM to store the processor's software code, and a JTAG UART to communicate via JTAG and display the memory test results in the host PC's console.
- SDRAM controller to control the off-chip DDR SDRAM device under test.
- Custom and pseudo-random binary sequence (PRBS) pattern generators and checkers to test the robustness of links.
- Pattern select multiplexer and demultiplexer to choose between the two pattern generators and checkers.
- Pattern writer and reader that interact with the SDRAM controller.
- Memory test controller.
Each section in this tutorial provides an overview describing the components that you instantiate. You can use the final system on hardware without a license, and perform the following actions with Intel® FPGA IP Evaluation Mode feature:
- Simulate the behavior of the system and verify its functionality.
- Generate time-limited device programming files for designs that incorporate Intel or partner IP.
- Program a device and verify your design in hardware.
You can use the Nios® II/e processor and the DDR SDRAM IP cores with a Quartus Prime subscription license. Design files for other development kit boards use different DDR SDRAM controllers to match the memory device available on the development kit.
In this tutorial, you instantiate the complete memory tester system in the top-level system along with the processor IP Cores, which are grouped as their own processor system, and the SDRAM Controller IP. The Nios® II processor includes a software program to control the memory tester system, which communicates with the SDRAM Controller to access the off-chip SDRAM device under test.
3.7.1. Software and Hardware Requirements
The Platform Designer System Design tutorial requires the following software and hardware requirements:
- Intel® Quartus® Prime software.
- Nios® II EDS.
- tt_qsys_design.zip design files, available from the Platform Designer Tutorial Design Example page. The design files include project files set up for select Intel development boards, and components that you can use in any Platform Designer design.
You can build the Platform Designer system in this tutorial for any Intel development board or your own custom board, if it meets the following requirements:
- An Intel Arria, Cyclone, or Stratix series FPGA.
- Minimum of 12k logic elements (LEs).
- Minimum of 128k of embedded memory.
- JTAG connection to the FPGA that provides a communications link back to the host so that you can monitor the memory test progress.
- Any memory that has a Platform Designer-based controller with an Avalon® Memory-Mapped (Avalon-MM) slave interface.
3.7.2. Download and Install the Tutorial Design Files
- On the Platform Designer Tutorial Design Example page, under Using this Design Example, click Platform Designer Tutorial Design Example (.zip) to download and install the tutorial design files for the Platform Designer tutorial.
- Extract the contents of the archive file to a directory on your computer. Do not use spaces in the directory path name.
In place of following all steps in this tutorial to create subsystem, hierarchical, and top-level design files, you can copy the completed design files listed below into the tt_qsys_design\quartus_ii_projects_for_boards\<development_board_type> directory, depending on your board type.
- The two completed subsystems: pattern_generator_system.qsys, and pattern_checker_system.qsys from the tt_qsys_design\completed_subsystems directory.
- The hierarchical system memory_tester_system.qsys from the tt_qsys_design\completed_subsystems\completed_memory_tester_system directory.
-
The top-level hierarchical system top_system.qsys from the tt_qsys_design\quartus_ii_projects_for_boards\<development_board_type> \backup_and_completed_top_system\completed_top_system directory.
3.7.3. Open the Tutorial Project
The following design requirements are included in the Platform Designer tutorial design files:
- Intel® Quartus® Prime project I/O pin assignments and Synopsys Design Constraint (.sdc) timing assignments for each supported development board.
- Parameterized Nios® II processor core and software to communicate with the host PC that controls the memory test system that you develop.
- Parameterized DDR SDRAM controller to use the memory on the development board.
To open the tutorial project:
- Open the Intel® Quartus® Prime software.
- To open the Intel® Quartus® Prime Project File (.qpf) for your board, click File > Open Project.
- Browse to the tt_qsys_design\quartus_ii_projects_for_boards\<development_board>\ directory.
- Select the relevant board-specific .qpf file, and then click Open.
3.7.4. Creating Platform Designer Systems
- Data pattern generator—The data pattern generator generates high-speed streaming data, which performs either as a PRBS, or as a soft programmable sequence, for example, “walking ones.” The design sends the data with an Avalon® -Streaming ( Avalon® -ST) connection to the pattern writer of the memory master and control logic. The data pattern generator writes the data to memory based on commands issued by the controller logic. When the design writes the data to memory, the pattern reader logic reads the contents back and sends it to the data pattern verification logic.
- Data pattern checker—The data pattern checker accepts the data read back by the pattern reader from an Avalon® -ST connection. The design verifies the data pattern to ensure that the pattern it writes to memory is identical to the data that it reads back.
3.7.4.1. Create a Data Pattern Generator Platform Designer System
You must use the exact system names described in this tutorial in order for the provided scripts to function correctly.
3.7.4.1.1. Create a New Platform Designer System and Set up the Clock Source
- In the Intel® Quartus® Prime software, click Tools > Platform Designer to create a new Platform Designer design.
- In the System Contents tab, Platform Designer shows a clock source instance, clk_0. To open the clock source settings, right-click clk_0, and then click Edit.
- Turn off Clock frequency is known to indicate that, when created, the higher-level hierarchical system that instantiates this subsystem provides the clock frequency.
- Click Finish.
- Click File > Save As to save the Platform Designer system.
- In the Save As dialog box, type pattern_generator_system, and then click Save.
If Platform Designer prompts you to open the top_system.qsys file, click Cancel in the Open dialog box
3.7.4.1.2. Add a Pipeline Bridge
To determine the required address width for a bridge, you must know the required addresses span of the other components in the system. Memory-mapped component interfaces outside the system address each interface in the system by specifying a memory offset value relative to the base address of the bridge.
A pipeline bridge can also improve system timing performance by optionally adding pipeline registers to the design.
- In the Library search box, type bridge to filter the component list and show only bridge components.
- Select Avalon® -MM Pipeline Bridge, and then click Add.
-
In the parameter
editor, under Parameters, type
11 for the
Address width.
This width accommodates the memory span of all memory-mapped components behind the bridge in this system. As you add the other components in the system, you specify their base addresses within the span of the address space.
-
Accept all other
default settings, and then click
Finish.
The pipeline bridge is added to your system with the instance name mm_bridge_0.
- On the System Contents tab, right-click mm_bridge_0, click Rename, and then type mm_bridge.
- In the Clock column for the mm_bridge clk interface, select clk_0 from the list.
- To export the mm_bridge s0 interface, double-click the Export column, and then type slave.
3.7.4.1.3. Add a Custom Pattern Generator
The component is programmed with the pattern data and a pattern length. When the end of the pattern is reached, the custom pattern generator cycles back to the first element of the pattern. This custom pattern generator generates the following standard memory tester patterns:
- Walking ones
- Walking zeros
- Low frequency
- Alternating low frequency
- High frequency
- Alternating high frequency
- Synchronous PRBS
The width of the memory dictates the walking ones or zeros pattern lengths. For example, when testing a 32-bit memory, the walking ones or zeros pattern is 32 elements in length before repeating. The high and low frequency patterns contain only two elements before repeating. The synchronous PRBS pattern is the longest pattern containing 256 elements before repeating.
This custom pattern generator contains three interfaces, two of which control the generated pattern, and a third interface which control the behavior of the custom pattern generated. The processor accesses the pattern_access interface, which is write only, to program the elements of the custom pattern that are sent to the pattern writer core, and the csr interface, which is used for the control and status registers. The st_pattern_output is the streaming source interface that sends data to the pattern writer core.
To add the custom pattern generator:
- In the IP Catalog, expand Memory Test Microcores, and then double-click Custom Pattern Generator.
- In the parameter editor, accept the default parameters, and then click Finish.
- Rename the instance to custom_pattern_generator.
- Set the custom_pattern_generator clock interface to clk_0.
- To connect the custom_pattern_generator csr interface to the mm_bridge m0 interface, in the Connections column, click to fill in the connection dot between the custom_pattern_generator csr interface and the mm_bridge m0 interface.
-
Connect the
custom_pattern_generator pattern_access interface to the
mm_bridge m0 interface.
The processor accesses the system through the m0 interface to communicate with the csr and pattern_access interfaces.
-
To assign the
custom_pattern_generator csr interface to a base address of
0400, in the
Base column, double-click the
0x00000000 address, and then enter
400 for the base address, which is in hexadecimal
format.
If the Base column is locked for the custom_pattern_generator csr, right-click and then click Unlock Base Address.
The address space represents memory accessible by the processor. Each address specifies a location in memory that can be addressed and accessed, and each interface must have a unique address range. The address space of each interface is determined by its base address and its memory span, or how much memory is required for that interface.
You can see the default address range of the pattern_access interface in the Base and End columns on the System Contents tab.
You assign a base address for the csr interface that is higher than the end address of the pattern_access interface to avoid conflicting with the address space of the pattern_access interface.
3.7.4.1.4. Add a PRBS Pattern Generator
For example, a 32-bit PRBS pattern generator repeats the pattern after it sends 4,294,967,295 elements. You set the width of the PRBS generator based on the (local) data width of the memory on your board.
The PRBS pattern generator has two interfaces; the csr and the st_pattern_output streaming source interface. The csr interface controls the behavior of the PRBS pattern generated. The st_pattern_output streaming source interface sends data to the pattern writer component.
- In the IP Catalog, expand Memory Test Microcores, and then double-click PRBS Pattern Generator.
- In the parameter editor, accept the default parameters, and then click Finish.
- Rename the instance to prbs_pattern_generator.
- Set the prbs_pattern_generator clock interface to clk_0.
- Connect the prbs_pattern_generator csr interface to the mm_bridge m0 interface.
- Assign the prbs_pattern_generator csr interface to a base address of 0x0420, which is a base address just higher than the end address of the custom_pattern_generator csr interface of 0x410.
3.7.4.1.5. Add a Two-to-One Streaming Multiplexer
The two-to-one streaming multiplexer component has the following interfaces:
- Two streaming inputs: st_input_A and st_input_B.
- One streaming output: st_output.
- One csr slave interface, which the processor controls to select whether input A or input B is sent to the streaming output.
The custom pattern generator connects to input A, and the PRBS pattern generator connects to input B.
- In the IP Catalog, expand Memory Test Microcores, and then double-click Two-to-one Streaming Mux.
- In the parameter editor, accept the default parameters, and then click Finish.
- Rename the instance to two_to_one_st_mux.
- Set the two_to_one_st_mux clock to clk_0.
- Connect the two_to_one_st_mux st_input_A interface to the custom_pattern_generator st_pattern_output interface.
- Connect the two_to_one_st_mux st_input_B interface to the prbs_pattern_generator st_pattern_output interface.
- Connect the two_to_one_st_mux csr interface to the mm_bridge m0 interface.
- Export the two_to_one_st_mux st_output interface with the name st_data_out.
-
Assign the
two_to_one_st_mux csr interface to a base address of
0x0440, which is a base address higher than the end address of
the
prbs_pattern_generator csr interface at base address
0x0420
The output of the two-to-one streaming multiplexer carries the pattern data from either the custom pattern generator or the PRBS pattern generator, to the pattern writer. The data, from the output of the two-to-one streaming multiplexer, achieves a throughput of one word per clock cycle.
3.7.4.1.6. Verify the Memory Address Map
You control the system by accessing the memory locations allocated to each component within the subsystem. To ensure that the memory map of the system you create matches the memory map of other components, you must verify the base addresses for the data pattern generator system.
On the Address Map tab, verify that the entries in the Address Map table match the values in in the table below. Red exclamation marks indicate that the address ranges overlap. Correct the base addresses, as appropriate, to ensure there are no overlapping addresses, and your map matches this tutorial’s guidelines.
Component | Address |
---|---|
custom_pattern_generator.csr | 0x00000400 – 0x0000040f |
custom_pattern_generator.pattern_access | 0x00000000 – 0x000003ff |
prbs_pattern_generator.csr | 0x00000420 – 0x0000043f |
two_to_one_st_mux.csr | 0x00000440 – 0x00000447 |
3.7.4.1.7. Connect the Reset Signals
You must connect all the reset signals, which eliminates the error messages in the Messages tab. Platform Designer allows multiple reset domains, or one reset signal for the system. In the design, you want to connect all the reset signals with the incoming reset signal. To connect all the reset signals, on the System menu, select Create Global Reset Network.
At this point in the system design, Platform Designer shows no remaining error messages. If you have any error messages in the Messages tab, review the procedures to create this system to ensure you did not miss a step. You can view the reset connections and the timing adapters on the System Contents tab, and by selecting Show System With Platform Designer Interconnect on the System menu.
3.7.4.1.8. Save the System
At this point, there should be no remaining error messages in the Messages tab, and the system is complete. Save the system.
3.7.4.2. Create a Data Pattern Checker Platform Designer System
The data pattern checker system receives a pattern from SDRAM and verifies it against the pattern from the data pattern generator. The pattern reader sends the data to a one-to-two streaming demultiplexer that routes the data to either the custom pattern checker or the PRBS pattern checker. The one-to-two streaming demultiplexer is soft programmable so that the processor can select which pattern checker IP core should verify the data that the pattern reader reads. The custom pattern checker is also soft programmable and is configured to match the same pattern as the custom pattern generator.
Refer to the Platform Designer Memory Tester figure for a graphical description.
3.7.4.2.1. Create a New Platform Designer System and Set Up the Clock Source
- In the Intel® Quartus® Prime software, click Tools > Platform Designer to create a new Platform Designer design.
- In the System Contents tab, Platform Designer shows a clock source instance, clk_0. To open the clock source settings, right-click clk_0, and then click Edit.
- Turn off Clock frequency is known to indicate that, when created, the higher-level hierarchical system that instantiates this subsystem provides the clock frequency.
- Click Finish.
- Click File > Save As to save the Platform Designer system.
- In the Save As dialog box, type pattern_checker_system, and then click Save.
3.7.4.2.2. Add a Pipeline Bridge
- In the Library search box, type bridge to filter the component list and show only bridge components.
- Select Avalon® -MM Pipeline Bridge, and then click Add.
-
In the parameter
editor, under Parameters, type
11 for the
Address width.
This width accommodates the memory span of all memory-mapped components behind the bridge in this system. As you add the other components in the system, you specify their base addresses within the span of the address space.
-
Accept all other
default settings, and then click
Finish.
The pipeline bridge is added to your system with the instance name mm_bridge_0.
- On the System Contents tab, right-click mm_bridge_0, click Rename, and then type mm_bridge.
- In the Clock column for the mm_bridge clk interface, select clk_0 from the list.
- To export the mm_bridge s0 interface, double-click the Export column, and then type slave.
3.7.4.2.3. Add a Custom Pattern Checker
- In the IP Catalog, expand Memory Test Microcores, and then double-click Custom Pattern Checker.
- In the parameter editor, accept the default parameters, and then click Finish.
- Rename the instance to custom_pattern_checker.
- Set the custom_pattern_checker clock to clk_0.
- Connect the custom_pattern_checker csr interface to the mm_bridge m0 interface.
- Connect the custom_pattern_checker pattern_access interface to the mm_bridge m0 interface.
- Assign the custom_pattern_checker csr interface to a base address of 0x0420.
- Maintain the custom_pattern_checker pattern_access interface base address of 0x0000.
3.7.4.2.4. Add the PRBS Pattern Checker
- In the IP Catalog, expand Memory Test Microcores, and then double-click PRBS Pattern Checker.
- In the parameter editor, accept the default parameters, and then click Finish.
- Rename the instance to prbs_pattern_checker.
- Set the prbs_pattern_checker clock to clk_0.
- Connect the prbs_pattern_checker csr interface to the mm_bridge m0 interface.
- Assign the prbs_pattern_checker csr interface to a base address of 0x0440.
3.7.4.2.5. Add a One-to-Two Streaming Demultiplexer
- In the IP Catalog, expand Memory Test Microcores, and then double-click One-to-two Streaming Demux.
- In the parameter editor, accept the default parameters, and then click Finish.
- Rename the instance to one_to_two_st_demux.
- Set the one_to_two_st_demux clock to clk_0.
- Export the one_to_two_st_demux st_input interface with the name st_data_in.
- Connect the one_to_two_st_demux csr interface to the mm_bridge m0 interface.
- Assign the one_to_two_st_demux csr interface to a base address of 0x0400.
- Connect the custom_pattern_checker st_pattern_input interface to the one_to_two_st_demux st_output_A interface.
- Connect the prbs_pattern_checker st_pattern_input interface to the one_to_two_st_demux st_output_B interface.
3.7.4.2.6. Verify the Memory Address Map
On the Address Map tab, verify that the entries in the Address Map table match the values in the table below. Red exclamation marks indicate that the address ranges overlap. Correct the base addresses, as appropriate, to ensure there are no overlapping addresses, and your map matches this tutorial’s guidelines.
Component | Address |
---|---|
one_to_two_st_demux.csr | 0x00000400 - 0x00000407 |
custom_pattern_checker.csr | 0x00000420 - 0x0000042f |
custom_pattern_checker.pattern_access | 0x00000000 - 0x000003ff |
prbs_pattern_checker.csr | 0x00000440 - 0x0000045f |
3.7.4.2.7. Connect the Reset Signals
You must connect all the reset signals, which eliminates the error messages in the Messages tab. Platform Designer allows multiple reset domains, or one reset signal for the system. In the design, you want to connect all the reset signals with the incoming reset signal. To connect all the reset signals, on the System menu, select Create Global Reset Network.
At this point in the system design, Platform Designer shows no remaining error messages. If you have any error messages in the Messages tab, review the procedures to create this system to ensure you did not miss a step. You can view the reset connections and the timing adapters on the System Contents tab, and by selecting Show System With Platform Designer Interconnect on the System menu.
3.7.4.2.8. Save the System
At this point, there should be no remaining error messages in the Messages tab, and the system is complete. Save the system.
3.7.5. Assemble a Hierarchical System
Hierarchical systems allow you to reuse modular system components. Additionally, hierarchical systems allow you to break large systems into smaller subsystems thus, creating more manageable designs.
The memory tester design includes the following lower-level subsystems:
- Data pattern generator—Generates and transmits Avalon® -ST data to the memory tester components.
- Data pattern checker—Receives and verifies Avalon® -ST data from the memory tester components.
3.7.5.1. Create the Hierarchical Memory Tester System
- In Platform Designer, create a new system called, memory_tester_system.
- For the clk instance, turn off Clock frequency is known to indicate that the higher-level hierarchical system that instantiates this subsystem provides the clock frequency.
- In the IP Catalog, select the Avalon® -MM Pipeline Bridge to add to your Platform Designer system.
-
For the
Avalon®
-MM Pipeline Bridge, in the parameter editor, type
13 for the
Address width.
To accommodate for the address translation from master to slave, that is a byte address as the input, and a word address (4 bytes) as the output, the address width increases from 11.
- Rename the instance to mm_bridge.
- Set the mm_bridge_clk interface to clk_0.
- Export the mm_bridge s0 interface with the name slave.
3.7.5.1.1. Add the Pattern Generator
The pattern generator system contains the following components:
- Pipeline bridge
- Custom pattern generator
- PRBS pattern generator
- Two-to-one streaming multiplexer
- Streaming timing adapters
- In the IP Catalog, under Project expand System, and then double-click pattern_generator_system.
- In the parameter editor, click Finish to accept the default settings.
- Rename the instance to pattern_generator_subsystem.
- Set the pattern_generator_subsystem clk to clk_0.
- Connect the pattern_generator_subsystem slave interface to the mm_bridge m0 interface.
- Connect the pattern_generator_subsystem reset interface to the clk_0 clk_reset interface.
3.7.5.1.2. Add the Pattern Checker
The pattern checker system contains the following components:
- Pipeline bridge
- Custom pattern checker
- PRBS pattern checker
- One-to-two demultiplexer
- In the IP Catalog, double-click pattern_checker_system from the System group.
- In the parameter editor, click Finish to accept the default settings.
- Rename the instance to pattern_checker_subsystem.
- Set the pattern_checker_subsystem clk to clk_0.
- Connect the pattern_checker_subsystem slave interface to the mm_bridge m0 interface.
- Connect the pattern_checker_subsystem reset interface to the clk_0 clk_reset interface.
3.7.5.1.3. Add Memory Master Components
Memory masters access the SDRAM controller by writing the test pattern to the memory and reading the pattern back for validation. The RAM test controller accepts commands from the processor and controls the memory masters. Each command contains a start address, test length in bytes, and memory block size in bytes. The RAM test controller segments the commands into smaller block transfers and issues the commands to the read and write masters independently via streaming connections.
When the pattern reader or writer components complete a block transfer, they signal to the RAM test controller that they are ready for another command. The RAM test controller issues the block-sized commands independently, which minimizes the number of idle cycles between memory transfers. The RAM test controller also ensures that the pattern reader never overtakes the pattern writer with respect to the memory locations it is testing, otherwise data corruption occurs.
The SDRAM controller is parameterized to use a local maximum burst length of 2. The pattern reader and writer components are also configured to match this burst length to maximize the memory bandwidth.
Add a Pattern Writer Component
- In the IP Catalog, double-click Pattern Writer from the Memory Test Microcores group.
- In the parameter editor, turn on Burst Enable.
- Ensure that the Maximum Burst Count is 2.
- Ensure that Enable Burst Re-alignment is turned on.
- To accept the other default parameters, click Finish.
- Rename the instance to pattern_writer.
- Set the pattern_writer clock to clk_0.
- Connect the pattern_writer st_data interface to the pattern_generator_subsystem st_data_out interface.
- Export the pattern_writer mm_data interface with the name write_master.
Add a Pattern Reader Component
- In the IP Catalog, double-click Pattern Reader from the Memory Test Microcores group.
- n the parameter editor, turn on Burst Enable.
- Ensure the Maximum Burst Count is 2.
- Ensure that Enable Burst Re-alignment is turned on.
- To accept the other default parameters, click Finish.
- Rename the instance to pattern_reader.
- Set the pattern_reader clock to clk_0.
- Connect the pattern_reader st_data interface to the pattern_checker_subsystem st_data_in interface.
- Export the pattern_reader mm_data interface with the name read_master.
Add a RAM Test Controller
- In the IP Catalog, double-click RAM Test Controller from the Memory Test Microcores group.
- In the parameter editor, click Finish to accept the default parameters.
- Rename the instance to ram_test_controller.
- Set the ram_test_controller clock to clk_0.
- Connect the ram_test_controller write_command interface to the pattern_writer_command interface.
- Connect the ram_test_controller read_command interface to the pattern_reader_command interface.
- Connect the ram_test_controller csr interface to the mm_bridge m0 interface.
Do not use the Generation tab at this point in the tutorial to generate HDL code for these subsystems. You must generate files for the entire top-level system, which includes all the subsystems. The batch script provided for you to program the device requires that only one system is generated in the project directory. The top-level design includes a Nios® II subsystem, and the Nios® II software build tools require the SOPC Information File (.sopcinfo) to be generated for the top-level design. If there are multiple .sopcinfo files, the batch script to program the device fails with an error from the software build tools.
3.7.5.1.4. Connect the Reset Signals
You must connect all the reset signals, which eliminates the error messages in the Messages tab. Platform Designer allows multiple reset domains, or one reset signal for the system. In the design, you want to connect all the reset signals with the incoming reset signal. To connect all the reset signals, on the System menu, select Create Global Reset Network.
At this point in the system design, Platform Designer shows no remaining error messages. If you have any error messages in the Messages tab, review the procedures to create this system to ensure you did not miss a step. You can view the reset connections and the timing adapters on the System Contents tab, and by selecting Show System With Platform Designer Interconnect on the System menu.
3.7.5.1.5. Verify the Memory Address Map
To ensure that the memory map of the system you create matches the memory map of other components, you must verify the base addresses for the memory tester system. In Platform Designer, on the Address Map tab, verify that the entries in Address Map table match the values in Table 3–1. Red exclamation marks indicate that the address ranges overlap. Correct the base addresses, as appropriate, to ensure there are no overlapping addresses.
Component | Base Address | Address |
---|---|---|
mm_bridge_0.s0 | N/A | N/A |
pattern_generator_subsystem.slave | 0x0 | 0x00000000 – 0x000007ff |
pattern_checker_subsystem.slave | 0x1000 | 0x0001000 – 0x000017ff |
ram_test_controller.csr | 0x800 | 0x00000800 – 0x0000081f |
3.7.5.1.6. Save the System
At this point, there should be no remaining error messages in the Messages tab, and the system is complete. Save the system.
3.7.5.2. Complete the Top-Level System
-
In Platform Designer, open the
top_system.qsys file from the
tt_qsys_design\quartus_ii_projects_for_boards\<development_board>
directory.
The top-level system is set up for your development board, with an external clock source, a processor system, and an SDRAM controller. You can view the clocks in top-level system on the Clock Settings tab, and the partially-completed system connections on the System Contents tab.
- In the IP Catalog, double-click memory_tester_system from the System group.
- Click Finish to accept the default parameters, and to add the memory tester system to the top-level system.
- Rename the system to memory_tester_subsystem.
-
On the
System Contents tab, use the arrows to move the
memory_tester_subsystem up between the
cpu_subsystem and the
sdram.
Since the cpu_subsystem controls the memory_tester_subsystem, and the memory_tester_subsystem controls the sdram, this positioning allows you to more easily visualize system performance.
-
Set the
memory_tester_subsystem clk to either the
sdram_sysclk (for ALTMEMPHY-based designs), or
sdram_afi_clk (for UniPHY-based designs).
Some boards have an FPGA and SDRAM device that use either the Intel DDR or DDR2 SDRAM Controller with ALTMEMPHY; others use the Intel DDR3 SDRAM controller with UniPHY.
- Connect the memory_tester_subsystem reset interface to the ext_clk clk_reset interface.
-
Connect the
memory_tester_subsystem reset interface to the
cpu_subsystem cpu_jtag_debug_reset interface.
This design exports the Nios® II processor JTAG debug reset output interface, jtag_debug_module_reset, from the cpu_subsystem with the interface name cpu_ jtag_debug_reset. The design must connect this Nios® II reset output to any component reset inputs that require resetting by the Nios II processor code or JTAG interface, and also to the Nios® II processor's reset input interface. The cpu_subsystem cpu_reset interface connects to the Nios® II processor's reset input interface. The top_level.qsys file connects the cpu_jtag_debug_reset interface to the cpu_reset interface.
- Connect the memory_tester_subsystem write_master and read_master interfaces to either the sdram s1 interface (for ALTMEMPHY-based designs), or sdram avl interface (for UniPHY-based designs).
- Connect the memory_tester_subsystem slave interface to the cpu_subsystem master interface.
- Maintain the base addresses of 0x0 for the memory_tester_subsystem slave interface, and for either the sdram s1 interface (for ALTMEMPHY-based designs), or sdram avl interface (for UniPHY-based designs).
The two slave interfaces can use the same address map range because different masters control them. The cpu_subsystem master interface controls the memory_tester_subsystem, and the memory_tester_subsystem write_master and read_master interfaces control the sdram interface.
3.7.6. Viewing the Memory Tester System in Platform Designer
You can use the Hierarchy tab, accessed from the View menu, to show the complete hierarchy of your design. The Hierarchy tab is a full system hierarchical navigator, which expands the system contents to show modules, interfaces, signals, contents of subsystems, and connections. The graphical interface of the Hierarchy tab displays a unique icon for each element represented in the system, including interfaces, directional pins, IP blocks, and system icons that show exported interfaces and the instances of components that make up a system.
Click Generate > HDL Example to view the HDL for an example instantiation of the system. The HDL example lists the signals from the exported interfaces in the system. The signal names are the exported interface name followed by an underscore, and then the signal name specified in the component or IP core. Most of the signals connect to the external SDRAM device.
3.7.7. Compiling and Downloading Software to a Development Board
Intel recommends that you download the memory tester system to a development board to complete the design process and test the memory interface of the board. If you do not have a development board you can follow the steps provided in the accompanying readme.txt file to learn more details about porting designs to FPGA devices or boards.
The Intel provided software tests the memory using various test parameters and patterns, and is scripted for compilation and download to the board.
- To download the top-level system to a development board, in Platform Designer, click Generate > Generate.
- Select the language for Create HDL design files for synthesis, and turn off the option to create a Block Symbol File (.bsf).
- Click Generate. Platform Designer generates HDL files for the system and the Intel® Quartus® Prime IP File (.qip) that provides the list of required HDL files for the Intel® Quartus® Prime compilation.
- When Platform Designer completes the generation, click Close.
- In the Intel® Quartus® Prime software, on the Project menu, click Add/Remove Files in Project and verify that the newly-generated .qip file, top_system.qip, and the timing constraints file, my_constraints.sdc appear in the Files list.
- Click Processing > Start Compilation. When compilation completes, click OK.
- Connect the development board to a supported programming cable.
- Click Tools > Nios® II Command Shell [gcc4].
- Type the following command to emulate your local c:/ drive for your Windows environment: cd /cygdrive/c/.
- Navigate to the quartus_ii_projects_for_boards\<development_board>\software directory.
-
Type the following
command at the
Nios® II command Shell:
./batch_script.sh.
The batch script compiles the Nios® II software and downloads the SRAM Object File (.sof) programming file to the FPGA.
The terminal window shows messages indicating the progress. If you see error messages related to the JTAG chain, check your programming cable installation and board setup to ensure that it is set up correctly.
After the script configures the FPGA, it downloads the compiled Nios II software to the board and establishes a terminal connection with the board. The test software performs test sweeps on the SDRAM by varying the following parameters:
- Pattern type
- Memory block size
- Memory block trail distance (number of blocks by which the pattern reader trails the pattern writer)
- Memory span tested
Ensure that you have only one set of generated system files in the project directory, otherwise the batch script to program the device fails with an error from the software build tools.
The memory throughput values appear in the command terminal as the memory is tested. These values are reported in hexadecimal and represent the number of clock cycles required to test the entire SDRAM address span. The output is restricted to hexadecimal due to a small software library that prints the characters to the terminal. Because the memory tester system writes to the memory and then reads it back, the number of bytes it accesses and reports in the transcript window is double the memory span. This number varies depending on the span of memory being tested for your memory device. Knowing the data width of the memory interface, the number of bytes transferred, and the number of clock cycles for the transfer, you can determine the memory access efficiency.
The SDRAM controller in the top-level Platform Designer system has a 32-bit local interface width, therefore memory data width in bytes is 4 bytes for the tutorial design.
Efficiency = 100 × total bytes transferred/(memory data width in bytes × total clock cycles)
The memory test runs until the design finishes testing the complete memory. To end the test early, type Ctrl+C in the command window. To calculate the efficiency for the last throughput numbers in, convert the hexadecimal numbers to decimal, as follows:
- 0x4000000 bytes transferred is 0d67108864 total bytes transferred
- 0x107d856 clock cycles is 0d17291350 total clock cycles
Therefore, the efficiency for this example is:
100 × 67108864 / (4 × 17291350) = 97.0%
3.7.8. Debugging Your Design
If the memory test starts but does not complete successfully, the terminal displays failure messages. If you see failure messages from the memory test, review the previous sections and check that you have completed all of the instructions in this tutorial successfully. A missed connection or incorrect memory address assignment may cause the tester design to fail on the board.
Intel provides completed systems, so that you can verify your system designs. You can copy the completed systems into the project directory with different names, so that you can open two different instances of Platform Designer for a side-by-side comparison. Alternatively, you can replace your systems with the provided completed systems to run the memory tester design successfully.
3.7.9. Verifying Hardware in System Console
You can use the Intel® Quartus® Prime System Console to verify your system design. The design example files include scripts that exercise your system using System Console Tcl commands. The example uses a JTAG-to-Avalon Master Bridge component to drive the slave components, instead of a Nios® II processor system.
The \quartus_ii_projects_for_boards\<development_board>\system_console directory contains the run_sweep.tcl, base_address.tcl, and test_cases.tcl scripts. You use these scripts to set up and run memory tests on the development board projects. You can view the scripts to help you understand the System Console commands that drive the slave component registers. The scripts work with any board, if you keep the same Platform Designer system structure.
The run_sweep.tcl file is the main script, which calls the other two scripts. The base_address.tcl file includes information about the base addresses of the slave components from the previous chapters. If you change the base addresses of the slave components, you must also change the addresses in the base_address.tcl file. The test_cases.tcl file includes settings for memory span, memory block sizes, and memory block trail distance.
The run_sweep.tcl file contains Tcl commands for the following actions:
- Initialize the components
- Adjust test parameters
- Start the PRBS pattern checker, PRBS pattern generator, and RAM controller
- Continuously poll the stop and fail bits in the PRBS checker
3.7.9.1. Open the Tutorial Project
- Open the Intel® Quartus® Prime project in the project directory for your development board type.
- In Platform Designer, open top_system.qsys in the project directory for your development board type.
3.7.9.2. Add the JTAG-to- Avalon Master Bridge
- In the IP Catalog select JTAG to Avalon® Master Bridge, and then click Add.
- In the parameter editor, click Finish to accept the default parameters.
- Rename the instance to jtag_to_avalon_bridge.
- Connect the jtag_to_avalon_bridge master interface to the memory_tester_subsystem slave interface.
- Set the jtag_to_avalon_bridge clk domain to sdram_sysclk.
- Connect the jtag_avalon_bridge clk_reset interface to the ext_clk clk_reset interface.
- Connect the jtag_avalon_bridge clk_reset interface to either the sdram reset_request_n interface (for ALTMEMPHY-based designs), or sdram afi_reset interface (for UniPHY-based designs).
- Connect the jtag_avalon_bridge master_reset interface to the memory_tester_subsystem reset interface, and to either the sdram soft_reset_n interface (for ALTMEMPHY-based designs), or sdram soft_reset interface (for UniPHY-based designs).
- To disable the cpu_subsystem system, in the Use column, turn off Use, since you are replacing its function with the bridge and System Console.
- Save the jtag_to_avalon_bridge system.
3.7.9.3. Debug with System Console
- To download the programming file to your development board, in Platform Designer, click Generate > Generate.
- Select the language for Create HDL design files for synthesis.
- Click Generate. Platform Designer generates HDL files for the system and the .qip file, which provides the list of required HDL files for the Intel® Quartus® Prime compilation.
- When Platform Designer completes the generation, click Close.
- In the Intel® Quartus® Prime software, click Project > Add/Remove Files in Project, and verify that the project contains the top_system.qip.
- Click Processing > Start Compilation. When compilation completes, click OK.
- Connect the development board to a supported programming cable.
- Click Tools > Programmer.
- Check that the Programmer displays the correct programming hardware. Otherwise, click Hardware Setup and select the correct programming hardware, and then click Close.
- To program the device, click Start.
- In Platform Designer, click Tools > System Console.
- Before you execute scripts in System Console, navigate to the directory for the Tcl scripts, and then in Platform Designer System Console window, click File > Execute Script.
-
To start the memory
tests, run the
run_sweep.tcl file from the
tt_qsys_design\quartus_ii_projects_for_boards\<development_board>
\system_console directory.
When you run the run_sweep.tcl script, the System Console displays the progress of the tests in the Messages tab. The tests perform test sweeps on the SDRAM by varying the memory block size and memory block trail distance. When the tests finish successfully, Platform Designer generates a message that reports successful completion.
3.7.10. Simulating Custom Components
You can simulate a custom component with Platform Designer and the Avalon Verification IP Suite. You use Platform Designer to generate a testbench system for the design under test, and then perform a functional simulation with the ModelSim simulator. The Platform Designer-generated testbench uses the Avalon Verification IP Suite components.
3.7.10.1. Generate a Testbench System in Platform Designer
The custom pattern generator generates high-speed streaming data for testing memory devices. The soft-programmable custom pattern generator can generate multiple test patterns, and is programmed with the pattern data and pattern length. When the end of the pattern is reached, the custom pattern generator cycles back to the first element of the pattern.
If you do not want to use the Platform Designer-generated testbench system, you can create your own Platform Designer testbench system by adding the Avalon® Verification Suite Bus Functional Models (BFMs) or your own models for simulation. You can also generate a Platform Designer simulation model for the design or Platform Designer system under test, and use your own custom HDL testbench to provide the simulation stimulus.
3.7.10.1.1. Create a New Platform Designer System for the Design Under Test
- In the Intel® Quartus® Prime software, open the Intel® Quartus® Prime Project File, qsys_sim_tutorial.qpf, from the \simulation_tutorial directory.
- In Platform Designer, click File > New System to create a new Platform Designer design.
- To remove the clock source, which is not needed for this design, right-click clk_0, and then click Remove.
- In the IP Catalog, select Custom Pattern Generator from the Memory Test Microcores group, and then click Add.
- In the parameter editor, click Finish to accept the default parameters.
- Rename the instance to pg to provide a short instance name for the pattern generator.
3.7.10.1.2. Export Design Under Test
- In Platform Designer, on the System Contents tab, in the Export column, for each interface click Double-click to export, and maintain the default export names.
- Save the system as pattern_generator.
3.7.10.1.3. Generate a Testbench System
- In Platform Designer click Generate > Generate Testbench System.
- Under Testbench System, for Create testbench Platform Designer system, select Standard, BFMs for standard Platform Designer interfaces.
- Under Synthesis, select None for Create HDL design files for synthesis, and turn off Create block symbol file (.bsf).
- Click Generate.
- After Platform Designer generates the testbench, click Close.
Platform Designer generates this testbench system in the \simulation_tutorial\pattern_generator\testbench directory.
You can generate the simulation model for the Platform Designer testbench system at the same time by turning on Create testbench simulation model. However, the Platform Designer-generated testbench system's components names are assigned automatically and you may want to control the instance names to make it easier to run the test program for the BFMs. In this tutorial, you edit the Platform Designer testbench system before generating the simulation model.
3.7.10.1.4. Generate Testbench System's Simulation Models
- In Platform Designer, open the testbench system, pattern_generator_tb.qsys, from the simulation_tutorial\pattern_generator\testbench directory.
-
On the System
Contents tab, rename the instance as they appear in
Table 5–1.
Platform Designer-Generated Components' Names New Instance Name pattern_generator_inst DUT pattern_generator_inst_pg_clock_bfm clock_source pattern_generator_inst_pg_reset_bfm reset_source pattern_generator_inst_pg_csr_bfm csr_master pattern_generator_inst_pg_pattern_access_bfm pattern_master pattern_generator_inst_pg_pattern_output_bfm pattern_sink -
Double-click a BFM
component to open the parameter editor and view its settings. These BFM
components are available in the Avalon Verification Suite group in the library.
If necessary, you can change the parameters for the BFMs to ensure adequate
test coverage for your design.
The Platform Designer-generated testbench matches inserted BFMs with the exported interfaces from the design that they drive. The test program that provides stimulus to the BFMs must account for the matching interface. For example, an exported Avalon-MM slave interface (which expects word-aligned addresses) is connected to an Avalon master BFM, which expects and transacts word-aligned addresses instead of the byte or symbol addresses that are default for Avalon masters.
- Click Cancel to close the parameter editor without making changes.
- In the Generation dialog box, under Simulation, for Create simulation model, select Verilog.
- Under Testbench System, select None for Create testbench Platform Designer system and Create testbench simulation model.
- Under Synthesis, select None for Create HDL design files for synthesis, and turn off Create Block design files (.bsf).
- Save the system.
- Click Generate.
- After Platform Designer generates the testbench, click Close.
Platform Designer generates the testbench system’s simulation models in the \simulation_tutorial\pattern_generator\testbench\pattern_generator_tb\simulation directory.
Platform Designer generates the simulation models and a ModelSim simulation script (msim_setup.tcl), which compiles the required files for simulation and sets up commands to load the simulation in the ModelSim simulator. You can run this ModelSim script in ModelSim to compile, elaborate, or load for simulation.
In this tutorial, there is an external test program to provide simulation stimulus. The tutorial design files include a simulation script, load_sim.tcl that compiles the top-level simulation file and test program, and calls the Platform Designer-generated script to compile the required files.
3.7.10.2. Run Simulation In the ModelSim Software
You can run a simulation in the ModelSim software on the testbench that you created. To complete this simulation you use the test program provided in the design files. The test begins by writing a walking ones pattern to the design under test.
This test program performs the following actions:
- Reads a pattern file.
- Writes the pattern to the design under test via the pattern master BFM.
- Sets various design under test options via the CSR master BFM.
- Starts the design under test pattern generation.
- Collects data generated by the design under test.
- Compares the results against the original pattern file.
3.7.10.2.1. Set Up the Simulation Environment
The load_sim.tcl script sets simulation variables to set up the correct hierarchical paths in the Platform Designer-generated simulation model and ModelSim script. Additionally, the script identifies the top-level instance name for the simulation and provides the path to the location of the Platform Designer-generated files. Some functions, such as memory initialization, rely on correct hierarchical paths names in the simulation model.
The load_sim.tcl script performs the following actions:
- Sources the Platform Designer-generated ModelSim simulation script, msim_setup.tcl.
- Uses the command aliases defined in the msim_setup.tcl script to compile and elaborate the files for the Platform Designer testbench simulation model.
- Compiles and elaborates the extra simulation files for the tutorial—the test program and top-level simulation file that instantiates the test program.
- Loads the wave.do file that provides signals for the ModelSim waveform view.
3.7.10.2.2. Run the Simulation
- Start the ModelSim software.
- Click File > Change Directory, browse to the \simulation_tutorial directory, and then click OK.
- Click Compile > Compile Options.
- Click the Verilog & SystemVerilog tab, select Use SystemVerilog, and then click OK.
-
Click
File > Load
Ensure you activate the ModelSim Transcript window, otherwise the Load function is disabled.
-
Select the
load_sim.tcl script, and then click
Open.
The warning messages relate to unused connections in an ALTSYNCRAM megafunction. Because these ports are not used, you can ignore the warning messages.
-
Run the simulation for 40us. To run the simulation, in the
ModelSim Transcript window type the following command: run
40us.
You can run the h command to show the available options for the msim_setup.tcl script.
-
Observe the
results.
INFO: top.tb.reset_source.reset_deassert: Reset deasserted INFO: top.pgm: Starting test walking_ones.hex INFO: top.pgm.read_file: Read file walking_ones.hex success INFO: top.pgm.read_file: Read file walking_ones_rev.hex success INFO: top.pgm: Test walking_ones.hex passed
-
To run the low
frequency test, modify
\simulation_tutorial\test_include.svh according to
Table 12.
Table 12. Values for Low Frequency Pattern Test Macro New Value PATTERN_POSITION 0 NUM_OF_PATTERN 2 NUM_OF_PAYLOAD_BYTES 256 FILENAME low_freq.hex FILENAME_REV low_freq_rev.hex -
Reload the
load_sim.tcl script, run the simulation for 40us, and observe
the result in the Transcript window.
INFO: top.pgm: Starting test low_freq.hex INFO: top.pgm.read_file: Read file low_freq.hex success INFO: top.pgm.read_file: Read file walking_ones_rev.hex success INFO: top.pgm: Test low_freq.hex passed
-
To run the random
number pattern test, modify \simulation_tutorial\test_include.svh
according to
Table 13.
Table 13. Values for Random Number Pattern Test Macro New Value PATTERN_POSITION 32 NUM_OF_PATTERN 64 NUM_OF_PAYLOAD_BYTES 1024 FILENAME random_num.hex FILENAME_REV random_num_rev.hex -
Reload the
load_sim.tcl script, and run the simulation for 40us to
observe the following results.
INFO: top.pgm: Starting test random_num.hex INFO: top.pgm.read_file: Read file random_num.hex success INFO: top.pgm.read_file: Read file random_num_rev.hex success INFO: top.pgm: Test random_num.hex passed
3.7.11. View a Diagram of the Completed System
You set up the simulation environment for the custom pattern generator component and used BFM test code to perform simulation. You can test your own custom Platform Designer components with this method to verify their functionality before you integrate them into a complete system. You can also create a testbench system for a complete Platform Designer system with this method, and test your top-level system behavior with BFMs.
On the Platform Designer Tutorial Design Example page, click detailed diagram under Block Diagram to view a detailed diagram of the completed Memory Tester System.
3.8. Hardware System Design with Intel Quartus Prime and Platform Designer Revision History
Document Version | Changes |
---|---|
2017.06.12 | Added new sections:
|
2016.12.19 | Initial release. |
4. Software System Design with a Nios II Processor
This chapter describes the software flow in a Nios® II processor system design. It includes a detailed explanation and example on the Nios® II command line tools that are provided in the Nios® II Embedded Design Suite (EDS). Descriptions of both the Intel tools and the GNU tools are also included. Most of the commands are located in the bon and sdk subdirectories of your EDS installation.
Included is a description on how to develop the software flow and the software tools you can use in developing your embedded design system. Information about development with HAL drivers is also in this chapter.
4.1. Nios II Command-Line Tools
The Intel command line tools are useful for a range of activities, from board and system-level debugging to programming an FPGA configuration file (.sof). For these tools, the examples expand on the brief descriptions of the Intel-provided command-line tools for developing Nios® II programs in “Intel-Provided Embedded Development Tools” in the Nios® II Software Build Tools chapter of the Nios II Gen2 Software Developer’s Handbook. The Nios® II GCC toolchain contains the GNU Compiler Collection, GNU Binary Utilities (binutils), and newlib C library.
<command name> --help
To start the Nios® II command shell on Windows platforms, on the Start menu, click All Programs. On the All Programs menu, on the Intel submenu, on the Nios® II EDS <version> submenu, click Nios II <version> Command Shell.
<
Nios® II EDS install path>/nios2_command_shell.shr
The command shell is a Bourne-again shell (bash) with a pre-configured environment.
4.1.1. Intel Command-Line Tools for Board Bringup and Diagnostics
This section describes Intel command-line tools useful for Nios development board bringup and debugging.
4.1.1.1. jtagconfig
This command returns information about the devices connected to your host PC through the JTAG interface, for your use in debugging or programming. Use this command to determine if you configured your FPGA correctly.
Many of the other commands depend on successful JTAG connection. If you are unable to use other commands, check whether your JTAG chain differs from the simple, single-device chain used as an example in this section.
Type jtagconfig --help from a Nios® II command shell to display a list of options and a brief usage statement.
4.1.1.1.1. jtagconfig Usage Example
To use the jtagconfig command, perform the following steps:
- Open a Nios® II command shell.
- In the command shell, type the following command:
jtagconfig -n
jtagconfig Example Response
$ jtagconfig -n
1)
Intel® FPGA Download Cable [USB-0]
020050DD EP1S40/_HARDCOPY_FPGA_PROTOTYPE
Node 11104600
Node 0C006E00
The information in the response varies, depending on the particular FPGA, its configuration, and the JTAG connection cable type. The table below describes the information that appears in the response in the example.
Value | Description |
---|---|
Intel® FPGA Download Cable [USB-0] | The type of cable. You can have multiple cables connected to your workstation. |
EP1S40/_HARDCOPY_FPGA_PROTOTYPE | The device name, as identified by silicon identification number. |
Node 11104600 | The node number of a JTAG node inside the FPGA. The appearance of a node number between 11104600 and 11046FF, inclusive, in this system’s response confirms that you have a Nios® II processor with a JTAG debug module. |
Note 0C006E00 | The node number of a JTAG node inside the FPGA. The appearance of a node number between 0C006E00 and 0C006EFF, inclusive, in this system’s response confirms that you have a JTAG UART component. |
The device name is read from the text file pgm_parts.txt in your Quartus® Prime installation. In the example above, the name is EP1S40/_HARDCOPY_FPGA_PROTOTYPE because the silicon identification number on the JTAG chain for the FPGA device is 020050DD, which maps to the names EP1S40<device-specific name>, a couple of which end in the string _HARDCOPY_FPGA_PROTOTYPE. The internal nodes are nodes on the system-level debug (SLD) hub. All JTAG communication to an Intel FPGA passes through this hub, including advanced debugging capabilities such as the Signal Tap II embedded logic analyzer and the debugging capabilities in the Nios® II EDS.
The example above illustrates a single cable connected to a single-device JTAG chain. However, your computer can have multiple JTAG cables, connected to different systems. Each of these systems can have multiple devices in its JTAG chain. Each device can have multiple JTAG debug modules, JTAG UART modules, and other kinds of JTAG nodes. Use the jtagconfig -n command to help you understand the devices with JTAG connections to your host PC and how you can access them.
4.1.1.2. nios2-configure-sof
This command downloads the specified .sof and configures the FPGA according to its contents. At a Nios® II command shell prompt, type nios2-configure-sof --help for a list of available command-line options.
You must specify the cable and device when you have more than one JTAG cable ( Intel® FPGA Download Cable ) connected to your computer or when you have more than one device (FPGA) in your JTAG chain. Use the --cable and --device options for this purpose.
4.1.1.2.1. nios2-configure-sof Usage Example
To use the nios2-configure-sof command, perform the following steps:
- Open a Nios® II command shell.
- In the command shell, change to the directory in which your .sof is located. By default, the correct location is the top-level Intel® Quartus® Prime project directory.
- In the command shell, type the following
command:
nios2-configure-sof
The Nios® II EDS searches the current directory for a .sof and programs it through the specified JTAG cable.
4.1.1.3. system-console
The system-console command starts a Tcl-based command shell that supports low-level JTAG chain verification and full system-level validation.This tool is available in the Nios® II EDS starting in version 8.0.
This application is very helpful for low-level system debug, especially when bringing up a system. It provides a Tcl-based scripting environment and many features for testing your system.
The following important command-line options are available for the system-console command:
- The --script=<your script>.tcl option directs the System Console to run your Tcl script.
- The --cli option directs the System Console to open in your existing shell, rather than opening a new window.
- The --debug option directs the System Console to redirect additional debug output to stderr.
- The --project-dir=<project dir> option directs the System Console to the location of your hardware project. Ensure that you’re working with the project you intend—the JTAG chain details and other information depend on the specific project.
- The --jdi=<JDI file> option specifies the name-to-node mapping for the JTAG chain elements in your project.
For System Console usage examples and a comprehensive list of system console commands, refer to Analyzing and Debugging Designs with the System Console in volume 3 of the Intel® Quartus® Prime Handbook, on-line training is available.
4.1.2. Intel Command-Line Tools for Flash Programming
This section describes the command-line tools for programming your Nios® II-based design in flash memory.
When you use the Nios® II EDS to program flash memory, the Nios® II EDS generates a shell script that contains the flash conversion commands and the programming commands. You can use this script as the basis for developing your own command-line flash programming flow.
For more details about the Nios® II EDS and command-line usage of the Nios® II Flash Programmer and related tools, refer to the Nios® II Flash Programmer User Guide.
4.1.2.1. nios2-flash-programmer
This command programs common flash interface (CFI) memory. Because the Nios® II flash programmer uses the JTAG interface, the nios2-flash-programmer command has the same options for this interface as do other commands. You can obtain information about the command-line options for this command with the --help option.
4.1.2.1.1. nios2-flash-programmer Usage Example
You can perform the following steps to program a CFI device:
- Follow the steps in nios2-download, or use the Nios® II EDS, to program your FPGA with a design that interfaces successfully to your CFI device.
- Type the following command to verify that your flash device is detected
correctly:
nios2-flash-programmer –debug –base=<base address>
where <base address> is the base address of your flash device. The base address of each component is displayed in Platform Designer. If the flash device is detected, the flash memory’s CFI table contents are displayed.
- Convert your file to flash format (.flash) using one of the utilities elf2flash, bin2flash, or sof2flash described in elf2flash, bin2flash, and sof2flash.
- Type the following command to program the resulting .flash file in the CFI
device:
nios2-flash-programmer –base=<base address> <file>.flashr
- Optionally, type the following command to reset and start the processor at its
reset address:
nios2-download –g –r
4.1.2.2. elf2flash, bin2flash, and sof2flash
These three commands are often used with the nios2-flash-programmer command. The resulting .flash file is a standard .srec file.
The following two important command-line options are available for the elf2flash command:
- The -boot=<boot copier file>.srec option directs the elf2flash command to prepend a bootloader S-record file to the converted ELF file.
- The -after=<flash file>.flash option places the generated .flash file—the converted ELF file—immediately following the specified .flash file in flash memory.
The -after option is commonly used to place the .elf file immediately following the .sof in an erasable, programmable, configurable serial EPCS or EPCQ flash device.
Before it writes to any flash device, the Nios® II flash programmer erases the entire sector to which it expects to write. In EPCS and EPCQ devices, however, if you generate the software image using the elf2flash -after option, the Nios® II flash programmer places the software image directly following the hardware image, not on the next flash sector boundary. Therefore, in this case, the Nios® II flash programmer does not erase the current sector before placing the software image. However, it does erase the current sector before placing the hardware image.
When you use the flash programmer through the Nios® II SBT, you automatically create a script that contains some of these commands. Running the flash programmer creates a shell script (.sh) in the Debug or Release target directory of your project. This script contains the detailed command steps you used to program your flash memory.
Sample Auto-Generated Script:
#!/bin/sh # # This file was automatically generated by the Nios® II SBT For Eclipse. # # It will be overwritten when the flash programmer options change. # cd <full path to your project>/Debug # Creating .flash file for the FPGA configuration #"< Nios® II EDS install path>/bin/sof2flash" --offset=0x400000 \ --input="full path to your SOF" \ --output="<your design>.flash" # Programming flash with the FPGA configuration #"< Nios® II EDS install path>/bin/nios2-flash-programmer" --base=0x00000000 \ --sidp=0x00810828 --id=1436046714 \ --timestamp=1169569475 --instance=0 "<your design>.flash" # # Creating .flash file for the project "< Nios® II EDS install path>/bin/elf2flash" --base=0x00000000 --end=0x7fffff \ --reset=0x0 \ --input="<your project name>.elf" --output="ext_flash.flash" \ --boot="<path to the bootloader>/boot_loader_cfi.srec" # Programming flash with the project "< Nios® II EDS install path>/bin/nios2-flash-programmer" --base=0x00000000 \ --sidp=0x00810828 --id=1436046714 \ --timestamp=1169569475 --instance=0 "ext_flash.flash" # Creating .flash file for the read only zip file system "< Nios® II EDS install path>/bin/bin2flash" --base=0x00000000 --location=0x100000\ --input="<full path to your binary file>" --output="<filename>.flash" # Programming flash with the read only zip file system "< Nios® II EDS install path>/bin/nios2-flash-programmer" --base=0x00000000 \ --sidp=0x00810828 --id=1436046714 \ --timestamp=1169569475 --instance=0 "<filename>.flash"
The paths, file names, and addresses in the auto-generated script change depending on the names and locations of the files that are converted and on the configuration of your hardware design.
4.1.2.2.1. bin2flash Usage Example
To program an arbitrary binary file to flash memory, perform the following steps:
- Type the following command to generate your .flash file:
bin2flash --location=<offset from the base address> \ -input=<your file> --output=<your file>.flash
- Type the following command to program your newly created file to flash
memory:
nios2-flash-programmer -base=<base address> <your file>.flash
4.1.3. Intel Command-Line Tools for Software Development and Debug
This section describes Intel command-line tools that are useful for software development and debugging.
4.1.3.1. nios2-terminal
This command establishes contact with stdin, stdout, and stderr in a Nios II processor subsystem. stdin, stdout, and stderr are routed through a UART (standard UART or JTAG UART) module within this system.
The nios2-terminal command allows you to monitor stdout, stderr, or both, and to provide input to a Nios® II processor subsystem through stdin. This command behaves the same as the nios2-configure-sof command described in nios2-configure-sof with respect to JTAG cables and devices. However, because multiple JTAG UART modules may exist in your system, the nios2-terminal command requires explicit direction to apply to the correct JTAG UART module instance. Specify the instance using the -instance command-line option. The first instance in your design is 0 (-instance "0"). Additional instances are numbered incrementally, starting at 1 (-instance "1").
4.1.3.2. nios2-download
This command parses Nios® II .elf files, downloads them to a functioning Nios® II processor, and optionally runs the .elf file.
As for other commands, you can obtain command-line option information with the --help option. The nios2-download command has the same options as the nios2-terminal command for dealing with multiple JTAG cables and Nios® II processor subsystems.
4.1.3.2.1. nios2-download Usage Example
To download (and run) a Nios® II .elf program:
- Open a Nios® II command shell.
- Change to the directory in which your .elf file is located. If you use the Nios® II SBT for development, the correct location is often the Debug or Release subdirectory of your top-level project. If you use the Nios® II SBT, the correct location is the app folder.
- In the command shell, type the following command to download and start your
program:
nios2-download -g <project name>.elf
- Optionally, use the nios2-terminal command to connect to view any output or provide any input to the running program.
4.1.3.3. nios2-stackreport
This command returns a brief report on the amount of memory still available for stack and heap from your project's .elf file.
This command does not help you to determine the amount of stack or heap space your code consumes during runtime, but it does tell you how much space your code has to work in.
nios2-stackreport Command and Response
$ nios2-stackreport <your project>.elf Info: (<your project>.elf) 6312 KBytes program size (code + initialized data). Info: 10070 KBytes free for stack + heap.
4.1.3.3.1. nios2-stackreport Usage Example
To use the nios2-stackreport command, perform the following steps:
- Open a Nios® II command shell.
- Change to the directory in which your .elf file is located.
- In the command shell, type the following command:
nios2-stackreport <your project>.elf
4.1.3.4. validate_zip
The Nios® II EDS uses this command to validate that the files you use for the Read Only Zip Filing System are uncompressed. You can use it for the same purpose.
4.1.3.4.1. validate_zip Usage Example
To use the validate_zip command, perform the following steps:
- Open a Nios® II command shell.
- Change to the directory in which your .zip file is located.
- In the command shell, type the following command:
validate_zip <file>.zip
If no response appears, your .zip file is not compressed.
4.1.3.5. nios2-gdb-server
This command starts a GNU Debugger (GDB) JTAG conduit that listens on a specified TCP port for a connection from a GDB client, such as a nios2-elf-gdb client.
pkill -9 -f nios2-gdb-server
4.1.3.5.1. nios2-gdb-server Usage Example
The Nios® II SBT for Eclipse and most of the other available debuggers use the nios2-gdb-server and nios2-elf-gdb commands for debugging. You should never have to use these tools at this low level. However, in case you prefer to do so, this section includes instructions to start a GDB debugger session using these commands, and an example GDB debugging session.
You can perform the following steps to start a GDB debugger session:
- Open a Nios® II command shell.
- In the command shell, type the following command to start the GDB server on the
machine that is connected through a JTAG interface to the
Nios® II system you
wish to debug:
nios2-gdb-server --tcpport 2342 --tcppersist
If the transfer control protocol port 2342 is already in use, use a different port.
Following is the system response:
Using cable " Intel® FPGA Download Cable [USB-0]", device 1, instance 0x00 Pausing target processor: OK Listening on port 2342 for connection from GDB:
Now you can connect to your server (locally or remotely) and start debugging.
- Type the following command to start a GDB client that targets your .elf
file:
nios2-elf-gdb <file>.elf
Sample Debugging Session
GNU gdb 6.1 Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "--host=i686-pc-cygwin --target=nios2-elf"... (gdb) target remote <your_host>:2342 Remote debugging using <your_host>:2342 OS_TaskIdle (p_arg=0x0) at sys/alt_irq.h:127 127 { (gdb) load Loading section .exceptions, size 0x1b0 lma 0x1000020 Loading section .text, size 0x3e4f4 lma 0x10001d0 Loading section .rodata, size 0x4328 lma 0x103e6c4 Loading section .rwdata, size 0x2020 lma 0x10429ec Start address 0x10001d0, load size 281068 Transfer rate: 562136 bits/sec, 510 bytes/write. (gdb) step . . . (gdb) quit
Possible commands include the standard debugger commands load, step, continue, run, and quit. Press Ctrl+c to terminate your GDB server session.
4.1.4. Intel Command-Line Nios II Software Build Tools
The Nios® II software build tools are command-line utilities available from a Nios® II command shell that enable you to create application, board support package (BSP), and library software for a particular Nios® II hardware system. Use these tools to create a portable, self-contained makefile-based project that can be easily modified later to suit your build flow.
Unlike the Nios® II SBT-based flow, proficient use of these tools requires some expertise with the GNU make-based software build flow. Before you use these tools, refer to the Nios® II Software Build Tools and the Nios® II Software Build Tools Reference chapters of the Nios® II Software Developer's Handbook.
The following sections summarize the commands available for generating a BSP for your hardware design and for generating your application software. Many additional options are available in the Nios® II software build tools. For an overview of the tools summarized in this section, refer to the Nios® II Software Build Tools chapter of the Nios® II Software Developer's Handbook.
4.1.4.1. BSP Related Tools
Use the following command-line tools to create a BSP for your hardware design:
- nios2-bsp-create-settings creates a BSP settings file.
- nios2-bsp-update-settings updates a BSP settings file.
- nios2-bsp-query-settings queries an existing BSP settings file.
- nios2-bsp-generate-files generates all the files related to a given BSP settings file.
- nios2-bsp is a script that includes most of the functionality of the preceding commands.
- create-this-bsp is a high-level script that creates a BSP for a specific hardware design example.
4.1.4.2. Application Related Tools
Use the following commands to create and manipulate Nios® II application and library projects:
- nios2-app-generate-makefile creates a makefile for your application.
- nios2-lib-generate-makefile creates a makefile for your application library.
- create-this-app is a high-level script that creates an application for a specific hardware design example.
4.1.5. Rebuilding Software from the Command Line
Rebuilding software after minor source code edits does not require a GUI. You can rebuild the project from a Nios® II Command Shell, using your application's makefile. To build or rebuild your software, perform the following steps:
- Open a
Nios® II Command Shell by executing one of the following steps, depending
on your environment:
- In the Windows operating system, on the Start menu, point to Programs > Intel FPGA > Nios® II EDS, and click Nios® II Command Shell.
- In the Linux operating system, in a command shell, type the following
sequence of
commands:
cd < Nios® II EDS install path> ./nios2_command_shell.sh
- Change to the directory in which your makefile is located. If you use the Nios® II SBT for development, the correct location is often the Debug or Release subdirectory of your software project directory.
- In the Command Shell, type one of the following
commands:
make
or
make -s
The example below illustrates the output of the make command run on a sample system.
Sample Output From make -s Command
$ make -s Creating generated_app.mk... Creating generated_all.mk... Creating system.h... Creating alt_sys_init.c... Creating generated.sh... Creating generated.gdb... Creating generated.x... Compiling src1.c... Compiling src2.c... Compiling src3.c... Compiling src4.c... Compiling src5.c... Linking project_name.elf...
If you add new files to your project or make significant hardware changes, recreate the project with the original tool (the Nios® II SBT). Recreating the project recreates the makefile for the new version of your system after the modifications.
4.1.6. GNU Command-Line Tools
The Nios® II GCC toolchain contains the GNU Compiler Collection, the GNU binutils, and the newlib C library. You can follow links to detailed documentation from the Nios® II EDS documentation launchpad found in your Nios® II EDS distribution. To start the launchpad on Windows platforms, on the Start menu, click All Programs. On the All Programs menu, on the Nios® II EDS <version> submenu, click Literature. On Linux platforms, open < Nios® II EDS install dir>/documents/index.htm in a web browser. In addition, more information about the GNU GCC toolchain is available on the online.
4.1.6.1. nios2-elf-addr2line
This command returns a source code line number for a specific memory address. The command is similar to but more specific than the nios2-elf-objdump command described in nios2-elf-objdump and the nios2-elf-nm command described in nios2-elf-nm.
nios2-elf-addr2linecommand to help validate code that should be stored at specific memory addresses. The example below illustrates its usage and results:
nios2-elf-addr2line Utility Usage Example
$ nios2-elf-addr2line --exe=<your project>.elf 0x1000020
<
Nios® II EDS install path>/components/altera_nios2/HAL/src/alt_exception_entry.S:99
4.1.6.1.1. nios2-elf-addr2line Usage Example
To use the nios2-elf-addr2line command, perform the following steps:
- Open a Nios® II command shell.
- In the command shell, type the following command:
nios2-elf-addr2line <your project>.elf <your_address_0>,\ <your_address_1>,...,<your_address_n>
If your project file contains source code at this address, its line number appears.
4.1.6.2. nios2-elf-gdb
This command is a GDB client that provides a simple shell interface, with built-in commands and scripting capability. A typical use of this command is illustrated in the section nios2-gdb-server.
4.1.6.3. nios2-elf-readelf
Use this command to parse information from your project's .elf file. The command is useful when used with grep, sed, or awk to extract specific information from your .elf file.
4.1.6.3.1. nios2-elf-readelf Usage Example
To display information about all instances of a specific function name in your .elf file, perform the following steps:
- Open a Nios® II command shell.
- In the command shell, type the following command:
nios2-elf-readelf -symbols <project>.elf | grep <function name>
Search for the http_read_line Function Using nios2-elf-readelf
$ nios2-elf-readelf.exe –s my_file.elf | grep http_read_line 1106: 01001168 160 FUNC GLOBAL DEFAULT 3 http_read_line
Value | Description |
---|---|
1106 | Symbol instance number |
0100168 | Memory address, in hexadecimal format |
160 | Size of this symbol, in bytes |
FUNC | Type of this symbol (function) |
GLOBAL | Binding (values: GLOBAL, LOCAL, and WEAK) |
DEFAULT | Visibility (values: DEFAULT, INTERNAL, HIDDEN, and PROTECTED) |
3 | Index |
http_read_line | Symbol name |
You can obtain further information about the ELF file format online. Each of the ELF utilities has its own main page.
4.1.6.4. nios2-elf-ar
This command generates an archive (.a) file containing a library of object (.o) files. The Nios® II SBT uses this command to archive the System Library project.
4.1.6.4.1. nios2-elf-ar Usage Example
To archive your object files using the nios2-elf-ar command, perform the following steps:
- Open a Nios® II command shell.
- Change to the directory in which your object files are located.
- In the command shell, type the following command:
nios2-elf-ar q <archive_name>.a <object files>
The example shows how to create an archive of all of the object files in your current directory. In the example, the q option directs the command to append each object file it finds to the end of the archive. After the archive file is created, it can be distributed for others to use, and included as an argument in linker commands, in place of a long object file list.
nios2-elf-ar Command Response
$ nios2-elf-ar q <archive_name>.a *.o nios2-elf-ar: creating <archive_name>.a
4.1.6.5. Linker
Use the nios2-elf-g++ command to link your object files and archives into the final executable format, ELF.
4.1.6.5.1. Linker Usage Example
To link your object files and archives into a .elf file, open a Nios® II command shell and call nios2-elf-g++ with appropriate arguments. The following example command line calls the linker:
nios2-elf-g++ -T'<linker script>' -msys-crt0='<crt0.o file>' \ -msys-lib=<system library> -L '<The path where your libraries reside>' \ -DALT_DEBUG -O0 -g -Wall -mhw-mul -mhw-mulx -mno-hw-div \ -o <your project>.elf <object files> -lm
The exact linker command line to link your executable may differ. When you build a project in the Nios® II SBT, you can see the command line used to link your application. To turn on this option in the Nios® II SBT, on the Window menu, click Preferences, select the Nios® II tab, and enable Show command lines when running make. You can also force the command lines to display by running make without the -s option from a Nios II command shell.
4.1.6.6. nios2-elf-size
This command displays the total size of your program and its basic code sections.
4.1.6.6.1. nios2-elf-size Usage Example
To display the size information for your program, perform the following steps:
- Open a Nios® II command shell.
- Change to the directory in which your .elf file is located.
- In the command shell, type the following command:
nios2-elf-size <project>.elf
nios2-elf-size Command Usage
$ nios2-elf-size my_project.elf text data bss dec hex filename 272904 8224 6183420 6464548 62a424 my_project.elf
4.1.6.7. nios2-elf-strings
This command displays all the strings in a .elf file.
4.1.6.7.1. nios2-elf-strings Usage Example
nios2-elf-strings <project>.elf
4.1.6.8. nios2-elf-strip
This command strips all symbols from object files. All object files are supported, including ELF files, object files (.o) and archive files (.a).
4.1.6.8.1. nios2-elf-strip Usage Example
nios2-elf-strip <options> <project> .elf
4.1.6.8.2. nios2-elf-strip Usage Notes
The nios2-elf-strip command decreases the size of the .elf file.
This command is useful only if the Nios® II processor is running an operating system that supports ELF natively.If ELF is the native executable format, the entire .elf file is stored in memory, and the size savings matter.If not, the file is parsed and the instructions and data stored directly in memory, without the symbols in any case.
Linux is one operating system that supports ELF natively; uClinux is another. uClinux uses the flat (FLT) executable format, which is translated directly from the ELF.
4.1.6.9. nios2-elf-gdbtui
This command starts a GDB session in which a terminal displays source code next to the typical GDB console.
The syntax for the nios2-elf-gdbtui command is identical to that for the nios2-elf-gdb command described in nios2-elf-gdb.
Two additional GDB user interfaces are available for use with the Nios® II GDB Debugger. CGDB, a cursor-based GDB UI, is available at sourceforge.net. The Data Display Debugger (DDD) is highly recommended.
4.1.6.10. nios2-elf-gprof
This command allows you to profile your Nios® II system.
For details about this command and the Nios® II EDS-based results GUI, refer to AN 391: Profiling Nios® II Systems.
4.1.6.11. nios2-elf-gcc and g++
These commands run the GNU C and C++ compiler, respectively, for the Nios® II processor.
4.1.6.11.1. Compilation Command Usage Example
The following simple example shows a command line that runs the GNU C or C++ compiler:
nios2-elf-gcc(g++) <options> -o <object files> <C files>
4.1.6.11.2. More Complex Compilation Example
The example below is a Nios® II EDS-generated command line that compiles C code in multiple files in many directories.
Example nios2-elf-gcc Command Line
nios2-elf-gcc -xc -MD -c \ -DSYSTEM_BUS_WIDTH=32 -DALT_NO_C_PLUS_PLUS -DALT_NO_INSTRUCTION_EMULATION \ -DALT_USE_SMALL_DRIVERS -DALT_USE_DIRECT_DRIVERS -DALT_PROVIDE_GMON \ -I.. -I/cygdrive/c/Work/Projects/demo_reg32/Designs/std_2s60_ES/software/\ reg_32_example_0_syslib/Release/system_description \ -I/cygdrive/c/altera/70_b31/ip/sopc_builder_ip/altera_avalon_timer/HAL/inc \ -I/cygdrive/c/altera/70_b31/ip/sopc_builder_ip/altera_avalon_timer/inc \ -I/cygdrive/c/altera/70_b31/ip/sopc_builder_ip/altera_avalon_jtag_uart/HAL/inc \ -I/cygdrive/c/altera/70_b31/ip/sopc_builder_ip/altera_avalon_jtag_uart/inc \ -I/cygdrive/c/altera/70_b31/ip/sopc_builder_ip/altera_avalon_pio/inc \ -I/cygdrive/c/altera/70_b31/ip/sopc_builder_ip/altera_avalon_lcd_16207/HAL/inc \ -I/cygdrive/c/altera/70_b31/ip/sopc_builder_ip/altera_avalon_lcd_16207/inc \ -I/cygdrive/c/altera/70_b31/ip/sopc_builder_ip/altera_avalon_sysid/HAL/inc \ -I/cygdrive/c/altera/70_b31/ip/sopc_builder_ip/altera_avalon_sysid/inc \ -I/cygdrive/c/altera/70_b31/nios2eds/components/altera_nios2/HAL/inc \ -I/cygdrive/c/altera/70_b31/nios2eds/components/altera_hal/HAL/inc \ -DALT_SINGLE_THREADED -D__hal__ -pipe -DALT_RELEASE -O2 -g -Wall\ -mhw-mul -mhw-mulx -mno-hw-div -o obj/reg_32_buttons.o ../reg_32_buttons.c
4.1.6.12. nios2-elf-c++filt
This command demangles C++ mangled names. C++ allows multiple functions to have the same name if their parameter lists differ; to keep track of each unique function, the compiler mangles, or decorates, function names. Each compiler mangles functions in a particular way.
For a full explanation, including more details about how the different compilers mangle C++ function names, refer to standard reference sources for the C++ language compilers.
4.1.6.12.1. nios2-elf-c++filt Usage Example
To display the original, demangled function name that corresponds to a particular symbol name, you can type the following command:
nios2-elf-c++filt -n <symbol name>
For example,
nios2-elf-c++filt -n _Z11my_functionv
4.1.6.12.2. More Complex nios2-elf-c++filt Example
nios2-elf-strings <file>.elf | grep ^_Z | nios2-elf-c++filt -n
In this example, the nios2-elf-strings operation outputs all strings in the .elf file. This output is piped to a grep operation that identifies all strings beginning with _Z. (GCC always prepends mangled function names with _Z). The output of the grep command is piped to a nios2-elf-c++filt command. The result is a list of all demangled functions in a GCC C++ .elf file.
4.1.6.13. nios2-elf-nm
This command list the symbols in a .elf file.
4.1.6.13.1. nios2-elf-nm Usage Example
The following two simple examples illustrate the use of the nios2-elf-nm command:
- nios2-elf-nm <project>.elf
- nios2-elf-nm <project>.elf | sort -n
4.1.6.13.2. More Complex nios2-elf-nm Example
To generate a list of symbols from your .elf file in ascending address order, use the following command:
nios2-elf-nm <project>.elf | sort -n > <project>.elf.nm
The <project> .elf.nm file contains all of the symbols in your executable file, listed in ascending address order. In this example, the nios2-elf-nm command creates the symbol list. In this text list, each symbol’s address is the first field in a new line. The -n option for the sort command specifies that the symbols be sorted by address in numerical order instead of the default alphabetical order.
4.1.6.14. nios2-elf-objcopy
Use this command to copy from one binary object format to another, optionally changing the binary data in the process.
Though typical usage converts from or to ELF files, the objcopy command is not restricted to conversions from or to ELF files. You can use this command to convert from, and to, any of the formats listed in the table below.
Command (...-objcopy) | Comments |
---|---|
elf32-littlenios2, elf32-little | Header little endian, data little endian, the default and most commonly used format |
elf32-bignios2, elf32-big | Header big endian, data big endian |
srec | S-Record (SREC) output format |
symbolsrec | SREC format with all symbols listed in the file header, preceding the SREC data |
tekhex | Tektronix hexadecimal (TekHex) format |
binary | Raw binary format Useful for creating binary images for storage in flash on your embedded system |
ihex | Intel hexadecimal (ihex) format |
You can obtain information about the TekHex, ihex, and other text-based binary representation file formats online. As of the initial publication of this handbook, you can refer to the sbprojects.com knowledge-base entry on file formats.
4.1.6.14.1. nios2-elf-objcopy Usage Example
To create an SREC file from an ELF file, use the following command:
nios2-elf-objcopy –O srec <project>.elf <project>.srec
ELF is the assumed binary format if none is listed. For information about how to specify a different binary format, in a Nios® II command shell, type the following command:
nios2-elf-objcopy --help
4.1.6.15. nios2-elf-objdump
Use this command to display information about the object file, usually an ELF file.
The nios2-elf-objdump command supports all of the binary formats that the nios2- elf-objcopy command supports, but ELF is the only format that produces useful output for all command-line options.
4.1.6.15.1. nios2-elf-objdump Usage Description
The Nios® II EDS uses the following command line to generate object dump files:
nios2-elf-objdump -D -S -x <project>.elf > <project>.elf.objdump
4.1.6.16. nios2-elf-ranlib
Calling nios2-elf-ranlib is equivalent to calling nios2-elf-ar with the -s option (nios2-elf-ar -s).
For further information about this command, refer to nios2-elf-ar or type nios2-elf-ar --help in a Nios® II command shell.
4.2. Developing Nios II Software
This section provides in-depth information about software development for the Intel Nios® II processor. It complements the Nios® II Gen2 Software Developer’s Handbook by providing the following additional information:
- Recommended design practices—Best practice information for Nios® II software design, development, and deployment.
- Implementation information—Additional in-depth information about the implementation of application programming interfaces (APIs) and source code for each topic, if available.
- Pointers to topics—Informative background and resource information for each topic, if available.
Before reading this section, you should be familiar with the process of creating a simple board support package (BSP) and an application project using the Nios® II Software Build Tools development flow. The Software Build Tools flow is supported by Nios® II Software Build Tools for Eclipse™ as well as the Nios® II Command Shell. This section focuses on the Nios® II Software Build Tools for Eclipse, but most information is also applicable to project development in the Command Shell.
- Online training demonstrations located on the Embedded Software Designer Curriculum page of the Intel website.
- Documentation located on the Documentation: Nios® II Processor page of the Intel website, especially the "Getting Started from the Command Line" and "Getting Started with the Graphical User Interface" chapters of the Nios® II Gen2 Software Developer's Handbook.
- Example designs provided with the Nios® II Embedded Design Suite (EDS). The online training demonstrations describe these software design examples, which you can use as-is or as the basis for your own more complex designs.
This section is structured according to the Nios® II software development process. Each section describes Intel’s recommended design practices to accomplish a specific task.
When you install the Nios® II EDS, it is installed in the same directory with the Intel® Quartus® Prime software. For example, if the Intel® Quartus® Prime software is installed on the Windows operating system, and the root directory of the Intel® Quartus® Prime software is c:\altera\<version>\quartus, then the root directory of the Nios® II EDS is c:\altera\<version>\nios2eds. For simplicity, this handbook refers to the nios2eds directory as:
<
Nios® II EDS install dir>
4.2.1. Software Development Cycle
The Nios® II EDS includes a complete set of C/C++ software development tools for the Nios® II processor. In addition, a set of third-party embedded software tools is provided with the Nios® II EDS. This set includes the MicroC/OS-II real-time operating system and the NicheStack TCP/IP networking stack. This section focuses on the use of the Intel-created tools for Nios® II software generation. It also includes some discussion of third-party tools.
The Nios® II EDS is a collection of software generation, management, and deployment tools for the Nios® II processor. The toolchain includes tools that perform low-level tasks and tools that perform higher-level tasks using the lower-level tools. For more information on Linux, refer to rocketboards.org.
4.2.1.1. Nios II Software Design
This section contains brief descriptions of the software design tools provided by the Nios® II EDS, including the Nios® II SBT development flow.
4.2.1.1.1. Nios II Tools Overview
The Nios® II EDS provides the following tools for software development:
- GNU toolchain: GCC-based compiler with the GNU binary utilitiesNote: For an overview of these and other Intel-provided utilities, refer to the " Nios® II Command-Line Tools" chapter of this handbook.
- Nios® II processor-specific port of the newlib C library
- Hardware abstraction layer (HAL)
The HAL provides a simple device driver interface for programs to communicate with the underlying hardware. It provides many useful features such as a POSIX-like application program interface (API) and a virtual-device file system.
For more information about the Intel HAL, refer to The Hardware Abstraction Layer section of the Nios® II Gen2 Software Developer’s Handbook.
-
Nios® II SBT
The Nios® II SBT development flow is a scriptable development flow. It includes the following user interfaces:
- The Nios® II SBT for Eclipse—a GUI that supports creating, modifying, building, running, and debugging Nios® II programs. It is based on the Eclipse open development platform and Eclipse C/C++ development toolkit (CDT) plug-ins.
- The
Nios® II SBT command-line interface—From this interface, you can execute SBT command
utilities, and use scripts (or other tools) to combine the command
utilities in many useful ways.
For more information about the Nios® II SBT flow, refer to the Developing Nios® II Software chapter of this handbook.
Intel recommends that you view and begin your design with one of the available software examples that are installed with the Nios® II EDS. From simple “Hello, World” programs to networking and RTOS-based software, these examples provide good reference points and starting points for your own software development projects. The Hello World Small example program illustrates how to reduce your code size without losing all of the conveniences of the HAL.
4.2.1.1.2. Nios II Software Build Tools
The Nios® II SBT flow uses the Software Build Tools to provide a flexible, portable, and scriptable software build environment. Intel recommends that you use this flow. The SBT includes a command-line environment and fits easily in your preferred software or system development environment.
The SBT flow requires that you have a .sopcinfo file for your system. The flow includes the following steps to create software for your system:
- Create a board support package (BSP) for your system. The BSP is a layer of software that interacts with your development system. It is a makefile-based project.
- Create your application software:
- Write your code.
- Generate a makefile-based project that contains your code.
- Iterate through one or both of these steps until your design is complete.
For more information, refer to the software example designs that are shipped with every release of the Nios® II EDS. For more information about these examples, refer to one of the following sections:
- “Getting Started” in the Getting Started with the Graphical User Interface chapter of the Nios® II Gen2 Software Developer’s Handbook.
- “ Nios® II Example Design Scripts” in the Nios® II Software Build Tools Reference chapter of the Nios® II Gen2 Software Developer’s Handbook.
4.2.1.2. Nios II Software Development Process
This section provides an overview of the Nios® II software development process and introduces terminology. The rest of the chapter elaborates the description in this section.
The Nios® II software generation process includes the following stages and main hardware configuration tools:
- Hardware configuration
- Platform Designer
- Intel® Quartus® Prime software
- Software project management
- BSP configuration
- Application project configuration
- Editing and building the software project
- Running, debugging, and communicating with the target
- Ensuring hardware and software coherency
- Project management
- Software project development
- Developing with the Hardware Abstraction Layer (HAL)
- Programming the Nios® II processor to access memory
- Writing exception handlers
- Optimizing the application for performance and size
- Real-time operating system (RTOS) support
- Application deployment
- Linking (run-time memory)
- Boot loading the system application
- Programming flash memory
In this list of stages and tools, the subtopics under the topics Software project management, Software project development, and Application deployment correspond closely to sections in the chapter.
You create the hardware for the system using the Intel® Quartus® Prime and Platform Designer software. The main output produced by generating the hardware for the system is the SRAM Object File (.sof), which is the hardware image of the system, and the Platform Designer Information File (.sopcinfo), which describes the hardware components and connections.
The software generation tools use the .sopcinfo file to create a BSP project. The BSP project is a collection of C source, header and initialization files, and a makefile for building a custom library for the hardware in the system. This custom library is the BSP library file (.a). The BSP library file is linked with your application project to create an executable binary file for your system, called an application image. The combination of the BSP project and your application project is called the software project.
The application project is your application C source and header files and a makefile that you can generate by running Intel-provided tools. You can edit these files and compile and link them with the BSP library file using the makefile. Your application sources can reference all resources provided by the BSP library file. The BSP library file contains services provided by the HAL, which your application sources can reference. After you build your application image, you can download it to the target system, and communicate with it through a terminal application.
You can access the makefile in the Eclipse Project Explorer view after you have created your project in the Nios® II Software Build Tools for Eclipse framework.
The software project is flexible: you can regenerate it if the system hardware changes, or modify it to add or remove functionality, or tune it for your particular system. You can also modify the BSP library file to include additional Intel-supplied software packages, such as the read-only zip file system or TCP/IP networking stack (the NicheStack TCP/IP Stack). Both the BSP library file and the application project can be configured to build with different parameters, such as compiler optimizations and linker settings.
If you change the hardware system, you must recreate, update or regenerate the BSP project to keep the library header files up-to-date.
For information about how to keep your BSP up-to-date with your hardware, refer to “Revising Your BSP” in the Nios® II Software Build Tools chapter of the Nios® II Gen2 Software Developer's Handbook.
4.2.2. Software Project Mechanics
This section describes the recommended ways to edit, build, download, run, and debug your software application, primarily using the Nios® II Software Build Tools for Eclipse.
The Nios® II Software Build Tools flow is the recommended design flow for hardware designs that contain a Nios® II processor. This section describes how to configure BSP and application projects, and the process of developing a software project for a system that contains a Nios® II processor, including ensuring coherency between the software and hardware designs.
4.2.2.1. Software Tools Background
The Nios® II EDS provides a sophisticated set of software project generation tools to build your application image. The Nios® II Software Build Tools flow is available for project creation. The Nios® II Software Build Tools flow includes the Software Build Tools command-line interface and the Nios® II Software Build Tools for Eclipse.
- stdio output to an RS-232 UART cannot display on the System Console. To display stdio output on the System Console, configure your BSP to use a JTAG UART peripheral for stdout, using the hal.stdout BSP setting. If no JTAG UART is available in your hardware system, you can run nios2-terminal in a separate Nios® II Command Shell to capture stdio output.
Intel recommends that you use the Nios® II Software Build Tools for Eclipse to create new software projects. The Nios® II Software Build Tools are the basis for Intel’s future development.
A graphical user interface for configuring BSP libraries, called the Nios® II BSP Editor, is also available. The BSP Editor is integrated with the Nios® II Software Build Tools for Eclipse, and can also be used independently.
4.2.2.2. Development Flow Guidelines
The Nios® II Software Build Tools flow provides many services and functions for your use. Until you become familiar with these services and functions, Intel recommends that you adhere to the following guidelines to simplify your development effort:
- Begin with a known hardware design—The All Design Examples page of the Intel website includes a set of known working designs, called hardware example designs, which are excellent starting points for your own design. In addition, the Nios® II Hardware Development Tutorial walks through some example designs.
- Begin with a known software example design—The Nios® II EDS includes a set of preconfigured application projects for you to use as the starting point of your own application. Use one of these designs and parameterize it to suit your application goals.
- Follow pointers to documentation—Many of the application and BSP project source files include inline comments that provide additional information.
- Make incremental changes—Regardless of your end-application goals, develop your software application by making incremental, testable changes, to compartmentalize your software development process. Intel recommends that you use a version control system to maintain distinct versions of your source files as you develop your project.
4.2.2.3. Nios II Software Build Tools
The Nios® II Software Build Tools are a collection of command-line utilities and scripts. These tools allow you to build a BSP project and an application project to create an application image. The BSP project is a parameterizable library, customized for the hardware capabilities and peripherals in your system. When you create a BSP library file from the BSP project, you create it with a specific set of parameter values. The application project consists of your application source files and the application makefile. The source files can reference services provided by the BSP library file.
For the full list of utilities and scripts in the Nios® II Software Build Tools flow, refer to “Intel-Provided Embedded Development Tools” in the Nios® II Software Build Tools chapter of the Nios® II Gen2 Software Developer's Handbook.
4.2.2.3.1. The Nios II Software Build Tools for Eclipse
The Nios® II Software Build Tools for Eclipse provide a consistent development platform that works for all Nios® II processor systems. You can accomplish most software development tasks in the Nios® II Software Build Tools for Eclipse, including creating, editing, building, running, debugging, and profiling programs.
The Nios® II Software Build Tools for Eclipse are based on the popular Eclipse™ framework and the Eclipse C/C++ development toolkit (CDT) plug-ins. Simply put, the Nios® II Software Build Tools for Eclipse provides a GUI that runs the Nios® II Software Build Tools utilities and scripts behind the scenes.
For detailed information about the Nios® II Software Build Tools for Eclipse, refer to the Getting Started with the Graphical User Interface chapter of the Nios® II Gen2 Software Developer's Handbook. For details about Eclipse, visit the Eclipse Foundation website.
4.2.2.3.2. The Nios II Software Build Tools Command Line
In the Nios® II Software Build Tools command line development flow, you create, modify, build, and run Nios® II programs with Nios® II Software Build Tools commands typed at a command line or embedded in a script.
To debug your program, import your Software Build Tools projects to Eclipse. You can further edit, rebuild, run, and debug your imported project in Eclipse.
For further information about the Nios® II Software Build Tools and the Nios® II Command Shell, refer to the "Getting Started from the Command Line" chapter of the Nios® II Gen2 Software Developer's Handbook.
4.2.2.4. Configuring BSP and Application Projects
This section describes some methods for configuring the BSP and application projects that comprise your software application, while encouraging you to begin your software development with a software example design.
For information about using version control, copying, moving and renaming a BSP project, and transferring a BSP project to another person, refer to “Common BSP Tasks” in the Nios® II Software Build Tools chapter of the Nios Gen2 II Software Developer's Handbook.
4.2.2.4.1. Software Example Designs
The best way to become acquainted with the Nios® II Software Build Tools flow and begin developing software for the Nios® II processor is to use one of the pre-existing software example designs that are provided with the Nios® II EDS. The software example designs are preconfigured software applications that you can use as the basis for your own software development. The software examples can be found in the Nios® II installation directory.
For more information about the software example designs provided in the Nios II EDS, refer to “ Nios® II Embedded Design Examples” in the Overview of Nios® II Embedded Development chapter of the Nios® II Gen2 Software Developer’s Handbook.
To use a software example design, follow these steps:
- Set up a working directory that contains your system hardware, including the
system .sopcinfo file.Note: Ensure that you have compiled the system hardware with the Intel® Quartus® Prime software to create up-to-date .sof and .sopcinfo files.
- Start the
Nios® II Software Build Tools for Eclipse as follows:
- In the Windows operating system, on the Start menu, point to Programs > Nios® II EDS <version>, and click Nios® II <version> Software Build Tools for Eclipse.
- In the Linux operating system, in a command shell, type eclipse-nios2.
- Right-click anywhere in the Project Explorer view, point to New and click Nios® II Application and BSP from Template.
- Select an appropriate software example from the Templates list.Note: You must ensure that your system hardware satisfies the requirements for the software example design listed under Template description. If you use an Intel Nios® II development kit, the software example designs supplied with the kit are guaranteed to work with the hardware examples included with the kit.
- Next to Information File Name, browse to your working directory and select the .sopcinfo file associated with your system.
- In a multiprocessor design, you must select the processor on which to run the
software project.Note: If your design contains a single Nios® II processor, the processor name is automatically filled in.
- Fill in the project name.
- Click Next.
- Select Create a new BSP project based on the application project template.
- Click Finish. The Nios® II Software Build Tools generate an Intel HAL BSP for you.
If you do not want the Software Build Tools for Eclipse to automatically create a BSP for you, at Step 9, select Select an existing BSP project from your workspace. You then have several options:
- You can import a pre-existing BSP by clicking Import.
- You can create a HAL or MicroC/OS-II BSP as follows:
- Click Create. The Nios® II Board Support Package dialog box appears.
- Next to Operating System, select either HAL
or Micrium MicroC/OS-II.
You can select the operating system only at the time you create the BSP. To change operating systems, you must create a new BSP.
4.2.2.4.2. Selecting the Operating System (HAL versus MicroC/OS-II RTOS)
You have a choice of the following run-time environments (operating systems) to incorporate in your BSP library file:
- The Nios® II HAL—A lightweight, POSIX-like, single-threaded library, sufficient for many applications.
- The MicroC/OS-II RTOS—A real-time, multi-threaded environment. The Nios® II implementation of MicroC/OS-II is based on the HAL, and includes all HAL services.
After you select HAL or MicroC/OS-II, you cannot change the operating system for this BSP project.
4.2.2.4.3. Configuring the BSP Project
The BSP project is a configurable library. You can configure your BSP project to incorporate your optimization preferences—size, speed, or other features—in the custom library you create. This custom library is the BSP library file (.a) that is used by the application project.
Creating the BSP project populates the target directory with the BSP library file source and build file scripts. Some of these files are copied from other directories and are not overwritten when you recreate the BSP project. Others are generated when you create the BSP project.
The most basic tool for configuring BSPs is the BSP setting. Throughout this section, many of the project modifications you can make are based on BSP settings. In each case, this section presents the names of the relevant settings, and explains how to select the correct setting value. You can control the value of BSP settings several ways: on the command line, with a Tcl script, by directly adjusting the settings with the BSP Editor, or by importing a Tcl script to the BSP Editor.
Another powerful tool for configuring a BSP is the software package. Software packages add complex capabilities to your BSP. As when you work with BSP settings, you can add and remove software packages on the command line, with a Tcl script, directly with the BSP Editor, or by importing a Tcl script to the BSP Editor.
Intel recommends that you use the Nios® II BSP Editor to configure your BSP project. To start the Nios® II BSP Editor from the Nios® II Software Build Tools for Eclipse, right-click an existing BSP, point to Nios® II , and click BSP Editor.
For detailed information about how to manipulate BSP settings and add and remove software packages with the BSP Editor, refer to “Using the BSP Editor” in the Getting Started with the Graphical User Interface chapter of the Nios® II Gen2 Software Developer's Handbook. This chapter also discusses how to use Tcl scripts in the BSP Editor.
For information about manipulating BSP settings and controlling software packages at the command line, refer to “ Nios® II Software Build Tools Utilities” in the Nios® II Software Build Tools Reference chapter of the Nios® II Gen2 Software Developer's Handbook.
For details about available BSP settings, refer to “Settings Managed by the Software Build Tools” in the Nios® II Software Build Tools Reference chapter of the Nios® II Gen2 Software Developer's Handbook.
For a discussion of Tcl scripting, refer to “Software Build Tools Tcl Commands” in the Nios® II Software Build Tools Reference chapter of the Nios® II Gen2 Software Developer's Handbook.
MicroC/OS-II RTOS Configuration Tips
If you use the MicroC/OS-II RTOS environment, be aware of the following properties of this environment:
-
MicroC/OS-II BSP settings—The MicroC/OS-II RTOS
supports many configuration options. All of these options can be enabled and
disabled with BSP settings. Some of the options are enabled by default. A
comprehensive list of BSP settings for MicroC/OS-II is shown in the Settings tab of the
Nios® II BSP Editor.Note: The MicroC/OS-II BSP settings are also described in “Settings Managed by the Software Build Tools” in the Nios® II Software Build Tools Reference chapter of the Nios® II Gen2 Software Developer's Handbook.
- MicroC/OS-II setting modification—Modifying the MicroC/OS-II options modifies the system.h file, which is used to compile the BSP library file.
- MicroC/OS-II initialization—The core MicroC/OS-II RTOS is initialized during the execution of the C run-time initialization (crt0) code block. After the crt0 code block runs, the MicroC/OS-II RTOS resources are available for your application to use. For more information, refer to “crt0 Initialization”.
You can configure MicroC/OS-II with the BSP Editor. Figure 2–1 shows how you enable the MicroC/OS-II timer and queue code. The figure below shows how you specify a maximum of four timers for use with MicroC/OS-II.

The MicroC/OS-II configuration script in the example below performs the same MicroC/OS-II configuration as in the figure above and Figure 33: it enables the timer and queue code, and specifies a maximum of four timers.

MicroC/OS-II Tcl Configuration Script Example (ucosii_conf.tcl)
#enable code for UCOSII timers set_setting ucosii.os_tmr_en 1 #enable a maximum of 4 UCOSII timers set_setting ucosii.timer.os_tmr_cfg_max 4 #enable code for UCOSII queues set_setting ucosii.os_q_en 1
HAL Configuration Tips
If you use the HAL environment, be aware of the following properties of this environment:
-
HAL BSP settings—A comprehensive list of options is
shown in the Settings tab in the
Nios® II BSP Editor. These options include
settings to specify a pre- and post-process to run for each C or C++ file
compiled, and for each file assembled or archived.Note: For more information about BSP settings, refer to “Settings Managed by the Software Build Tools” in the Nios® II Software Build Tools Reference chapter of the Nios® II Gen2 Software Developer's Handbook.
- HAL setting modification—Modifying the HAL options modifies the system.h file, which is used to compile the BSP library file.
- HAL initialization—The HAL is initialized during the execution of the C run-time initialization (crt0) code block. After the crt0 code block runs, the HAL resources are available for your application to use.For more information, refer to the “crt0 Initialization” section.
You can configure the HAL in the BSP Editor. The figure below shows how you specify a UART to be used as the stdio device.
The Tcl script in the example performs the same configuration as in the figure: it specifies a UART to be used as the stdio device.

HAL Tcl Configuration Script Example (hal_conf.tcl)
#set up stdio file handles to point to a UART set default_stdio uart1 set_setting hal.stdin $default_stdio set_setting hal.stdout $default_stdio set_setting hal.stderr $default_stdio
Adding Software Packages
Intel supplies several add-on software packages in the Nios® II EDS. These software packages are available for your application to use, and can be configured in the BSP Editor from the Software Packages tab. The Software Packages tab allows you to insert and remove software packages in your BSP, and control software package settings. The software package table at the top of this tab lists each available software package. The table allows you to select the software package version, and enable or disable the software package.
The operating system determines which software packages are available.
The following software packages are provided with the Nios® II EDS:
- Host File System—Allows a Nios® II system to access a file system that resides on the workstation. For more information, refer to “The Host-Based File System”.
- Read-Only Zip File System—Provides access to a simple file system stored in flash memory. For more information, refer to “Read-Only Zip File System”.
- NicheStack TCP/IP Stack –
Nios® II Edition—Enables support of the NicheStack
TCP/IP networking stack. Note: The stack is provided as is but Intel does not offer additional support.
For more information about the NicheStack TCP/IP networking stack, refer to the Ethernet and the TCP/IP Networking Stack - Nios® II Edition chapter of the Nios® II Gen2 Software Developer's Handbook.
Using Tcl Scripts with the Nios II BSP Editor
The Nios® II BSP Editor supports Tcl scripting. Tcl scripting in the Nios® II BSP Editor is a simple but powerful tool that allows you to easily migrate settings from one BSP to another. This feature is especially useful if you have multiple software projects utilizing similar BSP settings. Tcl scripts in the BSP editor allow you to perform the following tasks:
- Regenerate the BSP from the command line
- Export a TCL script from an existing BSP as a starting point for a new BSP
- Recreate the BSP on a different hardware platform
- Examine the Tcl script to improve your understanding of Tcl command usage and BSP settings
You can configure a BSP either by importing your own manually-created Tcl script, or by using a Tcl script exported from the Nios® II BSP Editor.
You can apply a Tcl script only at the time that you create the BSP.
Exporting a Tcl Script
To export a Tcl script, follow these steps:
- Use the Nios® II BSP Editor to configure the BSP settings in an existing BSP project.
- In the Tools menu, click Export Tcl Script.
- Navigate to the directory where you wish to store your Tcl script.
- Select a file name for the Tcl script.
When creating a Tcl script, the Nios® II BSP Editor only exports settings that differ from the BSP defaults. For example, if the only non-default settings in the BSP are those shown in Configuring HAL stdio Device in BSP Editor, the BSP Editor exports the script shown in the example below.
Tcl Script Exported by BSP Editor
###################################################################### # # This is a generated Tcl script exported # by a user of the Intel FPGA Nios® II BSP Editor. # # It can be used with the Intel FPGA 'nios2-bsp' shell script '--script' # option to customize a new or existing BSP. # ###################################################################### ###################################################################### # # Exported Setting Changes # ###################################################################### set_setting hal.stdout uart1 set_setting hal.stderr uart1 set_setting hal.stdin uart1
For details about default BSP settings, refer to “Specifying BSP Defaults” in the Nios® II Software Build Tools chapter of the Nios® II Gen2 Software Developer's Handbook.
Importing a Tcl Script to Create a New BSP
The following example illustrates how to configure a new BSP with an imported Tcl script. You import the Tcl script with the Nios® II BSP Editor, when you create a new BSP settings file.
In this example, you create the Tcl script by hand, with a text editor. You can also use a Tcl script exported from another BSP, as described in “Exporting a Tcl Script”.
To configure a new BSP with a Tcl script, follow these steps:
- With any text editor, create a new file called example.tcl.
- Insert the contents of the example below in the file.
- In the Nios® II BSP Editor, in the File menu, click New BSP.
- In the BSP Settings File Name box, select a folder in which to save your new BSP settings file. Accept the default settings file name, settings.bsp.
- In the Operating System list, select Intel FPGA HAL.
- In the Additional Tcl script box, navigate to example.tcl.
- In the Platform Designer Information File Name box, select the .sopcinfo file.
- Click OK. The BSP Editor creates the new BSP. The settings modified by example.tcl appear as in the figure below.
Example 2–4. BSP Configuration Tcl Script example.tcl
set_setting hal.enable_reduced_device_drivers true set_setting hal.enable_sim_optimize true set_setting hal.enable_small_c_library true set_setting hal.enable_gprof true

Do not attempt to import an Intel FPGA HAL Tcl script to a MicroC/OS-II BSP or vice-versa. Doing so could result in unpredictable behavior, such as lost settings. Some BSP settings are OS-specific, making scripts from different OSes incompatible.
For more information about commands that can appear in BSP Tcl scripts, refer to “Software Build Tools Tcl Commands” in the Nios® II Software Build Tools Reference chapter of the Nios® II Gen2 Software Developer's Handbook.
4.2.2.4.4. Configuring the Application Project
You configure the application project by specifying source files and a valid BSP project, along with other command-line options to the nios2-app-generate-makefile or nios2-app-update-makefile commands.
Application Configuration Tips
Use the following tips to increase your efficiency in designing your application project:
-
Source file inclusion—To add source files to your project, drag them from
a file browser, such as Windows Explorer, and drop them in the Project
Explorer view in the
Nios® II Software Build Tools for Eclipse.
From the command line, several options are available for specifying the source files in your application project. If all your source files are in the same directory, use the --src-dir command-line option. If all your source files are contained in a single directory and its subdirectories, use the --src-rdir command-line option.
-
Makefile variables—When a new project is created in the
Nios® II Software
Build Tools for Eclipse, a makefile is automatically generated in the software
project directory. You can modify application makefile variables with the Nios
II Application Wizard.
From the command line, set makefile variables with the --set <var> <value> command-line option during configuration of the application project. The variables you can set include the pre- and post-processing settings BUILD_PRE_PROCESS and BUILD_POST_PROCESS to specify commands to be executed before and after building the application. Examine a generated application makefile to ensure you understand the current and default settings.
- Creating top level generation script—From the command line, simplify the parameterization of your application project by creating a top level shell script to control the configuration. The create-this-app scripts in the embedded processor design examples available from the All Design Examples web page are good models for your configuration script.
Linking User Libraries
You can create and use your own user libraries in the Nios® II Software Build Tools. The Nios II Software Build Tools for Eclipse includes the Nios® II Library wizard, which enables you to create a user library in a GUI environment.
You can also create user libraries in the Nios® II Command Shell, as follows:
- Create the library using the nios2-lib-generate-makefile command. This command generates a public.mk file.
- Configure the application project with the new library by running the nios2-app-generate-makefile command with the --use-lib-dir option. The value for the option specifies the path to the library's public.mk file.
4.2.2.4.5. Makefiles and the Nios II Software Build Tools for Eclipse
The Nios® II Software Build Tools for Eclipse create and manage the makefiles for Nios® II software projects. When you create a project, the Nios® II Software Build Tools create a makefile based on parameters and settings you select. When you modify parameters and settings, the Nios® II Software Build Tools update the makefile to match. BSP makefiles are based on the operating system, BSP settings, selected software packages, and selected drivers.
Nios® II BSP makefiles are handled differently from application and user library makefiles. Nios® II application and user library makefiles are based on source files that you specify directly. The following changes to an application or user library change the contents of the corresponding makefile:
- Change the application or user library name
- Add or remove source files
- Specify a path to an associated BSP
- Specify a path to an associated user library
- Enable, disable or modify compiler options
For information about BSPs and makefiles, refer to “Makefiles and the Nios® II Software Build Tools for Eclipse” in the Getting Started with the Graphical User Interface chapter of the Nios® II Gen2 Software Developer's Handbook.
4.2.2.4.6. Building and Running the Software in Nios II Software Build Tools for Eclipse
Building the Project
After you edit the BSP settings and properties, and generate the BSP (including the makefile), you can build your project. Right-click your project in the Project Explorer view and click Build Project.
Downloading and Running the Software
To download and run or debug your program, right-click your project in the Project Explorer view. To run the program, point to Run As and click Nios II Hardware.
Before you run your target application, ensure that your FPGA is configured with the target hardware image in your .sof file.
Communicating with the Target
The Nios® II Software Build Tools for Eclipse provide a console window through which you can communicate with your system. When you use the Nios® II Software Build Tools for Eclipse to communicate with the target, characters you input are transmitted to the target line by line. Characters are visible to the target only after you press the Enter key on your keyboard.
If you configured your application to use the stdio functions in a UART or JTAG UART interface, you can use the nios2-terminal application to communicate with your target subsystem. However, the Nios® II Software Build Tools for Eclipse and the nios2-terminal application handle input characters very differently.
On the command line, you must use the nios2-terminal application to communicate with your target. To start the application, type the following command: nios2-terminal
When you use the nios2-terminal application, characters you type in the shell are transmitted, one by one, to the target.
Software Debugging in Nios II Software Build Tools for Eclipse
This section describes how to debug a Nios® II program using the Nios II Software Build Tools for Eclipse. You can debug a Nios® II program on Nios® II hardware such as a Nios development board. To debug a software project, right-click the application project name, point to Debug As and click Nios® II Hardware.
For more information about using the Nios® II Software Build Tools for Eclipse to debug your application, refer to the Debugging Nios® II Designs chapter of the Embedded Design Handbook.
Run Time Stack Checking
For debugging purposes, it is useful to enable run-time stack checking, using the hal.enable_runtime_stack_checking BSP setting. When properly used, this setting enables the debugger to take control if the stack collides with the heap or with statically allocated data in memory.
For information about how to use run-time stack checking, refer to “Run-Time Analysis Debug Techniques” and Stack Overflow in the Debugging Nios® II Designs chapter. And "Run Time Stack Checking And Exception Debugging" section in the Getting Started with Graphical User Interface chapter of the Nios II Gen2 Software Developer's Handbook.
For more information about this and other BSP configuration settings, refer to “Settings Managed by the Software Build Tools” in the Nios® II Software Build Tools Reference chapter of the Nios® II Gen2 Software Developer's Handbook.
4.2.2.5. Ensuring Software Project Coherency
In some engineering environments, maintaining coherency between the software and system hardware projects is difficult. For example, in a mixed team environment in which a hardware engineering team creates new versions of the hardware, independent of the software engineering team, the potential for using the incorrect version of the software on a particular version of the system hardware is high. Such an error may cause engineers to spend time debugging phantom issues. This section discusses several design and software architecture practices that can help you avoid this problem.
4.2.2.5.1. Recommended Development Practice
The safest software development practice for avoiding the software coherency problem is to follow a strict hardware and software project hierarchy, and to use scripts to generate your application and BSP projects.
One best practice is to structure your application hierarchy with parallel application project and BSP project folders. In the recommended directory structure below, a top-level hardware project folder includes the Intel® Quartus® Prime project file, the Platform Designer-generated files, and the software project folder. The software project folder contains a subfolder for the application project and a subfolder for the BSP project. The application project folder contains a create-this-app script, and the BSP project folder contains a create-this-bsp script.
To build your own software project from the command line, create your own create-this-app and create-this-bsp scripts. Intel recommends that you also create clean-this-app and clean-this-bsp scripts. These scripts perform the following tasks:
- create-this-app—This bash script uses the nios2-app-generate-makefile command to create the application project, using the application software source files for your project. The script verifies that the BSP project is properly configured (a settings.bsp file is present in the BSP project directory), and runs the create-this-bsp script if necessary. The Intel-supplied create-this-app scripts that are included in the embedded design examples on the All Design Examples web page of the Intel website provide good models for this script.
-
clean-this-app—This bash script performs all necessary clean-up
tasks for the whole project, including the following:
- Call the application makefile with the clean-all target.
- Call the clean-this-bsp shell script.
- create-this-bsp—This bash script generates the BSP project. The script uses the nios2-bsp command, which can optionally call the configuration script bsp_settings.tcl. The nios2-bsp command references the <system_name> .sopcinfo file located in the hardware project folder. Running this script creates the BSP project, and builds the BSP library file for the system.
- clean-this-bsp—This bash script calls the clean target in the BSP project makefile and deletes the settings.bsp file.
The complete system generation process, from hardware to BSP and application projects, must be repeated every time a change is made to the system in Platform Designer. Therefore, defining all your settings in your create-this-bsp script is more efficient than using the Nios® II BSP Editor to customize your project. The system generation process follows:
- Hardware files generation—Using Platform Designer, write the updated system description to the <system_name> .sopcinfo file.
- Regenerate BSP project—Generate the BSP project with the create-this-bsp script.
- Regenerate application project—Generate the application project with the create-this-app script. This script typically runs the create-this-bsp script, which builds the BSP project by creating and running the makefile to generate the BSP library file.
- Build the system—Build the system software using the application and BSP makefile scripts. The create-this-app script runs make to build both the application project and the BSP library.
To implement this system generation process, Intel recommends that you use the following checklists for handing off responsibility between the hardware and software groups.
To hand off the project from the hardware group to the software group, perform the following steps:
- Hardware project hand-off—The hardware group provides copies of the <system_name> .sopcinfo and <system_name> .sof files. The software group copies these files to the software group’s hardware project folder.
- Recreate software project—The software team recreates the software application for the new hardware by running the create-this-app script. This script runs the create-this-bsp script.
- Build—The software team runs make in its application project directory to regenerate the software application.
To hand off the project from the software group to the hardware group, perform the following steps:
- Clean project directories—The software group runs the clean-this-app script.
- Software project folder hand-off—The software group provides the hardware group with the software project folder structure it generated for the latest hardware version. Ideally, the software project folder contains only the application project files and the application project and BSP generation scripts.
- Reconfigure software project—The hardware group runs the create-this-app script to reconfigure the group’s application and BSP projects.
- Build—The hardware group runs make in the application project directory to regenerate the software application.
4.2.2.5.2. Recommended Architecture Practice
Many of the hardware and software coherency issues that arise during the creation of the application software are problems of misplaced peripheral addresses. Because of the flexibility provided by Platform Designer, almost any peripheral in the system can be assigned an arbitrary address, or have its address modified during system creation. Implement the following practices to prevent this type of coherency issue during the creation of your software application:
-
Peripheral and Memory Addressing—The
Nios® II Software Build Tools
automatically generate a system header file, system.h, that defines a set
of #define symbols for every peripheral in the system. These
definitions specify the peripheral name, base address location, and address
span. If the Memory Management Unit (MMU) is enabled in your
Nios® II system,
verify that the address span for all peripherals is located in direct-mapped
memory, outside the memory address range managed by the MMU.
To protect against coherency issues, access all system peripherals and memory components with their system.h name and address span symbols. This method guarantees successful peripheral register access even after a peripheral's addressable location changes.
For example, if your system includes a UART peripheral named UART1, located at address 0x1000, access the UART1 registers using the system.h address symbol (iowr_32(UART1_BASE, 0x0, 0x10101010)) rather than using its address (iowr_32(0x1000, 0x0, 0x10101010)).
-
Checking peripheral values with the preprocessor—If you work in a large
team environment, and your software has a dependency on a particular hardware
address, you can create a set of C preprocessor #ifdef
statements that validate the hardware during the software compilation process.
These #ifdef statements validate the #define values in the
system.h file for each peripheral.
For example, for the peripheral UART1, assume the #define values in system.h appear as follows:
#define UART1_NAME "/dev/uart1" #define UART1_BASE 0x1000 #define UART1_SPAN 32 #define UART1_IRQ 6 . . .
In your C/C++ source files, add a preprocessor macro to verify that your expected peripheral settings remain unchanged in the hardware configuration. For example, the following code checks that the base address of UART1 remains at the expected value:
#if (UART1_BASE != 0x1000) #error UART should be at 0x1000, but it is not #endif
-
Ensuring coherency with the System ID core—Use the
System ID core. The System ID core is an Platform Designer peripheral that provides a unique
identifier for a generated hardware system. This identifier is stored in a
hardware register readable by the
Nios® II processor. This unique identifier is
also stored in the .sopcinfo file, which is then used to
generate the BSP project for the system. You can use the system ID core to
ensure coherency between the hardware and software by either of the following
methods:
- The first method is optionally implemented during system software development, when the Executable and Linking Format (.elf) file is downloaded to the Nios® II target. During the software download process, the value of the system ID core is checked against the value present in the BSP library file. If the two values do not match, this condition is reported. If you know that the system ID difference is not relevant, the system ID check can be overridden to force a download. Use this override with extreme caution, because a mismatch between hardware and software can lead you to waste time trying to resolve nonexistent bugs.
- The second method for using the system ID peripheral is useful in systems that do not have a Nios® II debug port, or in situations in which running the Nios® II software download utilities is not practical. In this method you use the C function alt_avalon_sysid_test(). This function reports whether the hardware and software system IDs match.
For more information about the System ID core, refer to the System ID Core chapter of the Embedded Peripherals IP User Guide.
4.2.3. Developing With the Hardware Abstraction Layer
The HAL for the Nios® II processor is a lightweight run-time environment that provides a simple device driver interface for programs to communicate with the underlying hardware. The HAL API is integrated with the ANSI C standard library. The HAL API allows you to access devices and files using familiar C library functions.
4.2.3.1. Overview of the HAL
This section describes how to use HAL services in your Nios® II software. It provides information about the HAL configuration options, and the details of system startup and HAL services in HAL-based applications.
4.2.3.1.1. HAL Configuration Options
To support the Nios® II software development flow, the HAL BSP library is self-configuring to some extent. By design, the HAL attempts to enable as many services as possible, based on the peripherals present in the system hardware. This approach provides your application with the least restrictive environment possible—a useful feature during the product development and board bringup cycle.
The HAL is configured with a group of settings whose values are determined by Tcl commands, which are called during the creation of the BSP project.
As mentioned in “Configuring the BSP Project”, Intel recommends you create a separate Tcl file that contains your HAL configuration settings.
HAL configuration settings control the boot loading process, and provide detailed control over the initialization process, system optimization, and the configuration of peripherals and services. For each of these topics, this section provides pointers to the relevant material elsewhere in this section.
4.2.3.1.2. Configuring the Boot Environment
Your particular system may require a boot loader to configure the application image before it can begin execution. For example, if your application image is stored in flash memory and must be copied to volatile memory for execution, a boot loader must configure the application image in the volatile memory. This configuration process occurs before the HAL BSP library configuration routines execute, and before the crt0 code block executes. A boot loader implements this process.
For more information, refer to “Linking Applications” and “Application Boot Loading and Programming System Memory”.
4.2.3.1.3. Controlling HAL Initialization
As noted in “HAL Initialization”, although most application debugging begins in the main() function, some tasks, such as debugging device driver initialization, require the ability to control overall system initialization after the crt0 initialization routine runs and before main() is called.
For an example of this kind of application, refer to the hello_alt_main software example design supplied with the Nios® II EDS installation.
4.2.3.1.4. Minimizing the Code Footprint and Increasing Performance
For information about increasing your application's performance, or minimizing the code footprint, refer to “Software Application Optimization”.
4.2.3.1.5. Configuring Peripherals and Services
For information about configuring and using HAL services, refer to “HAL Peripheral Services”.
4.2.3.2. System Startup in HAL-Based Applications
System startup in HAL-based applications is a three-stage process. First, the system initializes, then the crt0 code section runs, and finally the HAL services initialize. The following sections describe these three system-startup stages.
4.2.3.2.1. System Initialization
The system initialization sequence begins when the system powers up. The initialization sequence steps for FPGA designs that contain a Nios® II processor are the following:
- Hardware reset event—The board receives a power-on reset signal, which resets the FPGA.
- FPGA configuration—The FPGA is programmed with a .sof file, from a specialized configuration memory or an external hardware master. The external hardware master can be a CPLD device or an external processor.
- System reset—The Platform Designer system, composed of one or more Nios® II processors and other peripherals, receives a hardware reset signal and enters the components’ combined reset state.
- Nios® II processor(s)—Each Nios® II processor jumps to its preconfigured reset address, and begins running instructions found at this address.
-
Boot loader or program code—Depending on your system
design, the reset address vector contains a packaged boot loader, called a boot
image, or your application image. Use the boot loader if the application image
must be copied from non-volatile memory to volatile memory for program
execution. This case occurs, for example, if the program is stored in flash
memory but runs from SDRAM. If no boot loader is present, the reset vector jumps
directly to the .crt0 section of the application image. Do not use a boot loader
if you wish your program to run in-place from non-volatile or preprogrammed
memory.
For additional information about both of these cases, refer to “Application Boot Loading and Programming System Memory”.
- crt0 execution—After the boot loader executes, the processor jumps to the beginning of the program's initialization block—the .crt0 code section. The function of the crt0 code block is detailed in the next section.
4.2.3.2.2. crt0 Initialization
The crt0 code block contains the C run-time initialization code—software instructions needed to enable execution of C or C++ applications. The crt0 code block can potentially be used by user-defined assembly language procedures as well. The Intel-provided crt0 block performs the following initialization steps:
-
Calls alt_load macros—If the application is designed to
run from flash memory (the .text section runs from flash memory), the remaining
sections are copied to volatile memory.
For additional information, refer to “Configuring the Boot Environment”.
-
Initializes instruction cache—If the processor has an instruction cache,
this cache is initialized. All instruction cache lines are zeroed (without
flushing) with the initi instruction.Note: Platform Designer determines the processors that have instruction caches, and configures these caches at system generation. The Nios® II Software Build Tools insert the instruction-cache initialization code block if necessary.
- Initializes data cache—If the processor has a data cache, this cache is initialized. All data cache lines are zeroed (without flushing) with the initd instruction. As for the instruction caches, this code is enabled if the processor has a data cache.
-
Sets the stack pointer—The stack pointer is
initialized. You can set the stack pointer address.
For additional information refer to “HAL Linking Behavior”.
-
Clears the .bss section—The .bss section is
initialized to all zeros. You can set the .bss section address.
For additional information refer to “HAL Linking Behavior”.
-
Initializes stack overflow protection—Stack overflow
checking is initialized.
For additional information, refer to “Software Debugging in Nios® II Software Build Tools for Eclipse”.
-
Jumps to
alt_main()—The processor jumps to the
alt_main() function, which begins initializing the HAL BSP
run-time library.Note: If you use a third-party RTOS or environment for your BSP library file, the alt_main() function could be different than the one provided by the Nios® II EDS.
If you use a third-party compiler or library, the C run-time initialization behavior may differ from this description.
The crt0 code includes initialization short-cuts only if you perform hardware simulations of your design. You can control these optimizations by turning hal.enable_sim_optimize on or off.
For information about the hal.enable_sim_optimize BSP setting, refer to “Settings Managed by the Software Build Tools” in the Nios® II Software Build Tools Reference chapter of the Nios® II Gen2 Software Developer's Handbook.
The crt0.S source file is located in the <tools installation> /ip/altera/nios2_ip/altera_nios2/HAL/src directory.
4.2.3.2.3. HAL Initialization
As for any other C program, the first part of the HAL's initialization is implemented by the Nios® II processor's crt0.S routine. For more information, see “crt0 Initialization”. After crt0.S completes the C run-time initialization, it calls the HAL alt_main() function, which initializes the HAL BSP run-time library and subsystems.
The HAL alt_main() function performs the following steps:
- Initializes interrupts—Sets up interrupt support for the Nios® II processor (with the alt_irq_init() function).
- Starts MicroC/OS-II—Starts the MicroC/OS-II RTOS, if this RTOS is configured to run (with the ALT_OS_INIT and ALT_SEM_CREATE functions). For additional information about MicroC/OS-II use and initialization, refer to “Selecting the Operating System (HAL versus MicroC/OS-II RTOS)”.
-
Initializes device drivers—Initializes device drivers
(with the alt_sys_init() function). The
Nios® II
Software Build Tools automatically find all peripherals supported by the HAL,
and automatically insert a call to a device configuration function for each
peripheral in the alt_sys_init() code. To
override this behavior, you can disable a device driver with the
Nios® II BSP
Editor, in the Drivers tab.
For information about enabling and disabling device drivers, refer to “Using the BSP Editor” in the Getting Started with the Graphical User Interface chapter of the Nios® II Gen2 Software Developer's Handbook.
To disable a driver from the Nios® II Command Shell, use the following option to the nios2-bsp script:
--cmd set_driver <peripheral_name> none
For information about removing a device configuration function, and other methods of reducing the BSP library size, refer to Table 50.
- Configures stdio functions—Initializes stdio services for stdin, stderr, and stdout. These services enable the application to use the GNU newlib stdio functions and maps the file pointers to supported character devices.For more information about configuring the stdio services, refer to “Character Mode Devices”.
-
Initializes C++ CTORS and DTORS—Handles
initialization of C++ constructor and destructor functions. These function calls
are necessary if your application is written in the C++ programming language. By
default, the HAL configuration mechanism enables support for the C++ programming
language. Disabling this feature reduces your application's code footprint, as
noted in “Software Application Optimization”.
The Nios® II C++ language support depends on the GCC tool chain. The Nios® II GCC 4 C++ tool chain supports polymorphism, friendship and inheritance, multiple inheritance, virtual base classes, run-time type information (typeid), the mutable type qualifier, namespaces, templates, new-and-delete style dynamic memory allocation, operator overloading, and the Standard Template Library (STL). Exceptions and new-style dynamic casts are not supported.
-
Calls main()—Calls function main(), or application
program. Most applications are constructed using a main()
function declaration, and begin execution at this function.
If you use a BSP that is not based on the HAL and need to initialize it after the crt0.S routine runs, define your own alt_main() function. For an example, see the main() and alt_main() functions in the hello_alt_main.c file at < Nios® II EDS install dir> \examples\software\hello_alt_main.
After you generate your BSP project, the alt_main.c source file is located in the HAL/src directory.
4.2.3.3. HAL Peripheral Services
The HAL provides your application with a set of services, typically relying on the presence of a hardware peripheral to support the services. By default, if you configure your HAL BSP project from the command-line by running the nios2-bsp script, each peripheral in the system is initialized, operational, and usable as a service at the entry point of your C/C++ application (main()).
This section describes the core set of Intel-supplied, HAL-accessible peripherals and the services they provide for your application. It also describes application design guidelines for using the supplied service, and background and configuration information, where appropriate.
For more information about the HAL peripheral services, refer to the Developing Programs Using the Hardware Abstraction Layer chapter of the Nios II Gen2 Software Developer's Handbook. For more information about HAL BSP configuration settings, refer to the Nios® II Software Build Tools Reference chapter of the Nios® II Gen2 Software Developer's Handbook.
4.2.3.3.1. Timers
The HAL provides two types of timer services, a system clock timer and a timestamp timer. The system clock timer is used to control, monitor, and schedule system events. The timestamp variant is used to make high performance timing measurements. Each of these timer services is assigned to a single Intel Avalon Timer peripheral.
For more information about this peripheral, refer to the Interval Timer Core chapter of the Embedded Peripherals IP User Guide.
System Clock Timer
The system clock timer resource is used to trigger periodic events (alarms), and as a timekeeping device that counts system clock ticks. The system clock timer service requires that a timer peripheral be present in the Platform Designer system. This timer peripheral must be dedicated to the HAL system clock timer service.
The hal.sys_clk_timer setting controls the BSP project configuration for the system clock timer. This setting configures one of the timers available in your Platform Designer design as the system clock timer.
Intel provides separate APIs for application-level system clock functionality and for generating alarms.
Application-level system clock functionality is provided by two separate classes of APIs, one Nios® II specific and the other Unix-like. The Intel function alt_nticks returns the number of clock ticks that have elapsed. You can convert this value to seconds by dividing by the value returned by the alt_ticks_per_second() function. For most embedded applications, this function is sufficient for rudimentary time keeping.
The POSIX-like gettimeofday() function behaves differently in the HAL than on a Unix workstation. On a workstation, with a battery backed-up, real-time clock, this function returns an absolute time value, with the value zero representing 00:00 Coordinated Universal Time (UTC), January 1, 1970, whereas in the HAL, this function returns a time value starting from system power-up. By default, the function assumes system power-up to have occurred on January 1, 1970. Use the settimeofday() function to correct the HAL gettimeofday() response. The times() function exhibits the same behavior difference.
- System Clock Resolution—The timer’s period value specifies the rate at which the HAL BSP project increments the internal variable for the system clock counter. If the system clock increments too slowly for your application, you can decrease the timer's period in Platform Designer.
- Rollover—The internal, global variable that stores the number of system clock counts (since reset) is a 32-bit unsigned integer. No rollover protection is offered for this variable. Therefore, you should calculate when the rollover event occurs in your system, and plan the application accordingly.
- Performance Impact—Every clock tick causes the execution of an interrupt service routine. Executing this routine leads to a minor performance penalty. If your system hardware specifies a short timer period, the cumulative interrupt latency may impact your overall system performance.
The alarm API allows you to schedule events based on the system clock timer, in the same way an alarm clock operates. The API consists of the alt_alarm_start() function, which registers an alarm, and the alt_alarm_stop() function, which disables a registered alarm.
Consider the following common issues and important points before you implement an alarm:
- Interrupt Service Routine (ISR) context—A common mistake is to program the alarm callback function to call a service that depends on interrupts being enabled (such as the printf() function). This mistake causes the system to deadlock, because the alarm callback function occurs in an interrupt context, while interrupts are disabled.
- Resetting the alarm—The callback function can reset the alarm by returning a nonzero value. Internally, the alt_alarm_start() function is called by the callback function with this value.
- Chaining—The alt_alarm_start() function is capable of handling one or more registered events, each with its own callback function and number of system clock ticks to the alarm.
- Rollover—The alarm API handles clock rollover conditions for registered alarms seamlessly.
A good timer period for most embedded systems is 50 ms. This value provides enough resolution for most system events, but does not seriously impact performance nor roll over the system clock counter too quickly.
Timestamp Timer
The timestamp timer service provides applications with an accurate way to measure the duration of an event in the system. The timestamp timer service requires that a timer peripheral be present in the Platform Designer system. This timer peripheral must be dedicated to the HAL timestamp timer service.
Only one timestamp timer service may be identified in the BSP library file. This timer should be accessed only by HAL supplied routines.
The hal.timestamp_timer setting controls the BSP configuration for the timer. This setting configures one of the timers available in the Platform Designer design as the timestamp timer.
Intel provides a timestamp API. The timestamp API is very simple. It includes the alt_timestamp_start() function, which makes the timer operational, and the alt_timestamp() function, which returns the current timer count.
Consider the following common issues and important points before you implement a timestamp timer:
- Timer Frequency—The timestamp timer decrements at the clock rate of the clock that feeds it in the Platform Designer system. You can modify this frequency in Platform Designer.
- Rollover—The timestamp timer has no rollover event. When the alt_timestamp() function returns the value 0, the timer has run down.
- Maximum Time—The timer peripheral has 32 bits available to store the timer value. Therefore, the maximum duration a timestamp timer can count is ((1/timer frequency) × 232) seconds.
For more information about the APIs that control the timestamp and system clock timer services, refer to the HAL API Reference chapter of the Nios® II Gen2 Software Developer's Handbook.
4.2.3.3.2. Character Mode Devices
stdin, stdout, and stderr
The HAL can support the stdio functions provided in the GNU newlib library. Using the stdio library allows you to communicate with your application using functions such as printf() and scanf().
Currently, Intel supplies two system components that can support the stdio library, the UART and JTAG UART components. These devices can function as standard I/O devices.
To enable this functionality, use the --default_stdio <device> option during Nios® II BSP configuration. The stdin character input file variable and the stdout and stderr character output file variables can also be individually configured with the HAL BSP settings hal.stdin, hal.stdout, and hal.stderr.
Make sure that you assign values individually for each of the stdin, stdout, and stderr file variables that you use.
After your target system is configured to use the stdin, stdout, and stderr file variables with either the UART or JTAG UART peripheral, you can communicate with the target Nios® II system with the Nios® II EDS development tools. For more information about performing this task, refer to “Communicating with the Target”.
For more information about the --default_stdio <device> option, refer to “ Nios® II Software Build Tools Utilities” in the Nios® II Software Build Tools Reference chapter of the Nios® II Gen2 Software Developer's Handbook.
Blocking versus Non-Blocking I/O
Character mode devices can be configured to operate in blocking mode or non-blocking mode. The mode is specified in the device’s file descriptor. In blocking mode, a function call to read from the device waits until the device receives new data. In non-blocking mode, the function call to read new data returns immediately and reports whether new data was received. Depending on the function you use to read the file handle, an error code is returned, specifying whether or not new data arrived.
The UART and JTAG UART components are initialized in blocking mode. However, each component can be made non-blocking with the fnctl or the ioctl() function, as seen in the following open system call, which specifies that the device being opened is to function in non-blocking mode:
fd = open ("/dev/<your uart name>", O_NONBLOCK | O_RDWR);
The fnctl() system call shown in the example below specifies that a device that is already open is to function in non-blocking mode:
fnctl() System Call
/* You can specify <file_descriptor> to be * STDIN_FILENO, STDOUT_FILENO, or STDERR_FILENO * if you are using STDIO */ fnctl(<file_descriptor>, F_SETFL, O_NONBLOCK);
Non-Blocking Device Code Fragment
input_chars[128]; return_chars = scanf("%128s", &input_chars); if(return_chars == 0) { if(errno != EWOULDBLOCK) { /* check other errnos */ } } else { /* process received characters */ }
The behavior of the UART and JTAG UART peripherals can also be modified with an ioctl() function call. The ioctl() function supports the following parameters:
- For UART peripherals:
- TIOCMGET (reports baud rate of UART)
- TIOCMSET (sets baud rate of UART)
- For JTAG UART peripherals:
- TIOCSTIMEOUT (timeout value for connecting to workstation)
- TIOCGCONNECTED (find out whether host is connected)
The altera_avalon_uart_driver.enable_ioctl BSP setting enables and disables the ioctl() function for the UART peripherals. The ioctl() function is automatically enabled for the JTAG UART peripherals.
The ioctl() function is not compatible with the altera_avalon_uart_driver.enable_small_driver and hal.enable_reduced_driver BSP settings. If either of these settings is enabled, ioctl() is not implemented.
Adding Your Own Character Mode Device
If you have a custom device capable of character mode operation, you can create a custom device driver that the stdio library functions can use.
For information about how to develop the device driver, refer to AN459: Guidelines for Developing a Nios® II HAL Device Driver.
4.2.3.3.3. Flash Memory Devices
The HAL BSP library supports parallel common flash interface (CFI) memory devices and Intel erasable, programmable, configurable serial (EPCS) flash memory devices. A uniform API is available for both flash memory types, providing read, write, and erase capabilities.
Memory Initialization, Querying, and Device Support
Every flash memory device is queried by the HAL during system initialization to determine the kind of flash memory and the functions that should be used to manage it. This process is automatically performed by the alt_sys_init() function, if the device drivers are not explicitly omitted and the small driver configuration is not set.
After initialization, you can query the flash memory for status information with the alt_flash_get_flash_info() function. This function returns a pointer to an array of flash region structures—C structures of type struct flash_region—and the number of regions on the flash device.
Accessing the Flash Memory
The alt_flash_open() function opens a flash memory device and returns a descriptor for that flash memory device. After you complete reading and writing the flash memory, call the alt_flash_close() function to close it safely.
The HAL flash memory device model provides you with two flash access APIs, one simple and one fine-grained The simple API takes a buffer of data and writes it to the flash memory device, erasing the sectors if necessary. The fine-grained API enables you to manage your flash device on a block-by-block basis.
Both APIs can be used in the system. The type of data you store determines the most useful API for your application. The following general design guidelines help you determine which API to use for your data storage needs:
Simple API—This API is useful for storing arbitrary streams of bytes, if the exact flash sector location is not important. Examples of this type of data are log or data files generated by the system during run-time, which must be accessed later in a continuous stream somewhere in flash memory.
Fine-Grained API—This API is useful for storing units of data, or data sets, which must be aligned on absolute sector boundaries. Examples of this type of data include persistent user configuration values, FPGA hardware images, and application images, which must be stored and accessed in a given flash sector (or sectors).
For examples that demonstrate the use of APIs, refer to the “Using Flash Devices” section in the Developing Programs Using the Hardware Abstraction Layer chapter of the Nios® II Gen2 Software Developer's Handbook.
Configuration and Use Limitations
If you use flash memories in your system, be aware of the following properties of this memory:
- Code Storage—If your application runs code directly from the flash memory, the flash manipulation functions are disabled. This setting prevents the processor from erasing the memory that holds the code it is running. In this case, the symbols ALT_TEXT_DEVICE, ALT_RODATA_DEVICE, and ALT_EXCEPTIONS_DEVICE must all have values different from the flash memory peripheral. (Note that each of these #define symbols names a memory device, not an address within a memory device).
- Small Driver—If the small driver flag is set for the software—the hal.enable_reduced_device_drivers setting is enabled—then the flash memory peripherals are not automatically initialized. In this case, your application must call the initialization routines explicitly.
- Thread safety—Most of the flash access routines are not thread-safe. If you use any of these routines, construct your application so that only one thread in the system accesses these function.
- EPCS flash memory limitations—The Intel EPCS memory has a serial interface. Therefore, it cannot run Nios® II instructions and is not visible to the Nios® II processor as a standard random-access memory device. Use the Intel-supplied flash memory access routines to read data from this device.
- File System—The HAL flash memory API does not support a flash file system in which data can be stored and retrieved using a conventional file handle. However, you can store your data in flash memory before you run your application, using the read-only zip file system and the Nios® II flash programmer utility. For information about the read-only zip file system, refer to “Read-Only Zip File System”.
For more information about the configuration and use limitations of flash memory, refer to the “Using Flash Devices” section in the Developing Programs Using the Hardware Abstraction Layer chapter of the Nios® II Gen2 Software Developer's Handbook. For more information about the API for the flash memory access routines, refer to the HAL API Reference chapter of the Nios® II Gen2 Software Developer’s Handbook.
4.2.3.3.4. Direct Memory Access Devices
The HAL Direct Memory Access (DMA) model uses DMA transmit and receive channels. A DMA operation places a transaction request on a channel. A DMA peripheral can have a transmit channel, a receive channel, or both. This section describes three possible hardware configurations for a DMA peripheral, and shows how to activate each kind of DMA channel using the HAL memory access functions.
The DMA peripherals are initialized by the alt_sys_init() function call, and are automatically enabled by the nios2-bsp script.
DMA Configuration and Use Model
The following examples illustrate use of the DMA transmit and receive channels in a system. The information complements the information available in “Using DMA Devices” in the Developing Programs Using the Hardware Abstraction Layer chapter of the Nios® II Gen2 Software Developer's Handbook.
Regardless of the DMA peripheral connections in the system, initialize a transmit channel by running the alt_dma_txchan_open() function, and initialize a receive DMA channel by running the alt_dma_rxchan_open() function. The following sections describe the use model for some specific cases.
RX-Only DMA Component
A typical RX-only DMA component moves the data it receives from another component to memory. In this case, the receive channel of the DMA peripheral reads continuously from a fixed location in memory, which is the other peripheral's data register. The following sequence of operations directs the DMA peripheral:
- Open the DMA peripheral—Call the alt_dma_rxchan_open() function to open the receive DMA channel.
- Enable DMA ioctl operations—Call the alt_dma_rxchan_ioctl() function to set the ALT_DMA_RX_ONLY_ON flag. Use the ALT_DMA_SET_MODE_<n> flag to set the data width to match that of the other peripheral’s data register.
- Configure the other peripheral to run—The Nios® II processor configures the other peripheral to begin loading new data in its data register.
- Queue the DMA transaction requests—Call the alt_avalon_dma_prepare() function to begin a DMA operation. In the function call, you specify the DMA receive channel, the other peripheral’s data register address, the number of bytes to transfer, and a callback function to run when the transaction is complete.
TX-Only DMA Component
A typical TX-only DMA component moves data from memory to another component. In this case, the transmit channel of the DMA peripheral writes continuously to a fixed location in memory, which is the other peripheral's data register. The following sequence of operations directs the DMA peripheral:
- Open the DMA peripheral—Call the alt_dma_txchan_open() function to open the transmit DMA channel.
- Enable DMA ioctl operations—Call the alt_dma_txchan_ioctl() function to set the ALT_DMA_TX_ONLY_ON flag. Use the ALT_DMA_SET_MODE_<n> flag to set the data width to match that of the other peripheral’s data register.
- Configure the other peripheral to run—The Nios® II processor configures the other peripheral to begin receiving new data in its data register.
- Queue the DMA transaction requests—Call the alt_avalon_dma_send() function to begin a DMA operation. In the function call, you specify the DMA transmit channel, the other peripheral’s data register address, the number of bytes to transfer, and a callback function to run when the transaction is complete.
RX and TX DMA Component
A typical RX and TX DMA component performs memory-to-memory copy operations. The application must open, configure, and assign transaction requests to both DMA channels explicitly. The following sequence of operations directs the DMA peripheral:
- Open the DMA RX channel—Call the alt_dma_rxchan_open() function to open the DMA receive channel.
- Enable DMA RX ioctl operations—Call the alt_dma_rxchan_ioctl() function to set the ALT_DMA_RX_ONLY_OFF flag. Use the ALT_DMA_SET_MODE_<n> flag to set the data width to the correct value for the memory transfers.
- Open the DMA TX channel—Call the alt_dma_txchan_open() function to open the DMA transmit channel.
- Enable DMA TX ioctl operations—Call the alt_dma_txchan_ioctl() function to set the ALT_DMA_TX_ONLY_OFF flag. Use the ALT_DMA_SET_MODE_<n> flag to set the data width to the correct value for the memory transfers.
- Queue the DMA RX transaction requests—Call the alt_avalon_dma_prepare() function to begin a DMA RX operation. In the function call, you specify the DMA receive channel, the address from which to begin reading, the number of bytes to transfer, and a callback function to run when the transaction is complete.
- Queue the DMA TX transaction requests—Call the alt_avalon_dma_send() function to begin a DMA TX operation. In the function call, you specify the DMA transmit channel, the address to which to begin writing, the number of bytes to transfer, and a callback function to run when the transaction is complete.
The DMA peripheral does not begin the transaction until the DMA TX transaction request is issued.
For examples of DMA device use, refer to “Using DMA Devices” in the Developing Programs Using the Hardware Abstraction Layer chapter of the Nios II Gen2 Software Developer's Handbook.
DMA Data-Width Parameter
The DMA data-width parameter is configured in Platform Designer to specify the widths that are supported. In writing the software application, you must specify the width to use for a particular transaction. The width of the data you transfer must match the hardware capability of the component.
Consider the following points about the data-width parameter before you implement a DMA peripheral:
- Peripheral width—When a DMA component moves data from another peripheral, the DMA component must use a single-operation transfer size equal to the width of the peripheral’s data register.
- Transfer length—The byte transfer length specified to the DMA peripheral must be a multiple of the data width specified.
- Odd transfer sizes—If you must transfer an uneven number of bytes between memory and a peripheral using a DMA component, you must divide up your data transfer operation. Implement the longest allowed transfer using the DMA component, and transfer the remaining bytes using the Nios® II processor. For example, if you must transfer 1023 bytes of data from memory to a peripheral with a 32-bit data register, perform 255 32-bit transfers with the DMA and then have the Nios® II processor write the remaining 3 bytes.
Configuration and Use Limitations
If you use DMA components in your system, be aware of the following properties of these components:
-
Hardware configuration—The following aspects of the hardware
configuration of the DMA peripheral determine the HAL service:
- DMA components connected to peripherals other than memory support only half of the HAL API (receive or transmit functionality). The application software should not attempt to call API functions that are not available.
- The hardware parameterization of the DMA component determines the data width of its transfers, a value which the application software must take into account.
- IOCTL control—The DMA ioctl() function call enables the setting of a single flag only. To set multiple flags for a DMA channel, you must call ioctl() multiple times.
- DMA transaction slots—The current driver is limited to four transaction slots. If you must increase the number of transaction slots, you can specify the number of slots using the macro ALT_AVALON_DMA_NSLOTS. The value of this macro must be a power of two.
- Interrupts—The HAL DMA service requires that the DMA peripheral's interrupt line be connected in the system.
- User controlled DMA accesses—If the default HAL DMA access routines are too unwieldy for your application, you can create your own access functions. For information about how to remove the default HAL DMA driver routines, refer to “Reducing Code Size”.
For more information about the HAL API for accessing DMA devices, refer to “Using DMA Devices” in the Developing Programs Using the Hardware Abstraction Layer chapter of the Nios® II Gen2 Software Developer's Handbook and to the HAL API Reference chapter of the Nios® II Gen2 Software Developer's Handbook.
4.2.3.3.5. Files and File Systems
The HAL provides two simple file systems and an API for dealing with file data. The HAL uses the GNU newlib library's file access routines, found in file.h, to provide access to files. In addition, the HAL provides the following file systems:
- Host-based file system—Enables a Nios® II system to access the host workstation's file system
- Read-only zip file system—Enables simple access to preconfigured data in the Nios® II system memory
Several more conventional file systems that support both read and write operations are available through third-party vendors. For up-to-date information about the file system solutions available for the Nios® II processor, visit the Nios II Processor page of the Intel website, and look for Intel FPGA Embedded Alliance.
To make either of these software packages visible to your application, you must enable it in the BSP. You can enable a software package either in the BSP Editor, or from the command line. The names that specify the host-based file system and read-only zip file system packages are altera_hostfs and altera_ro_zipfs, respectively.
The Host-Based File System
The host-based file system enables the Nios® II system to manipulate files on a workstation through a JTAG connection. The API is a transparent way to access data files. The system does not require a physical block device.
Consider the following points about the host-based file system before you use it:
- Communication speed—Reading and writing large files to the Nios® II system using this file system is slow.
- Debug use mode—The host-based file system is only available during debug sessions from the Nios® II debug perspective. Therefore, you should use the host-based file system only during system debugging and prototyping operations.
- Incompatibility with direct drivers—The host-based file system only works if the HAL BSP library is configured with direct driver mode disabled. However, enabling this mode reduces the size of the application image. For more information, refer to “Software Application Optimization”.
For more information about the host file system, refer to “Using File Subsystems” in the Developing Programs Using the Hardware Abstraction Layer chapter of the Nios® II Gen2 Software Developer’s Handbook.
Read-Only Zip File System
The read-only zip file system is a lightweight file system for the Nios® II processor, targeting flash memory.
Consider the following points about the read-only zip file system before you use it:
- Read-Only—The read-only zip file system does not implement writes to the file system.
- Configuring the file system—To create the read-only zip file system you must create a binary file on your workstation and use the Nios® II flash programmer utility to program it in the Nios® II system.
- Incompatibility with direct drivers—The read-only zip file system only works if the HAL BSP library is configured with direct driver mode disabled. However, enabling this mode reduces the size of the application image. For more information, refer to “Software Application Optimization”.
For more information, refer to the Read-Only Zip File System and Developing Programs Using the Hardware Abstraction Layer chapters of the Nios® II Gen2 Software Developer's Handbook. Also the read-only zip file system Nios® II software example design listed in “ Nios® II Design Example Scripts” in the Nios® II Software Build Tools Reference chapter of the Nios® II Gen2 Software Developer’s Handbook.
4.2.3.3.6. Unsupported Devices
The HAL provides a wide variety of native device support for Intel-supplied peripherals. However, your system may require a device or peripheral that Intel does not provide. In this case, one or both of the following two options may be available to you:
- Obtain a device through Intel's third-party program
- Incorporate your own device
Intel's third-party program information is available on the Nios® II embedded software partners page. Refer to the Nios® II Processor page of the Intel website, and look for Intel FPGA Embedded Alliance.
Incorporating your own custom peripheral is a two-stage process. First you must incorporate the peripheral in the hardware, and then you must develop a device driver.
For more information about how to incorporate a new peripheral in the hardware, refer to the Nios® II Hardware Development Tutorial. For more information about how to develop a device driver, refer to the Developing Device Drivers for the Hardware Abstraction Layer chapter of the Nios® II Gen2 Software Developer's Handbook and AN459: Guidelines for Developing a Nios® II HAL Device Driver.
4.2.3.4. Accessing Memory With the Nios II Processor
It can be difficult to create software applications that program the Nios® II processor to interact correctly with data and instruction caches when it reads and writes to peripherals and memories. There are also subtle differences in how the different Nios® II processor cores handle these operations, that can cause problems when you migrate from one Nios® II processor core to another.
This section helps you avoid the most common pitfalls. It provides background critical to understanding how the Nios® II processor reads and writes peripherals and memories, and describes the set of software utilities available to you, as well as providing sets of instructions to help you avoid some of the more common problems in programming these read and write operations.
4.2.3.4.1. Creating General C/C++ Applications
You can write most C/C++ applications without worrying about whether the processor's read and write operations bypass the data cache. However, you do need to make sure the operations do not bypass the data cache in the following cases:
- Your application must guarantee that a read or write transaction actually reaches a peripheral or memory. This guarantee is critical for the correct functioning of a device driver interrupt service routine, for example.
- Your application shares a block of memory with another processor or Avalon interface master peripheral.
4.2.3.4.2. Accessing Peripherals
If your application accesses peripheral registers, or performs only a small set of memory accesses, Intel recommends that you use the default HAL I/O macros, IORD and IOWR. These macros guarantee that the accesses bypass the data cache.
Two types of cache-bypass macros are available. The HAL access routines whose names end in _32DIRECT, _16 DIRECT, and _8 DIRECT interpret the offset as a byte address. The other routines treat this offset as a count to be multiplied by four bytes, the number of bytes in the 32-bit connection between the Nios® II processor and the system interconnect fabric. The _32DIRECT, _16DIRECT, and _8DIRECT routines are designed to access memory regions, and the other routines are designed to access peripheral registers.
The example below shows how to write a series of half-word values into memory. Because the target addresses are not all on a 32-bit boundary, this code sample uses the IOWR_16DIRECT macro.
Writing Half-Word Locations
/* Loop across 100 memory locations, writing 0xdead to */ /* every half word location... */ for(i=0, j=0;i<100;i++, j+=2) { IOWR_16DIRECT(MEM_START, j, (unsigned short)0xdead); }
The example below shows how to access a peripheral register. In this case, the write is to a 32-bit boundary address, and the code sample uses the IOWR macro.
Peripheral Register Access
unsigned int control_reg_val = 0; /* Read current control register value */ control_reg_val = IORD(BAR_BASE_ADDR, CONTROL_REG); /* Enable "start" bit */ control_reg_val |= 0x01; /* Write "start" bit to control register to start peripheral */ IOWR(BAR_BASE_ADDR, CONTROL_REG, control_reg_val);
4.2.3.4.3. Sharing Uncached Memory
If your application must allocate some memory, operate on that memory, and then share the memory region with another peripheral (or processor), use the HAL-supplied alt_uncached_malloc() and alt_uncached_free() functions. Both of these functions operate on pointers to bypass cached memory.
To share uncached memory between a Nios® II processor and a peripheral, perform the following steps:
- malloc memory—Run the alt_uncached_malloc() function to claim a block of memory from the heap. If this operation is successful, the function returns a pointer that bypasses the data cache.
- Operate on memory—Have the Nios® II processor read or write the memory using the pointer. Your application can perform normal pointer-arithmetic operations on this pointer.
- Convert pointer—Run the alt_remap_cached() function to convert the pointer to a memory address that is understood by external peripherals.
- Pass pointer—Pass the converted pointer to the external peripheral to enable it to perform operations on the memory region.
4.2.3.4.4. Sharing Memory With Cache Performance Benefits
Another way to share memory between a data-cache enabled Nios® II processor and other external peripherals safely without sacrificing processor performance is the delayed data-cache flush method. In this method, the Nios® II processor performs operations on memory using standard C or C++ operations until it needs to share this memory with an external peripheral.
To implement delayed data-cache flushing, the application image programs the Nios® II processor to follow these steps:
- Processor operates on memory—The Nios® II processor performs reads and writes to a memory region. These reads and writes are C/C++ pointer or array based accesses or accesses to data structures, variables, or a malloc'ed region of memory.
- Processor flushes cache—After the Nios® II processor completes the read and write operations, it calls the alt_dcache_flush() instruction with the location and length of the memory region to be flushed. The processor can then signal to the other memory master peripheral to operate on this memory.
- Processor operates on memory again—When the other peripheral has completed its operation, the Nios® II processor can operate on the memory once again. Because the data cache was previously flushed, any additional reads or writes update the cache correctly.
The example below shows an implementation of delayed data-cache flushing for memory accesses to a C array of structures. In the example, the Nios® II processor initializes one field of each structure in an array, flushes the data cache, signals to another master that it may use the array, waits for the other master to complete operations on the array, and then sums the values the other master is expected to set.
Data-Cache Flushing With Arrays of Structures
struct input foo[100]; for(i=0;i<100;i++) foo[i].input = i; alt_dcache_flush(&foo, sizeof(struct input)*100); signal_master(&foo); for(i=0;i<100;i++) sum += foo[i].output;
The example below shows an implementation of delayed data-cache flushing for memory accesses to a memory region the Nios® II processor acquired with malloc().
Data-Cache Flushing With Memory Acquired Using malloc()
char * data = (char*)malloc(sizeof(char) * 1000); write_operands(data); alt_dcache_flush(data, sizeof(char) * 1000); signal_master(data); result = read_results(data); free(data);
The alt_dcache_flush_all() function call flushes the entire data cache, but this function is not efficient. Intel recommends that you flush from the cache only the entries for the memory region that you make available to the other master peripheral.
4.2.3.5. Handling Exceptions
The HAL infrastructure provides a robust interrupt handling service routine and an API for exception handling. The Nios® II processor can handle exceptions caused by hardware interrupts, unimplemented instructions, and software traps.
This section discusses exception handling with the Nios® II internal interrupt controller. The Nios® II processor also supports an external interrupt controller (EIC), which you can use to prioritize interrupts and make other performance improvements.
For information about the EIC, refer to the Programming Model chapter of the Nios® II Gen2 Processor Reference Handbook. For information about the exception handler software routines, HAL-provided services, API, and software support for the EIC, refer to the Exception Handling chapter of the Nios® II Gen2 Software Developer's Handbook.
Consider the following common issues and important points before you use the HAL-provided exception handler:
- Prioritization of interrupts—The Nios® II processor does not prioritize its 32 interrupt vectors, but the HAL exception handler assigns higher priority to lower numbered interrupts. You must modify the interrupt request (IRQ) prioritization of your peripherals in Platform Designer.
- Nesting of interrupts—The HAL infrastructure allows interrupts to be nested— higher priority interrupts can preempt processor control from an exception handler that is servicing a lower priority interrupt. However, Intel recommends that you not nest your interrupts because of the associated performance penalty.
- Exception handler environment—When creating your exception handler, you must ensure that the handler does not run interrupt-dependent functions and services, because this can cause deadlock. For example, an exception handler should not call the IRQ-driven version of the printf() function.
- VIC block—Vector interrupt controller block provides an interface to the interrupts in your system. The VIC offers high-performance, low-latency interrupt handling. The VIC prioritizes interrupts in hardware and outputs information about the highest-priority pending interrupt. For more information, refer to the "Vectored Interrupt Controller Core" chapter of the Embedded Peripheral IP User Guide.
4.2.3.6. Modifying the Exception Handler
In some very special cases, you may wish to modify the existing HAL exception handler routine or to insert your own interrupt handler for the Nios® II processor. However, in most cases you need not modify the interrupt handler routines for the Nios® II processor for your software application.
Consider the following common issues and important points before you modify or replace the HAL-provided exception handler:
- Interrupt vector address—The interrupt vector address for each Nios® II processor is set during compilation of the FPGA design. You can modify it during hardware configuration in Platform Designer.
- Modifying the exception handler—The HAL-provided exception handler is fairly robust, reliable, and efficient. Modifying the exception handler could break the HAL-supplied interrupt handling API, and cause problems in the device drivers for other peripherals that use interrupts, such as the UART and the JTAG UART.
You may wish to modify the behavior of the exception handler to increase overall performance. For guidelines for increasing the exception handler’s performance, refer to “Accelerating Interrupt Service Routines”.
4.2.4. Linking Applications
This section discusses how the Nios® II software development tools create a default linker script, what this script does, and how to override its default behavior. The section also includes instructions to control some common linker behavior, and descriptions of the circumstances in which you may need them.
4.2.4.1. Background
When you generate your project, the Nios® II Software Build Tools generate two linker-related files, linker.x and linker.h. linker.x is the linker command file that the generated application's makefile uses to create the .elf binary file. All linker setting modifications you make to the HAL BSP project affect the contents of these two files.
4.2.4.2. Linker Sections and Application Configuration
Every Nios® II application contains .text, .rodata, .rwdata, .bss, .heap, and .stack sections. Additional sections can be added to the .elf file to hold custom code and data.
These sections are placed in named memory regions, defined to correspond with physical memory devices and addresses. By default, these sections are automatically generated by the HAL. However, you can control them for a particular application.
4.2.4.3. HAL Linking Behavior
This section describes the default linking behavior of the BSP generation tools and how to control the linking explicitly.
4.2.4.3.1. Default BSP Linking
During BSP configuration, the tools perform the following steps automatically:
- Assign memory region names—Assign a name to each system memory device, and add each name to the linker file as a memory region.
- Find largest memory—Identify the largest read-and-write memory region in the linker file.
- Assign sections—Place the default sections (.text, .rodata, .rwdata, .bss, .heap, and .stack) in the memory region identified in the previous step.
- Write files—Write the linker.x and linker.h files.
Usually, this section allocation scheme works during the software development process, because the application is guaranteed to function if the memory is large enough.
The rules for the HAL default linking behavior are contained in the Intel-generated Tcl scripts bsp-set-defaults.tcl and bsp-linker-utils.tcl found in the < Nios® II EDS install dir>/sdk2/bin directory. These scripts are called by the nios2-bsp-create-settings configuration application. Do not modify these scripts directly.
4.2.4.3.2. User-Controlled BSP Linking
You can manage the default linking behavior in the Linker Script tab of the Nios® II BSP Editor. You can manipulate the linker script in the following ways:
- Add a memory region—Maps a memory region name to a physical memory device.
- Add a section mapping—Maps a section name to a memory region. The Nios® II BSP Editor allows you to view the memory map before and after making changes.
For more information about the linker-related BSP configuration commands, refer to “Using the BSP Editor” in the Getting Started with the Graphical User Interface chapter of the Nios® II Gen2 Software Developer's Handbook.
4.3. Nios II MPU Usage
The Nios® II MPU Usage section covers the basic features of the Nios® II processor’s optional memory protection unit (MPU), describing how to use it without the support of an operating system (OS). When the Nios® II MPU is enabled and properly configured, it monitors all processor data and instruction accesses and triggers exceptions when illegal accesses are attempted.
Also included are two design examples, with notes about how they work. These examples walk you through making use of the Nios® II processor's MPU in an environment based on the Intel hardware abstraction layer (HAL), without an OS. One of the examples uses the MPU to detect the following three issues commonly seen when debugging embedded systems:
- Stack overflow
- Null pointer
- Wild pointer
After you have studied the code and understand the design examples described in this section, you have the skills to use the Nios® II MPU successfully in your HAL-based design. These examples illustrate the basics of how to use mpubase and mpuacc to configure your MPU prior to enabling it.
4.3.1. Requirements
4.3.2. General Usage
This section describes the process of configuring the Nios® II MPU hardware and writing software to support it.
4.3.2.1. Adding the MPU Hardware
To add an MPU to your system, you must use a Nios® II/f core. In Platform Designer, enable the MPU by turning on Include MPU in the Core Nios® II tab of the Nios® II parameter editor interface, as shown in below.

Use the MMU and MPU Settings tab, as shown below, to configure the MPU.

Option | Allowed Values | Default Value |
---|---|---|
Use Limit for Region Range | Off or On | Off |
Number of Data Regions | 2—32 | 8 |
Minimum Data Region Size | 256 bytes—1 MB | 4 KB |
Number of Instruction Regions | 2—32 | 8 |
Minimum Instruction Region Size | 256 bytes—1 MB | 4 KB |
You can configure the MPU to define the size of its memory regions in either of the following ways:
- Define region size by specifying an address mask
- Define region size by specifying the end address
By default, the MPU defines region sizes with an address mask. To define region sizes with an end address, turn on Use Limit for Region Range. For detailed information about the two methods of specifying region size, refer to “MPU Register Details” section.
The minimum region size is crucial to understanding MPU run-time configuration. The minimum region size, <min_region>, specifies the granularity of the MPU memory map. The size of any particular memory region must be an integer multiple of <min_region>.
Most of the MPU parameters controlled by software are based on the minimum region size. You can specify separate values of <min_region> for data and instruction regions.
4.3.2.2. Writing Software for the MPU
This section describes the process of writing software to configure and manage the Nios® II MPU.
4.3.2.2.1. MPU Programming Guidelines
Software is responsible for enabling and configuring the MPU as well as maintaining MPU region information. In a single-threaded operating environment (such as the Intel FPGA HAL), use a global data structure to store the MPU region information.
The Nios® II MPU must be disabled before software attempts to configure it.
Software normally initializes the MPU after reset. If it is necessary to change MPU regions or region permissions after reset, software also reinitializes the MPU.
Every region supported by the MPU must be either configured or disabled before allowing application code to execute. Leaving a region enabled and unconfigured results in undefined behavior. For details about how to disable an MPU region, refer to “Defining Regions with mpubase and mpuacc” section.
Depending on the complexity of your software, you might need to define several MPU configurations, each with a different set of regions or region permissions. This technique is typically used by an operating system. For details, refer to “Operating Systems and the MPU” section.
4.3.2.2.2. Operating Systems and the MPU
Even if you are not using an operating system, it is helpful to understand the techniques that an OS uses to manage an MPU.
When an operating system uses an MPU, it typically defines two or more MPU configurations. One configuration defines the permissions that the MPU applies to operating system or kernel level accesses. One or more configurations define the permissions available to user or application processes. The OS might also define additional configurations for non-user purposes. For example, there might be a special factory task that can modify system-critical information like product serial numbers or media access control (MAC) addresses in flash or other nonvolatile memory. Such a task is likely to need a special set of memory and device permissions.
The operating system disables the MPU, reconfigures it, and then re-enables it whenever the processor needs to run in a different MPU configuration. For example, the OS might need to change MPU configurations upon the following types of events:
- Exception
- Return from exception
- Operating system call
- Return from operating system call
The exact circumstances under which MPU reconfiguration is required depends on the OS implementation and settings.
4.3.2.2.3. MPU Register Details
This section describes the register maps, the meanings of the register fields, and how the register fields are used.
When you initialize the MPU you use two registers: mpubase and mpuacc.
Register mpubase Usage
Bit Fields | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
BASE3 | |||||||||||||||
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
BASE3 | 0 | INDEX2 | D |
Field | Description | Access | Reset | Available |
---|---|---|---|---|
BASE | BASE is the base memory address of the region identified by the INDEX and D fields. | Read/Write | 0 | Only with MPU |
INDEX | INDEX is the region index number. | Read/Write | 0 | Only with MPU |
D | D is the region access bit. When D =1, INDEX refers to a data region. When D = 0, INDEX refers to an instruction region. | Read/Write | 0 | Only with MPU |
You specify an MPU region by writing a value representing the region's base address to the BASE field, a unique index to the INDEX field, and the region type (data or instruction) to field D.
The BASE field represents the region's base address, in the form described by the equation below. The BASE field can only represent addresses aligned to an integer multiple of <min_region>. For example, if the minimum region size is 16 kilobytes (KB), regions can be located at addresses such as 0x0, 0x4000, 0x8000, ... .
BASE = <base address>/<min_region>
For example, if the region starts at 0x1000 and the minimum region size is 256 bytes, set the BASE field to 0x10, which is 0x1000/256.
The INDEX field provides a unique identifier for the region. INDEX also specifies the priority of the region. The lower the index value, the higher the region’s priority.
Use the D field to specify the region type: data or instruction.
Register mpuacc Usage
mpuacc has two possible layouts, depending on the Platform Designer generation-time option Use limit for region range, as described in Adding the MPU Hardware section. This option controls whether the mpuacc register contains a MASK or LIMIT field. The table below shows the layout of the mpuacc register with the MASK field.
Bit Fields | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
MASK[n-1:p]4 | |||||||||||||||
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
MASK[n-1:p]4 | 0 | MT | PERM | RD | WR |
Bit Fields | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
LIMIT[n:p]4 | |||||||||||||||
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
LIMIT[n:p]4 | 0 | MT | PERM | RD | WR |
Field | Description | Access | Reset | Available |
---|---|---|---|---|
MASK | MASK specifies the size of the region. | Read/Write | 0 | Only with MPU |
LIMIT | LIMIT specifies the upper address limit of the region. | Read/Write | 0 | Only with MPU |
MT | (MT) Memory Type:
|
Read/Write | 0 | Only with MPU |
PERM | PERM specifies the access permissions for the region. | Read/Write | 0 | Only with MPU |
RD | RD is the read region flag. When RD = 1, wrctl instructions to the mpuacc register perform a read operation. | Write | 0 | Only with MPU |
WR | WR is the write region flag. When WR = 1, wrctl instructions to the mpuacc register perform a write operation. | Write | 0 | Only with MPU |
If the mpuacc register is configured with the MASK field, the MASK field represents the size of your region. The value of MASK is defined in the equation below.
MASK = 0xFFFFFF << log2 ( <region_size> >> 8 )
The table below lists every possible MASK value for an MPU configured with a256-byte minimum region size.
MASK Encoding | Region Size |
---|---|
0xFFFFFF | 256 bytes |
0xFFFFFE | 512 bytes |
0xFFFFFC | 1 KB |
0xFFFFF8 | 2 KB |
0xFFFFF0 | 4 KB |
0xFFFFE0 | 8 KB |
0xFFFFC0 | 16 KB |
0xFFFF80 | 32 KB |
0xFFFF00 | 64 KB |
0xFFFE00 | 128 KB |
0xFFFC00 | 256 KB |
0xFFF800 | 512 KB |
0xFFF000 | 1 MB |
0xFFE000 | 2 MB |
0xFFC000 | 4 MB |
0xFF8000 | 8 MB |
0xFF0000 | 16 MB |
0xFE0000 | 32 MB |
0xFC0000 | 64 MB |
0xF80000 | 128 MB |
0xF00000 | 256 MB |
0xE00000 | 512 MB |
0xC00000 | 1 GB |
0x800000 | 2 GB |
0x000000 | 4 GB |
If the mpuacc register is configured with the LIMIT field, LIMIT represents the address immediately following the upper end of your region. For example, suppose the MPU’s minimum region size is 256 bytes, and you need to set up the following region:
- The region starts at 0x1000
- The region ends at 0x1FFF
To set up the desired region, configure mpubase.BASE and mpuacc.LIMIT as shown in the following list:
- Set mpubase.BASE to 0x10, which is 0x1000/256 or (0x1000 >> 8)
- Set mpuacc.LIMIT to 0x20, which is 0x2000/256 or (0x2000 >> 8)
Use the C field to specify whether a data region is to be cached. Usually, you set C for memory regions and clear it for regions representing registers or general-purpose memory-mapped I/O.
The PERM field defines the permissions for the region, as shown in the two tables below.
PERM Encoding | Supervisor Permissions | User Permissions |
---|---|---|
000 | None | None |
001 | Execute | None |
010 | Execute | Execute |
PERM Encoding | Supervisor Permissions | User Permissions |
---|---|---|
000 | None | None |
001 | Read | None |
010 | Read | Read |
100 | Read/Write | None |
101 | Read/Write | Read |
110 | Read/Write | Read/Write |
Defining Regions with mpubase and mpuacc
The mpubase register works in conjunction with the mpuacc register to set and retrieve MPU region information. Use the RD and WR fields of mpuacc to instruct the MPU to perform an MPU region read or write, as shown in the following list:
- Set mpuacc.RD = 1 to perform an MPU region read operation.
- Set mpuacc.WR = 1 to perform an MPU region write operation.
An MPU region must be disabled if it is not in use. To disable a region, software sets up the following conditions:
- mpubase.BASE is any nonzero value.
- If the MPU is configured to define region size by mask, mpuacc.MASK represents 0x100000000, which is 232 (the size of the Nios® II address space). For example, if the minimum region size is 256, or 0x100 bytes, mpuacc.MASK is 0x100000000 / 0x100, or 0x10000000.
- If the MPU is configured to define region size by limit, mpuacc.LIMIT = 0.
4.3.2.2.4. Flow Summary
In a Nios® II system with an MPU, whenever MPU initialization or reinitialization is required, the software is responsible for the following tasks:
-
Ensure that the MPU is disabled.
Note: At system reset, the MPU is disabled by default. At other times, software must disable the MPU before reconfiguring regions.
- Initialize and configure the MPU with region information.
- Enable the MPU prior to executing task-specific or single-threaded application code.
4.3.3. Nios II MPU Design Examples
The design examples accompanying this section illustrate the use of the Nios® II MPU in a single-threaded environment, such as the Intel FPGA HAL.
This design example is based on Nios® II classic processor. For more information about MPU register, refer to Nios II Classic Processor Reference Guide.
4.3.3.1. Working with the MPU Design Examples
- The
Nios® II Embedded Evaluation Kit
(NEEK), Cyclone® III EditionNote: The NEEK is no longer available. However, the design examples use only on-chip hardware resources. Therefore, it is easy to port the designs to a different hardware platform.
- Quartus® software version 9.1.
You also need the following:
- Nios® II Embedded Design Suite (EDS).
- The design example archive file, an540_91.zip .
Unzip an540_91.zip to a working directory on your computer. We refer to this directory throughout this section as <design examples>. Be sure to preserve the directory structure of the extracted software archive. Extraction creates a directory structure tree under <design examples> with the following subdirectories:
- MPU_Design_limit/software_examples/app/mpu_basic
- MPU_Design_limit/software_examples/app/mpu_exc_detection
- MPU_Design_limit/software_examples/bsp/mpu_example_bsp
- MPU_Design_msk/software_examples/app/mpu_basic
- MPU_Design_msk/software_examples/app/mpu_exc_detection
- MPU_Design_msk/software_examples/bsp/mpu_example_bsp
4.3.3.2. Example Hardware
The simple hardware designs, emphasizing MPU usage, are easily portable to other hardware platforms. There are two design examples, both targeting the NEEK. In one, the MPU specifies region sizes by mask, and in the other the MPU specifies region sizes by limit. Aside from this detail of MPU instantiation, the two designs are identical.
The address map is designed to make MPU configuration very straightforward. For instance, the instr_ram and stack_ram memories reside on valid region boundaries, and the JTAG UART base address is unique and aligned to a valid region boundary, as illustrated in Figure 40.
The figure below illustrates one of the design examples as it appears in Platform Designer. The hardware addresses fall on valid MPU region boundaries. While this constraint is not required, it is more convenient for the software engineer.

4.3.3.3. Region Layout Considerations
This section describes how to select MPU region locations and sizes to make the most effective use of the MPU. For information about the mechanics of setting up MPU regions, refer to “MPU Register Details” section.
Each region size must be an integer power of two. You must ensure that each region is aligned to an address that is an integer multiple of its size.

A low-priority exclusion region spans the entire 2 GB address space from 0x0 to 0x80000000.
Regions can overlap. For example, you can place a higher-priority region inside a lower-priority region. region[3] in mpu_utils.c illustrates this technique, creating a small exclusion region from 0x21000 to 0x21040, as shown in Figure 3. Any access to addresses in the 0x21000 to 0x21040 range is controlled by the exclusion region rather than the stack_ram region (region[4]), because the exclusion region has the higher priority.

A low-priority exclusion region spans the entire 2 GB address space from 0x0 to 0x80000000.
4.3.3.4. Software
The design files accompanying this section include the following example software projects:
- mpu_basic—Configures the MPU with several data and instruction regions, and prints a simple message.
-
mpu_exc_detection—Configures the MPU with the same data instruction
regions as in mpu_basic, and sets up an exception handler to detect the
following conditions:
- Null pointer
- Wild pointer
- Stack overflow
The software examples in each subdirectory are identical. The code is written to detect the whether the MPU is configured for mask or limit region sizes, and to behave appropriately.
The mpu_exc_detection example detects stack overflow by creating a small high-priority exclusion data region in the middle of a larger data region where both the stack and the heap reside. Whenever the stack grows downwards or the heap grows upwards into this exclusion region, the MPU triggers an exception and the software detects it.
The mpu_exc_detection example detects null pointer usage by making sure that no regions include offset 0x0. The example system is designed such that no components (memory or otherwise) are located at this offset. If software attempts to access address 0x0, the MPU triggers an exception, allowing the software to recover. If you ensure that memories are preinitialized to zero, null pointer detection helps protects against uninitialized data access.
The mpu_exc_detection example detects wild pointer usage by creating very large low-priority exclusion regions covering the majority of the memory map. In this way, if the Nios® II processor attempts to access an address outside of valid memory and peripheral I/O address space, the MPU triggers an exception and software can detect it.
Both of these software examples use the MPU utility functions and macros in mpu_utils.c and mpu_utils.h. In both examples, initialization and reinitialization are handled by two functions: one for data regions, and one for instruction regions. In most real-world systems, a single function is sufficient to handle initialization and reinitialization for both types of regions.
4.3.3.4.1. MPU Utilities
You can find helpful MPU utility functions and macros in the mpu_utils.c and mpu_utils.h files in each software example. The following functions are the most important for you to understand:
- nios2_mpu_data_init()—A system-specific function. In your own code, write an equivalent function to specify the MPU data regions in your design.
- nios2_mpu_inst_init()—A system-specific function. In your own code, write an equivalent function to specify the MPU instruction regions in your design.
- nios2_mpu_load_region()—Configures an MPU region with specific parameters.
- nios2_mpu_enable()—Enables the entire MPU.
- nios2_mpu_disable()—Disables the entire MPU.
Each utility function makes use of the Nios2MPURegion data structure shown in the example below.
Nios2MPURegion Data Structure
typedef struct { unsigned int base; unsigned int index; unsigned int mask; unsigned int c; unsigned int perm; } Nios2MPURegion;
The example below shows nios2_mpu_inst_init() for the mpu_basic software example. The constants NIOS2_MPU_NUM_INST_REGIONS and NIOS2_MPU_REGION_USES_LIMIT are defined in system.h.
In nios2_mpu_inst_init() in the mpu_basic Software Example, region[0] grants execution access to the instr_ram memory in both user and supervisor modes, as shown in Figure 41. region[1] grants execution access to the break and trace memory (starting at 0x1000) in both modes. The other two MPU instruction regions grant no execution permissions to the entire Nios® II address space. Because their priorities, 2 and 3, are lower than the first two regions, the code stored in the instr_ram runs, and the break and trace features work correctly. However, if code attempts to execute outside those regions, the MPU triggers an exception.
The final statement in nios2_mpu_inst_init() calls nios2_mpu_load_region() to configure the region with the information contained in the structure.
nios2_mpu_inst_init() in the mpu_basic Software Example
void nios2_mpu_inst_init() { unsigned int mask; Nios2MPURegion region[NIOS2_MPU_NUM_INST_REGIONS]; //Main instruction region. region[0].index = 0; region[0].base = 0x400; // Byte Address 0x10000 #ifdef NIOS2_MPU_REGION_USES_LIMIT region[0].mask = 0x500; // Byte Address 0x14000 #else region[0].mask = 0x1ffff00; #endif region[0].c = 1; region[0].perm = MPU_INST_PERM_SUPER_EXEC_USER_EXEC; //Instruction region for break address. region[1].index = 1; region[1].base = 0x40; // Byte Address 0x1000 #ifdef NIOS2_MPU_REGION_USES_LIMIT region[1].mask = 0x60; // Byte Address 0x1800 #else region[1].mask = 0x1ffffe0; #endif region[1].c = 1; region[1].perm = MPU_INST_PERM_SUPER_EXEC_USER_EXEC; //Rest of the regions are maximally sized and permissive. #ifdef NIOS2_MPU_REGION_USES_LIMIT mask = 0x2000000; #else mask = 0x0; #endif unsigned int num_of_region = NIOS2_MPU_NUM_INST_REGIONS; unsigned int index; for (index = 2; index < num_of_region; index++){ region[index].base = 0x0; region[index].index = index; region[index].mask = mask; region[index].c = 0; region[index].perm = MPU_INST_PERM_SUPER_NONE_USER_NONE; } nios2_mpu_load_region(region, num_of_region, 0); }
The example below shows the function prototype for nios2_mpu_load_region().
nios2_mpu_load_region()
void nios2_mpu_load_region ( Nios2MPURegion region[], unsigned int num_of_region, unsigned int d);
- Nios2MPURegion—An array of data structures, each representing an MPU region
- num_of_region—The number of regions
- d—The region type (instruction or data)
nios2_mpu_load_region() configures the MPU according to the arguments passed by the calling function.
The MPU is disabled by default at system restart. After the MPU is configured, the example uses nios2_mpu_enable() and nios2_mpu_disable() to enable and disable the MPU. Whenever you reconfigure the MPU, you must first disable it, and re-enable it after configuring.
The software examples accompanying this section are commented to help you understand how each example works. Most of the complexity of managing the MPU and its regions is embodied in the MPU utility functions and macros in mpu_utils.c and mpu_utils.h, allowing you to focus on the top-level software flow.
4.3.3.4.2. Building the Software
To create and build a software example, execute the following steps:
- Identify the directory containing the software example that you want to run, based on the hardware example that you want to use. For example, to run the mpu_basic software example on the MPU_Design_limit hardware design example, the directory is <design examples> /MPU_Design_limit/software_examples/app/ mpu_basic.
-
Use one of the following methods to open the
Nios® II Command Shell: