Vous êtes sur la page 1sur 26

TP1: Implémentation d’un SoC à base de

NiosII sur la carte DE1_SoC


Designing with Quartus Labs

Avec le développement des composants programmables de type FPGA à haute intégration, il devient possible
d’implémenter logiciellement des systèmes complexes qui autrefois nécessitaient le développement d’une puce
spécifique (ASIC = Application-Specific Integrated Circuit). Les deux plus grands fabriquant de FPGA XILINX
et ALTERA fournissent aujourd’hui des outils logiciels qui permettent de concevoir des SoPC (Systems on
Programmable Chips).

On aborde ici le domaine du CoDesign logiciel et matériel. En effet, on conçoit des systèmes embarqués qui
intègrent à la fois des processeurs généralistes capables d’exécuter des programmes (logiciel) et des blocs IP
(Intellectual Properties). La conception des éléments logiciels et matériels du système se fait conjointement.

Revenons sur la notion d’IP. Ce sont des blocs fonctionnels généralement complexes qui sont réutilisables et que
l’on peut facilement intégrer au SoPC que l’on conçoit. Ils peuvent être de type matériel et dans ce cas ils sont
optimisés pour une technologie ou de type logiciel et décrits par un langage de programmation (VHDL, Verilog,
C++, etc.). Généralement les interfaces avec ces blocs IP sont normalisées. Dans la pratique, différentes sociétés
mettent à disposition des IP cores pour différentes applications. Ces composants sont généralement payants et
sont souvent cryptés (le code source n’est pas disponible). ALTERA fournit une bibliothèque d’IP cores que l’on
peut tester en mode OpenCore plus, c’est-à-dire que le bloc fonctionne tant que la carte FPGA est liée au PC ou
il s’arrête de fonctionner au bout d’une Heure.

Il existe également des blocs IP en logiciel libre que l’on trouve sur OpenCores : http://opencores.org/

Pour construire un SoPC, il faut disposer d’une unité de calcul, c’est-à-dire d’un processeur. Il y a de nombreuses
possibilités, les cœurs les plus connus étant les cœurs ARM. En ce qui concerne ALTERA nous pouvons disposer
du cœur NIOS II gratuitement qui est un processeur 32 bits à architecture RISC (Reduced Instruction Set Core).
Ce processeur s’interface facilement avec des périphériques via le bus propriétaire Avalon-MM (Avalon Memory
Mapped).
Le processeur NIOS II est décliné en trois versions dont la puissance dépend des besoins du système à concevoir
(cf. Figure 2). La Figure 3 donne les puissances en MIPS (Million of Instructions Per Seconds) pour les
différentes versions du processeur NIOS II et de la plateforme FPGA utilisée.

Créé par Y. DOUZE / modifié par P. SIGNORILE 2


Designing with Quartus Labs

Objectifs:

- Familiarisation avec l’outil PlatformDesigner.


- Création d’un système complet à base du softcore NIOS II.
- Compiler et exécuter du code sur le Nios II.

Dans la première partie de ce TP, vous allez apprendre à utiliser les outils (Quartus II et
PlatformDesigner) qui vont vous permettre de créer votre plate-forme hardware en implémentant le
processeur Nios II et un ensemble de périphériques de base. Dans une deuxième partie, vous allez utiliser
l’outil NiosII Embedded Design Suite (basé sur Eclipse) qui permet d’écrire et compiler des programmes
en C (software) qui vont être exécutés sur cette plate-forme.
Pour tous les TPs, vous allez utiliser la carte d’expérimentation DE1_SOC qui comprend un SoC
FPGA Cyclone 5 de chez Intel Altera et plusieurs composants externes listés ci-dessous :

• FPGA
o Cyclone V SoC 5CSEMA5F31C6 Device
o Dual-core ARM Cortex-A9 (HPS)
o 85K Programmable Logic Elements
o 4450 Kbits Embedded Memory
o 6 Fractional PLLs
o 2 Hard Memory Controllers
• Configuration and Debug
o Quad Serial Configuration Device - EPCQ256 on FPGA
o On-board USB Blaster II (Normal type B USB Connector)
• Memory Device
o 64MB (32Mx16) SDRAM on FPGA
o 1GB (2x256Mx16) DDR3 SDRAM on HPS
o MicroSD Card Socket on HPS
• Communication
o 2 Port USB 2.0 Host (ULPI interface with USB type A connector)
o USB to UART (micro USB type B connector)
o 10/100/1000 Ethernet
o PS/2 mouse/keyboard
o IR Emitter/Receiver
• Connectors
o Two 40-pin Expansion Headers
o One 10-pin ADC Input Header
o One LTC connector (One Serial Peripheral Interface (SPI) Master ,one I2C and one GPIO
interface)
• Display
o 24-bit VGA DAC
• Audio
o 24-bit CODEC, Line-in, and microphone-in jacks
• Video Input
o TV Decoder (NTSC/PAL/SECAM) and TV-in connector
• Switches, Buttons, and Indicators
o 4 User Keys (FPGA x4)
o 10 User switches (FPGA x10)
o 11 User LEDs (FPGA x10 ; HPS x 1)
o 2 HPS Reset Buttons (HPS_RST_n and HPS_WARM_RST_n)
o Six 7-segment displays
• Sensors
o G-Sensor on HPS

