Altera DE1 - SOPC
Introduction
Hardware
Design Flow
Quartus II Project
Top-Level Entitiy
Heartbeat
System PLL
Design Constraints File
Nios II - SOPC
Compile the design
Assign the pins
Compile the design again
Program the FPGA
Credits
Download for DE1
Download for DE0-Nano

(2) ChibiOS/RT
 

Introduction

This tutorial provides comprehensive information that will help you understand how to create a microprocessor system on your FPGA development board and run software on it. This system will be based on the Altera Nios II processor. Later I will show you how to use the ChibiOS/RT on the Nios II. The tutorial is divided in the following sessions:

  1. Altera DE1
  2. ChibiOS/RT

It is recommended to start with the Altera DE1, which is this session here. This tutorial use the Quartus II and Nios II SBT software version 11.1.

I do not want to write every time "Quartus II" or "Nios II" in this tutorial. Therefore I will use the short form "Quartus" and "Nios".

Hello Altera, if you like this tutorial and want to donate something, no problem. You can find my contact data on the imprint page

Hardware

For this tutorial an Altera DE1 Board was used:

The DE1 board provides a lot of functionality. But for this tutorial only the following subset was used:

  • Cyclone II (EP2C20F484C7)
  • Build in USB Blaster
  • 8MByte SDRAM
  • 4 Push-button switches
  • 10 Toggle switches
  • 8 Green User LEDs
  • 10 Red User LEDs
  • 50 MHz oscillator

Design Flow

The first step in the FPGA design flow starts with the design entry. The standard design entry methods are using schematics or a hardware description language (HDL), such as Verilog or VHDL. The design entry step is where the designer creates the digital circuit to be implemented inside the FPGA. The flow then proceeds through compilation, simulation, programming, and verification in the FPGA hardware.

This tutorial describes all of the steps except the simulation. The part of the Design is a huge part. Therefore it is divided in smaller chunks. I assume that the Quartus software and the USB-Blaster driver is already installed on your PC. If not, please take this step before.

At the end of this tutorial you will have created a FPGA design which contains a Nios processor. In the next session, (2) ChibiOS/RT we will create a ChibiOS application which runs on the Nios cpu. Let's start with the Top-Level Entity...

Quartus II Project

First of all we must create a new Quartus project. A project is a set of files that maintain information about your FPGA design. The Quartus Settings File (.qsf) and Quartus Project File (.qpf) files are the primary files in a Quartus project.

Start the Quartus software and select "File > New Project Wizard". The window will look like:

(Click inside the picture to expand)

Click "Next"and enter the following information about your project: (Note: File names, project names, and directories in the Quartus software cannot contain spaces. In general, do not use spaces in file names or directories.).

What is the working directory for this project? Enter a directory in which you will store your Quartus project files for this design. Here I will use "c:\my_design\de1_chibios" What is the name of this project? Please use "de1_chibios"

What is the name of the top-level design entity for this project? Please use "de1_chibios" here too. The next window should look like:

(Click inside the picture to expand)

Click "Next". Now you will come to page 2 of 5 (Add File), press "Next" too. In the next window you must assign a FPGA device to your design. Change the "Device family" to "Cyclone II" and use "EP2C20F484C7" for the device. The dialog should look like:

(Click inside the picture to expand)

Click "Next" twice, the summary should look like:

(Click inside the picture to expand)

Click "Finish", now you have created the "de1_chibios" project. The "Project Navigator" should look like:

Next we will create the Top-Level Entity.

Top-Level Entity

Btw, what is a "Top-Level Entity"? It is the outer rim of your design which represent the interconnections to the outer world of the FPGA. Quartus supports the following options for a Top-Level Entity:

  • Block Diagram/Schematic File
  • VHDL File
  • Verilog File

Here in this tutorial I will use a Verilog File for the Top-Level Entity. Compared to a Block Diagram a HDL File is not so clearly represented, but more fexible for me. Now we will start to create the Top-Level Entity.

Therefore select "File > New... > Verilog HDL File", the window will look like:

Press "OK" now. A new blank file (Verilog1.v) was created by Quartus, it should look like:

(Click inside the picture to expand)

Now we will cheat a little bit, here I have prepared the file for you. Please copy the content of de1_chibios to the new file which was created by Quartus. The file is "divided" in the following "section":

  • Module definition
  • Input / Output definition
  • Definition for local "variables" like wires
  • HDL code

