13. Simulate and implement SoPC design

13.1. Introduction

In this tutorial, we will learn to design embedded system on FPGA board using Nios-II processor, which is often known as ‘System on Programmable chip (SoPC)’. Before beginning the SoPC design, let’s understand the difference between ‘computer system’, ‘embedded system’ and ‘SoPC system’. Computer systems, e.g. personal computers (PCs), support various end user applications. Selection of these computer systems for few specific applications, e.g. timers settings, displays and buzzers in microwave-ovens or washing machines etc., is not a cost effective choice. The Embedded systems are cost effective solution for such cases, where only few functionalities are required in the system. Since, embedded systems are designed for specific tasks, therefore the designs can be optimized based on the applications. Further, SoPC systems are the programmable embedded systems i.e. we can design the embedded systems using VHDL/Verilog codes and implement them on the FPGA board.

Nios II is a 32-bit embedded-processor architecture designed for Altera-FPGA board. In Fig. 13.1, various steps are shown to design the SoPC system on the FPGA board using Nios-II processor. In this chapter, these steps are discussed and a system is designed which displays the message on the computer and blinks one LED using FPGA board. Further, the outputs of this system is verified using Modelsim. It is recommended to read first two chapters before practicing the codes, as various issues related to the use of Nios software are discussed in these chapters.

../_images/NIOSFlowChart.jpg

Fig. 13.1 Flow chart for creating the embedded system

Note

Note that, the NIOS-projects can not be run directly on the system, after downloading it from the website; therefore only ‘necessary files are provided on the website. Please see Appendix 17 to compile and synthesize the provided codes.

Note

Also, if you change the location of the project in your system (after creating it) or change the FPGA-board, then you need to follow the instructions in the Appendix 17 again.

13.2. Creating Quartus project

First, we need to create the project at desired location, with following steps,

  • Path to project directory should not contain any spaces in the names of folder as shown in Fig. 13.2, as path will not be detected by the Nios-II software in later part of the tutorial.
../_images/createProject.jpg

Fig. 13.2 Create project

  • Choose the correct FPGA device as shown in Fig. 13.3. If you do not have any, then select correct device family and use it for rest of the tutorial. Note that, ‘simulation’ is the most important process of the design, and FPGA board is not required for creating and simulating the embedded design. Hence, if you don’t have FPGA board, you can still use the tutorial. Implementation of the design on the FPGA board requires the loading the ‘.sof’ and ‘.elf’ files on the board, which is not a big deal.
../_images/createProjectPage3.jpg

Fig. 13.3 Select FPGA device

  • Lastly, choose the correct simulation-software and language i.e. Modelsim-Altera and Verilog respectively as shown in Fig. 13.4.
../_images/createProjectPage4.jpg

Fig. 13.4 Select simulation software

13.3. Create custom peripherals

We can create peripheral devices e.g. adder, divider or clock generator using Verilog. Then these devices can be used in creating the SoPC using Nios-II software as discussed in Section 13.4. For simplicity of the tutorial, only predefined-peripherals are used in the designs, which are available in Nios-II software. Creating and using the custom-peripherals will be discussed in later chapters.

13.4. Create and Generate SoPC using Qsys

SoPC can be created using two tools in Quartus software i.e. ‘SOPC builder’ and ‘Qsys’ tools. Since Qsys is the recommended tool by the Altera, therefore we will use this tool for generating the SoPC system. To open the Qsys tool, go to Tools–>Qsys in Quartus software. Next, follow the below steps to create the SoPC system,

  • Rename ‘clk_0’ to ‘clk’ by right clicking the name (optional step). Note that, renaming steps are optional; but assigning appropriate names to the components is good practice as we need to identify these components in later tutorial.
  • In component library, search for Nios processor as shown in Fig. 13.5 and select the Nios II/e (i.e. economy version) for this tutorial. Note that various errors are displayed in the figure, which will be removed in later part of this section. Next, rename the processor to ‘nios_blinkingLED’ and connect the clock and reset port to ‘clk’ device, by clicking on the circles as shown in Fig. 13.6.
../_images/AddNiosProcessor.jpg

Fig. 13.5 Add Nios processor

../_images/ConnectClock.jpg