Créé par Y. DOUZE / modifié par P. SIGNORILE 3


Designing with Quartus Labs

• Power
o 12V DC Input

Partie 1 : Hardware

Le processeur Nios II est un soft processeur, définit avec un langage de description matérielle, qui
peut être implémenté sur les FPGA Intel Altera en utilisant la suite logicielle Quartus II. Pour
implémenter un système complet, il est nécessaire d’ajouter d’autres éléments au processeur, tel que des
mémoires, des interfaces d’entrées/sorties, des temporisateurs (timers) et des interfaces de
communications.
Un système complet à base de Nios II peut être implémenté sur la carte DE1-SoC comme le montre
la figure ci-dessous.

Host Computer

USB-Blaster
Interface

Cyclone II Timer NIOS II JTAG Debug JTAG UART


FPGA Chip Module
Processor Interface

Avalon Switch Fabric

On-Chip SRAM SDRAM Flash Parallel I/O Serial I/O


Memory Interface Interface Interface Interface Interface

SRAM SDRAM Flash Parallel I/O Serial I/O


Chip Chip Chip port lines port lines

Pour ce premier TP, vous allez uniquement implémenter les périphériques de base qui permettent de réaliser
des applications simples telles que :
- Allumer des LEDs séquentiellement,
- Lire les valeurs des interrupteurs et des boutons poussoirs.
- Afficher des valeurs sur les afficheurs 7 segments

Créé par Y. DOUZE / modifié par P. SIGNORILE 4


Designing with Quartus Labs

- Communiquer avec le PC via une liaison série

Au niveau hardware, pour réaliser ces applications, vous avez besoin d’implémenter les périphériques
suivants (comme le montre la figure ci-dessous) :
- Un microprocesseur et sa mémoire.
- Des entrées/sorties d’usages général (GPIO) pour les LEDs, les interrupteurs, les boutons poussoirs et
les afficheurs 7 segments.
- D’un temporisateur pour l’affichage séquentiel sur les LEDs
- D’un UART pour les transmissions séries.

Host Computer

USB-Blaster
Interface

Cyclone Chip Timer NIOS II JTAG Debug JTAG UART


Processor Module Interface

Avalon Switch Fabric

On-Chip ADC Switches parallel LEDs parallel 7 segments


RAM input interface output interface parallel output
interface

……….. ….....
ADC I2C ……
[SW9..SW0] HEX5 HEX0
[LED9…LED0]
[KEY2..KEY0]

Créé par Y. DOUZE / modifié par P. SIGNORILE 5


Designing with Quartus Labs

Vous allez découvrir à travers cet exercice la suite logicielle d’Altera. Le sujet de cet exercice
contient des instructions très précises qu’il faut suivre rigoureusement pour construire votre système.

1. Créez un répertoire « …. /tp_train », récupérez et copiez y le fichier « tp1.zip ».

2. Dézipper le fichier : « tp1.zip » clic droit et Extract to here (extraire ici)

3. Lancer Quartus II et ouvrez le projet DE1_SoC_ADC.qpf se trouvant sous « tp1/DE1_SoC_ADC_source » en


lançant (file  open  project)

4. La synthèse des circuits numériques demande beaucoup de calculs et de ressources processeur et peuvent prendre
beaucoup de temps. Pour diminuer au maximum les temps de synthèse, allé dans le menu Assignements 
Settings, sélectionnez la section Compilation Process Settings, vérifier que la case Use Smart Compilation est
cochée. Validé et terminé en cliquant sur OK.

5. Le projet est déjà configuré pour utiliser le FPGA de la carte DE1_SoC et permet dans l’état actuel de récupérer
les données de l’ADC. Nous allons agrémenter ce projet pour rajouter plusieurs périphériques.

6. Une fois que ceci est bien vérifié, vous allez commencer à construire votre Système On Programmable
Chip (SoPC). Dans cet exercice, nous allons partir d’une base Pour cela, démarrez platform designer en

allant sur Tools  PlatformDesigner… ou alors en cliquant sur l’icône suivante : puis ouvrez le
projet DE1_SoC_QSYS.qsys proposé dans la fenêtre.

L’outil ouvre le projet de base qui est donné par Terasic pour tester le périphérique ADC (Analogic Digital
Converter).
Vous allez construire votre System On Chip sur mesure.
Pour cela vous disposez de périphériques dans la librairie de composants (partie gauche de la fenêtre présentée
ci-dessous : « IP catalog  Library ») que vous pouvez rajouter à votre système (partie droite de la fenêtre
: « System Contents »).

