User Login


Sie sind noch nicht eingeloggt!

     anmelden |  registrieren

Termine


21. - 23.05.2013: Darmstadt |
PLC2 Tcl/Tk

27. - 28.05.2013: Darmstadt |
PLC2 Embedded C/C++ Primer für ZYNQ

27. - 29.05.2013: Berlin |
TRIAS - Signal Integrity for Hardware Designers

Boards


Terasic Altera DE1 Board (Cyclone II EP2C20)
    

Links


FPGA Hersteller:  Altera
Xilinx
Lattice
FPGA Schulungen:  PLC2
El Camino
Trias
Weiteres:  VHDL ORG

Literatur


Vincent Himpe

Digitale Logik selbst entwickeln: Von 0 und 1 zum FPGA

Jahr: 2012
ISBN-10: 3895762547

Einbinden eines NIOS2 Prozessors in ein VHDL Design

Ihr wollt IP-Cores auf einem Altera System benutzen und habt Fragen bzw. Probleme - dann seht hier nach.

Einbinden eines NIOS2 Prozessors in ein VHDL Design

Beitragvon Tobias » Fr 19. Feb 2010, 12:22

Hallo,

da ich schon des öfteren von unseren Studenten gefragt worden bin, wie sie in ihr Design eine Soft-CPU integrieren können, dachte ich mir ich ergreife mal die Initiative und gebe mal ein kleines abgespecktes Beispiel für die Einbindung einer Altera NIOS2-CPU in ein bestehendes VHDL-Design. Eine ausführlichere Anleitung findet ihr direkt bei Altera unter http://www.altera.com/literature/tt/tt_nios2_hardware_tutorial.pdf.