Fig. 13.6 Rename Nios processor and connect the ports

  • Next add the ‘onchip memory’ to the system with 20480 (i.e. 20k) bytes as shown in Fig. 13.7 and rename it to RAM. For different FPGA boards, we may need to reduce the memory size, if the ‘memory-overflow’ error is displayed during ‘generation’ process in Fig. 13.14.
../_images/onchipMemory.jpg

Fig. 13.7 Add onchip memory to the system

  • After that, search for ‘JTAG UART’ and add it with default settings. It is used for the communication of the FPGA device to Nios software. More specifically, it is required display the outputs of the ‘printf’ commands on the Nios software.
  • Next, add a PIO device for blinking the LED. Search for PIO device and add it as ‘1 bit’ PIO device (see Fig. 13.8), because we will use only one blinking LED. Since, the PIO device, i.e. ‘LED’, is available as external port, therefore name of the ‘external_connection’ must be defined as shown in Fig. 13.9.
../_images/PIO.jpg

Fig. 13.8 Add 1 bit PIO for one blinking LED

../_images/LEDsettings.jpg

Fig. 13.9 Settings for PIO and other device

  • Then, add all the connections as shown in the Fig. 13.9. Also, add the JTAG slave to the data master of Nios processors i.e. IRQ in Fig. 13.10
../_images/interupt.jpg

Fig. 13.10 Connect IRQ

  • Next, double click on the to the Nios processor i.e. ‘nios_blinkingLED’ in the Fig. 13.9; and set RAM as reset and exception vectors as shown in Fig. 13.11.
../_images/NiosRam.jpg

Fig. 13.11 Setting Reset and Exception vector for Nios processor

  • Then, go to Systems–>Assign Base Address. This will assign the unique addresses for all the devices. With the help of these address, the devices can be accessed by C/C++ codes in Nios-II software. If everything is correct till this point, we will get the ‘0 Errors, 0 Warnings’ message as shown in Fig. 13.12.
../_images/CompleteNIOS.jpg

Fig. 13.12 0 errors and 0 warnings

  • Finally, to allow the simulation of the designs, go to ‘generation’ tab and set the tab as shown in the Fig. 13.13. Note that, VHDL can not be used as simulation language, as this version of Quartus does not support it. Since, generated verilog files are used for the simulation settings settings only, therefore we need not to look at these files. Hence it does not matter, whether these files are created using VHDL or Verilog.
../_images/simulationQsys.jpg

Fig. 13.13 Simulation settings

  • Save the system with desired name e.g. ‘nios_blinkingLED.qsys’ and click on generate button. If system is generated successfully, we will get the message as shown in Fig. 13.14
../_images/SystemGeneated.jpg

Fig. 13.14 System generated successfully

  • After this process, a ‘nios_blinkingLED.sopcinfo’ file will be generated, which is used by Nios-II software to create the embedded design. This file contains all the information about the components along with their base addresses etc. Further, two more folders will be created inside the ‘nios_blinkingLED’ folder i.e. ‘synthesis’ and ‘testbench’. These folders are generated as we select the ‘synthesis’ and ‘simulation’ options in Fig. 13.13, and contains various information about synthesis (e.g. ‘nios_blinkingLED.qip’ file) and simulation (e.g. ‘nios_blinkingLED_tb.qsys’ file). The ‘nios_blinkingLED.qip’ file will be used for the creating the top module for the design i.e. LEDs will be connected to FPGA board using this file; whereas ‘nios_blinkingLED_tb.qsys’ contains the information about simulation waveforms for the testbenches. Lastly, ‘nios_blinkingLED_tb.spd’ is generated which is used by Nios software to start the simulation process.
  • In this way, SoPC system can be generated. Finally, close the Qsys tool. In next section, Nios software will be used to create the blinking-LED system using ‘nios_blinkingLED.sopcinfo’ file.

13.5. Create Nios system

In previous section, we have created the SoPC system and corresponding .sopcinfo file was generated. In this section, we will use the .sopcinfo file to create a system with blinking LED functionality.

To open the Nios software from Quarturs software, click on Tools–>Nios II software Build Tools for Eclipse. If you are using it first time, then it will ask for work space location; you can select any location for this.

13.6. Add and Modify BSP

To use the .sopcinfo file, we need to create a ‘board support package (BSP)’. Further, BSP should be modify for simulation purpose, as discussed in this section.