Créé par Y. DOUZE / modifié par P. SIGNORILE 6


Designing with Quartus Labs

Ce système utilise plusieurs IP :


• Clk_50 : le périphérique qui gère la clk et le reset du système. L’horloge de base est générée
par un quartz externe avec une fréquence de 50 MHz.
• Nios2_qsys : l’instance du processeur Nios2
• Onchip_memory2 : la RAM du système qui va contenir le code à exécuter par le processeur
• Sysid_qsys : une IP qui permet d’identifier votre système
• Jtag_uart : une interface qui permet de faire du debug de la carte
• Pll_sys : un périphérique PLL qui permet de créer des nouvelles horloges qui fonctionnent
à des fréquences différentes de l’horloge principale. Notamment pour fournir une horloge
pour le périphérique ADC.
• Adc_ltc2308 : périphérique sur mesure qui permet de s’interfacer avec le convertisseur
Analogique Numérique LTC2308
• Sw : périphérique GPIO connecté avec les interrupteurs (Switch).

Créé par Y. DOUZE / modifié par P. SIGNORILE 7


Designing with Quartus Labs

Pour la suite, vous allez rajouter plusieurs périphériques pour s’interfacer avec les LEds rouge (LEDR), les
afficheurs 7 segments (HEX0 à HEX5) et les boutons poussoir (KEY).

7. Dans un premier temps, vous allez rajouter l’interface pour les LEDs. Dans la catégorie Processors and
Peripherals et ensuite Peripherals, sélectionnez l’élément PIO (Parallel I/O) et cliquez sur le bouton Add…
Choisissez une taille de 10 bit avec le mode Output. Cliquez sur Finish et renommez le périphérique en
LEDR.

8. Il faut ensuite double cliquer sur la case à l’intersection de la ligne external_connection et la colonne Export
comme sur la figure ci-dessous :

9. Refaites la même chose pour l’afficheur 7 segments HEX0 en choisissant 7 bits au lieu de 10 bits et en le
renommant HEX0.

10. Refaites la même chose pour les 5 autres afficheurs 7 segments en choisissant 7 bits et en le renommant
HEX1 à HEX5.

11. Ensuite, vous allez rajouter les interfaces pour les boutons poussoirs (KEY). Dans la catégorie Processors
and Peripherals et ensuite Peripherals, sélectionnez encore l’élément PIO (Parallel I/O) et cliquez sur le
bouton Add… Choisissez une taille de 4 bits avec le mode Input. Cliquez sur Finish et renommez le
périphérique en KEY.

12. Il faut ensuite double cliquer sur la case à l’intersection de la ligne Conduit et la colonne Export.

13. Rajout un temporisateur : vous allez rajoutez le temporisateur qui va vous permettre de faire des
opérations séquentielles sur les LEDs. Dans la catégorie Processors and Peripherals et ensuite
Peripherals, sélectionnez l’élément Interval Timer et cliquez sur le bouton Add… Laissez les
paramètres par défaut et cliquez sur Finish. Renommez le périphérique en interval_timer.

Créé par Y. DOUZE / modifié par P. SIGNORILE 8


Designing with Quartus Labs

14. Sauvegardez votre système (File  Save).

Votre projet PlatformDesigner devrait ressembler à la figure suivante :

Créé par Y. DOUZE / modifié par P. SIGNORILE 9


Designing with Quartus Labs

15. Le système est maintenant complet. Il faut ensuite relier tous les éléments à une horloge, un
Reset et les placer dans l’espace mémoire géré par le processeur.

Créé par Y. DOUZE / modifié par P. SIGNORILE 10


Designing with Quartus Labs

Tous les périphériques seront reliés à l’horloge clk qui sort du composant clk_50. Pour effectuer une
connexion à cette horloge il faut cliquer sur la ligne de connexion correspondant à clk avec la souris (le
point blanc passe en noir pour matérialiser la connexion) :

Les signaux reset de tous les composants doivent être connectée avec le signal clk_reset fournit par le
composant clk_50 et le signal debug_module_reset du composant nios2_qsys afin que le bouton reset
extérieur au CPU et l’interface JTAG puisse faire un reset de l’ensemble des modules de votre SoPC.

Il faut également connecter le port data_master du nios2_qsys avec le port s1 de tous les périphériques.

16. Pour s’assurer que toutes les adresses de base sont valides et bien aligné, allez dans le menu System et
cliquez sur Assign Base Addresses.

17. Relier les sources d’interruption comme sur la figure ci-dessus.

18. Pour s’assurer que les IRQ (interruptions) ne sont pas en conflit, allez dans le menu System et cliquez sur
Assign Interrupt Numbers.
19. Les interconnexions pour le système d’horloge, le système de reset et le processeur avec ses périphériques,
il faut respecter scrupuleusement les connections comme sur la figure ci-dessous :

