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:
- Altera DE1
- 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)
|