13.6.1. Add BSP

To add BSP, go to File–>New–>Nios II Board Support Package. Fill the project name field and select the .sopcinfo file as shown in Fig. 13.15. Rest of the field will be filled automatically.

../_images/CreateBSP.jpg

Fig. 13.15 Add board support package (BSP)

After clicking on finish, BSP_blinkingLED folder will be created which contains various files e.g. system.h, io.h and drivers etc. These files are generated based on the information in the .sopcfile e.g. in Fig. 13.16, which shows the partial view of system.h file, contains the information about LED along with the base address (note that, this LED was added along with base address in Section 13.4). Note that, address location is defined as ‘LED_BASE’ in the system.h file; and we will use this name in the tutorial instead of using the actual base address. In this way, we need not to modify the ‘C/C++’ codes, when the base address of the LED is changed during Qsys modification process.

../_images/systemH.jpg

Fig. 13.16 system.h file

13.6.2. Modify BSP (required for using onchip memory)

Note

Some modifications are required in the BSP file for using onchip memory (due to it’s smaller size). Also, due to smaller size of onchip memory, C++ codes can not be used for NIOS design. Further, these settings are not required for the cases where external RAM is used for memory e.g. SDRAM (discussed in Chapter 15); and after adding external RAM, we can use C++ code for NIOS design as well.

To modify the BSP, right click on ‘BSP_blinkingLED’ and then click on Nios II–>BSP Editor. Then select the ‘enable_reduce_device_drivers’ and ‘enable_small_c_library’ as shown in Fig. 13.17; then click on the ‘generate’ button to apply the modifications.

../_images/modifyBSP.jpg

Fig. 13.17 Modify BSP

13.7. Create application using C/C++

In previous section, various information are generated by BSP based to .sopcinfo file. In this section, we will write the ‘C’ application to blink the LED. Further, we can write the code using C++ as well.

To create the application, go to File–>New–>Nios II Application. Fill the application name i.e. ‘Application_blinkingLED’ and select the BSP location as shown in Fig. 13.18.

To create the C application, right click on the ‘Application_blinkingLED’ and go to New–>Source File. Write the name of source file as ‘main.c’ and select the ‘Default C source template’.

../_images/createApplication.jpg

Fig. 13.18 Create Application

Next, write the code in ‘main.c’ file as shown in Listing 13.1. After writing the code, right click on the ‘Application_blinkingLED’ and click on ‘build project’.

Explanation Listing 13.1

The ‘io.h’ file at Line 2, contains various functions for operations on input/output ports e.g. IOWR(base, offset, data) at Line 15 is define in it. Next, IOWR uses three parameter i.e. base, offset and data which are set to ‘LED_BASE’, ‘0’ and ‘led_pattern’ respectively at Line 15. ‘LED_BASE’ contains the based address, which is defined in ‘system.h’ file at Line 4 (see Fig. 13.16 as well). Lastly, ‘alt_u8’ is the custom data-type (i.e. unsigned 8-bit integer), which is used at line 7 and defined in ‘alt_types.h’ at Line 3. It is required because, for predefined C data types e.g. int and long etc. the size of the data type is defined by the compiler; but using ‘alt_types.h’ we can define the exact size for the data.

Since ‘alt_u8’ is 8 bit wide, therefore led_pattern is initialized as ‘0$times$01’ (i.e. 0000-0001) at Line 7. Then this value is inverted at Line 14 (for blinking LED). Lastly, this pattern is written on the LED address at Line 15. Second parameter, i.e. offset is set to 0, because we want to write the pattern on LED_BASE (not to other location with respect of LED_BASE). Also, dummy loop is used at Line 19 is commented, which will be required for visual verification of the blinking LED in Section 13.11.

Listing 13.1 Blinking LED with C application
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
//main.c
#include "io.h"  // required for IOWR
#include "alt_types.h" // required for alt_u8
#include "system.h"  // contains address of LED_BASE

int main(){
    alt_u8 led_pattern = 0x01; // on the LED

    //uncomment below line for visual verification of blinking LED
    //int i, itr=250000;

    printf("Blinking LED\n");
    while(1){
        led_pattern = ~led_pattern; // not the led_pattern
        IOWR(LED_BASE, 0, led_pattern); // write the led_pattern on LED

        //uncomment 'for loop' in below line for visual verification of blinking LED
        // dummy for loop to add delay in blinking, so that we can see the bliking.
        //for (i=0; i<itr; i ++){}
  }
}