Créé par Y. DOUZE / modifié par P. SIGNORILE 11


Designing with Quartus Labs

Créé par Y. DOUZE / modifié par P. SIGNORILE 12


Designing with Quartus Labs

20. Vous pouvez maintenant aller sur le menu Generate  Generate HDL, sélectionnez le langage VHDL
et cliquez sur le bouton Generate en bas de cette fenêtre. Le logiciel va générer votre Soc fait sur mesure
à base de Nios II. Cette opération consiste a généré tout le code HDL (VHDL) des IP que vous avez
instancié dans le système. Cette opération prend un certain temps, pour éviter de perdre du temps, passé
à la suite avant d’attendre la fin de la génération.

21. Retournez dans Quartus II. Dans la suite, vous allez instancier le composant créé par
« platformDesigner » avec les entrées/sorties du FPGA.
Pour cela, vous allez instancier le nios2_SoC dans le fichier VHDL DE1_SoC_Basic_Nios2_SoC.vhd.

Voici ci-dessous un exemple de code VHDL qui permet d’instancier le processeur DE1_SoC_Qsys créer
précédemment. Vous pouvez trouver un exemple d’instanciation du composant DE1_SoC_Qsys en allant
sur Generate  Show Instanciation Template

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity DE1_SoC_Basic_Nios2_SOC is
port (
-- Inputs
CLOCK_50 : in std_logic;
KEY : in std_logic_vector (3 downto 0);
SW : in std_logic_vector (9 downto 0);
----- ADC -------
ADC_CONVST : out std_logic;

Créé par Y. DOUZE / modifié par P. SIGNORILE 13


Designing with Quartus Labs

ADC_DIN : out std_logic;


ADC_DOUT : in std_logic;
ADC_SCLK : out std_logic;
-- Outputs
LEDR : out std_logic_vector (9 downto 0);
HEX0 : out std_logic_vector (6 downto 0);
HEX1 : out std_logic_vector (6 downto 0);
HEX2 : out std_logic_vector (6 downto 0);
HEX3 : out std_logic_vector (6 downto 0);
HEX4 : out std_logic_vector (6 downto 0);
HEX5 : out std_logic_vector (6 downto 0)
);
end entity;
architecture struct of DE1_SoC_Basic_Nios2_SOC is
component DE1_SoC_QSYS is
port (
clk_clk : in std_logic := 'X';
reset_reset_n : in std_logic := 'X';
adc_ltc2308_conduit_end_CONVST : out std_logic;
adc_ltc2308_conduit_end_SCK : out std_logic;
adc_ltc2308_conduit_end_SDI : out std_logic;
adc_ltc2308_conduit_end_SDO : in std_logic := 'X';
sw_external_connection_export : in std_logic_vector(9 downto 0) :=
(others => 'X');
pll_sys_locked_export : out std_logic;
pll_sys_outclk2_clk : out std_logic;
hex0_external_connection_export : out std_logic_vector(6 downto 0);
ledr_external_connection_export : out std_logic_vector(9 downto 0);
hex1_external_connection_export : out std_logic_vector(6 downto 0);
hex2_external_connection_export : out std_logic_vector(6 downto 0);
hex3_external_connection_export : out std_logic_vector(6 downto 0);
hex4_external_connection_export : out std_logic_vector(6 downto 0);
hex5_external_connection_export : out std_logic_vector(6 downto 0);
key_external_connection_export : in std_logic_vector(3 downto 0) :=
(others => 'X')
);
end component DE1_SoC_QSYS;

begin
u0 : component DE1_SoC_QSYS port map (
clk_clk => CLOCK_50,
reset_reset_n => KEY(0),
adc_ltc2308_conduit_end_CONVST => ADC_CONVST,
adc_ltc2308_conduit_end_SCK => ADC_SCLK,
adc_ltc2308_conduit_end_SDI => ADC_DIN,
adc_ltc2308_conduit_end_SDO => ADC_DOUT,
sw_external_connection_export => SW,
hex0_external_connection_export => HEX0,
ledr_external_connection_export => LEDR,
hex1_external_connection_export => HEX1,
hex2_external_connection_export => HEX2,
hex3_external_connection_export => HEX3,
hex4_external_connection_export => HEX4,
hex5_external_connection_export => HEX5,
key_external_connection_export => KEY
);
end architecture;

Il faut ensuite rajouter le SoC généré par PlatformDesigner dans le projet ainsi que le fichier VHDL
précédemment modifié. Pour cela, allez sur Project  Add/Remove Files in Project… et rajouter le
fichier DE1_SC_Basic_Nios2_SoC.vhd. Il faut également rajouter le fichier DE1_SoC_QSYS.qip qui
se trouve dans le dossier DE1_SoC_QSYS/synthesis/

Créé par Y. DOUZE / modifié par P. SIGNORILE 14


Designing with Quartus Labs