The Quartus editor window should look like:

(Click inside the picture to expand)


I will try to explain the "section" of this Verilog file. But if you are not familiar with Verilog, sorry I am a beginner too (perhaps this could be a book for the german readers, FPGA-Design mit Verilog. I have this book and I like it. Any other hints are welcome.).

module / endmodule will be used to define a functional unit. Our module here is named "de1_chibios". It must be have this name, because in the section before we have use "de1_chibios" for the name of the Top-Level Entity, you remember?

Even you must define the interconnections to the outside of the module. In case of the Top-Level Entitiy, this are the connections to the outside of the FPGA.

E.g. CLOCK_50, this is the clock for the FPGA. But is it an input or output?

The next "section" is the input / output section, where the direction of the signals are defined. CLOCK_50 is defined as an input here.

Local "variables", what is this? I will use this section for wires or registers which are used internaly by this module. Here the wire CLK_SYS, CLK_10 and pll_locked are defined.

And in the end, there is the HDL "section". Here we will reference other modules which are used by the design.

I do not know if this are the correct formal description. As I mention before, I am a beginner too, and my field of activity is the software development.


OK, now the file must be saved. Use "File > Save", navigate to "c:\my_design\de1_chibios" and type "de1_chibios.v" for the filename. The dialog should look like:

Press "Save" to close this dialog. Now we can go to the next step.

Heartbeat

At the end of the tutorial you will program the FPGA. But in the moment you have no real feadback if your design is working. Therefore a blinking LED will be added which start after programming the FPGA. This is now the "heartbeat" of the FPGA. The same procedure like before.

Select "File > New... > Verilog HDL File", press "OK". A new blank file (Verilog2.v) was created by Quartus. Here we will cheat a little bit too. Please copy the content of simple_counter to the new file, which was create by Quartus.

Now the file must be saved. Use "File > Save", navigate to "c:\my_design\de1_chibios" and type "simple_counter.v" for the filename. Press "Save" to close the dialog.

Take a look in the "Files" tab of the "Project Navigator", here you sould find two files now, de1_shibios.v and simple_counter.v. The window will look like:

(Click inside the picture to expand)

In the next step we will create the "engine" of the design. A PLL driven by the external clock.

System PLL

The PLL will be created with a Wizard, therefore use "Tools > MegaWizard Plug-In Manager". The MegaWizard Plug-In Manager (what a long name) appears, the first window will look like:

(Click inside the picture to expand)

Click "Next". In the new page [page 2a] expand the folder "I/O" and select ALTPLL. For "Which device family will you be using" select "Cyclone II". Under “Which type of output file do you want to create?” select "Verilog HDL". And for “What name do you want for the output file?” type "pll_sys.v". The page should now look like:

(Click inside the picture to expand)

Click "Next", and be prepared for a long story, you will see now page 3 of 10
( not "Seven of Nine" ). For device speed grade choose 7 and set the frequency of the inclock0 input to 50 MHz. The window should look like:

(Click inside the picture to expand)

Click "Next". Now you are on page 4 of 10, unselect all options first, and select "Create 'locked' output" and "Hold 'locked' output low for". Use 25000 for "cycles after the PLL initializes". The locked output will be used to hold the Nios in reset while the PLL is not locked.


Pardon, why 25000? Please take a look in the Cyclone II Data Sheet, here specaily in the
DC Characteristics and Timing Specifications. Search for "t LOCK" in the PLL Specifications table. Here you will find a maximum locked time of 500us. Now divide the 500us by the input clock period, here 50 MHz. 500us / 20ns = 25000


The window should look like:

(Click inside the picture to expand)

Click "Next" twice. Now you are on page 6 of 10, and will setup the output clock for c0. Select "Enter output clock frequency" and set frequency to 100 Mhz. The window should look like:

(Click inside the picture to expand)

Again, click "Next". Now you are on page 7 of 10. We need c1 for the SDRAM, therefore enable the option "Use this clock" and select "Enter output clock frequency". The same like before. Set the frequency to 100 MHz. And set the "Clock phase shift" to -54deg.


