Kommandozeile?
Ja, das ist deutlich bequemer als die grafische Programmieroberfläche. Das Laden eines FPGA mit einer Bitstrom-Datei (bitstream file) ist eine wiederkehrende Aufgabe. Es ist immer dieselbe Datei, dasselbe FPGA, auf demselben Board, das am selben Rechner hängt. Und irgendwie machen die GUI-Werkzeuge daraus eine einschüchternde Zeremonie – und manchmal sogar ein Quiz, wenn nicht genau erkannt werden kann, welcher Baustein angeschlossen ist und ich den genauen wissen soll.
Mit der Kommandozeile ist es buchstäblich nur eine Sache des passenden Befehls aus der Bash-Historie und Enter drücken. Und erstaunlicherweise stellt das Kommandozeilen-Werkzeug nicht die albernen Fragen, die das GUI-Werkzeug stellt.
Zuerst ein wenig herumspielen
Richte die Umgebung ein:
$ /path/to/quartus/15.1/nios2eds/nios2_command_shell.sh
Um alle erkannten Geräte aufzulisten (das Programmierkabel wird automatisch erkannt):
$ quartus_pgm --auto
Info: *******************************************************************
Info: Running Quartus Prime Programmer
Info: Version 15.1.0 Build 185 10/21/2015 SJ Lite Edition
Info: Copyright (C) 1991-2015 Altera Corporation. All rights reserved.
[ ... ]
Info: agreement for further details.
Info: Processing started: Sun May 27 15:06:22 2018
Info: Command: quartus_pgm --auto
Info (213045): Using programming cable "USB-BlasterII [2-5.1]"
1) USB-BlasterII [2-5.1]
02B040DD 5CGTFD9(A5|C5|D5|E5)/..
020A40DD 5M2210Z/EPM2210
[ ... ]
Man beachte, dass das Auflisten der Geräte wie oben gezeigt nicht notwendig ist, um den Bitstrom zu laden. Es kann vielleicht nützlich sein, um die Position des FPGA in der JTAG-Kette zu bestimmen. Wirklich etwas, das man einmal macht, um das Board zu erkunden.
jtagd
Es ist wichtig, sich dieses Daemons bewusst zu sein, der auf TCP/IP-Port 1309 lauscht. Er ist dafür verantwortlich, mit dem JTAG-Adapter über den USB-Bus zu sprechen; sowohl die GUI-Programmieroberfläche als auch das Kommandozeilen-Werkzeug verlassen sich darauf. Wenn kein Daemon läuft, starten beide ihn.
Aber wenn man mehrere Versionen von Quartus verwendet, kann dies eine Quelle der Verwirrung sein, insbesondere wenn man zuerst versucht, ein FPGA mit einer älteren Version zu laden, und dann eine neuere Version verwendet. Das liegt daran, dass die neuere Version von Quartus die ältere Version von jtagd weiterverwendet. Und dieser ältere jtagd unterstützt möglicherweise FPGAs nicht, die die neuere Version von Quartus kennt. Die Schlussfolgerung ist also: Wenn seltsame Dinge passieren, könnte das helfen, und schaden wird es sowieso nicht:
$ killall jtagd
FPGA laden
quartus_pgm gibt den Großteil seiner Ausgabe in grünem Text aus. Grundsätzlich gilt: Wenn kein roter Text erscheint, ist alles gut gegangen.
$ quartus_pgm -m jtag -o "p;path/to/file.sof"
Alternativ kann man die Position des Bausteins in der JTAG-Kette explizit angeben (insbesondere wenn es nicht das erste Gerät ist). In diesem Fall ist es @1, bedeutet also das erste Gerät in der JTAG-Kette. Wenn es das zweite Gerät ist, nimmt man @2 usw.
$ quartus_pgm -m jtag -o "p;path/to/file.sof@1"
Info: *******************************************************************
Info: Running Quartus Prime Programmer
Info: Version 15.1.0 Build 185 10/21/2015 SJ Lite Edition
Info: Copyright (C) 1991-2015 Altera Corporation. All rights reserved.
Info: Your use of Altera Corporation's design tools, logic functions
Info: and other software and tools, and its AMPP partner logic
Info: functions, and any output files from any of the foregoing
Info: (including device programming or simulation files), and any
Info: associated documentation or information are expressly subject
Info: to the terms and conditions of the Altera Program License
Info: Subscription Agreement, the Altera Quartus Prime License Agreement,
Info: the Altera MegaCore Function License Agreement, or other
Info: applicable license agreement, including, without limitation,
Info: that your use is for the sole purpose of programming logic
Info: devices manufactured by Altera and sold by Altera or its
Info: authorized distributors. Please refer to the applicable
Info: agreement for further details.
Info: Processing started: Sun May 27 15:35:02 2018
Info: Command: quartus_pgm -m jtag -o p;path/to/file.sof@1
Info (213045): Using programming cable "USB-BlasterII [2-5.1]"
Info (213011): Using programming file p;path/to/file.sof@1 with checksum 0x061958E1 for device 5CGTFD9E5F35@1
Info (209060): Started Programmer operation at Sun May 27 15:35:05 2018
Info (209016): Configuring device index 1
Info (209017): Device 1 contains JTAG ID code 0x02B040DD
Info (209007): Configuration succeeded -- 1 device(s) configured
Info (209011): Successfully performed operation(s)
Info (209061): Ended Programmer operation at Sun May 27 15:35:09 2018
Info: Quartus Prime Programmer was successful. 0 errors, 0 warnings
Info: Peak virtual memory: 432 megabytes
Info: Processing ended: Sun May 27 15:35:09 2018
Info: Elapsed time: 00:00:07
Info: Total CPU time (on all processors): 00:00:03
Wenn etwas schiefgeht – etwa ein nicht passender Baustein, ein Fehler beim Scannen der JTAG-Kette oder sonst etwas –, wird man das kaum übersehen können, denn die Fehler werden in Rot angezeigt. Das Gute an der Kommandozeilen-Schnittstelle ist, dass jeder Versuch komplett von vorne beginnt; man muss also nur das Board einschalten und es erneut versuchen.
Cyclone-10-GX-FPGA-Entwicklungsboard
Dieses Board hat mir einigen zusätzlichen Ärger bereitet, deshalb ein paar Worte dazu. Wenn dieses Board mit einem Computer verbunden ist, erscheint es als 09fb:6810, aber nach dem Versuch, das FPGA zu laden (man beachte das „@2“ am Ende) mit:
$ quartus_pgm -m jtag -o "p;thecode.sof@2"
Error (213019): Can't scan JTAG chain. Error code 86.
Daraufhin ändert sich die ID des Geräts auf 09fb:6010. Es findet also eindeutig eine Neuprogrammierung der Firmware statt (das Systemprotokoll zeigt eine Trennung und erneute Verbindung mit der neuen ID). Das Board wird von Quartus’ GUI-Programmierungstool als GX0000406 erkannt, aber ein Klick auf „Auto Detect“ führt zu „Unable to scan device chain. Hardware is not connected“.
Also gut, wie wäre es mit einem Scan-Versuch?
$ quartus_pgm --auto
[ ... ]
Info (213045): Using programming cable "10CGX0000406 [1-5.1.2]"
1) 10CGX0000406 [1-5.1.2]
Unable to read device chain - Hardware not attached
Das Problem war in meinem Fall offenbar, dass der laufende jtagd von einer älteren Quartus-Version gestartet worden war, die Cyclone-10-Bausteine nicht erkannte. Also befolge den Ratschlag oben und beende ihn. Danach funktionierte das Programmieren mit dem obigen Befehl mit Quartus Pro 17.1:
$ quartus_pgm --auto
[...]
Info (213045): Using programming cable "USB-BlasterII [1-5.1.2]"
1) USB-BlasterII [1-5.1.2]
031820DD 10M08SA(.|ES)/10M08SC
02E120DD 10CX220Y