22. Une fois que vous avez connecté toutes les entrées/sorties de votre FPGA avec les entrées/sorties de votre
SoC, il faut choisir ce composant comme top-level de votre design. Sur l’onglet Files, clic droit sur le
fichier DE1_SoC_Basic_Nios2_SoC.vhd et choisir Set as top-level entity.

23. Maintenant, vous pouvez faire la synthèse de votre design. Depuis le menu Processing, sélectionnez Start
Compilation ou alors, cliquez directement sur l’icône . Après quelques minutes, la fenêtre
Compilation Report - Flow summary apparait et vous donne les résultats de la synthèse et du placement
routage. Cette page vous renseigne sur la place occupée par votre design dans le FPGA :
• Le nombre d’éléments logiques utilisés (Total Logic element)
• Le nombre de registres (Total Registers)
• Le nombre de pins (Total Pins)
• L’espace mémoire utilisés (Total Memory bits)
• Le nombre de multiplieur utilisés (Embedded multiplier 9-bit)
• Le nombre de PLL

24. Maintenant il faut connecter les entrées/sorties de l’entité top-level du fichier VHDL avec les
entrées/sorties physiques du FPGA. Pour cela allez dans Assignements  Pin Planner et précisez les
noms des pins du FPGA dans la colonne Location correspondant au nom donné dans l’entité top-level.
Pour cela, il faut se reporter à la documentation technique de la carte (DE1-SoC_User_Manual.pdf). Par
exemple, pour les boutons poussoirs : KEY(0)  PIN_AA14, KEY(1)  PIN_AA15, etc…

Vous devriez avoir le résultat suivant :

Préciser les noms des pins du FPGA pour toutes les entrées/sorties comme précisé dans le User Manual
de la carte DEI-SoC.

25. Relancer la compilation complète afin de prendre en compte l’affectation des pins
26. Assurez-vous que la carte est alimentée. Connectez la carte à votre PC avec le câble USB (connecteur
BLASTER de la carte DEI-SOC et pas UART). Lancez le programmateur depuis le menu Tools 
Programmer ou l’icône . Une fenêtre apparait, cliquez sur OK. Le nom du type de câble (USB-
Blaster) doit apparaitre à côtés de Hardware Setup…
Si ce n’est pas le cas, cliquez sur le bouton Hardware Setup. Ensuite sélectionnez votre type de câble dans
le menu Currently selected hardware. Si votre câble n’est pas là, essayez de le faire apparaitre en cliquant

Créé par Y. DOUZE / modifié par P. SIGNORILE 15


Designing with Quartus Labs

sur le bouton Add Hardware… Une fois que votre câble est sélectionné, fermer la fenêtre en cliquant sur
Close.

27. Le fichier appelé « bitstream » qui contient l’architecture à implémenter dans le FPGA porte le nom du
projet Quartus avec l’extension « .sof » et se retrouve généralement dans le dossier output_files.
Dans la liste des devices, vous voyez la partie HPS du SoC-FPGA Vous devrez cliquez sur le bouton
Auto Detect pour faire apparaitre le FPGA dans la liste des Device et sélectionner 5CSEMA5.
Ensuite sur le nom du FPGA (5CSEMA5F31) cliquez sur le bouton Add File… afin de sélectionner le
fichier.sof. Cochez la case Program/configure qui correspond à votre fichier.sof et ensuite cliquez sur le
bouton Start afin de programmer le FPGA.
Attention 2 fichiers de types « .sof » apparaissent. Choisir le fichier
« DE1_SoC_ADC_time_limited.sof »

28. Si tout va bien, le FPGA est maintenant configuré !

29. Vous avez maintenant terminé la partie Hardware et vous allez passer à la partie Software avec l’outil
Nios II SBT (Software Build Tool) qui est un environnement de développement basé sur Eclipse.

Partie 2 : Software

1. Dans les étapes suivantes, vous allez compiler un programme pour votre SOPC, le télécharger dans la
mémoire SRAM et l’exécuter.

Créé par Y. DOUZE / modifié par P. SIGNORILE 16


Designing with Quartus Labs

• Pour cela, retournez dans PlatformDesigner, ouvrir l’outil NiosII SBT à partir du menu Tools
 Nios II Software Built Tool for Eclipse. Au démarrage on vous demande de sélectionner le
répertoire de travail. Choisissez le répertoire par défaut.

2. Créer un nouveau projet en sélectionnant File  New  Nios II Application and BSP from Template
dans la barre des menus.
• Dans la partie Target Hardware Information, vous devez spécifiez par un fichier.
sopcinfo qu’elle est la cible sur laquelle vous allez développer. Il s’agit de la cible que
nous venons de créer précédemment.
• Naviguez vers le chemin de votre projet afin de sélectionner le fichier
DE1_SoC_QSYS.sopcinfo.
• Choisissez le nom de votre projet (niosII_training_project par exemple).
• Dans la fenêtre « Project template » choisissez Hello_word
• Puis cliquez sur « finish »

