14. Reading data from peripherals

14.1. Introduction

In Chapter 13, the values of the variables in the code i.e. ‘led_pattern’ were sent to PIO (peripheral input/output) device i.e. LED. In this chapter, we will learn to read the values from the PIO. More specifically, the values will be read from the external switches. These values will decide the blinking rate of the LED. Further, we will not create a new ‘.qsys’ file, but modify the previous ‘.qsys’ file to generate the new system. Also, we will see the procedures to modify the existing Nios project i.e. BSP and Application files (instead of creating the new project).

14.2. Modify Qsys file

First create or open a Quartus project as discussed in Chapter 13. Then open the ‘Qsys’ file, which we have created in the previous chapter and modify the file as below,

  • Modify LED port: Double click on the ‘led’ and change the ‘Width’ column to ‘2’ from ‘1’; because in this chapter, we will use two LEDs which will blink alternatively.

  • Add Switch Port: Next, add a new PIO device and set it to ‘output’ port with width ‘8’ as shown in Fig. 14.1. Next, rename it to ‘switch’ and modify it’s clock, reset and external connections as shown in Fig. 14.2.


    Fig. 14.1 Add switch of width 8


    Fig. 14.2 Rename and Modify the port for Switch

  • Next, assign base address by clicking on System–>Assign base addresses.

  • Finally, generate the system, by clicking on the ‘Generate button’ with correct simulation settings, as shown in Fig. 13.14.

14.3. Modify top level design in Quartus

Since, LED port is modified and the ‘switch’ port is added to the system, therefore top level module should be modified to assign proper connections to the FPGA chip. Top level design for this purpose is shown in Listing 14.1.

Listing 14.1 Modify top level design in Quartus
// blinkingLED_VisualTest.v
module blinkingLED_VisualTest
    input wire CLOCK_50, reset,
    input wire [7:0] SW,
    output wire[1:0] LEDR

nios_blinkingLED u0 (
      .clk_clk                          (CLOCK_50), // clk.clk
      .reset_reset_n                    (reset), // reset.reset_n
      .switch_external_connection_export (SW),    // switch_external_connection_export.export
      .led_external_connection_export   (LEDR)  // led_external_connection.export

14.4. Modify Nios project

Since ‘Qsys’ system is modified, therefore corresponding ‘.sopcinfo’ file is modified also. Now, we need to update the system according to the new ‘.sopcinfo’ file.

14.4.1. Adding Nios project to workspace

If ‘workspace is changed’ or ‘BSP/Application files are removed’ from the current workspace, then we need to add these files again in the project, as discussed below,


If the location of the project is changed, then we need to created the NIOS project again, as shown in Appendix 17.

  • First go to Files–>Import–>’Import Nios II software…’ as shown in Fig. 14.3; and select the ‘application’ from the ‘software’ folder (see Fig. 14.4) inside the main directory. Finally, give it the correct name i.e. ‘Application_blinkingLED’ as shown in Fig. 14.5


    Fig. 14.3 Import Application and BSP files


    Fig. 14.4 Application and BSP files are in software folder


    Fig. 14.5 Add application Name i.e. Application_blinkingLED

  • Similarly, add the BSP folder in the current workspace.

  • Now, open the ‘system.h’ file in the BSP. Here, we can see that LED data width is still ‘1’ as shown in Fig. 14.6. Also, we can not find the ‘switch’ entries in the system.h file.


    Fig. 14.6 LED data width is not updated to ‘2’

  • To update the BSP, right click on the BSP folder and go to Nios–>Generate BSP. It will update the BSP files.

  • Sometimes, proper addresses are not assigned during generation in ‘Qsys’ system as shown in Fig. 14.7. Here, SWITCH_BASE is set to ‘0$times$0’. To remove this problem, assign base addresses again and regenerate the system as discussed in Section 14.2.


    Fig. 14.7 Base address is not assigned to switch

14.5. Add ‘C’ file for reading switches

Next, modify the ‘main.c’ file as shown in Listing 14.2. Finally, build the system by pressing ‘ctrl+B’.

Explanation Listing 14.2

‘IORD(base, offset)’ command is used the read the values form I/O ports as shown at Line 19 of the listing. Line 19 reads the values of the switches; which is multiply by variable ‘itr’ (see Line 22), to set the delay value base on switch patterns. Also, ‘iter ‘value is set to ‘1000’ at Line 11, so that multiplication can produce sufficient delay to observe the blinking LEDs.
Listing 14.2 Blinking LED with C application
#include "io.h"
#include "alt_types.h"
#include "system.h"

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

    // swValue : to store the value of switch
    // swDelay = swValue * iter, is the overall delay
    int i, swDelay, swValue, itr=1000;

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

        // read the value of switch
        swValue = IORD(SWITCH_BASE, 0);

        // calculate delay i.e. multiply switch value by 1000
        swDelay = swValue * itr;

        // dummy loop for delay
        for (i=0; i<swDelay; i ++){}

14.6. Simulation and Implementation

If build is successful, then we can simulate and implement the system as discussed in Chapter 13. Fig. 14.8 and Fig. 14.9 illustrate the simulation results for switch patterns ‘0000-0000’ and ‘0000-0001’ respectively. Note that, blinking patterns are shown by ‘01’ and ‘10’, which indicates that LEDs will blink alternatively. Also, blinking-time-periods for patterns ‘0000-0000’ and ‘0000-0001’ are ‘4420 ns’ and ‘1057091 ns’ respectively (see square boxes in the figures), which show that blinking periods depend on the switch patterns.


Fig. 14.8 Simulation waveforms with switch pattern ‘0000-0000’


Fig. 14.9 Simulation waveforms with switch pattern ‘0000-0001’

To implement the design, compile the top level design in Quartus and load the ‘.sof’ file on the FPGA chip. Then load the ‘.elf’ file from Nios software to FPGA chip. After this, we can see the alternatively blinking LEDs on the board.

14.7. Conclusion

In this chapter, values from the PIO device i.e. switch patterns are read using IORD command. These switch patterns are used to decide the blinking rate of the LEDs. Further, we discussed the procedure to modify the existing Qsys, Quartus and Nios to extend the functionalities of the system.