Zu Begin öffnet ihr euer bestehendes VHDL-Design und startet von dort aus den Quartus SOPC-Builder
(Handbuch des SOPC-Builders http://www.altera.com/literature/lit-sop.jsp).

SOPC-Builder Einstellungen:

Hier müsst ihr nun zu allererst einen Namen und das gewünschte Ausgabeformat (VHDL/Verilog) für die zu erstellende Komponente festlegen (z.B. CPU).

Bild

Im linken Fenster "System Contents" werden jetzt alle notwendigen Komponenten ausgewählt. Für die korrekte Funktion einer NIOS2 CPU wird nicht nur die Komponenten NIOS II Processor benötigt, sondern zusätzlich noch eine System ID Peripheral, eine JTAG UART, ein Interval Timer, ein RAM (intern oder extern als Programmspeicher) im Beispiel ein SDRAM, sowie die Anschlüsse für die externe Peripherie PIO (Parallel I/O) welche in unserem kleinen Beispiel durch 10 rote und 8 grüne LEDs sowie 4 Drucktaster repräsentiert werden soll.

Durch Doppelklicken auf die jeweilige Komponente in Fenster System Contents wird diese dem System hinzugefügt. Es öffnet sich für jede Komponente ein Setup-Fenster in dem der ANweder nun diverse Einstellungen bzgl. der späteren Verwendung treffen kann.

Bild

Clock Settings:

Damit der Prozessor arbeiten kann benötigt er noch einen Takt. In meinem Beispiel verwende ich für den SDRAM 50MHz (clk_50) und für alle anderen Komponenten 100MHz (clk_100). Dies wird im oberen Fenster Clock Settings eingestellt und später jeder Komponente einzeln in der Spalte Clock zugewiesen.

Bild

NIOS II Processor:

Prinzipiell gibt es für den NIOS2 drei Ausbaustufen:

    NIOS II/e -economy
    NIOS II/s -standard
    NIOS II/f -fast

Die Auswahl bleibt dem Anwender überlassen, wichtig ist jedoch die Einstellung der Größen für den Instruction und Data Cache. Dieser ist abhängig von der maximal zur Verfügung stehenden Größe des FPGA internen RAMs oder des extern verwendeten SDRAMs. Unter Reset_Vector und Exception_Vector wird der zu verwendende Speicher (hier SDRAM) eingestellt. Zusätzlich kann noch unter Custom Instructions ein Interrupt_vector (für z.B. die Taster) eingebunden werden.

System ID Peripheral:

Die System ID wird automatisch generiert und dient der eindeutigen Identifikation des Prozessorkerns. Anhand dieser ID erkennt später der Altera Compiler ob ein geschriebenes C/C++ Programm auf der ausgewählten CPU lauffähig ist oder nicht. Wichtig: Darauf achten die Komponente von sysid_0 in sysid umbenennen!

JTAG UART:

Hier empfielt sich für den Anfang keine Veränderungen in den Grundeinstellungen vorzunehmen. Diese Komponente kann direkt integriert werden.

SDRAM:

Bei der Verwendung eines externen SDRAMs ist die Größe des RAMs sowie dessen Timing-Parameter einzustellen. In der Regel reicht die Einstellung Custom und eine Veränderung der Datenbreite um den SDRAM anzupassen. Genaue ANgaben sind dem jeweiligen Datenblatt des verwendeten SDRAMs zu entnehmen.

Interval Timer:

Ein Interval Timer wird benötigt um genaue zeitabhängige Berechnungen mit dem Controller durchzuführen. Hier können für den Anfang die Grundeinstellungen so übernommen werden.

PIO (Parallel I/O):

Hier werden die externen Schnittstellen für die Anbindung der LEDs und der Drucktaster vorgenommen.
Dafür erstellen wir zuerst ein 4 Bit breites PIO als Eingang mit synchronem Capturing zur steigenden Flanke und einem IRQ flankengesteuert. Anschließend einen 10 Bit breiten Ausgangsport für die roten und einen 8 Bit breiten Ausgangsport für die grünen LEDs. Nach dem Einbinden können die Ports noch beliebig umbenannt werden (z.B. button_pio, ledr_pio und ledg_pio). Anhand dieser Bezeichungen lassen sich die Ports und Komponenten später sehr gut im VHDL-Code wiederfinden sowie ein gezieltes ansprechen aus dem C-Code erst möglich. Achtung: Bei der Verwendung eines Eingansports als Interrupt, muss diesem eine eindeutige Interruptadresse zugeweisen werden. Der SOPC-Builder weist standardmäßig die 0 zu. Das kann zu Konfllikten führen wenn diese Adresse mehrmals auftaucht.

Nun sollte der Aufbau folgendermaßen aussehen:

Bild

Werden keine Warnungen im unteren Programmbildschirm aufgezeigt kann über "Generate" die CPU erzeugt werden. Nach erfolgreicher Erstellung findet man nun im Projektordner mehrere Dateien mit dem oben gewählten Namen (hier cpu.xxx)

Einbinden in die Top-Level-Entity:

Um nun die erstellte CPU (die erstellten Ein- bzw. Ausgänge der CPU-Entity könnt ihr einfach aus der vom SOPC-Builder erzeugten Datei cpu.vhd entnehmen) in das Top-Level-Design einzubinden wird eine neue Komponente nach z.B. folgendem Schema erstellt:

Code: Alles auswählen
component cpu
   port(
      clk                              :  IN STD_LOGIC;
      clk_50                           :  IN STD_LOGIC;
      reset_n                          :  IN STD_LOGIC;
      -- the SDRAM pio
      zs_addr_from_the_sdram           : OUT STD_LOGIC_VECTOR (11 DOWNTO 0);
      zs_ba_from_the_sdram             : OUT STD_LOGIC_VECTOR ( 1 DOWNTO 0);
      zs_cas_n_from_the_sdram          : OUT STD_LOGIC;
      zs_cke_from_the_sdram            : OUT STD_LOGIC;
      zs_cs_n_from_the_sdram           : OUT STD_LOGIC;
      zs_dq_to_and_from_the_sdram      : INOUT STD_LOGIC_VECTOR (15 DOWNTO 0);
      zs_dqm_from_the_sdram            : OUT STD_LOGIC_VECTOR ( 1 DOWNTO 0);
      zs_ras_n_from_the_sdram          : OUT STD_LOGIC;
      zs_we_n_from_the_sdram           : OUT STD_LOGIC;
      -- the_button_pio
      in_port_to_the_button_pio        :  IN STD_LOGIC_VECTOR (3 DOWNTO 0);
      -- the_led_pio
      out_port_from_the_ledg_pio       : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
      out_port_from_the_ledr_pio       : OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
      );
end component;

Anschließend müssen Signale definiert werden mit denen die Ports verbunden werden sollen:

Code: Alles auswählen
signal sig_reset     : std_logic:='1';
signal sig_clk_50    : std_logic;
signal sig_clk_100   : std_logic;
signal sig_ledg      : std_logic_vector(7 downto 0);
signal sig_ledr      : std_logic_vector(0 to 9);

(Die Signale sig_ledg und sig_legdr sollen zur Ansteuerung von LEDs dienen. Diese können jedoch auch genau wie die Ports zum externen SDRAM direkt auf die FPGA-Pins geführt werden)

Anschließend wird die CPU über eine Port-Map mit dem restlichen Design verknüpft:

Code: Alles auswählen
C0:cpu
   port map(clk                              => sig_clk_100,
            clk_50                           => sig_clk_50,
            reset_n                          => sig_reset,
            -------------------------------------------------------------------
            zs_addr_from_the_sdram           => dram_addr,   
            zs_ba_from_the_sdram(1)          => dram_ba1,   
            zs_ba_from_the_sdram(0)          => dram_ba0,
            zs_cas_n_from_the_sdram          => dram_cas,   
            zs_cke_from_the_sdram            => dram_cke,   
            zs_cs_n_from_the_sdram           => dram_cs,          
            zs_dq_to_and_from_the_sdram      => dram_dq,          
            zs_dqm_from_the_sdram(1)         => dram_udqm,   
            zs_dqm_from_the_sdram(0)         => dram_ldqm,
            zs_ras_n_from_the_sdram          => dram_ras,   
            zs_we_n_from_the_sdram           => dram_we,   
            -------------------------------------------------------------------
            in_port_to_the_button_pio(0)     => key0,
            in_port_to_the_button_pio(1)     => key1,
            in_port_to_the_button_pio(2)     => key2,
            in_port_to_the_button_pio(3)     => key3,
            -------------------------------------------------------------------
            out_port_from_the_ledg_pio       => sig_ledg,
            out_port_from_the_ledr_pio       => sig_ledr
            );   

Nun noch das gesamte Design synthetisieren und in das FPGA laden. Anschließend kann die CPU via NIOS II IDE Umgebung bequem in C/C++ programmiert werden. Eine einfache Beschreibung für die Ansteuerung der LEDs über die NIOS2-CPU aus einem C-Programm findet ihr unter http://www.fpga-talk.de/forum/viewtopic.php?f=9&t=17.

Gruß Tobias
Benutzeravatar
Tobias
 
Beiträge: 228
Registriert: Do 10. Dez 2009, 09:49

Re: Einbinden eines NIOS2 Prozessors in ein VHDL Design

Beitragvon chk1987 » Di 29. Jan 2013, 09:03

Danke Tobias!

So ein kleines Tutorial hat mir noch gefehlt. Das werd ich direkt mal testen
chk1987
 
Beiträge: 6
Registriert: Di 27. Mär 2012, 09:49


Zurück zu Altera IP-Core Ecke

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste

cron