3. Cependant, le projet C/C++ est vide et nous devons y ajouter le code applicatif.
• Pour cela développer le répertoire niosII_training_project.
• Ensuite sélectionner le fichier hello_world.c
• Remplacer le code simple par le code suivant en changeant si besoin les adresses des
pointeurs volatile avec les adresses des périphériques qui sont spécifiés dans
« PlatformDesigner » dans la fenêtre « address map » :

/* This program demonstrates use of parallel ports in the DE1-SoC Basic Computer
*
* It performs the following:
* 1. displays the SW switch values on the red LED
* 2. displays a rotating pattern on the HEX displays
* 3. Read the analog value from the 6 ADC channels
*/
#include <stdio.h>
#include <io.h>
#include <unistd.h>
#include "system.h"
void main(void){
/* Declare volatile pointers to I/O registers (volatile means that IO load
* and store instructions will be used to access these pointer locations,
* instead of regular memory loads and stores)
*/
volatile int * red_LED_ptr = (int *) 0x00081090; // red LED address
volatile int * HEX0_ptr = (int *) 0x00081080; // HEX0 address
volatile int * HEX1_ptr = (int *) 0x00081070; // HEX0 address
volatile int * SW_switch_ptr = (int *) 0x000810A0; // SW slider switch
address
volatile int * KEY_ptr = (int *) 0x00081020; // pushbutton KEY address
int HEX_bits = 0x0000000F;// pattern for HEX displays
int SW_value, KEY_value;
volatile int delay_count;// volatile so the C compiler doesn't remove the loop
int ch = 0;
const int nReadNum = 10; // max 1024
int i, Value, nIndex=0;
printf("Hello World !");
while(1){
ch = IORD(SW_BASE, 0x00) & 0x07;
SW_value = *(SW_switch_ptr); // read the SW slider switch values
*(red_LED_ptr) = SW_value; // light up the red LEDs
*(HEX0_ptr) = HEX_bits; // display pattern on HEX3 ... HEX0

Créé par Y. DOUZE / modifié par P. SIGNORILE 17


Designing with Quartus Labs

/* rotate the pattern shown on the HEX displays */


if (HEX_bits & 0x80)
HEX_bits = (HEX_bits << 1) | 1;
else
HEX_bits = HEX_bits << 1;
printf("======================= %d, ch=%d\r\n", nIndex++, ch);
// set measure number for ADC convert
IOWR(ADC_LTC2308_BASE, 0x01, nReadNum);
// start measure
IOWR(ADC_LTC2308_BASE, 0x00, (ch << 1) | 0x00);
IOWR(ADC_LTC2308_BASE, 0x00, (ch << 1) | 0x01);
IOWR(ADC_LTC2308_BASE, 0x00, (ch << 1) | 0x00);
usleep(1);
// wait measure done
while ((IORD(ADC_LTC2308_BASE,0x00) & 0x01) == 0x00);
// read adc value
for(i=0;i<nReadNum;i++){
Value = IORD(ADC_LTC2308_BASE, 0x01);
printf("CH%d=%.3fV (0x%04x)\r\n", ch, (float)Value/1000.0, Value);
}
usleep(200*1000);
} // while
}

Créé par Y. DOUZE / modifié par P. SIGNORILE 18


Designing with Quartus Labs

Créé par Y. DOUZE / modifié par P. SIGNORILE 19


Designing with Quartus Labs

Exemple pour les adresses des périphériques dans PlatformDesigner :

4. Maintenant, sélectionnez le répertoire niosII_training_project_bsp, faites un clic droit et


choisissez NiosII BSP Editor.
• Dans cette page, vous pouvez choisir toutes les propriétés de votre système.
• Assurez-vous que stdout, stderr et stdin soit configuré sur jtag_uart. Ce choix de
configuration signifie que le JTAG est la sortie standard de votre système. Dans ce cas,
les fonctions printf() ou scanf() permettent d’écrire ou de lire des données sur le bus série
du JTAG_UART.
Vérifiez que sys_clk_timer soit configuré avec interval_timer.
Cliquez sur Generate et ensuite Exit.

5. Maintenant vous allez compiler le code,


• Pour cela, sélectionnez le répertoire niosII_training_project, ensuite avec le clic droit

sélectionnez Build Project ou alors cliquez sur l’icône suivante :


Note : Vous pouvez faire en sorte que la compilation soit faite en arrière-plan (background), ou
alors laisser l’exécution de cette tâche en premier plan (forground). Lorsque la compilation
s’exécute en arrière-plan, vous avez la possibilité d’utiliser l’outil pour faire d’autres
opérations.

6. Après que la compilation soit terminée, il faut télécharger le programme sur la cible.
• Pour cela sélectionner le répertoire niosII_training_project, avec le clic droit
sélectionnez Run As  Nios II Hardware.
Note 1 : Si une fenêtre s’ouvre, allez dans l’onglet Target Connection et cliquez sur Refresh
Connections