13.8. Simulate the Nios application

In previous section, we built the Nios application. To simulate this system, right click on ‘Application_blinkingLED’ and go to Run as–>NOIS II Modelsim. Then select the location of Modelsim software i.e. ‘win32aloem’ or ‘win64aloem’ folder as shown in Fig. 13.19; this can be found inside the folders where Altera software is installed.

../_images/ModelsimLocation.jpg

Fig. 13.19 Search for Modelsim location

Next, click on the advance button in Fig. 13.19 and a new window will pop-up. Fill the project location as shown in Fig. 13.20 and close the pop-up window. This location contains the ‘.spd’ file, which is required for simulation.

../_images/ProjectLocationSImulation.jpg

Fig. 13.20 Search for Project Location

After above step, ‘Qsys testbench simulation package descriptor file name’ column will be filled with ‘.spd’ file automatically as shown in Fig. 13.21. If not, do it manually by searching the file, which is available in the project folder. If everything is correct, then apply and run buttons will be activated. Click on apply and then run button to start the simulation.

../_images/RunSimulation.jpg

Fig. 13.21 Run simulation

Modelsim window will pop-up after clicking the run button, which will display all the external ports as shown in Fig. 13.22. Right click on the external signals and click on ‘add to wave’. Next go to transcript section at the bottom of the modelsim and type ‘run 3 ms’. The simulator will be run for 3 ms and we will get outputs as shown in Fig. 13.23. In the figure, there are 3 signals i.e. clock, reset and LED, where last waveform i.e. ‘nios_blinkingled_inst_led_external_connection_export’ is the output waveform, which will be displayed on the LEDs.

../_images/modelsimPopUp.jpg

Fig. 13.22 Modelsim window

../_images/modelsimOutputs.jpg

Fig. 13.23 Blinking LED simulation waveform

13.9. Adding the top level Verilog design

In last section, we designed the Nios system for blinking LED and tested it in modelsim. Now, next task is to implement this design on FPGA board. For this we, need to add a top level design, which connects all the input and output ports on the FPGA. Here, we have only three ports i.e. clock, reset and LEDs.

First add the design generated by the Qsys system to the project. For this, we need to add the ‘.qip’ file into the project. This file can be found in ‘synthesis folder as shown in Fig. 13.24.

../_images/AddQip.jpg

Fig. 13.24 Adding .qip file (available in synthesis folder)

Next, we need to add a new Verilog file for port mapping. For this, create a new Verilog file with name ‘blinkingLED_VisualTest.vhd’ as shown in Listing 13.2. Then set it as ‘top level entity’ by right clicking it. Further, this declaration and port map code can be copied from Qsys software as well, which is available on ‘HDL example’ tab as shown in Fig. 13.25.

../_images/qsysCode.jpg

Fig. 13.25 Copy port mapping code from Qsys

13.10. Load the Quartus design (i.e. .sof/.pof file)

Before loading the desing on FPGA board, import the pin assignments from Assignments–>Import assignments and select the ‘DE2_PinAssg_PythonDSP.csv’ file, which is available on the website along with the codes. Lastly, compile the design and load the generated ‘.sof’ or ‘.pof’ file on the FPGA chip.

Listing 13.2 Top level design
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// blinkingLED_VisualTest.v
module blinkingLED_VisualTest
(   
    input wire CLOCK_50, reset,
    output wire[1:0] LEDR
);

nios_blinkingLED u0 (
      .clk_clk                        (CLOCK_50), // clk.clk
      .reset_reset_n                  (reset), // reset.reset_n
      .led_external_connection_export (LEDR[0])  // led_external_connection.export
 );
 
endmodule

13.11. Load the Nios design (i.e. ‘.elf’ file)

In previous section, Verilog design is loaded on the FPGA board. This loading creates all the necessary connections on the FPGA board. Next we need to load the Nios design, i.e. ‘.elf file’, on the board. Since 50 MHz clock is too fast for visualizing the blinking of the LED, therefore a dummy loop is added in the ‘main.c’ file (see Lines 10 and 19) as shown in Listing 13.3. This dummy loop generates delay, hence LED does not change its state immediately.