Why -54deg? Please take a look in the DE1 tutorial folder from your DE1 CD. Here you will find a PDF file, tut_DE2_sdram_vhdl.pdf (DE2 is not a typo here). This PDF will explain why you need a phase shift in chapter 5. But in the document 3ns is used for a clock of 50MHz. 3ns at 50MHz is equivalent to 54 deg. Help, if anyone comes to an other result, please send me a note. Btw, here we are using 100MHz instead of 50MHz. Therefore I decide to change from ns to deg.


The window look like:

(Click inside the picture to expand)

Please click "Next" now. You will come to page 8 of 10. Here we will use c2 too, it will be used for the simple_counter. Enable the option "Use this clock" and select "Enter output clock frequency". Set the frequency to 10 MHz. The window should now look like:

(Click inside the picture to expand)

And now, press "Finish" twice. The MegaWizard Plug-In Manager will be closed. And the following dialog is shown:

Press "Yes" to add the Quartus IP to your design. A pll_sys IP block was created and added to your project. The "Files" folder from the "Project Navigator" should look like:

Timing constraints, what is this? We will create this file in the next section.

Design Constraints File

Select "File > New... > Synopsys Design Constraints File", press "OK". A new blank file (SDC1.sdc) was created by Quartus. Again, we will cheat here too. Please copy the content of de1_chibios_sdc to the new file, which was create by Quartus.

Now the file must be saved. Use "File > Save", navigate to "c:\my_design\de1_chibios" and type "de1_chibios.sdc" for the filename. Press "Save" to close the dialog. The "Files" folder from the "Project Navigator" should look like:


Why we need a SDC File? To give the TimeQuest Timing Analyzer the possibility to check if the timing of the design will fit in the FPGA, some "parameters" for the calculation are needed. This "parameters" are stored in the SDC file. For example you will find the following line in the file:

create_clock -period 50MHz [get_ports CLOCK_50]

This line tells the Analyzer that there exist a port with the name "CLOCK_50". It will be used as a clock signal with 50 MHz.

Even there will not only timing parameters saved in this file. For more information please take a look in the documentation. Help, if someone can explain it better, please send me a note.


In the next section the "CPU" will be designed.

Nios II - SOPC

We will not really create the CPU here itself. We will create the system with CPU and peripherals. Btw, SOPC stands for system on programmable chip.

Start the SOPC Builder by using "Tools > SOPC Builder", the new windows will look like:

(Click inside the picture to expand)

Rename the "System Name" to de1_sopc, and use "Verilog" for the "Target HDL", the dialog should now look like:

Press "OK" and you will be asked to use Qsys, the next generation of SOPC Builder:

Sorry, I do not have worked with Qsys before. Therefore we will use the "old" SOPC Builder. Press "OK" now. The next window will look like:

(Click inside the picture to expand)

Double click the "clk_0" name in the "Clock Settings" table and rename clk_0 to "clk_sys", even double click the 50,0 MHz and change it to "100,0". It will now look like:

In the left hand-side Component Library tree, select "Library > Processors > Nios II Processor", it should look like:

Press the "Add…" button to open the Nios II component wizard. The wizard will look like:

(Click inside the picture to expand)

We want to add a little more speed to the CPU, therefore press "Next", the "Caches and Memory Interfaces" page is active. Change the "Instruction Cache" to "8 Kbytes" and the "Data Chache" to "4 Kbytes". The window should look like:

(Click inside the picture to expand)

Click "Finish" to return to the main window, it should look like:

(Click inside the picture to expand)

Select the cpu_0 component and right-click, then select "Rename":

After this, you can update the "cpu_0" to "cpu", it should now look like:

(Click inside the picture to expand)

Add a second component by selecting "Library > Memories and Memory Controllers > External Memory Interfaces > SDRAM Interfaces > SDRAM Controller" and clicking the "Add…" button. The SDRAM wizard will be opened. Change the "Presets" to "Custom", and the "Data width Bits" to "16". The window of the wizard should look like:

(Click inside the picture to expand)

Press "Next >", the window should look like:

(Click inside the picture to expand)

Click "Finish" to return to the main window. Important, rename the "sdram_0" to "sdram", the system should look like:

(Click inside the picture to expand)

Now the system contains a CPU and an external SDRAM. The next step will be to add the System ID. Therefore select "Library > Peripherals > Debug and Performance > System ID Peripheral" and click the "Add..." button. We will use the default values of the wizard, press "Finish". Important, rename "sysid_0" to "sysid". The main window should now look like:

(Click inside the picture to expand)

We need a UART over JTAG too. Therefore select "Library > Interface Protocols > Serial > JTAG UART" and click the "Add…" button. The wizard will look like:

(Click inside the picture to expand)

We are going to use the default settings for this component, so click "Finish" to close the wizard. Important, rename "jtag_uart_0" to "jtag_uart". The main window will now look like:

(Click inside the picture to expand)

Now we need some GPIO' to control the LEDs and reading the switches. Add the "Library > Peripherals > Microcontroller Peripherals >PIO (Parallel I/O)" component to the system. For the green LEDs we need a output port with a width of 8 bit. Set the "Width" to "8" and the "Direction" to "Output". The window of the wizard will look like:

(Click inside the picture to expand)

Click "Finish" to close the wizard. Important, rename "pio_0" to "pio_led_green". The main window will now look like:

(Click inside the picture to expand)

The same procedure like before, but now for the red LEDs. Add the "Library > Peripherals > Microcontroller Peripherals >PIO (Parallel I/O)" component to the system. We need a output port with a width of 9 bit (yes the board has 10 LEDs, but we want to use one LED for the heartbeat). Set the "Width" to "9" and the "Direction" to "Output". Press "Finish". Important, rename "pio_0" to "pio_led_red". The main window will now look like:

(Click inside the picture to expand)

Please add now the last output port for the 7-segment display. But here we need 28 bits. Important, rename the port to pio_7seg. The main window should now look like:

(Click inside the picture to expand)

We need two more ports, but now we need input ports for the switches and keys. Add the "Library > Peripherals > Microcontroller Peripherals > PIO (Parallel I/O)" component to the system. For the keys we need an input port with a width of 4 bit. Set the "Width" to "4" and the "Direction" to "Input". The window of the wizard will look like:

(Click inside the picture to expand)

Press "Finish". Important, rename "pio_0" to "pio_key". The main window will now look like:

(Click inside the picture to expand)

We need a port again. Add an input port for the switches, here we need 10 bits. Important, rename "pio_0" to "pio_sw". The main window will now look like:

(Click inside the picture to expand)

For the ChibiOS/RT we need a timer too. Use "Library > Peripherals > Microcontroller Peripherals > Interval Timer" and click the "Add…" button. Set the "Period" to 1 ms. The wizard will look like:

(Click inside the picture to expand)

If the settings are equal like in the the picture, press "Finish" otherwise you must change it. Important, do not rename the timer_0. The main window will now look like:

(Click inside the picture to expand)

And the last component is a real UART. Therefore select "Library > Interface Protocols > Serial > UART (RS-232 Serial Port) " and click the "Add…" button. The wizard will look like:

(Click inside the picture to expand)

Check if the settings are equal, press "Finish" otherwise you must change it. Important, do not rename the uart_0. The main window will now look like:

(Click inside the picture to expand)

Now we must solve the "To Do" points which are mention in the output window:

  • To Do: cpu: No reset vector has been specified for this CPU.
  • To Do: cpu: No exception vector has been specified for this CPU.

Right click on the cpu component and select "Edit…" from the list. The wizard page of the cpu will be opened. Change the "Reset Vector" and "Exception Vector" to "sdram". The window of the wizard should now look like:

(Click inside the picture to expand)

Click "Finish". The two "To Do" are now gone. The main window will look like:

(Click inside the picture to expand)

The next step is to assign a base address to each component. Select "System > Assign Base Addresses":


Then, select "File > Refresh System":


After that there should be no error in the message window:

Click "Close". And there should be no errors in the main window too:

(Click inside the picture to expand)

The two warnings:

  • Warning: cpu: Custom Instruction components can be edited...
  • Warning: cpu: Disabling the assign CPUID control register value manually will ...

can be ignored for the moment.

Click the "Generate" button, a window will pop up which will look like:

Click "Save", and use "de1_sopc" for the filename. The dialog should look like:

Press "Save" to close this dialog. Now the SOPC Builder will generate the system. This can take a moment.

At the end you should see the Info: "System generation was successful."

(Click inside the picture to expand)

Click "Exit" to exit the SOPC Builder and return to the Quartus window. Right click on the "Files folder" in the Project Navigator:


Click "Add/Remove Files in Project...". A "Settings" dialog will be opened which will look like:

(Click inside the picture to expand)

We will now add the Verilog file which was created by the SOPC Builder.
Therefore press the "..." button on the left side of the "Add" button:


The "Select File" dialog will pop up, select "de1_sopc.v" and press "Open". Now you can use the "Add" button to add the file to the project:


Press "Add". The file "de1_sopc.v" will now be listed by the other files too. Click "OK" to close the dialog. You will now find the "de1_sopc.v" in the "Project Navigator" too. The "Files" folder from the "Project Navigator" should look like:

In the next section we will compile the design.

Compile the design

Compile the project, by selecting "Processing > Start Compilation":


This will start the compilation process which can take a while:

(Click inside the picture to expand)

At the end of the compilation process a dialog box should appear which give you the information about a successful completion:

In the next section we will assign the pins of the FPGA.

Assign the pins

Now we can assign the input and output pins of the FPGA. But first of all we want to set all unused pins to input tri-stated. Therefore use "Assignments > Device...". The device window will be opened:

(Click inside the picture to expand)

Click "Device and Pin Options...". A new window will pop up. Change here the "Reserved all unused pins:" option to "As input tri-stated with weak pull-up". The window should look like:

(Click inside the picture to expand)

Click "OK" twice to close both windows. Now I will show you how to assign the pin for CLOCK_50. To open the "Pin Planer", use "Assignments > Pin Planner". A new window will be opened, it will look like:

(Click inside the picture to expand)

Double-click in the "Location" column for the CLOCK_50 signal to open a drop-down list. Select here "PIN_L1", you will got the pin information from the data sheet of the DE1 board. Now double-click in the "I/O Standard" column and select "3.3-V LVTTL".

The window should now look like:

(Click inside the picture to expand)

You must repeat this procedure for all pins of your design. Do you want to cheat here? Yes, are you sure? OK, close the "Pin Planer" first. Use "File > Open...", now change the "File type" to "All Files (*.*)" and select the "de1_chibios.qsf" file. Open this file.

This is the file where the pin assigment is stored too. Copy the content of this file at the end of the qsf file. After this, close the qsf file, click "Yes" if Quartus want to save.

Hopefully Quartus has accept the input? We will check this and open the "Pin Planer" again. Use "Assignments > Pin Planner" and scroll through the "All Pins" list. It looks that the cheat was working on my side :o)

(Click inside the picture to expand)

We must compile the design again, this will be done in the next section.

Compile the design again

Like in the section before. Compile the project, by selecting "Processing > Start Compilation":


This will start the compilation process which can take a while. "Please hold the line..."

At the end of the compilation process a dialog box should appear which give you the information about a successful completion:

There should be no, I will repeat it, no "Critical Warning" available. The SOF file was created and we can program the FPGA in the next section.

Program the FPGA

I assumed that you have connect the DE1 board still with your computer and the USB-Blaster driver is still installed. For programming the FPGA select "Tools > Programmer". Because of the absent Nios  license I got a message about the OpenCore Plus feature:

Press "OK", and the programmer window will be opened:

(Click inside the picture to expand)

Everythink looks ok here. Click the "Start" button to program the FPGA. If you have problems to program the FPGA, press the "Start" button again. If the LEDR9 is blinking and the "Progress" indicator looks like:

The 7-segment display shows 8888, and the green and red LEDs are off?

Drum roll, congratulations, you have created, compiled, and programmed your first FPGA design! The compiled SRAM Object File (.sof) is loaded onto the FPGA on the development board and the design should be running.

In the next session I will show you how to use ChibiOS/RT on the DE1 board.

Credits

  • Thanks go to Terasic which give me the permision to use parts of the DE0-Nano
    user manual for this tutorial.
  • And many thanks goes to the "spell checker" too, if I have found someone.

Download for Altera DE1

Top-Level Entity de1_chibios for the Altera DE1 Board.

Simple counter from the DE0-Nano example.

Synopsys Design Constraints File for the Altera DE1 Board.

The final Quartus ChibiOS Verilog project for the Altera DE1 Board (42 KB)

The final Quartus ChibiOS VHDL project for the Altera DE1 Board (43 KB)

Download for Altera DE0-Nano

Quartus ChibiOS VHDL project for the Altera DE0-Nano board (468 KB)