Créé par Y. DOUZE / modifié par P. SIGNORILE 20


Designing with Quartus Labs

Note2 : dans System ID Check cochez les deux cases Ignore Mismatched System ID et Ignore
Mismatched System TimeStamp et enfin cliquez sur Run

Cette commande va télécharger le programme dans la RAM et l’exécuter.


Vous devriez observer sur la fenêtre de console le message « Hello World » afficher par la
commande printf().
Vous devriez également voir les LEDs des deux dernier afficheur 7 segments évoluer, les autres
afficheurs étant allumés en permanence.
Maintenant modifiez la valeur sur les interrupteurs et vérifiez que le résultat est recopié sur les
LEDs rouges.

7. Maintenant, vous allez tester le debugger.


• Lancer le debugger en sélectionnant le répertoire niosII_training_project.
• Ensuite avec le clic droit sélectionnez Debug As  Nios II Hardware. Le debugger va
se lancer, se connecter et télécharger le code sur la cible. (Choisir Yes lorsqu’on va vous
demander de changer de perspective pour le debug).

8. Activer l’affichage des numéros de ligne.


• Pour cela, allez sur Window dans le menu et ensuite Préférences.

Créé par Y. DOUZE / modifié par P. SIGNORILE 21


Designing with Quartus Labs

• Ouvrir le répertoire General et ensuite sélectionnez Editors  Text Editors.


• Activer le carré Show line numbers et puis appuyer sur OK.

9. Positionnez des points d’arrêts sur une ou deux lignes.


• Pour positionner un point d’arrêt, il suffit de placer le curseur dans la partie grise à gauche
des numéros de ligne et faire un double clic. Un petit rond bleu doit normalement
apparaitre à côtés du numéro de ligne indiquant qu’un point d’arrêt a été positionné.
• Cliquez sur le bouton resume . Le programme s’arrête sur le premier point d’arrêt.

10. Maintenant, sélectionnez la fenêtre Variables et visualiser la valeur de la variable sw.


• Pour afficher la valeur en hexadécimal, sélectionnez la variable SW_Value, avec un clic
droit choisissez Format et ensuite Hexadécimal.
• Vérifiez que la valeur de SW_Value correspond à la position des interrupteurs sur la carte
DE1_SoC.
• Afficher également la valeur de KEY_Value en hexadécimal.

11. Vous pouvez également faire du pas à pas avec le debugger. Pour cela appuyer sur l’icône
suivante :

12. En faisant du pas à pas, vous devriez voir évoluer la valeur de HEX_bits évolué et l’état des
afficheurs 7 segments évoluer sur la carte.

13. Changez la position des interrupteurs et en cliquant sur l’icône , vérifiez que la valeur de
SW_Value change en conséquence.

14. Pour arrêter le debugger. Allez dans le sous-menu Debug, ensuite faire un clic droit sur le
nom du projet logiciel qui est en train d’être debugger et sélectionnez Terminate and Remove.

Créé par Y. DOUZE / modifié par P. SIGNORILE 22


Designing with Quartus Labs

15. Pour revenir à la fenêtre de l’IDE, cliquez sur la double flèche en haut à droite de l’écran

et sélectionnez Nios II

Partie 3 : Utiliser la couche d’abstraction matérielle (HAL et/ou drivers)

Dans le programme précédent, l’accès aux périphériques se fait directement par l’adresse de
ceux-ci. On peut également accéder aux périphériques en utilisant les « drivers » de la couche
d’abstraction matérielle appelé HAL (Hardware Abstraction Layer) fournit par Altera. Ces
fonctions facilitent l’accès aux ressources matérielles de chaque périphérique.
L’ensemble des fonctions (ou driver) sont dans le bsp (Board Support Package) du projet, donc
dans notre cas dans le NiosII_training_project_bsp

Dans cette partie, on propose de remplacer les instructions qui permettent de lire ou d’écrire sur
les interfaces parallèles par les fonctions fournis par Altera.

Pour cela, il faut inclure la librairie suivante qui se trouve dans le NiosII_training_project_bsp
(driver  inc) :

#include "altera_avalon_pio_regs.h"

Par exemple, Pour la lecture des interrupteurs, on peut utiliser la fonction suivante :
SW_value = IORD_ALTERA_AVALON_PIO_DATA (SW_BASE);

Pour l’écriture sur les LEDs vertes on peut utiliser la fonction suivante :
IOWR_ALTERA_AVALON_PIO_DATA(LEDR_BASE, SW_value);

Créé par Y. DOUZE / modifié par P. SIGNORILE 23


Designing with Quartus Labs