Listing 13.3 Blinking LED with C application
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
//main.c
#include "io.h"  // required for IOWR
#include "alt_types.h" // required for alt_u8
#include "system.h"  // contains address of LED_BASE

int main(){
    alt_u8 led_pattern = 0x01; // on the LED

    //uncomment below line for visual verification of blinking LED
    int i, itr=250000;

    printf("Blinking LED\n");
    while(1){
        led_pattern = ~led_pattern; // not the led_pattern
        IOWR(LED_BASE, 0, led_pattern); // write the led_pattern on LED

        //uncomment 'for loop' in below line for visual verification of blinking LED
        // dummy for loop to add delay in blinking, so that we can see the bliking.
        for (i=0; i<itr; i ++){}
  }
}

After these changes, right click on the ‘Application_blikingLED’ folder and click on Run as–>Nios II Hardware. The may load correctly and we can see the outputs. Otherwise a window will appear as shown in Fig. 13.26. If neither window appears nor design loaded properly, then go to Run–>Run Configuration–>Nios II Harware and select a hardware or create a harware by double-clicking on it.

../_images/RunConfig1.jpg

Fig. 13.26 Run configuration

Next, go to ‘Target connection’ tab and click on ‘refresh connection’ and select the two ignore-boxes of ‘System ID checks’ as shown in Fig. 13.27. Then click on the run button. Keep the reset button high, while loading the design, otherwise design will not be loaded on the FPGA chip.

../_images/RunConfig2.jpg

Fig. 13.27 Run configuration settings

Once Nios design is loaded successfully, then ‘Blinking LED’ will be displayed on the ‘Nios II console’. Now if we change the reset to ‘0’ and then ‘1’ again; then the message will be displayed again as shown in Fig. 13.28. Further, bilking LED can be seen after this process.

../_images/FinalOutput.jpg

Fig. 13.28 Final outputs

13.12. Saving NIOS-console’s data to file

In Section 13.11, the message ‘Blinking LED’ is displayed on the NIOS console. Most of the time, we need to store the data in a file for further processing e.g. in Chapter 15, sine waveforms are generated using NIOS, and the resulted data is saved in a file and then plotted using Python; note that this plotting operation can not be performed when data in displayed on the NIOS console.

Please see the video: NIOS II - Save data to the file using JTAG-UART if you have problem with this part of tutorial.

To save the data on a file, first build the project as discussed in the Section 13.7. Next, right click on the ‘Application_BlinkingLED’ and go to ‘NIOS II–>NIOS II Command Shell’. Then, in the command prompt, execute the following two commands,

  • nios2-download -g Application_BlinkingLED.elf} : This will load the NIOS design on the FPGA board.
  • nios2-terminal.exe -q –quiet > blinkOut.txt: This will save the messages in the file ‘blinkOut.txt’, which will be saved in the ‘Application_BlinkingLED’ folder. We can now, reset the system and ‘Blinking LED’ message will be displayed twice as shown in Fig. 13.28.
  • ‘-q –quiet’ options is used to suppress the NIOS-generated message in the file. For more options, we can use ‘–help’ option e.g. nios2-terminal –help.
  • Lastly, ‘> sign’ erases the contents of existing file before writing in it. To append the current outputs at the end of the existing file, use ‘>>’ option, instead of ‘>’.
  • We can run these two commands in one step using ‘&&’ operators i.e.
nios2-download -g Application\_BlinkingLED.elf &&  nios2-terminal.exe -q --quiet > ../../python/data/blinkOut.txt}.

In this case, ‘../../python/data/blinkOut.txt’ command will save the ‘blinkOut.txt’ file by going two folders-back i.e. ‘../../’, then it will save the file in ‘data’ folder which is inside the ‘python’ folder. In this way, we can save the results at any location.

13.13. Conclusion

In this tutorial, we saw various steps to create a embedded Nios processor design. We design the system for blinking the LED and displaying the message on the ‘Nios II console’ window. Also, we learn the simulation methods for Nios-II designs. In next chapter, we will learn about adding components to the ‘Qsys’ file. Also, we will see the process of updating the BSP according to new ‘.sopcinfo’ file.