Dans les 2 cas le paramètre NOM_DU_PERIPHERIQUE_BASE (comme SW_BASE ou


LEDR_BASE) correspond à l’adresse du périphérique dans l’espace adressable du Nios II. Vous
pouvez retrouver la valeur de cette adresse dans le fichier system.h. Ce fichier renseigne sur les
paramètres de votre système. Pour pouvez trouver ce fichier dans le répertoire
NiosII_training_project_bsp.

Par exemple, relevez l’adresse de SW_BASE et vérifiez que c’est bien la même que celle spécifié
dans PlatformDesigner.

Remplacez l’ensemble des instructions qui permettent d’accéder aux port parallèles (LEDs,
interrupteurs, boutons poussoirs, afficheurs 7 segments) par des fonctions Altera.

Vous n’aurez donc plus besoin des instructions qui renseignent les adresses des périphériques :
volatile int * red_LED_ptr = (int *) 0x00081090; // red LED address
volatile int * HEX0_ptr = (int *) 0x00081080; // HEX0 address
volatile int * HEX1_ptr = (int *) 0x00081080; // HEX0 address
volatile int * SW_switch_ptr = (int *) 0x000810A0; // SW slider switch address
volatile int * KEY_ptr = (int *) 0x00081020; // pushbutton KEY address

Après modification vous allez recompiler le code et retester le logiciel comme dans les étapes 5
et 6

Créé par Y. DOUZE / modifié par P. SIGNORILE 24


Designing with Quartus Labs

Partie 4 : Exercices

Après avoir testé le programme donné en exemple qui recopie les valeurs des interrupteurs sur les LEDs, qui fait
évoluer l’état des Led sur les afficheurs 7 segments, modifier ce code pour répondre aux questions suivantes :

1. Envoyez de manière continu la valeur des interrupteurs (sw) sur la console (avec la fonction printf() ) et
générez un chenillard sur les LEDs (une seule LED allumer qui fait un va et vient de gauche à droite).

2. Ecrire un nouveau programme qui permet de commander la valeur à afficher sur des LEDs rouges et les
valeurs à afficher sur les afficheurs 7 segments à partir de la console de l’IDE. Pour cela il faut utiliser la
fonction scanf(). Pour que les commandes soient décodées correctement par la cible, il faut inventer un codage
explicite. Par exemple :
• Pour afficher la valeur 100 sur les LEDs rouges, envoyer la commande r 100 (r comme red)
• Pour afficher la valeur 3 sur l’afficheur HEX0, envoyer la commande h0 3.
• Pour afficher la valeur 9 sur l’afficheur HEX3, envoyer la commande h3 9.
• Etc…

3. Faire un chenillard sur les LEDs rouges commandé en vitesse par les boutons poussoirs (KEY). Par exemple,
le défilement du chenillard s’accélère si vous appuyez sur le bouton poussoir KEY[2], et le défilement ralentit
si vous appuyez sur le bouton poussoir KEY[1]. Attention ! KEY[0] est utilisé comme reset du système.

4. Générer un compteur sur les afficheurs 7 segments dont la vitesse d’incrémentation est commandé par les
boutons poussoirs (KEY[2] et KEY[1]).

Partie 5 : Ping-Pong

1. Le jeu de Ping Pong consiste à faire défiler les 10 leds comme un chenillard mais à chaque fois que la
dernière LED (de droite ou de gauche) est allumée il faut que l’un des deux joueurs appui sur le bouton
poussoir correspondant (KEY2 pour le joueur de gauche et KEY1 pour le joueur de droite) pour que la
balle (le défilement des LEDs) reparte dans l’autre sens.
Dans un premier temps, vous n’avez pas à gérer le nombre de service par joueur. Faites-en sorte que celui
qui a perdu, perd son service.

2. La principale modification à apporter consiste à faire défiler les LEDs de plus en plus rapidement au fur
et à mesure de l’échange. La vitesse est réinitialisée à chaque changement de sens, c’est-à-dire à chaque
fois qu’un joueur a perdu son service. Pour cela modifier la fin de while pour rendre paramétrable le temps
de boucle.
3. for(i=0;i<nReadNum;i++){
4. Value = IORD(ADC_LTC2308_BASE, 0x01);
5. printf("CH%d=%.3fV (0x%04x)\r\n", ch, (float)Value/1000.0,
Value);
6. }
7. usleep(200*1000);
8. } // while
9. }

10. Affichage de la vitesse en décimale sur les afficheurs 7 segments

Créé par Y. DOUZE / modifié par P. SIGNORILE 25


Designing with Quartus Labs

Pour aller plus loin si vous avez le temps


11. Remplacer l’affichage de la vitesse par l’affichage du score de la partie de Ping-Pong sur les afficheurs 7
segments. Vous avez le choix de la manière d’afficher les résultats de la partie

12. Complétez votre code afin de compter les services pour que chaque joueur effectue 5 services et laisse
ensuite l’autre joueur servir.

Créé par Y. DOUZE / modifié par P. SIGNORILE 26

Vous aimerez peut-être aussi