<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Horstsch</id>
	<title>Mikrocontroller.net - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Horstsch"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/Horstsch"/>
	<updated>2026-04-21T08:00:05Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=FPGA_Konfiguration_mit_AVR_Butterfly&amp;diff=67072</id>
		<title>FPGA Konfiguration mit AVR Butterfly</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=FPGA_Konfiguration_mit_AVR_Butterfly&amp;diff=67072"/>
		<updated>2012-06-27T19:45:42Z</updated>

		<summary type="html">&lt;p&gt;Horstsch: aufgehübscht&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
[[Bild:carrierboard_butterfly_xapp058.png | right | 300px]]&lt;br /&gt;
Dieses Projekte stellt gewissermaßen eine Ergänzung zu [[Low_Cost_FPGA_Konfiguration]] dar.&lt;br /&gt;
Es wurde ein [[AVR Butterfly]] genutzt, um einen FPGA Xilinx Spartan-3-1000 via [[JTAG]] zu konfigurieren. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
Da die Pins CCLK, Din und Done nicht zugänglich sind, mußte der Weg über die [[JTAG]]-Schnittstelle gegangen werden. Es wurde ein kleines Trägerboard für den Butterfly entwickelt, um alle benötigten Schnittstellen bequem unterzubringen.&lt;br /&gt;
&lt;br /&gt;
Der Dataflash auf dem Butterfly-Board hat eine Größe von 512 kByte. Da passen die ca. 402 kByte Konfigurationsdaten [http://www.xilinx.com/support/documentation/user_guides/ug332.pdf] für den der Spartan-3-1000 gut rein. Wer einen größeren FPGA konfigurieren möchte, braucht also auch den passenden Speicher dafür.&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:schematic_butterfly_xapp058.png | thumb | left | 400px| Schaltplan]]&lt;br /&gt;
&lt;br /&gt;
Der Butterfly wird mit einer externen Betriebsspannung von 3,3 V versorgt. Damit ergeben sich 3,3 V Pegel für die JTAG-Schnittstelle (Achtung, bei neueren FPGAs liegt die JTAG-Spannung bei 2,5 V oder 1,8 V). Die Referenzspannung der Zielhardware kann per Software geprüft werden.&lt;br /&gt;
&lt;br /&gt;
Das eigentliche Programmiergerät kann an JTAG_IN angeschlossen werden. Auf den in XAPP058 angegebenen Multiplexer zum Umschalten der JTAG-Quelle kann verzichtet werden, da der Mikrocontroller seine Ausgänge (ebenso wie das Programmiergerät) bei Nichtgebrauch hochohmig schaltet. Man darf natürlich nicht gleichzeitig mit dem Programmer und dem AVR per JTAG auf das FPGA zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
Als Grundgerüst für die Butterfly-Software wurde die gcc-Portiertung der Butterfly-Demo [http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#bf_app] verwendet.&lt;br /&gt;
Um die Daten sicher in den Dataflash zu bekommen, wird das XMODEM-Protokoll verwendet. Dazu gibt es von Atmel die Application Note AVR350 [http://www.atmel.com/Images/doc1472.pdf]. Und um letztendlich den FPGA zu konfigurieren, wurde von Xilinx die Application Note XAPP058 [http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf] benutzt.&lt;br /&gt;
 &lt;br /&gt;
Damit das alles in den 16 kByte Flash des ATmega169 passt, wurde der Democode entschlackt.&lt;br /&gt;
Dann erfolgt die Anpassung des Xilinx-Codes: MAX_LEN (lenval.h) muß rigeros verringert werden, damit die Datenstrukturen von Xilinx in den Speicher von 1 kByte passen. Ich habe 128 gewählt. Das ist auch die maximale Größe, die Impact für die Konfigurationshäppchen verwendet. Außerdem muß noch die Kompression deaktiviert werden: XSVF_SUPPORT_COMPRESSION (micro.c). Damit schrumpft die Variable xsvfInfo auf 546 Byte.&lt;br /&gt;
&lt;br /&gt;
Alle Funktionen können bequem über das Bedienpanel des Butterfly abgerufen werden:&lt;br /&gt;
&lt;br /&gt;
=== Menüstruktur ===&lt;br /&gt;
[[Bild:menu_struktur.png | 300px ]]&lt;br /&gt;
&lt;br /&gt;
== Workflow ==&lt;br /&gt;
Im Allgemeinen wird sich der folgende Workflow ergeben:&lt;br /&gt;
# XSVF-Daten generieren&lt;br /&gt;
# Download&lt;br /&gt;
# Konfigurieren des FPGA&lt;br /&gt;
&lt;br /&gt;
=== XSVF-Daten generieren ===&lt;br /&gt;
Die XSVF-Dateien können inzwischen direkt durch Xilinx-Impact erstellt werden.&lt;br /&gt;
Ich nutze dafür dieses kleine Skript (bit2xsvf.cmd):&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
setmode -bs&lt;br /&gt;
setCable -port xsvf -file &amp;quot;design.xsvf&amp;quot;&lt;br /&gt;
addDevice -p 1 -file &amp;quot;design.bit&amp;quot;&lt;br /&gt;
program -p 1&lt;br /&gt;
closeCable&lt;br /&gt;
quit&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Durch &amp;lt;c&amp;gt;$ impact -batch bit2xsvf.cmd&amp;lt;/c&amp;gt; wird die XSVF-Datei auf der Kommandozeile erstellt.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
Für den Download der XSVF-Datei in den Dataflash wird die serielle Schnittstelle auf 115200 Baud eingestellt und die Datei per XMODEM transferiert.&lt;br /&gt;
Mit der Linux-Kommandozeile geht das z.B. so:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
$ stty -F /dev/ttyS0 115200&lt;br /&gt;
$ sz --xmodem design.xsvf &amp;gt; /dev/ttyS0 &amp;lt; /dev/ttyS0&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zur Kontrolle, kann der Inhalt des Dataflash auf der seriellen Schnittstelle ausgegeben werden (dump):&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
Page: 0&lt;br /&gt;
0x0000: 0x07 0x00 0x13 0x00 0x14 0x00 0x12 0x00 0x12 0x01 0x04 0x00 0x00 0x00 0x00 0x02 ................&lt;br /&gt;
0x0010: 0x06 0x09 0x08 0x00 0x00 0x00 0x20 0x01 0x0F 0xFF 0xFF 0xFF 0x09 0x00 0x00 0x00 ...... .........&lt;br /&gt;
0x0020: 0x00 0xF1 0x42 0x80 0x93 0x02 0x06 0x09 0x09 0x00 0x00 0x00 0x00 0xF1 0x42 0x80 ..B...........B.&lt;br /&gt;
0x0030: 0x93 0x02 0x06 0x3F 0x02 0x06 0x0B 0x04 0x00 0x00 0x36 0xB0 0x02 0x06 0x05 0x04 ...?......6.....&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Konfigurieren des FPGA ===&lt;br /&gt;
Die eigentliche Konfiguration des FPGA erfolgt mit dem Menüpunkt &amp;quot;Program FPGA&amp;quot;.&lt;br /&gt;
Wenn alles geklappt hat steht nach kurzer Zeit &amp;quot;done&amp;quot; im Display, sonst erhält man eine entsprechende Fehlermeldung.&lt;br /&gt;
&lt;br /&gt;
== Optimierungen ==&lt;br /&gt;
In der ersten funktionierenden Implementation benötigte das Programm ca. 400 Sekunden um das FPGA zu konfigurieren. Das entspricht einer Datentransferrate von 1,1 kByte/s. Völlig unakzeptabel.&lt;br /&gt;
&lt;br /&gt;
Also musste optimiert werden. Der RC-Oszillator des AVR wird beim Startup auf 1 MHz Taktfrequenz kalibriert. Wenn man den Takteiler von 8 auf 1 stellt, läuft der AVR schon mit 8 MHz. Durch Programmieren des OSCCAL-Registers mit 0x7F ließ sich mein ATmega auf 15 MHz beschleunigen. Damit ließ sich die Konfigurationszeit auf 25 Sekunden (17 kByte/s) verringern. Schon besser.&lt;br /&gt;
&lt;br /&gt;
Damit sich die Zeit für den XMODEM-Transfer ebenfalls verkürzt, wird die Baudrate der seriellen Schnittstelle auf 115200 eingestellt. Der ATmega läuft nur für die Konfiguration mit der vollen Geschwindigkeit. Für eine fehlerfreie serielle Datenübertragung wird der RC-Oszillator auf eine Taktfrequenz von 11,0592 MHz kalibriert.&lt;br /&gt;
Bei wem das nicht klappen sollte, der muß eine kleinere Taktfrequenz im Makefile (F_CPU) einstellen. Laut ATmega169-Datenblatt müßten 8 MHz +/-10 Prozent immer funktionieren.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Geschwindigkeitssteigerung konnte durch die Nutzung des USI-Moduls erreicht werden. Normalerweise werden TDI, TDO, TCK und TMS durch Bitbanging erzeugt. Xilinx hat diese Funktionen in ports.c schön gekapselt. Sehr portabel, aber nicht schnell.&lt;br /&gt;
Durch direkten Aufruf der USI-Register in der Funktion xsvfShiftOnly konnte eine weitere wesentliche Beschleunigung erreicht werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin ist die Reihenfolge der Bits in den JTAG-Daten (LSB...MSB) nicht passend für das USI-Datenregister. Es müssen also alle Bytes gespiegelt werden. Am schnellsten geht dies mit einer Tabelle, die leider etwas Speicher kostet. Außerdem wurde die Zählerbreite lNumBits von 32 auf 16 Bit reduziert.&lt;br /&gt;
&lt;br /&gt;
Damit ergibt sich letztendlich eine akzeptable Konfigurationszeit von 5,6 Sekunden und damit eine Transferrate von 75 kByte/s. Der Flash des ATmega169 ist mit 12 kByte gut gefüllt, läßt aber noch etwas Luft für Erweiterungen.&lt;br /&gt;
&lt;br /&gt;
== Ausblick ==&lt;br /&gt;
Um die folgenden Features könnte das Projekt noch erweitert werden:&lt;br /&gt;
* Lesen der Konfiguration von SD-Karte&lt;br /&gt;
* direkte Interpretation von .bit-Dateien&lt;br /&gt;
* Unterstützung von komprimierten Daten&lt;br /&gt;
&lt;br /&gt;
== Download ==&lt;br /&gt;
[[media:butterfly_xapp058.zip]]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/user_guides/ug332.pdf UG332 Spartan-3 Generation Configuration User Guide]&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#bf_app AVR Butterfly Application code port to avr-gcc]&lt;br /&gt;
* [http://www.atmel.com/Images/doc1472.pdf AVR350: Xmodem CRC Receive Utility for AVR]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf XAPP058 Xilinx In-System Programming Using an Embedded Microcontroller]&lt;br /&gt;
&lt;br /&gt;
[[Category:FPGA-Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Boards]]&lt;/div&gt;</summary>
		<author><name>Horstsch</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=FPGA_Konfiguration_mit_AVR_Butterfly&amp;diff=67054</id>
		<title>FPGA Konfiguration mit AVR Butterfly</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=FPGA_Konfiguration_mit_AVR_Butterfly&amp;diff=67054"/>
		<updated>2012-06-26T22:10:22Z</updated>

		<summary type="html">&lt;p&gt;Horstsch: /* Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
Dieses Projekte stellt gewissermaßen eine Ergänzung zu [[Low_Cost_FPGA_Konfiguration]] dar.&lt;br /&gt;
Hier wurde ein [[AVR Butterfly]] genutzt, um einen FPGA Xilinx Spartan-3-1000 via [[JTAG]] zu konfigurieren. &lt;br /&gt;
&lt;br /&gt;
[[Bild:carrierboard_butterfly_xapp058.png| right | 360px]]&lt;br /&gt;
== Hardware ==&lt;br /&gt;
Da die Pins CCLK, Din und Done nicht zugänglich sind, mußte der Weg über die [[JTAG]]-Schnittstelle gegangen werden. Es wurde ein kleines Trägerboard für den Butterfly entwickelt, um alle benötigten Schnittstellen bequem unterzubringen.&lt;br /&gt;
&lt;br /&gt;
Der Dataflash auf dem Butterfly-Board hat eine Größe von 512 kByte. Da passen die ca. 402 kByte Konfigurationsdaten [http://www.xilinx.com/support/documentation/user_guides/ug332.pdf] für den der Spartan-3-1000 gut rein. Wer einen größeren FPGA konfigurieren möchte, braucht also auch den passenden Speicher dafür.&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:schematic_butterfly_xapp058.png | thumb | left | 640px| Schaltplan]]&lt;br /&gt;
&lt;br /&gt;
Der Butterfly wird mit einer externen Betriebsspannung von 3,3 V versorgt. Damit ergeben sich 3,3 V Pegel für die JTAG-Schnittstelle. Achtung, bei neueren FPGAs liegt die JTAG-Spannung bei 2,5 V oder 1,8 V. Die Referenzspannung der Zielhardware kann per Software geprüft werden.&lt;br /&gt;
&lt;br /&gt;
Das eigentliche Programmiergerät kann an JTAG_IN angeschlossen werden. Auf den in XAPP058 angegebenen Multiplexer zum Umschalten der JTAG-Quelle kann verzichtet werden, da der Mikrocontroller seine Ausgänge (ebenso wie das Programmiergerät) bei Nichtgebrauch hochohmig schaltet. Man darf natürlich nicht gleichzeitig mit dem Programmer und dem AVR per JTAG auf das FPGA zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
Als Grundgerüst für die Butterfly-Software wurde die gcc-Portiertung der Butterfly-Demo [http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#bf_app] verwendet.&lt;br /&gt;
Um die Daten sicher in den Dataflash zu bekommen, wird das XMODEM-Protokoll verwendet. Dazu gibt es von Atmel die Application Note AVR350 [http://www.atmel.com/Images/doc1472.pdf]. Und um letztendlich den FPGA zu konfigurieren wurde von Xilinx die Application Note XAPP058 [http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf] benutzt.&lt;br /&gt;
 &lt;br /&gt;
Damit das alles in den 16 kByte Flash des ATmega169 passt, wurde der Democode entschlackt.&lt;br /&gt;
Dann erfolgt die Anpassung des Xilinx-Codes: MAX_LEN (lenval.h) muß rigeros verringert werden, damit die Datenstrukturen von Xilinx in den Speicher von 1 kByte passen. Ich habe 128 gewählt. Das ist auch die maximale Größe, die Impact für die Konfigurationshäppchen verwendet. Außerdem muß noch die Kompression deaktiviert werden: XSVF_SUPPORT_COMPRESSION (micro.c). Damit schrumpft die Variable xsvfInfo auf 546 Byte.&lt;br /&gt;
&lt;br /&gt;
Alle Funktionen können bequem über das Bedienpanel des Butterfly abgerufen werden:&lt;br /&gt;
&lt;br /&gt;
=== Menüstruktur ===&lt;br /&gt;
[[Bild:menu_struktur.png]]&lt;br /&gt;
&lt;br /&gt;
== Workflow ==&lt;br /&gt;
Im Allgemeinen wird sich der folgende Workflow ergeben:&lt;br /&gt;
* XSVF-Daten generieren&lt;br /&gt;
* Download&lt;br /&gt;
* Konfigurieren des FPGA&lt;br /&gt;
&lt;br /&gt;
=== XSVF-Daten generieren ===&lt;br /&gt;
Die XSVF-Dateien können inzwischen direkt durch Xilinx-Impact erstellt werden.&lt;br /&gt;
Ich nutze dafür dieses kleine Skript (bit2xsvf.cmd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setmode -bs&lt;br /&gt;
setCable -port xsvf -file &amp;quot;design.xsvf&amp;quot;&lt;br /&gt;
addDevice -p 1 -file &amp;quot;design.bit&amp;quot;&lt;br /&gt;
program -p 1&lt;br /&gt;
closeCable&lt;br /&gt;
quit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Durch &amp;lt;pre&amp;gt;$ impact -batch bit2xsvf.cmd&amp;lt;/pre&amp;gt; wird die XSVF-Datei auf der Kommandozeile erstellt.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
Für den Download der XSVF-Datei in den Dataflash wird die serielle Schnittstelle auf 115200 Baud eingestellt und die Datei per XMODEM transferiert.&lt;br /&gt;
Mit der Linux-Kommandozeile geht das z.B. so:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ stty -F /dev/ttyS0 115200&lt;br /&gt;
$ sz --xmodem design.xsvf &amp;gt; /dev/ttyS0 &amp;lt; /dev/ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zur Kontrolle, kann der Inhalt des Dataflash auf der seriellen Schnittstelle ausgegeben werden (dump):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Page: 0&lt;br /&gt;
0x0000: 0x07 0x00 0x13 0x00 0x14 0x00 0x12 0x00 0x12 0x01 0x04 0x00 0x00 0x00 0x00 0x02 ................&lt;br /&gt;
0x0010: 0x06 0x09 0x08 0x00 0x00 0x00 0x20 0x01 0x0F 0xFF 0xFF 0xFF 0x09 0x00 0x00 0x00 ...... .........&lt;br /&gt;
0x0020: 0x00 0xF1 0x42 0x80 0x93 0x02 0x06 0x09 0x09 0x00 0x00 0x00 0x00 0xF1 0x42 0x80 ..B...........B.&lt;br /&gt;
0x0030: 0x93 0x02 0x06 0x3F 0x02 0x06 0x0B 0x04 0x00 0x00 0x36 0xB0 0x02 0x06 0x05 0x04 ...?......6.....&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Konfigurieren des FPGA ===&lt;br /&gt;
Die eigentliche Konfiguration des FPGA erfolgt mit dem Menüpunkt &amp;quot;Program FPGA&amp;quot;.&lt;br /&gt;
Wenn alles geklappt hat steht nach kurzer Zeit &amp;quot;done&amp;quot; im Display, sonst erhält man eine entsprechende Fehlermeldung.&lt;br /&gt;
&lt;br /&gt;
== Optimierungen ==&lt;br /&gt;
In der ersten funktionierenden Implementation benötigte das Programm ca. 400 Sekunden um das FPGA zu konfigurieren. Das entspricht einer Datentransferrate von 1,1 kByte/s. Völlig unakzeptabel.&lt;br /&gt;
&lt;br /&gt;
Also musste optimiert werden. Der RC-Oszillator des AVR wird beim Startup auf 1 MHz Taktfrequenz kalibriert. Wenn man den Takteiler von 8 auf 1 stellt, läuft der AVR schon mit 8 MHz. Durch Programmieren des OSCCAL-Registers mit 0x7F ließ sich mein ATmega auf 15 MHz beschleunigen. Damit ließ sich die Konfigurationszeit auf 25 Sekunden (17 kByte/s) verringern. Schon besser.&lt;br /&gt;
&lt;br /&gt;
Damit sich die Zeit für den XMODEM-Transfer ebenfalls verkürzt, wird die Baudrate der seriellen Schnittstelle auf 115200 eingestellt. Der ATmega läuft nur für die Konfiguration mit der vollen Geschwindigkeit. Für eine fehlerfreie serielle Datenübertragung wird der RC-Oszillator auf eine Taktfrequenz von 11,0592 MHz kalibriert.&lt;br /&gt;
Bei wem das nicht klappen sollte, der muß eine kleinere Taktfrequenz im Makefile (F_CPU) einstellen. Laut ATmega169-Datenblatt müßten 8 MHz +/-10 Prozent immer funktionieren.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Geschwindigkeitssteigerung konnte durch die Nutzung des USI-Moduls erreicht werden. Normalerweise werden TDI, TDO, TCK und TMS durch Bitbanging erzeugt. Xilinx hat diese Funktionen in ports.c schön gekapselt. Sehr portabel, aber nicht schnell.&lt;br /&gt;
Durch direkten Aufruf der USI-Register in der Funktion xsvfShiftOnly konnte eine weitere wesentliche Beschleunigung erreicht werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin ist die Reihenfolge der Bits in den JTAG-Daten (LSB...MSB) nicht passend für das USI-Datenregister. Es müssen also alle Bytes gespiegelt werden. Am schnellsten geht dies mit einer Tabelle, die leider etwas Speicher kostet. Außerdem wurde die Zählerbreite lNumBits von 32 auf 16 Bit reduziert.&lt;br /&gt;
&lt;br /&gt;
Damit ergibt sich letztendlich eine akzeptable Konfigurationszeit von 5,6 Sekunden und damit eine Transferrate von 75 kByte/s. Der Flash des ATmega169 ist mit 12 kByte gut gefüllt, läßt aber noch etwas Luft für Erweiterungen.&lt;br /&gt;
&lt;br /&gt;
== Ausblick ==&lt;br /&gt;
Um die folgenden Features könnte das Projekt noch erweitert werden:&lt;br /&gt;
* Lesen der Konfiguration von SD-Karte&lt;br /&gt;
* direkte Interpretation von .bit-Dateien&lt;br /&gt;
* Unterstützung von komprimierten Daten&lt;br /&gt;
&lt;br /&gt;
== Download ==&lt;br /&gt;
[[media:butterfly_xapp058.zip]]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/user_guides/ug332.pdf UG332 Spartan-3 Generation Configuration User Guide]&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#bf_app AVR Butterfly Application code port to avr-gcc]&lt;br /&gt;
* [http://www.atmel.com/Images/doc1472.pdf AVR350: Xmodem CRC Receive Utility for AVR]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf XAPP058 Xilinx In-System Programming Using an Embedded Microcontroller]&lt;br /&gt;
&lt;br /&gt;
[[Category:FPGA-Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Boards]]&lt;/div&gt;</summary>
		<author><name>Horstsch</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=FPGA_Konfiguration_mit_AVR_Butterfly&amp;diff=67053</id>
		<title>FPGA Konfiguration mit AVR Butterfly</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=FPGA_Konfiguration_mit_AVR_Butterfly&amp;diff=67053"/>
		<updated>2012-06-26T21:59:26Z</updated>

		<summary type="html">&lt;p&gt;Horstsch: /* Hardware */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
Dieses Projekte stellt gewissermaßen eine Ergänzung zu [[Low_Cost_FPGA_Konfiguration]] dar.&lt;br /&gt;
Hier wurde ein [[AVR Butterfly]] genutzt, um einen FPGA Xilinx Spartan-3-1000 via [[JTAG]] zu konfigurieren. &lt;br /&gt;
&lt;br /&gt;
[[Bild:carrierboard_butterfly_xapp058.png| right | 360px]]&lt;br /&gt;
== Hardware ==&lt;br /&gt;
Da die Pins CCLK, Din und Done nicht zugänglich sind, mußte der Weg über die [[JTAG]]-Schnittstelle gegangen werden. Es wurde ein kleines Trägerboard für den Butterfly entwickelt, um alle benötigten Schnittstellen bequem unterzubringen.&lt;br /&gt;
&lt;br /&gt;
Der Dataflash auf dem Butterfly-Board hat eine Größe von 512 kByte. Da passen die ca. 402 kByte Konfigurationsdaten [http://www.xilinx.com/support/documentation/user_guides/ug332.pdf] für den der Spartan-3-1000 gut rein. Wer einen größeren FPGA konfigurieren möchte, braucht also auch den passenden Speicher dafür.&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:schematic_butterfly_xapp058.png | thumb | left | 640px| Schaltplan]]&lt;br /&gt;
&lt;br /&gt;
Der Butterfly wird mit einer externen Betriebsspannung von 3,3 V versorgt. Damit ergeben sich 3,3 V Pegel für die JTAG-Schnittstelle. Achtung, bei neueren FPGAs liegt die JTAG-Spannung bei 2,5 V oder 1,8 V. Die Referenzspannung der Zielhardware kann per Software geprüft werden.&lt;br /&gt;
&lt;br /&gt;
Das eigentliche Programmiergerät kann an JTAG_IN angeschlossen werden. Auf den in XAPP058 angegebenen Multiplexer zum Umschalten der JTAG-Quelle kann verzichtet werden, da der Mikrocontroller seine Ausgänge (ebenso wie das Programmiergerät) bei Nichtgebrauch hochohmig schaltet. Man darf natürlich nicht gleichzeitig mit dem Programmer und dem AVR per JTAG auf das FPGA zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
Als Grundgerüst für die Butterfly-Software wurde die gcc-Portiertung der Butterfly-Demo [http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#bf_app] verwendet.&lt;br /&gt;
Um die Daten sicher in den Dataflash zu bekommen, wird das XMODEM-Protokoll verwendet. Dazu gibt es von Atmel die Application Note AVR350 [http://www.atmel.com/Images/doc1472.pdf]. Und um letztendlich den FPGA zu konfigurieren wurde von Xilinx die Application Note XAPP058 [http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf] benutzt.&lt;br /&gt;
 &lt;br /&gt;
Damit das alles in den 16 kByte Flash des ATmega169 passt, wurde der Democode entschlackt.&lt;br /&gt;
Dann erfolgt die Anpassung des Xilinx-Codes: MAX_LEN (lenval.h) muß rigeros verringert werden, damit die Datenstrukturen von Xilinx in den Speicher von 1 kByte passen. Ich habe 128 gewählt. Das ist auch die maximale Größe, die Impact für die Konfigurationshäppchen verwendet. Außerdem muß noch die Kompression deaktiviert werden: XSVF_SUPPORT_COMPRESSION (micro.c). Damit schrumpft die Variable xsvfInfo auf 546 Byte.&lt;br /&gt;
&lt;br /&gt;
Alle Funktionen können bequem über das Bedienpanel des Butterfly abgerufen werden:&lt;br /&gt;
&lt;br /&gt;
=== Menüstruktur ===&lt;br /&gt;
[[Bild:menu_struktur.png]]&lt;br /&gt;
&lt;br /&gt;
== Workflow ==&lt;br /&gt;
Im Allgemeinen wird sich der folgende Workflow ergeben:&lt;br /&gt;
* XSVF-Daten generieren&lt;br /&gt;
* Download&lt;br /&gt;
* Konfigurieren des FPGA&lt;br /&gt;
&lt;br /&gt;
=== XSVF-Daten generieren ===&lt;br /&gt;
Die XSVF-Dateien können inzwischen direkt durch Xilinx-Impact erstellt werden.&lt;br /&gt;
Ich nutze dafür dieses kleine Skript (bit2xsvf.cmd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setmode -bs&lt;br /&gt;
setCable -port xsvf -file &amp;quot;design.xsvf&amp;quot;&lt;br /&gt;
addDevice -p 1 -file &amp;quot;design.bit&amp;quot;&lt;br /&gt;
program -p 1&lt;br /&gt;
closeCable&lt;br /&gt;
quit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Durch &amp;lt;pre&amp;gt;$ impact -batch bit2xsvf.cmd&amp;lt;/pre&amp;gt; wird die XSVF-Datei auf der Kommandozeile erstellt.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
Für den Download der XSVF-Datei in den Dataflash wird die serielle Schnittstelle auf 115200 Baud eingestellt und die Datei per XMODEM transferiert.&lt;br /&gt;
Mit der Linux-Kommandozeile geht das z.B. so:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ stty -F /dev/ttyS0 115200&lt;br /&gt;
$ sz --xmodem design.xsvf &amp;gt; /dev/ttyS0 &amp;lt; /dev/ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zur Kontrolle, kann der Inhalt des Dataflash auf der seriellen Schnittstelle ausgegeben werden (dump):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Page: 0&lt;br /&gt;
0x0000: 0x07 0x00 0x13 0x00 0x14 0x00 0x12 0x00 0x12 0x01 0x04 0x00 0x00 0x00 0x00 0x02 ................&lt;br /&gt;
0x0010: 0x06 0x09 0x08 0x00 0x00 0x00 0x20 0x01 0x0F 0xFF 0xFF 0xFF 0x09 0x00 0x00 0x00 ...... .........&lt;br /&gt;
0x0020: 0x00 0xF1 0x42 0x80 0x93 0x02 0x06 0x09 0x09 0x00 0x00 0x00 0x00 0xF1 0x42 0x80 ..B...........B.&lt;br /&gt;
0x0030: 0x93 0x02 0x06 0x3F 0x02 0x06 0x0B 0x04 0x00 0x00 0x36 0xB0 0x02 0x06 0x05 0x04 ...?......6.....&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Konfigurieren des FPGA ===&lt;br /&gt;
Die eigentliche Konfiguration des FPGA erfolgt mit dem Menüpunkt &amp;quot;Program FPGA&amp;quot;.&lt;br /&gt;
Wenn alles geklappt hat steht nach kurzer Zeit &amp;quot;done&amp;quot; im Display, sonst erhält man eine entsprechende Fehlermeldung.&lt;br /&gt;
&lt;br /&gt;
== Optimierungen ==&lt;br /&gt;
In der ersten funktionierenden Implementation benötigte das Programm ca. 400 Sekunden um das FPGA zu konfigurieren. Das entspricht einer Datentransferrate von 1,1 kByte/s. Völlig unakzeptabel.&lt;br /&gt;
&lt;br /&gt;
Also musste optimiert werden. Der RC-Oszillator des AVR wird beim Startup auf 1 MHz Taktfrequenz kalibriert. Wenn man den Takteiler von 8 auf 1 stellt, läuft der AVR schon mit 8 MHz. Durch Programmieren des OSCCAL-Registers mit 0x7F ließ sich mein ATmega auf 15 MHz beschleunigen. Damit ließ sich die Konfigurationszeit auf 25 Sekunden (17 kByte/s) verringern. Schon besser.&lt;br /&gt;
&lt;br /&gt;
Damit sich die Zeit für den XMODEM-Transfer ebenfalls verkürzt, wird die Baudrate der seriellen Schnittstelle auf 115200 eingestellt. Der ATmega läuft nur für die Konfiguration mit der vollen Geschwindigkeit. Für eine fehlerfreie serielle Datenübertragung wird der RC-Oszillator auf eine Taktfrequenz von 11,0592 MHz kalibriert.&lt;br /&gt;
Bei wem das nicht klappen sollte, der muß eine kleinere Taktfrequenz im Makefile (F_CPU) einstellen. Laut ATmega169-Datenblatt müßten 8 MHz +/-10 Prozent immer funktionieren.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Geschwindigkeitssteigerung konnte durch die Nutzung des USI-Moduls erreicht werden. Normalerweise werden TDI, TDO, TCK und TMS durch Bitbanging erzeugt. Xilinx hat diese Funktionen in ports.c schön gekapselt. Sehr portabel, aber nicht schnell.&lt;br /&gt;
Durch direkten Aufruf der USI-Register in der Funktion xsvfShiftOnly konnte eine weitere wesentliche Beschleunigung erreicht werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin ist die Reihenfolge der Bits in den JTAG-Daten (LSB...MSB) nicht passend für das USI-Datenregister. Es müssen also alle Bytes gespiegelt werden. Am schnellsten geht dies mit einer Tabelle, die leider etwas Speicher kostet. Außerdem wurde die Zählerbreite lNumBits von 32 auf 16 Bit reduziert.&lt;br /&gt;
&lt;br /&gt;
Damit ergibt sich letztendlich eine akzeptable Konfigurationszeit von 5,6 Sekunden und damit eine Transferrate von 75 kByte/s. Der Flash des ATmega169 ist mit 12 kByte gut gefüllt, läßt aber noch etwas Luft für Erweiterungen.&lt;br /&gt;
&lt;br /&gt;
== Ausblick ==&lt;br /&gt;
Um die folgenden Features könnte das Projekt noch erweitert werden:&lt;br /&gt;
* Lesen der Konfiguration von SD-Karte&lt;br /&gt;
* direkte Interpretation von .bit-Dateien&lt;br /&gt;
* Unterstützung von komprimierten Daten&lt;br /&gt;
&lt;br /&gt;
== Download ==&lt;br /&gt;
[[media:butterfly_xapp058.zip]]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/user_guides/ug332.pdf UG332 Spartan-3 Generation Configuration User Guide]&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#bf_app AVR Butterfly Application code port to avr-gcc]&lt;br /&gt;
* [http://www.atmel.com/Images/doc1472.pdf AVR350: Xmodem CRC Receive Utility for AVR]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf XAPP058 Xilinx In-System Programming Using an Embedded Microcontroller]&lt;br /&gt;
&lt;br /&gt;
[[Category:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Horstsch</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=FPGA_Konfiguration_mit_AVR_Butterfly&amp;diff=67052</id>
		<title>FPGA Konfiguration mit AVR Butterfly</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=FPGA_Konfiguration_mit_AVR_Butterfly&amp;diff=67052"/>
		<updated>2012-06-26T21:57:43Z</updated>

		<summary type="html">&lt;p&gt;Horstsch: /* Schaltplan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
Dieses Projekte stellt gewissermaßen eine Ergänzung zu [[Low_Cost_FPGA_Konfiguration]] dar.&lt;br /&gt;
Hier wurde ein [[AVR Butterfly]] genutzt, um einen FPGA Xilinx Spartan-3-1000 via [[JTAG]] zu konfigurieren. &lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
Da die Pins CCLK, Din und Done nicht zugänglich sind, mußte der Weg über die [[JTAG]]-Schnittstelle gegangen werden. Es wurde ein kleines Trägerboard für den Butterfly entwickelt, um alle benötigten Schnittstellen bequem unterzubringen.&lt;br /&gt;
[[Bild:carrierboard_butterfly_xapp058.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Der Dataflash auf dem Butterfly-Board hat eine Größe von 512 kByte. Da passen die ca. 402 kByte Konfigurationsdaten [http://www.xilinx.com/support/documentation/user_guides/ug332.pdf] für den der Spartan-3-1000 gut rein. Wer einen größeren FPGA konfigurieren möchte, braucht also auch den passenden Speicher dafür.&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:schematic_butterfly_xapp058.png | thumb | left | 640px| Schaltplan]]&lt;br /&gt;
&lt;br /&gt;
Der Butterfly wird mit einer externen Betriebsspannung von 3,3 V versorgt. Damit ergeben sich 3,3 V Pegel für die JTAG-Schnittstelle. Achtung, bei neueren FPGAs liegt die JTAG-Spannung bei 2,5 V oder 1,8 V. Die Referenzspannung der Zielhardware kann per Software geprüft werden.&lt;br /&gt;
&lt;br /&gt;
Das eigentliche Programmiergerät kann an JTAG_IN angeschlossen werden. Auf den in XAPP058 angegebenen Multiplexer zum Umschalten der JTAG-Quelle kann verzichtet werden, da der Mikrocontroller seine Ausgänge (ebenso wie das Programmiergerät) bei Nichtgebrauch hochohmig schaltet. Man darf natürlich nicht gleichzeitig mit dem Programmer und dem AVR per JTAG auf das FPGA zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
Als Grundgerüst für die Butterfly-Software wurde die gcc-Portiertung der Butterfly-Demo [http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#bf_app] verwendet.&lt;br /&gt;
Um die Daten sicher in den Dataflash zu bekommen, wird das XMODEM-Protokoll verwendet. Dazu gibt es von Atmel die Application Note AVR350 [http://www.atmel.com/Images/doc1472.pdf]. Und um letztendlich den FPGA zu konfigurieren wurde von Xilinx die Application Note XAPP058 [http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf] benutzt.&lt;br /&gt;
 &lt;br /&gt;
Damit das alles in den 16 kByte Flash des ATmega169 passt, wurde der Democode entschlackt.&lt;br /&gt;
Dann erfolgt die Anpassung des Xilinx-Codes: MAX_LEN (lenval.h) muß rigeros verringert werden, damit die Datenstrukturen von Xilinx in den Speicher von 1 kByte passen. Ich habe 128 gewählt. Das ist auch die maximale Größe, die Impact für die Konfigurationshäppchen verwendet. Außerdem muß noch die Kompression deaktiviert werden: XSVF_SUPPORT_COMPRESSION (micro.c). Damit schrumpft die Variable xsvfInfo auf 546 Byte.&lt;br /&gt;
&lt;br /&gt;
Alle Funktionen können bequem über das Bedienpanel des Butterfly abgerufen werden:&lt;br /&gt;
&lt;br /&gt;
=== Menüstruktur ===&lt;br /&gt;
[[Bild:menu_struktur.png]]&lt;br /&gt;
&lt;br /&gt;
== Workflow ==&lt;br /&gt;
Im Allgemeinen wird sich der folgende Workflow ergeben:&lt;br /&gt;
* XSVF-Daten generieren&lt;br /&gt;
* Download&lt;br /&gt;
* Konfigurieren des FPGA&lt;br /&gt;
&lt;br /&gt;
=== XSVF-Daten generieren ===&lt;br /&gt;
Die XSVF-Dateien können inzwischen direkt durch Xilinx-Impact erstellt werden.&lt;br /&gt;
Ich nutze dafür dieses kleine Skript (bit2xsvf.cmd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setmode -bs&lt;br /&gt;
setCable -port xsvf -file &amp;quot;design.xsvf&amp;quot;&lt;br /&gt;
addDevice -p 1 -file &amp;quot;design.bit&amp;quot;&lt;br /&gt;
program -p 1&lt;br /&gt;
closeCable&lt;br /&gt;
quit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Durch &amp;lt;pre&amp;gt;$ impact -batch bit2xsvf.cmd&amp;lt;/pre&amp;gt; wird die XSVF-Datei auf der Kommandozeile erstellt.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
Für den Download der XSVF-Datei in den Dataflash wird die serielle Schnittstelle auf 115200 Baud eingestellt und die Datei per XMODEM transferiert.&lt;br /&gt;
Mit der Linux-Kommandozeile geht das z.B. so:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ stty -F /dev/ttyS0 115200&lt;br /&gt;
$ sz --xmodem design.xsvf &amp;gt; /dev/ttyS0 &amp;lt; /dev/ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zur Kontrolle, kann der Inhalt des Dataflash auf der seriellen Schnittstelle ausgegeben werden (dump):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Page: 0&lt;br /&gt;
0x0000: 0x07 0x00 0x13 0x00 0x14 0x00 0x12 0x00 0x12 0x01 0x04 0x00 0x00 0x00 0x00 0x02 ................&lt;br /&gt;
0x0010: 0x06 0x09 0x08 0x00 0x00 0x00 0x20 0x01 0x0F 0xFF 0xFF 0xFF 0x09 0x00 0x00 0x00 ...... .........&lt;br /&gt;
0x0020: 0x00 0xF1 0x42 0x80 0x93 0x02 0x06 0x09 0x09 0x00 0x00 0x00 0x00 0xF1 0x42 0x80 ..B...........B.&lt;br /&gt;
0x0030: 0x93 0x02 0x06 0x3F 0x02 0x06 0x0B 0x04 0x00 0x00 0x36 0xB0 0x02 0x06 0x05 0x04 ...?......6.....&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Konfigurieren des FPGA ===&lt;br /&gt;
Die eigentliche Konfiguration des FPGA erfolgt mit dem Menüpunkt &amp;quot;Program FPGA&amp;quot;.&lt;br /&gt;
Wenn alles geklappt hat steht nach kurzer Zeit &amp;quot;done&amp;quot; im Display, sonst erhält man eine entsprechende Fehlermeldung.&lt;br /&gt;
&lt;br /&gt;
== Optimierungen ==&lt;br /&gt;
In der ersten funktionierenden Implementation benötigte das Programm ca. 400 Sekunden um das FPGA zu konfigurieren. Das entspricht einer Datentransferrate von 1,1 kByte/s. Völlig unakzeptabel.&lt;br /&gt;
&lt;br /&gt;
Also musste optimiert werden. Der RC-Oszillator des AVR wird beim Startup auf 1 MHz Taktfrequenz kalibriert. Wenn man den Takteiler von 8 auf 1 stellt, läuft der AVR schon mit 8 MHz. Durch Programmieren des OSCCAL-Registers mit 0x7F ließ sich mein ATmega auf 15 MHz beschleunigen. Damit ließ sich die Konfigurationszeit auf 25 Sekunden (17 kByte/s) verringern. Schon besser.&lt;br /&gt;
&lt;br /&gt;
Damit sich die Zeit für den XMODEM-Transfer ebenfalls verkürzt, wird die Baudrate der seriellen Schnittstelle auf 115200 eingestellt. Der ATmega läuft nur für die Konfiguration mit der vollen Geschwindigkeit. Für eine fehlerfreie serielle Datenübertragung wird der RC-Oszillator auf eine Taktfrequenz von 11,0592 MHz kalibriert.&lt;br /&gt;
Bei wem das nicht klappen sollte, der muß eine kleinere Taktfrequenz im Makefile (F_CPU) einstellen. Laut ATmega169-Datenblatt müßten 8 MHz +/-10 Prozent immer funktionieren.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Geschwindigkeitssteigerung konnte durch die Nutzung des USI-Moduls erreicht werden. Normalerweise werden TDI, TDO, TCK und TMS durch Bitbanging erzeugt. Xilinx hat diese Funktionen in ports.c schön gekapselt. Sehr portabel, aber nicht schnell.&lt;br /&gt;
Durch direkten Aufruf der USI-Register in der Funktion xsvfShiftOnly konnte eine weitere wesentliche Beschleunigung erreicht werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin ist die Reihenfolge der Bits in den JTAG-Daten (LSB...MSB) nicht passend für das USI-Datenregister. Es müssen also alle Bytes gespiegelt werden. Am schnellsten geht dies mit einer Tabelle, die leider etwas Speicher kostet. Außerdem wurde die Zählerbreite lNumBits von 32 auf 16 Bit reduziert.&lt;br /&gt;
&lt;br /&gt;
Damit ergibt sich letztendlich eine akzeptable Konfigurationszeit von 5,6 Sekunden und damit eine Transferrate von 75 kByte/s. Der Flash des ATmega169 ist mit 12 kByte gut gefüllt, läßt aber noch etwas Luft für Erweiterungen.&lt;br /&gt;
&lt;br /&gt;
== Ausblick ==&lt;br /&gt;
Um die folgenden Features könnte das Projekt noch erweitert werden:&lt;br /&gt;
* Lesen der Konfiguration von SD-Karte&lt;br /&gt;
* direkte Interpretation von .bit-Dateien&lt;br /&gt;
* Unterstützung von komprimierten Daten&lt;br /&gt;
&lt;br /&gt;
== Download ==&lt;br /&gt;
[[media:butterfly_xapp058.zip]]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/user_guides/ug332.pdf UG332 Spartan-3 Generation Configuration User Guide]&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#bf_app AVR Butterfly Application code port to avr-gcc]&lt;br /&gt;
* [http://www.atmel.com/Images/doc1472.pdf AVR350: Xmodem CRC Receive Utility for AVR]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf XAPP058 Xilinx In-System Programming Using an Embedded Microcontroller]&lt;br /&gt;
&lt;br /&gt;
[[Category:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Horstsch</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=FPGA_Konfiguration_mit_AVR_Butterfly&amp;diff=67051</id>
		<title>FPGA Konfiguration mit AVR Butterfly</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=FPGA_Konfiguration_mit_AVR_Butterfly&amp;diff=67051"/>
		<updated>2012-06-26T21:56:09Z</updated>

		<summary type="html">&lt;p&gt;Horstsch: /* Schaltplan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
Dieses Projekte stellt gewissermaßen eine Ergänzung zu [[Low_Cost_FPGA_Konfiguration]] dar.&lt;br /&gt;
Hier wurde ein [[AVR Butterfly]] genutzt, um einen FPGA Xilinx Spartan-3-1000 via [[JTAG]] zu konfigurieren. &lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
Da die Pins CCLK, Din und Done nicht zugänglich sind, mußte der Weg über die [[JTAG]]-Schnittstelle gegangen werden. Es wurde ein kleines Trägerboard für den Butterfly entwickelt, um alle benötigten Schnittstellen bequem unterzubringen.&lt;br /&gt;
[[Bild:carrierboard_butterfly_xapp058.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Der Dataflash auf dem Butterfly-Board hat eine Größe von 512 kByte. Da passen die ca. 402 kByte Konfigurationsdaten [http://www.xilinx.com/support/documentation/user_guides/ug332.pdf] für den der Spartan-3-1000 gut rein. Wer einen größeren FPGA konfigurieren möchte, braucht also auch den passenden Speicher dafür.&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:schematic_butterfly_xapp058.png|1095px]]&lt;br /&gt;
&lt;br /&gt;
Der Butterfly wird mit einer externen Betriebsspannung von 3,3 V versorgt. Damit ergeben sich 3,3 V Pegel für die JTAG-Schnittstelle. Achtung, bei neueren FPGAs liegt die JTAG-Spannung bei 2,5 V oder 1,8 V. Die Referenzspannung der Zielhardware kann per Software geprüft werden.&lt;br /&gt;
&lt;br /&gt;
Das eigentliche Programmiergerät kann an JTAG_IN angeschlossen werden. Auf den in XAPP058 angegebenen Multiplexer zum Umschalten der JTAG-Quelle kann verzichtet werden, da der Mikrocontroller seine Ausgänge (ebenso wie das Programmiergerät) bei Nichtgebrauch hochohmig schaltet. Man darf natürlich nicht gleichzeitig mit dem Programmer und dem AVR per JTAG auf das FPGA zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
Als Grundgerüst für die Butterfly-Software wurde die gcc-Portiertung der Butterfly-Demo [http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#bf_app] verwendet.&lt;br /&gt;
Um die Daten sicher in den Dataflash zu bekommen, wird das XMODEM-Protokoll verwendet. Dazu gibt es von Atmel die Application Note AVR350 [http://www.atmel.com/Images/doc1472.pdf]. Und um letztendlich den FPGA zu konfigurieren wurde von Xilinx die Application Note XAPP058 [http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf] benutzt.&lt;br /&gt;
 &lt;br /&gt;
Damit das alles in den 16 kByte Flash des ATmega169 passt, wurde der Democode entschlackt.&lt;br /&gt;
Dann erfolgt die Anpassung des Xilinx-Codes: MAX_LEN (lenval.h) muß rigeros verringert werden, damit die Datenstrukturen von Xilinx in den Speicher von 1 kByte passen. Ich habe 128 gewählt. Das ist auch die maximale Größe, die Impact für die Konfigurationshäppchen verwendet. Außerdem muß noch die Kompression deaktiviert werden: XSVF_SUPPORT_COMPRESSION (micro.c). Damit schrumpft die Variable xsvfInfo auf 546 Byte.&lt;br /&gt;
&lt;br /&gt;
Alle Funktionen können bequem über das Bedienpanel des Butterfly abgerufen werden:&lt;br /&gt;
&lt;br /&gt;
=== Menüstruktur ===&lt;br /&gt;
[[Bild:menu_struktur.png]]&lt;br /&gt;
&lt;br /&gt;
== Workflow ==&lt;br /&gt;
Im Allgemeinen wird sich der folgende Workflow ergeben:&lt;br /&gt;
* XSVF-Daten generieren&lt;br /&gt;
* Download&lt;br /&gt;
* Konfigurieren des FPGA&lt;br /&gt;
&lt;br /&gt;
=== XSVF-Daten generieren ===&lt;br /&gt;
Die XSVF-Dateien können inzwischen direkt durch Xilinx-Impact erstellt werden.&lt;br /&gt;
Ich nutze dafür dieses kleine Skript (bit2xsvf.cmd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setmode -bs&lt;br /&gt;
setCable -port xsvf -file &amp;quot;design.xsvf&amp;quot;&lt;br /&gt;
addDevice -p 1 -file &amp;quot;design.bit&amp;quot;&lt;br /&gt;
program -p 1&lt;br /&gt;
closeCable&lt;br /&gt;
quit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Durch &amp;lt;pre&amp;gt;$ impact -batch bit2xsvf.cmd&amp;lt;/pre&amp;gt; wird die XSVF-Datei auf der Kommandozeile erstellt.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
Für den Download der XSVF-Datei in den Dataflash wird die serielle Schnittstelle auf 115200 Baud eingestellt und die Datei per XMODEM transferiert.&lt;br /&gt;
Mit der Linux-Kommandozeile geht das z.B. so:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ stty -F /dev/ttyS0 115200&lt;br /&gt;
$ sz --xmodem design.xsvf &amp;gt; /dev/ttyS0 &amp;lt; /dev/ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zur Kontrolle, kann der Inhalt des Dataflash auf der seriellen Schnittstelle ausgegeben werden (dump):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Page: 0&lt;br /&gt;
0x0000: 0x07 0x00 0x13 0x00 0x14 0x00 0x12 0x00 0x12 0x01 0x04 0x00 0x00 0x00 0x00 0x02 ................&lt;br /&gt;
0x0010: 0x06 0x09 0x08 0x00 0x00 0x00 0x20 0x01 0x0F 0xFF 0xFF 0xFF 0x09 0x00 0x00 0x00 ...... .........&lt;br /&gt;
0x0020: 0x00 0xF1 0x42 0x80 0x93 0x02 0x06 0x09 0x09 0x00 0x00 0x00 0x00 0xF1 0x42 0x80 ..B...........B.&lt;br /&gt;
0x0030: 0x93 0x02 0x06 0x3F 0x02 0x06 0x0B 0x04 0x00 0x00 0x36 0xB0 0x02 0x06 0x05 0x04 ...?......6.....&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Konfigurieren des FPGA ===&lt;br /&gt;
Die eigentliche Konfiguration des FPGA erfolgt mit dem Menüpunkt &amp;quot;Program FPGA&amp;quot;.&lt;br /&gt;
Wenn alles geklappt hat steht nach kurzer Zeit &amp;quot;done&amp;quot; im Display, sonst erhält man eine entsprechende Fehlermeldung.&lt;br /&gt;
&lt;br /&gt;
== Optimierungen ==&lt;br /&gt;
In der ersten funktionierenden Implementation benötigte das Programm ca. 400 Sekunden um das FPGA zu konfigurieren. Das entspricht einer Datentransferrate von 1,1 kByte/s. Völlig unakzeptabel.&lt;br /&gt;
&lt;br /&gt;
Also musste optimiert werden. Der RC-Oszillator des AVR wird beim Startup auf 1 MHz Taktfrequenz kalibriert. Wenn man den Takteiler von 8 auf 1 stellt, läuft der AVR schon mit 8 MHz. Durch Programmieren des OSCCAL-Registers mit 0x7F ließ sich mein ATmega auf 15 MHz beschleunigen. Damit ließ sich die Konfigurationszeit auf 25 Sekunden (17 kByte/s) verringern. Schon besser.&lt;br /&gt;
&lt;br /&gt;
Damit sich die Zeit für den XMODEM-Transfer ebenfalls verkürzt, wird die Baudrate der seriellen Schnittstelle auf 115200 eingestellt. Der ATmega läuft nur für die Konfiguration mit der vollen Geschwindigkeit. Für eine fehlerfreie serielle Datenübertragung wird der RC-Oszillator auf eine Taktfrequenz von 11,0592 MHz kalibriert.&lt;br /&gt;
Bei wem das nicht klappen sollte, der muß eine kleinere Taktfrequenz im Makefile (F_CPU) einstellen. Laut ATmega169-Datenblatt müßten 8 MHz +/-10 Prozent immer funktionieren.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Geschwindigkeitssteigerung konnte durch die Nutzung des USI-Moduls erreicht werden. Normalerweise werden TDI, TDO, TCK und TMS durch Bitbanging erzeugt. Xilinx hat diese Funktionen in ports.c schön gekapselt. Sehr portabel, aber nicht schnell.&lt;br /&gt;
Durch direkten Aufruf der USI-Register in der Funktion xsvfShiftOnly konnte eine weitere wesentliche Beschleunigung erreicht werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin ist die Reihenfolge der Bits in den JTAG-Daten (LSB...MSB) nicht passend für das USI-Datenregister. Es müssen also alle Bytes gespiegelt werden. Am schnellsten geht dies mit einer Tabelle, die leider etwas Speicher kostet. Außerdem wurde die Zählerbreite lNumBits von 32 auf 16 Bit reduziert.&lt;br /&gt;
&lt;br /&gt;
Damit ergibt sich letztendlich eine akzeptable Konfigurationszeit von 5,6 Sekunden und damit eine Transferrate von 75 kByte/s. Der Flash des ATmega169 ist mit 12 kByte gut gefüllt, läßt aber noch etwas Luft für Erweiterungen.&lt;br /&gt;
&lt;br /&gt;
== Ausblick ==&lt;br /&gt;
Um die folgenden Features könnte das Projekt noch erweitert werden:&lt;br /&gt;
* Lesen der Konfiguration von SD-Karte&lt;br /&gt;
* direkte Interpretation von .bit-Dateien&lt;br /&gt;
* Unterstützung von komprimierten Daten&lt;br /&gt;
&lt;br /&gt;
== Download ==&lt;br /&gt;
[[media:butterfly_xapp058.zip]]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/user_guides/ug332.pdf UG332 Spartan-3 Generation Configuration User Guide]&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#bf_app AVR Butterfly Application code port to avr-gcc]&lt;br /&gt;
* [http://www.atmel.com/Images/doc1472.pdf AVR350: Xmodem CRC Receive Utility for AVR]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf XAPP058 Xilinx In-System Programming Using an Embedded Microcontroller]&lt;br /&gt;
&lt;br /&gt;
[[Category:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Horstsch</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=FPGA_Konfiguration_mit_AVR_Butterfly&amp;diff=67050</id>
		<title>FPGA Konfiguration mit AVR Butterfly</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=FPGA_Konfiguration_mit_AVR_Butterfly&amp;diff=67050"/>
		<updated>2012-06-26T21:55:34Z</updated>

		<summary type="html">&lt;p&gt;Horstsch: /* Hardware */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
Dieses Projekte stellt gewissermaßen eine Ergänzung zu [[Low_Cost_FPGA_Konfiguration]] dar.&lt;br /&gt;
Hier wurde ein [[AVR Butterfly]] genutzt, um einen FPGA Xilinx Spartan-3-1000 via [[JTAG]] zu konfigurieren. &lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
Da die Pins CCLK, Din und Done nicht zugänglich sind, mußte der Weg über die [[JTAG]]-Schnittstelle gegangen werden. Es wurde ein kleines Trägerboard für den Butterfly entwickelt, um alle benötigten Schnittstellen bequem unterzubringen.&lt;br /&gt;
[[Bild:carrierboard_butterfly_xapp058.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Der Dataflash auf dem Butterfly-Board hat eine Größe von 512 kByte. Da passen die ca. 402 kByte Konfigurationsdaten [http://www.xilinx.com/support/documentation/user_guides/ug332.pdf] für den der Spartan-3-1000 gut rein. Wer einen größeren FPGA konfigurieren möchte, braucht also auch den passenden Speicher dafür.&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:schematic_butterfly_xapp058.png]]&lt;br /&gt;
&lt;br /&gt;
Der Butterfly wird mit einer externen Betriebsspannung von 3,3 V versorgt. Damit ergeben sich 3,3 V Pegel für die JTAG-Schnittstelle. Achtung, bei neueren FPGAs liegt die JTAG-Spannung bei 2,5 V oder 1,8 V. Die Referenzspannung der Zielhardware kann per Software geprüft werden.&lt;br /&gt;
&lt;br /&gt;
Das eigentliche Programmiergerät kann an JTAG_IN angeschlossen werden. Auf den in XAPP058 angegebenen Multiplexer zum Umschalten der JTAG-Quelle kann verzichtet werden, da der Mikrocontroller seine Ausgänge (ebenso wie das Programmiergerät) bei Nichtgebrauch hochohmig schaltet. Man darf natürlich nicht gleichzeitig mit dem Programmer und dem AVR per JTAG auf das FPGA zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
Als Grundgerüst für die Butterfly-Software wurde die gcc-Portiertung der Butterfly-Demo [http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#bf_app] verwendet.&lt;br /&gt;
Um die Daten sicher in den Dataflash zu bekommen, wird das XMODEM-Protokoll verwendet. Dazu gibt es von Atmel die Application Note AVR350 [http://www.atmel.com/Images/doc1472.pdf]. Und um letztendlich den FPGA zu konfigurieren wurde von Xilinx die Application Note XAPP058 [http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf] benutzt.&lt;br /&gt;
 &lt;br /&gt;
Damit das alles in den 16 kByte Flash des ATmega169 passt, wurde der Democode entschlackt.&lt;br /&gt;
Dann erfolgt die Anpassung des Xilinx-Codes: MAX_LEN (lenval.h) muß rigeros verringert werden, damit die Datenstrukturen von Xilinx in den Speicher von 1 kByte passen. Ich habe 128 gewählt. Das ist auch die maximale Größe, die Impact für die Konfigurationshäppchen verwendet. Außerdem muß noch die Kompression deaktiviert werden: XSVF_SUPPORT_COMPRESSION (micro.c). Damit schrumpft die Variable xsvfInfo auf 546 Byte.&lt;br /&gt;
&lt;br /&gt;
Alle Funktionen können bequem über das Bedienpanel des Butterfly abgerufen werden:&lt;br /&gt;
&lt;br /&gt;
=== Menüstruktur ===&lt;br /&gt;
[[Bild:menu_struktur.png]]&lt;br /&gt;
&lt;br /&gt;
== Workflow ==&lt;br /&gt;
Im Allgemeinen wird sich der folgende Workflow ergeben:&lt;br /&gt;
* XSVF-Daten generieren&lt;br /&gt;
* Download&lt;br /&gt;
* Konfigurieren des FPGA&lt;br /&gt;
&lt;br /&gt;
=== XSVF-Daten generieren ===&lt;br /&gt;
Die XSVF-Dateien können inzwischen direkt durch Xilinx-Impact erstellt werden.&lt;br /&gt;
Ich nutze dafür dieses kleine Skript (bit2xsvf.cmd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setmode -bs&lt;br /&gt;
setCable -port xsvf -file &amp;quot;design.xsvf&amp;quot;&lt;br /&gt;
addDevice -p 1 -file &amp;quot;design.bit&amp;quot;&lt;br /&gt;
program -p 1&lt;br /&gt;
closeCable&lt;br /&gt;
quit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Durch &amp;lt;pre&amp;gt;$ impact -batch bit2xsvf.cmd&amp;lt;/pre&amp;gt; wird die XSVF-Datei auf der Kommandozeile erstellt.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
Für den Download der XSVF-Datei in den Dataflash wird die serielle Schnittstelle auf 115200 Baud eingestellt und die Datei per XMODEM transferiert.&lt;br /&gt;
Mit der Linux-Kommandozeile geht das z.B. so:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ stty -F /dev/ttyS0 115200&lt;br /&gt;
$ sz --xmodem design.xsvf &amp;gt; /dev/ttyS0 &amp;lt; /dev/ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zur Kontrolle, kann der Inhalt des Dataflash auf der seriellen Schnittstelle ausgegeben werden (dump):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Page: 0&lt;br /&gt;
0x0000: 0x07 0x00 0x13 0x00 0x14 0x00 0x12 0x00 0x12 0x01 0x04 0x00 0x00 0x00 0x00 0x02 ................&lt;br /&gt;
0x0010: 0x06 0x09 0x08 0x00 0x00 0x00 0x20 0x01 0x0F 0xFF 0xFF 0xFF 0x09 0x00 0x00 0x00 ...... .........&lt;br /&gt;
0x0020: 0x00 0xF1 0x42 0x80 0x93 0x02 0x06 0x09 0x09 0x00 0x00 0x00 0x00 0xF1 0x42 0x80 ..B...........B.&lt;br /&gt;
0x0030: 0x93 0x02 0x06 0x3F 0x02 0x06 0x0B 0x04 0x00 0x00 0x36 0xB0 0x02 0x06 0x05 0x04 ...?......6.....&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Konfigurieren des FPGA ===&lt;br /&gt;
Die eigentliche Konfiguration des FPGA erfolgt mit dem Menüpunkt &amp;quot;Program FPGA&amp;quot;.&lt;br /&gt;
Wenn alles geklappt hat steht nach kurzer Zeit &amp;quot;done&amp;quot; im Display, sonst erhält man eine entsprechende Fehlermeldung.&lt;br /&gt;
&lt;br /&gt;
== Optimierungen ==&lt;br /&gt;
In der ersten funktionierenden Implementation benötigte das Programm ca. 400 Sekunden um das FPGA zu konfigurieren. Das entspricht einer Datentransferrate von 1,1 kByte/s. Völlig unakzeptabel.&lt;br /&gt;
&lt;br /&gt;
Also musste optimiert werden. Der RC-Oszillator des AVR wird beim Startup auf 1 MHz Taktfrequenz kalibriert. Wenn man den Takteiler von 8 auf 1 stellt, läuft der AVR schon mit 8 MHz. Durch Programmieren des OSCCAL-Registers mit 0x7F ließ sich mein ATmega auf 15 MHz beschleunigen. Damit ließ sich die Konfigurationszeit auf 25 Sekunden (17 kByte/s) verringern. Schon besser.&lt;br /&gt;
&lt;br /&gt;
Damit sich die Zeit für den XMODEM-Transfer ebenfalls verkürzt, wird die Baudrate der seriellen Schnittstelle auf 115200 eingestellt. Der ATmega läuft nur für die Konfiguration mit der vollen Geschwindigkeit. Für eine fehlerfreie serielle Datenübertragung wird der RC-Oszillator auf eine Taktfrequenz von 11,0592 MHz kalibriert.&lt;br /&gt;
Bei wem das nicht klappen sollte, der muß eine kleinere Taktfrequenz im Makefile (F_CPU) einstellen. Laut ATmega169-Datenblatt müßten 8 MHz +/-10 Prozent immer funktionieren.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Geschwindigkeitssteigerung konnte durch die Nutzung des USI-Moduls erreicht werden. Normalerweise werden TDI, TDO, TCK und TMS durch Bitbanging erzeugt. Xilinx hat diese Funktionen in ports.c schön gekapselt. Sehr portabel, aber nicht schnell.&lt;br /&gt;
Durch direkten Aufruf der USI-Register in der Funktion xsvfShiftOnly konnte eine weitere wesentliche Beschleunigung erreicht werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin ist die Reihenfolge der Bits in den JTAG-Daten (LSB...MSB) nicht passend für das USI-Datenregister. Es müssen also alle Bytes gespiegelt werden. Am schnellsten geht dies mit einer Tabelle, die leider etwas Speicher kostet. Außerdem wurde die Zählerbreite lNumBits von 32 auf 16 Bit reduziert.&lt;br /&gt;
&lt;br /&gt;
Damit ergibt sich letztendlich eine akzeptable Konfigurationszeit von 5,6 Sekunden und damit eine Transferrate von 75 kByte/s. Der Flash des ATmega169 ist mit 12 kByte gut gefüllt, läßt aber noch etwas Luft für Erweiterungen.&lt;br /&gt;
&lt;br /&gt;
== Ausblick ==&lt;br /&gt;
Um die folgenden Features könnte das Projekt noch erweitert werden:&lt;br /&gt;
* Lesen der Konfiguration von SD-Karte&lt;br /&gt;
* direkte Interpretation von .bit-Dateien&lt;br /&gt;
* Unterstützung von komprimierten Daten&lt;br /&gt;
&lt;br /&gt;
== Download ==&lt;br /&gt;
[[media:butterfly_xapp058.zip]]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/user_guides/ug332.pdf UG332 Spartan-3 Generation Configuration User Guide]&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#bf_app AVR Butterfly Application code port to avr-gcc]&lt;br /&gt;
* [http://www.atmel.com/Images/doc1472.pdf AVR350: Xmodem CRC Receive Utility for AVR]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf XAPP058 Xilinx In-System Programming Using an Embedded Microcontroller]&lt;br /&gt;
&lt;br /&gt;
[[Category:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Horstsch</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Carrierboard_butterfly_xapp058.png&amp;diff=67049</id>
		<title>Datei:Carrierboard butterfly xapp058.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Carrierboard_butterfly_xapp058.png&amp;diff=67049"/>
		<updated>2012-06-26T21:54:26Z</updated>

		<summary type="html">&lt;p&gt;Horstsch: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Horstsch</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Schematic_butterfly_xapp058.png&amp;diff=67048</id>
		<title>Datei:Schematic butterfly xapp058.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Schematic_butterfly_xapp058.png&amp;diff=67048"/>
		<updated>2012-06-26T21:53:38Z</updated>

		<summary type="html">&lt;p&gt;Horstsch: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Horstsch</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Menu_struktur.png&amp;diff=67047</id>
		<title>Datei:Menu struktur.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Menu_struktur.png&amp;diff=67047"/>
		<updated>2012-06-26T21:52:43Z</updated>

		<summary type="html">&lt;p&gt;Horstsch: hat eine neue Version von „Datei:Menu struktur.png“ hochgeladen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Horstsch</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Menu_struktur.png&amp;diff=67046</id>
		<title>Datei:Menu struktur.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Menu_struktur.png&amp;diff=67046"/>
		<updated>2012-06-26T21:51:02Z</updated>

		<summary type="html">&lt;p&gt;Horstsch: hat eine neue Version von „Datei:Menu struktur.png“ hochgeladen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Horstsch</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Menu_struktur.png&amp;diff=67045</id>
		<title>Datei:Menu struktur.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Menu_struktur.png&amp;diff=67045"/>
		<updated>2012-06-26T21:47:15Z</updated>

		<summary type="html">&lt;p&gt;Horstsch: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Horstsch</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Butterfly_xapp058.zip&amp;diff=67044</id>
		<title>Datei:Butterfly xapp058.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Butterfly_xapp058.zip&amp;diff=67044"/>
		<updated>2012-06-26T21:46:33Z</updated>

		<summary type="html">&lt;p&gt;Horstsch: Quellen für AVR-Butterfly als XSVF-Player nach XAPP058&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Quellen für AVR-Butterfly als XSVF-Player nach XAPP058&lt;/div&gt;</summary>
		<author><name>Horstsch</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Low_Cost_FPGA_Konfiguration&amp;diff=67043</id>
		<title>Low Cost FPGA Konfiguration</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Low_Cost_FPGA_Konfiguration&amp;diff=67043"/>
		<updated>2012-06-26T21:41:48Z</updated>

		<summary type="html">&lt;p&gt;Horstsch: /* Zukunftsaussichten */ link added&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Wenn man FPGAs auf selbst entworfenen Platinen einsetzen möchte, stellt sich oft das Problem des Konfigurationsspeichers. Die meisten FPGAs sind SRAM-basiert und haben keinen [[Speicher#NV-RAM | nichtflüchtigen]] Speicher auf dem Chip bzw. im gleichen Gehäuse (Ausnahmen sind Spartan-3N von Xilinx, XP und XP2 von Lattice und die FPGAs von Actel in Antifuse-Technologie). Also muss irgendwie ein Speicher her. Dazu gibt es mehrere Möglichkeiten.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Konfigurationsmethode || Vorteile || Nachteile&lt;br /&gt;
|-&lt;br /&gt;
| PC mit Programmierkabel || einfache und schnelle Programmierung || Platine kann nur mit PC genutzt werden&lt;br /&gt;
|-&lt;br /&gt;
| Spezial-PROM&amp;lt;BR/&amp;gt; z.&amp;amp;nbsp;B. Xilinx XCFxxS || einfachste Anwendung || hoher Preis&amp;lt;BR/&amp;gt;schlechte Verfügbarkeit für Hobbybastler&lt;br /&gt;
|-&lt;br /&gt;
| Standard-EEPROM mit [[SPI]] || einfache Anwendung&amp;lt;BR/&amp;gt;billig  || nur bei einigen FPGA-Familien möglich (z.&amp;amp;nbsp;B. Spartan3E)&lt;br /&gt;
|-&lt;br /&gt;
| Mikrocontroller mit &amp;lt;BR/&amp;gt;internem oder externem Flash || sehr gute Verfügbarkeit für Hobbybastler&amp;lt;BR/&amp;gt;billig || zusätzlicher Mikrocontroller nötig&amp;lt;BR/&amp;gt;wenn das FPGA allein auf der Platine betrieben wird&amp;lt;BR/&amp;gt;Zusatzaufwand für die Programmierung des EEPROMs und Mikrocontrollers &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel soll die letzte Methode näher beleuchten. Dabei wird ein FPGA vom Typ Spartan 2 von [http://www.xilinx.com Xilinx] sowie ein [[Mikrocontroller]] der [[AVR]]-Familie vom Typ Tiny12 von Atmel eingesetzt. Da die FPGAs anderer Hersteller aber sehr ähnlich konfiguriert werden, kann man das Ganze leicht anpassen.&lt;br /&gt;
&lt;br /&gt;
== FPGA Konfiguration mit Mikrocontroller ==&lt;br /&gt;
&lt;br /&gt;
Für kleine bis mittlere FPGAs wird nur verhältnismässig wenig Konfigurationsspeicher benötigt. Auf der anderen Seite gibt es kleine [[Speicher#EEPROM | EEPROMs]] im SO-8 Gehäuse mit [[I2C]] Schnittstelle. Damit kann sehr kostengünstig und platzsparend die Konfiguration gespeichert werden. Nun braucht man nur noch einen kleinen Mikrocontroller, welcher das EEPROM ausliest und die Daten zum FPGA schickt. Glücklicherweise gibt es auch die im sehr kleinen SO-8 Gehäuse. Damit ist die Lösung sehr platzsparend.&lt;br /&gt;
&lt;br /&gt;
{| border =&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot;| FPGA-Familie&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot;| Typ&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot;| Konfiguration&amp;lt;BR&amp;gt;[Bit]&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; | EEPROM-Anzahl&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; | Konfigurationszeit [s]&amp;lt;BR&amp;gt;I2C mit 400kBit/s&lt;br /&gt;
|-&lt;br /&gt;
! 24C128 || 24C256 || 24C512&lt;br /&gt;
|-&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; | Spartan 2&lt;br /&gt;
| XC2S15    &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 197.696  &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2  &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1    &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1    &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0,5&lt;br /&gt;
|-&lt;br /&gt;
| XC2S30   &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 336.768  &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3  &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0,8&lt;br /&gt;
|-&lt;br /&gt;
| XC2S50   &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 559.200  &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1,4&lt;br /&gt;
|-&lt;br /&gt;
| XC2S100  &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 781.216  &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
|-&lt;br /&gt;
| XC2S150  &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 1.040.096 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2,6&lt;br /&gt;
|-&lt;br /&gt;
| XC2S200  &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 1.335.840 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | * &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3,3&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;4&amp;quot; | Spartan 3&lt;br /&gt;
| XC3S50   &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 439.264  &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1,1&lt;br /&gt;
|-&lt;br /&gt;
| XC3S200  &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 1.047.616 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2,6&lt;br /&gt;
|-&lt;br /&gt;
| XC3S400  &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 1.699.136 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | * &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4,2&lt;br /&gt;
|-&lt;br /&gt;
| XC3S1000 &lt;br /&gt;
| align=&amp;quot;right&amp;quot;| 3.223.488 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | * &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | * &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8,1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schaltung ==&lt;br /&gt;
&lt;br /&gt;
Die Schaltung ist recht einfach. Über den [[I2C]]-[[Bus]] wird ein oder mehrere EEPROMs ausgelesen. Zur Konfiguration sind nur die vier Signale CCLK, Din, Done und PROGRAM benötigt. Der FPGA wird im &#039;&#039;Slave Serial Mode&#039;&#039; betrieben. Da der 8-polige Mikrocontroller aber nur 5 wirklich freie IO-Pins hat, müssen Reset und PROGRAM verbunden werden. Das ist aber kein Problem, im Gegenteil, hier werden FPGA und Mikrocontroller parallel in den Resetzustand versetzt, wenn die Versorgungsspannung angelegt wird oder manuell PROGAMM auf LOW gezogen wird. Es ist jeder beliebige [[AVR]] verwendbar, da das Programm sehr klein ist und keinerlei spezielle Resourcen benötigt, nicht einmal SRAM. Es können EEPROMs mit 128, 256 oder 512kbit eingesetzt werden. Allerdings müssen alle die gleiche Grösse haben. Eine LED am Signal SDA wird zur Fehleranzeige verwendet. Es sollte ein Low Current Typ mit niedriger Flusspannung sein (also keinen blauen oder weissen [[LED]]s). R5 dient der Entkopplung von DONE zur [[ISP]]-Schnittstelle. Damit kann der AVR in der Schaltung programmiert werden.&lt;br /&gt;
&lt;br /&gt;
[[bild: fpga_config.png | thumb | left | 640px| Schaltplan des FPGA Konfigurators]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmierung des Mikrocontrollers ==&lt;br /&gt;
&lt;br /&gt;
Die Programmierung des Konfigurationsprogramms erfolgt in Assembler. Zum einen um eine minimale Programmgrösse und maximale Geschwindigkeit zu erziehlen. Zum anderen, weil kleine AVRs ohne SRAM vom AVR-GCC nicht unterstützt werden. Das ist aber unkritisch, das Programm ist klein und damit überschaubar.&lt;br /&gt;
&lt;br /&gt;
Nach dem Reset wird der Oszillator auf maximalen Takt gestellt, der ist beim Tiny12 sowieso nicht so hoch, max. 2,5 MHz. Dann werden die IOs und Variablen initialisiert. Am I2C-Bus können maximal acht EEPROMs angeschlossen werden, weil diese ICs nur maximal drei konfigurierbare Adressbits besitzen, einige Typen sogar nur zwei. Wenn die Größe der Konfigurationsdatei die Größe eines einzelnen EEPROMS übersteigt, muss schrittweise aus den einzelnen EEPROMs gelesen werden. Dazu muss der jeweilige EEPROM zum Beginn adressiert werden. Danach können lückenlos die Daten aus dem EEPROM gelesen werden. Nachdem alle Bytes geladen wurden wird noch ein zusätzliches Byte geschickt, um die Startsequenz des FPGAs auszulösen. Ist die Konfiguration erfolgreich verlaufen ist danach der FPGA in Funktion. Das wird durch das Signal &#039;&#039;Done&#039;&#039; angezeigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
.include &amp;quot;tn12def.inc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;*******************************************************************************&lt;br /&gt;
;*&lt;br /&gt;
;* A small but fine FPGA configurator&lt;br /&gt;
;* using a Tiny 12 and serial EEPROMs &lt;br /&gt;
;*&lt;br /&gt;
;* Up to eigth EEPROMs can be cascaded on the I2C bus&lt;br /&gt;
;* All devices must be of same size&lt;br /&gt;
;*&lt;br /&gt;
;* theoritical limit is 8x64kB = 512 kB&lt;br /&gt;
;*&lt;br /&gt;
;* Examles for FPGA config size&lt;br /&gt;
;* Spartan-II : XC2S200(biggest family member): 166,980 Bytes&lt;br /&gt;
;* Spartan-3  : XC3S1000                      : 402,936 Bytes&lt;br /&gt;
;*&lt;br /&gt;
;* Configuration speed is ~8.5kBytes/s @ 2MHz&lt;br /&gt;
;* Top speed is ~ 43kB/s @ 10 MHz, 400kHz limit of I2C&lt;br /&gt;
;*&lt;br /&gt;
;* example uses a Xilinx XC2S30 with 42.096 bytes config size&lt;br /&gt;
;* and a ST24C512 with 64 kB&lt;br /&gt;
&lt;br /&gt;
.equ fpga_size   = 42096;           ; FPGA config file size&lt;br /&gt;
.equ EEPROM_size = 65536;           ; EEPROM size per device&lt;br /&gt;
.equ F_CPU_MHz   = 2;               ; CPU clock in MHz, 1..10&lt;br /&gt;
&lt;br /&gt;
.equ bitreverse  = 0               &lt;br /&gt;
&lt;br /&gt;
;*  = 0 , bits will be copied bit by bit from EEPROM to FPGA, faster configuration&lt;br /&gt;
;*        binary files must have same bitorder as required by FPGA (MSB first)&lt;br /&gt;
;*        For Xilinx, the bit files must be processed by bitdreher.exe!!!&lt;br /&gt;
&lt;br /&gt;
;*  = 1 , bits will be copied byte by bytes from EEPROM and written bit reversed to FPGA, slow configuration&lt;br /&gt;
;*        binary files must have reverse bitorder as required by FPGA (LSB first)&lt;br /&gt;
;*        For Xilinx, the bit files are generated this way by default&lt;br /&gt;
&lt;br /&gt;
;*******************************************************************************&lt;br /&gt;
 &lt;br /&gt;
.equ cfg_port = portb&lt;br /&gt;
.equ cfg_ddr  = ddrb&lt;br /&gt;
.equ cfg_pin  = pinb  &lt;br /&gt;
&lt;br /&gt;
.equ DIN   = PB0        ; FPGA serial configuration&lt;br /&gt;
.equ DONE  = PB1&lt;br /&gt;
.equ CCLK  = PB2&lt;br /&gt;
.equ SDA   = PB3        ; Connection to I2C EEPROM&lt;br /&gt;
.equ SCL   = PB4&lt;br /&gt;
&lt;br /&gt;
; Reset is connected to FPGA AND AVR, so we have a automatic Power-on reset&lt;br /&gt;
&lt;br /&gt;
; some marcos to support readability&lt;br /&gt;
&lt;br /&gt;
.macro SDA_LOW&lt;br /&gt;
    sbi     cfg_ddr, sda    ; open drain, low&lt;br /&gt;
.endmacro &lt;br /&gt;
&lt;br /&gt;
.macro SDA_HIGH&lt;br /&gt;
    cbi     cfg_ddr, sda    ; open drain, high&lt;br /&gt;
.endmacro&lt;br /&gt;
&lt;br /&gt;
.macro SCL_LOW&lt;br /&gt;
    sbi     cfg_ddr, scl    ; open drain, low&lt;br /&gt;
.endmacro &lt;br /&gt;
&lt;br /&gt;
.macro SCL_HIGH&lt;br /&gt;
    cbi     cfg_ddr, scl    ; open drain, high&lt;br /&gt;
.endmacro&lt;br /&gt;
&lt;br /&gt;
.macro DIN_LOW&lt;br /&gt;
    cbi     cfg_port, din   ; push pull&lt;br /&gt;
.endmacro &lt;br /&gt;
&lt;br /&gt;
.macro DIN_HIGH&lt;br /&gt;
    sbi     cfg_port, din   ; push pull&lt;br /&gt;
.endmacro&lt;br /&gt;
&lt;br /&gt;
.macro CCLK_LOW&lt;br /&gt;
    cbi     cfg_port, cclk  ; push pull&lt;br /&gt;
.endmacro &lt;br /&gt;
&lt;br /&gt;
.macro CCLK_HIGH&lt;br /&gt;
    sbi     cfg_port, cclk  ; push pull&lt;br /&gt;
.endmacro&lt;br /&gt;
&lt;br /&gt;
.macro i2c_error_check&lt;br /&gt;
    brts    PC+2&lt;br /&gt;
    rjmp    error_i2c&lt;br /&gt;
.endmacro&lt;br /&gt;
&lt;br /&gt;
; add a delay to reach given delay time&lt;br /&gt;
; usage&lt;br /&gt;
; delay_1 time [Unit 0.1us], clocks_already_done&lt;br /&gt;
.macro delay&lt;br /&gt;
&lt;br /&gt;
; calculate number of remaining clocks&lt;br /&gt;
; +1 is safety margin to account for integer truncation&lt;br /&gt;
&lt;br /&gt;
.set clks = @0*F_CPU_MHz/10-@1+1&lt;br /&gt;
&lt;br /&gt;
; use optimized delay blocks with &amp;quot;nonsense&amp;quot; commands to have maximum&lt;br /&gt;
; delay with minimum code size&lt;br /&gt;
&lt;br /&gt;
.if clks==1&lt;br /&gt;
    nop&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==2&lt;br /&gt;
    ld  null, z&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==3&lt;br /&gt;
    lpm&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==4&lt;br /&gt;
    lpm&lt;br /&gt;
    nop&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==5&lt;br /&gt;
    lpm&lt;br /&gt;
    ld  null, z&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==6&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==7&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    nop&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==8&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    ld  null,z&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==9&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==10&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    nop&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==11&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    ld  null, z&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==12&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==13&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    nop&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==14&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    ld  null, z&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.endmacro&lt;br /&gt;
&lt;br /&gt;
.def zero  = r1         ; always zero&lt;br /&gt;
.def one   = r2         ; always one&lt;br /&gt;
.def null  = r3         ; write only ;-)&lt;br /&gt;
.def tmp1  = r16        ; general purpose&lt;br /&gt;
.def tmp2  = r17&lt;br /&gt;
.def tmp3  = r18&lt;br /&gt;
.def cnt0  = r19        ; loop counter, 24 Bit&lt;br /&gt;
.def cnt1  = r20&lt;br /&gt;
.def cnt2  = r21            &lt;br /&gt;
.def i2c   = r22        ; I2C address, used for multiple devices&lt;br /&gt;
.def abs0  = r23        ; data counter, 24 Bit&lt;br /&gt;
.def abs1  = r24        ; &lt;br /&gt;
.def abs2  = r25&lt;br /&gt;
&lt;br /&gt;
;*&lt;br /&gt;
;*******************************************************************************&lt;br /&gt;
&lt;br /&gt;
.cseg&lt;br /&gt;
; lets go&lt;br /&gt;
&lt;br /&gt;
; initialize stack&lt;br /&gt;
&lt;br /&gt;
; hardware stack for Tiny12, no init necessary&lt;br /&gt;
&lt;br /&gt;
; full speed, ~2 MHz with ATtiny12&lt;br /&gt;
&lt;br /&gt;
    ldi     tmp1,0xFF&lt;br /&gt;
    out     osccal, tmp1&lt;br /&gt;
&lt;br /&gt;
; config IOs&lt;br /&gt;
&lt;br /&gt;
    ldi     tmp1, (1&amp;lt;&amp;lt;cclk) | (1&amp;lt;&amp;lt;din)&lt;br /&gt;
    out     cfg_ddr,tmp1&lt;br /&gt;
&lt;br /&gt;
    ldi     tmp1, (1&amp;lt;&amp;lt;done)&lt;br /&gt;
    out     cfg_port,tmp1           ; internal pull up for DONE&lt;br /&gt;
&lt;br /&gt;
; generate constant registers&lt;br /&gt;
&lt;br /&gt;
    sub     zero,zero&lt;br /&gt;
    ldi     tmp1,1&lt;br /&gt;
    mov     one,tmp1&lt;br /&gt;
    ldi     i2c,0xA0                ; I2C base address&lt;br /&gt;
&lt;br /&gt;
; set byte counter&lt;br /&gt;
&lt;br /&gt;
    ldi     abs0,byte1(fpga_size)&lt;br /&gt;
    ldi     abs1,byte2(fpga_size)&lt;br /&gt;
    ldi     abs2,byte3(fpga_size)&lt;br /&gt;
        &lt;br /&gt;
; wait 10ms for FPGA to finish power up and clear config space&lt;br /&gt;
&lt;br /&gt;
    ldi     tmp1,10&lt;br /&gt;
    rcall   wait&lt;br /&gt;
&lt;br /&gt;
; when using multiple EEPROMs, we must address them individual&lt;br /&gt;
&lt;br /&gt;
device_loop:&lt;br /&gt;
&lt;br /&gt;
; number of remaining bytes &amp;gt;EEPROM_size ?&lt;br /&gt;
&lt;br /&gt;
    ldi     tmp1,byte1(EEPROM_size)&lt;br /&gt;
    ldi     tmp2,byte2(EEPROM_size)&lt;br /&gt;
    ldi     tmp3,byte3(EEPROM_size)&lt;br /&gt;
&lt;br /&gt;
    cp      abs0,tmp1&lt;br /&gt;
    cpc     abs1,tmp2&lt;br /&gt;
    cpc     abs2,tmp3&lt;br /&gt;
    brge    device_loop_big     ; &amp;gt;= EEPROM_size&lt;br /&gt;
&lt;br /&gt;
    ; less than EEPROM_size, copy remaining bytes&lt;br /&gt;
    mov     cnt0,abs0       ; remaining bytes&lt;br /&gt;
    mov     cnt1,abs1&lt;br /&gt;
    mov     cnt2,abs2&lt;br /&gt;
    mov     abs0,zero       ; set zero&lt;br /&gt;
    mov     abs1,zero&lt;br /&gt;
    mov     abs2,zero&lt;br /&gt;
    rjmp    device_loop_init&lt;br /&gt;
&lt;br /&gt;
device_loop_big:&lt;br /&gt;
    mov     cnt0,tmp1       ; EEPROM_size loop&lt;br /&gt;
    mov     cnt1,tmp2&lt;br /&gt;
    mov     cnt2,tmp3&lt;br /&gt;
    sub     abs0,tmp1       ; - EEPROM_size&lt;br /&gt;
    sbc     abs1,tmp2&lt;br /&gt;
    sbc     abs2,tmp3&lt;br /&gt;
&lt;br /&gt;
device_loop_init:&lt;br /&gt;
    subi    cnt0,1          ; -1, since last byte must be read with no ACK&lt;br /&gt;
    sbci    cnt1,0          ; outside the loop&lt;br /&gt;
    sbci    cnt2,0&lt;br /&gt;
&lt;br /&gt;
; write first adress&lt;br /&gt;
&lt;br /&gt;
    rcall   i2c_start&lt;br /&gt;
    mov     tmp1, i2c       ; load i2c address&lt;br /&gt;
    rcall   i2c_write&lt;br /&gt;
    i2c_error_check&lt;br /&gt;
    ldi     tmp1, 0         ; write adress 0&lt;br /&gt;
    rcall   i2c_write&lt;br /&gt;
    i2c_error_check&lt;br /&gt;
    ldi     tmp1, 0&lt;br /&gt;
    rcall   i2c_write&lt;br /&gt;
    i2c_error_check&lt;br /&gt;
    rcall   i2c_stop&lt;br /&gt;
&lt;br /&gt;
    rcall   i2c_start&lt;br /&gt;
    mov     tmp1, i2c       ; load i2c address&lt;br /&gt;
    subi    tmp1,-1         ; +1, read access&lt;br /&gt;
    rcall   i2c_write&lt;br /&gt;
    i2c_error_check&lt;br /&gt;
    set                     ; set T-Flag, continous reading&lt;br /&gt;
&lt;br /&gt;
main_loop:&lt;br /&gt;
&lt;br /&gt;
.if bitreverse==1           &lt;br /&gt;
;   configuration uses online bit reverse, slow&lt;br /&gt;
&lt;br /&gt;
    rcall   i2c_read&lt;br /&gt;
    rcall   fpga_write&lt;br /&gt;
&lt;br /&gt;
.else&lt;br /&gt;
;   configuration uses offline bit reverse, fast (bitdreher.exe)&lt;br /&gt;
&lt;br /&gt;
; read a byte from I2C and parallel send it to the FPGA&lt;br /&gt;
; fast version&lt;br /&gt;
    ldi     tmp2, 8         ; loop counter&lt;br /&gt;
&lt;br /&gt;
main_bit_loop:&lt;br /&gt;
    scl_high                ; SCL rising edge&lt;br /&gt;
    sbic    cfg_pin,sda     ; copy SDA to Din&lt;br /&gt;
    din_high&lt;br /&gt;
    sbis    cfg_pin,sda&lt;br /&gt;
    din_low&lt;br /&gt;
    delay 7, 6              ; minimum LOW time 0,6µs + 0.1µs safty margin&lt;br /&gt;
    scl_low                 ; falling edge generates new bit&lt;br /&gt;
    cclk_high               ; LOW time min. 9 CLKs&lt;br /&gt;
    cclk_low&lt;br /&gt;
    delay 14, 9             ; minimum HIGH time 1,3µs + 0.1µs safty margin&lt;br /&gt;
    dec     tmp2&lt;br /&gt;
    brne    main_bit_loop&lt;br /&gt;
&lt;br /&gt;
; write ACK to EEPROM&lt;br /&gt;
&lt;br /&gt;
    sda_low                 ; write ACK, more to read&lt;br /&gt;
    delay  1, 0&lt;br /&gt;
    scl_high&lt;br /&gt;
    delay  7, 2&lt;br /&gt;
    scl_low&lt;br /&gt;
    sda_high&lt;br /&gt;
    delay  14, 10&lt;br /&gt;
&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
    subi    cnt0,1          ; decrement data counter&lt;br /&gt;
    sbci    cnt1,0&lt;br /&gt;
    sbci    cnt2,0&lt;br /&gt;
    brne    main_loop&lt;br /&gt;
&lt;br /&gt;
    clt                     ; no ACK for last byte of block&lt;br /&gt;
    rcall   i2c_read&lt;br /&gt;
    rcall   fpga_write&lt;br /&gt;
&lt;br /&gt;
    rcall   i2c_stop&lt;br /&gt;
    subi    i2c,-2          ; +2, increment I2C address bits&lt;br /&gt;
&lt;br /&gt;
; number of remaining data bytes = 0 ?&lt;br /&gt;
&lt;br /&gt;
    cp      abs0,zero&lt;br /&gt;
    cpc     abs1,zero&lt;br /&gt;
    cpc     abs2,zero&lt;br /&gt;
    breq    main_end        ; nothing left to copy, finish&lt;br /&gt;
&lt;br /&gt;
    rjmp    device_loop     ; process next data block&lt;br /&gt;
&lt;br /&gt;
main_end:&lt;br /&gt;
    ldi     tmp1,0&lt;br /&gt;
    rcall   fpga_write      ; one more dummy byte for FPGA startup&lt;br /&gt;
&lt;br /&gt;
    ldi     tmp1,1&lt;br /&gt;
    rcall   wait            ; wait for DONE to go HIGH (open drain)&lt;br /&gt;
    sbis    cfg_pin, done   ; check if DONE is HIGH (= FPGA config OK)&lt;br /&gt;
    rjmp    error_fpga      ; something went wrong during configuration&lt;br /&gt;
    ldi     tmp1, (1&amp;lt;&amp;lt;SE) | (1&amp;lt;&amp;lt;SM)     &lt;br /&gt;
    out     mcucr,tmp1      ; power down sleep mode&lt;br /&gt;
    sleep                   ; good night&lt;br /&gt;
    &lt;br /&gt;
;  no wake up here, only through reset&lt;br /&gt;
&lt;br /&gt;
; i2c has no ACK, fast blinking&lt;br /&gt;
&lt;br /&gt;
error_i2c:&lt;br /&gt;
    sda_low&lt;br /&gt;
    ldi     tmp1,100&lt;br /&gt;
    rcall   wait&lt;br /&gt;
    sda_high&lt;br /&gt;
    ldi     tmp1,100&lt;br /&gt;
    rcall   wait&lt;br /&gt;
    rjmp    error_i2c&lt;br /&gt;
&lt;br /&gt;
; FPGA configuration error, DONE stays low, slow blinking&lt;br /&gt;
&lt;br /&gt;
error_fpga:&lt;br /&gt;
    sda_low&lt;br /&gt;
    ldi     tmp1,250&lt;br /&gt;
    rcall   wait&lt;br /&gt;
    ldi     tmp1,250&lt;br /&gt;
    rcall   wait&lt;br /&gt;
    sda_high&lt;br /&gt;
    ldi     tmp1,250&lt;br /&gt;
    rcall   wait&lt;br /&gt;
    ldi     tmp1,250&lt;br /&gt;
    rcall   wait&lt;br /&gt;
    rjmp    error_fpga&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
&lt;br /&gt;
; functions&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
&lt;br /&gt;
; just wait N*1ms, N is given in tmp1&lt;br /&gt;
&lt;br /&gt;
wait:&lt;br /&gt;
    ldi     tmp2,20*F_CPU_MHz&lt;br /&gt;
wait_1:&lt;br /&gt;
    ldi     tmp3,16&lt;br /&gt;
wait_2:&lt;br /&gt;
    dec     tmp3&lt;br /&gt;
    brne    wait_2&lt;br /&gt;
    dec     tmp2&lt;br /&gt;
    brne    wait_1&lt;br /&gt;
    dec     tmp1&lt;br /&gt;
    brne    wait&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
&lt;br /&gt;
; write a byte to I2C&lt;br /&gt;
; input  : tmp1   : data&lt;br /&gt;
; output : T-flag : ACK (0= NACK (SDA high), 1 = ACK (SDA low))&lt;br /&gt;
 &lt;br /&gt;
i2c_write:&lt;br /&gt;
    ldi     tmp2, 8     ; loop conter&lt;br /&gt;
i2c_write_loop:&lt;br /&gt;
&lt;br /&gt;
    sbrs    tmp1,7      ; copy MSB to SDA&lt;br /&gt;
    sda_low&lt;br /&gt;
    sbrc    tmp1,7&lt;br /&gt;
    sda_high&lt;br /&gt;
&lt;br /&gt;
    delay 14, 8 &lt;br /&gt;
    scl_high&lt;br /&gt;
    delay 7, 2&lt;br /&gt;
    scl_low&lt;br /&gt;
    lsl     tmp1        ; get next bit&lt;br /&gt;
    dec     tmp2&lt;br /&gt;
    brne    i2c_write_loop&lt;br /&gt;
&lt;br /&gt;
; check ACK from EEPROM&lt;br /&gt;
    sda_high&lt;br /&gt;
    delay 14, 5&lt;br /&gt;
    scl_high&lt;br /&gt;
    clt                     ; clear T-Flag, = no ACK!&lt;br /&gt;
    sbis    cfg_pin,sda     ; check SDA is ACK=0 (positive ACK)&lt;br /&gt;
    set                     ; ACK=0, OK&lt;br /&gt;
    delay 7, 5&lt;br /&gt;
    scl_low&lt;br /&gt;
    delay 14, 7     &lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
&lt;br /&gt;
; read a byte from I2C&lt;br /&gt;
; input  : T-flag : ACK, (0= NACK (SDA high), 1 = ACK (SDA low))&lt;br /&gt;
; output : tmp1   : data&lt;br /&gt;
i2c_read:&lt;br /&gt;
    ldi     tmp2, 8         ; loop conter&lt;br /&gt;
i2c_read_loop:&lt;br /&gt;
    scl_high&lt;br /&gt;
    clc                     ; copy SDA to carry&lt;br /&gt;
    sbic    cfg_pin, sda    ; read SDA&lt;br /&gt;
    sec                     ; set carry&lt;br /&gt;
    rol     tmp1            ; shift in next bit&lt;br /&gt;
    delay 7, 6&lt;br /&gt;
    scl_low                 ; minimum pulse width LOW = 1.3µs = 13 clks @10 MHz&lt;br /&gt;
    delay 14, 5&lt;br /&gt;
    dec     tmp2&lt;br /&gt;
    brne    i2c_read_loop&lt;br /&gt;
&lt;br /&gt;
; write ACK to EEPROM&lt;br /&gt;
&lt;br /&gt;
    brtc    i2c_read_no_ack&lt;br /&gt;
    sda_low                 ; write ACK, more to read&lt;br /&gt;
    rjmp    i2c_read_send_ack&lt;br /&gt;
i2c_read_no_ack:&lt;br /&gt;
    sda_high                ; no ACK, stop reading&lt;br /&gt;
i2c_read_send_ack:&lt;br /&gt;
    delay 14, 6&lt;br /&gt;
    scl_high&lt;br /&gt;
    delay 7, 2&lt;br /&gt;
    scl_low&lt;br /&gt;
    sda_high                ; release SDA&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
&lt;br /&gt;
; Create a I2C START Condition&lt;br /&gt;
  &lt;br /&gt;
i2c_start:&lt;br /&gt;
    delay 5, 2&lt;br /&gt;
    sda_low&lt;br /&gt;
    delay 5, 2&lt;br /&gt;
    scl_low&lt;br /&gt;
    delay 30, 7&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
&lt;br /&gt;
; Create a I2C STOP Condition&lt;br /&gt;
&lt;br /&gt;
i2c_stop:&lt;br /&gt;
    delay 5, 2&lt;br /&gt;
    sda_low&lt;br /&gt;
    delay 5,2 &lt;br /&gt;
    scl_high&lt;br /&gt;
    delay 5,2&lt;br /&gt;
    sda_high&lt;br /&gt;
    delay 30, 7&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
&lt;br /&gt;
; write a byte to FPGA, with bit reversal&lt;br /&gt;
; input  : tmp1   : data&lt;br /&gt;
&lt;br /&gt;
.if bitreverse==1       &lt;br /&gt;
.message &amp;quot;Bit reverse ON, slow configuration.&amp;quot;  &lt;br /&gt;
; configuration uses online bit reverse, slow&lt;br /&gt;
; bit reverse, LSB first&lt;br /&gt;
fpga_write:&lt;br /&gt;
    ldi     tmp2, 8     ; loop conter&lt;br /&gt;
fpga_write_loop:&lt;br /&gt;
&lt;br /&gt;
    sbrs    tmp1,0      ; copy LSB to DIN&lt;br /&gt;
    din_low&lt;br /&gt;
    sbrc    tmp1,0&lt;br /&gt;
    din_high&lt;br /&gt;
&lt;br /&gt;
    cclk_high           ; generate cclk pulse&lt;br /&gt;
    cclk_low&lt;br /&gt;
    lsr     tmp1        ; get next bit&lt;br /&gt;
    dec     tmp2&lt;br /&gt;
    brne    fpga_write_loop&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
.else&lt;br /&gt;
.message &amp;quot;Bit reverse OFF, fast configuration.&amp;quot; &lt;br /&gt;
; configuration uses offline bit reverse, fast (bitdreher.exe)&lt;br /&gt;
; no bit reverse, MSB first&lt;br /&gt;
fpga_write:&lt;br /&gt;
    ldi     tmp2, 8     ; loop conter&lt;br /&gt;
fpga_write_loop:&lt;br /&gt;
&lt;br /&gt;
    sbrs    tmp1,7      ; copy MSB to DIN&lt;br /&gt;
    din_low&lt;br /&gt;
    sbrc    tmp1,7&lt;br /&gt;
    din_high&lt;br /&gt;
&lt;br /&gt;
    cclk_high           ; generate cclk pulse&lt;br /&gt;
    cclk_low&lt;br /&gt;
    lsl     tmp1        ; get next bit&lt;br /&gt;
    dec     tmp2&lt;br /&gt;
    brne    fpga_write_loop&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
.endif&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fehlererkennung ==&lt;br /&gt;
&lt;br /&gt;
Seitens des FPGAs ist Done ein [[Ausgangsstufen Logik-ICs#Open Collector | Open Drain]] Ausgang. Im AVR wird der interne Pull-Up eingeschaltet, um das Signal auf HIGH ziehen zu können. Ist jedoch ein Fehler aufgetreten (CRC-Fehler im Datenstrom), bleibt Done auf LOW. Der AVR prüft Done am Ende der Konfiguration. Ist Done gleich HIGH, geht er in den Power Down [[Sleep Mode]] um Strom zu sparen. Ist aber ein Fehler aufgetreten und Done somit LOW, wird das durch langsames Blinken der LED an SDA angezeigt (~1 Hz). Tritt während der Adressierung des EEPROMs ein Fehler auf (kein ACK vom EEPROM), dann wird dies durch schnelles Blinken der LED angezeigt (~5 Hz). Im Normalfall treten diese Ereignisse nur sehr selten auf, z.&amp;amp;nbsp;B. bei einem EEPROM-Defekt durch Alterung/Datenverlust oder einer Störung der Datenübertragung durch starke Störimpulse. Aber zur Programmierung und zum Testen sind sie sehr nützlich.&lt;br /&gt;
&lt;br /&gt;
== Nutzung ==&lt;br /&gt;
&lt;br /&gt;
Die Nutzung der Schaltung ist recht einfach. Im Quellcode müssen nur drei Variablen an das jeweilige Projekt angepasst werden. Soll ein anderer AVR-Typ verwendet werden können auch die Pins einfach zugewiesen werden. Danach wird das Programm assembliert und per [[ISP]] in den AVR geschrieben. Abschliessend sollten die Fuses gesetzt werden. Der Takt des interen RC-Oszillators sollte möglichst hoch gewählt werden, bis ca. 10 MHz ist das Progamm ohne Änderungen nutzbar. Wenn verfügbar sollte der Brown Out Detector eingeschaltet werden und mit ca. 2,7V Schwellspannung betrieben werden. Für den hier verwendeten Tiny12 muss das Fuse-Byte mit 0x12 beschrieben werden. &#039;&#039;&#039;HALT!&#039;&#039;&#039; Wenn jetzt der Reset gelöst wird läuft der AVR sofort los und versucht die Daten aus den EEPROMs zu lesen. Da diese aber noch nicht programmiert sind werden keine sinnvollen Daten ins FPGA geladen. Das schadet dem FPGA zwar nicht, aber die Konfiguration scheitert! In der Folge wird SDA vom AVR kontinuierlich zwischen LOW und HIGH umgeschaltet, um den Fehler durch Blinken der LED zu signalisieren. Damit ist aber keine Programmierung der EEPROMs mehr möglich!&lt;br /&gt;
&lt;br /&gt;
Mögliche Auswege:&lt;br /&gt;
&lt;br /&gt;
* RESET auf LOW halten&lt;br /&gt;
* die EEPROMs &#039;&#039;&#039;vor&#039;&#039;&#039; dem AVR programmieren&lt;br /&gt;
&lt;br /&gt;
Im Normalfall wird man den zweiten Weg wählen. Denn während der Entwicklung wird man meist das FPGA über [[JTAG]] konfigurieren. Erst wenn alles komplett funktioniert wird man die Konfiguration einmalig in den EEPROM schreiben.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis!&#039;&#039;&#039; Wird während der Entwicklungsphase das FPGA über JTAG programmiert, muss in den Optionen für &amp;quot;Generate Programming File&amp;quot; unter Startup Options -&amp;gt; FPGA Start-up Clock  &amp;quot;JTAG&amp;quot; gewählt werden. &lt;br /&gt;
&lt;br /&gt;
Die Programmierung der EEPROMs erfolgt mit [http://www.lancos.com Ponyprog]. Mittels einfachem Adapter kann man direkt auf den I2C-Bus gehen, es werden nur SDA, SCL und GND benötigt, die Pull-Ups sind schon auf dem Board. Das Board muss dazu natürlich mit Spannung versorgt werden.&lt;br /&gt;
&lt;br /&gt;
[[bild:i2c_adapter.png| framed | left | I2C Adapter für Ponyprog]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Ablauf der EEPROM-Programmierung sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
* In den Optionen für &amp;quot;Generate Programming File&amp;quot; muss unter Startup Options -&amp;gt; FPGA Start-up Clock &amp;quot;CCLK&amp;quot; gewählt werden. &lt;br /&gt;
* Im Xilinx ISE den kompletten Synthesezyklus inclusive &amp;quot;Generate Programming File&amp;quot; durchlaufen.&lt;br /&gt;
* IMPACT starten und eine PROM-Datei im BIN Format erzeugen.&lt;br /&gt;
* Jetzt hat man die Wahl zwischen zwei Möglichkeiten.&lt;br /&gt;
** Die Daten direkt in den EEPROM schreiben. Dann müssen sie beim Lesen und anschliessender Ausgabe zum FPGA in der Reihenfolge der Bits vertauscht werden, das kostet natürlich Zeit&lt;br /&gt;
** Die Daten mit einem kleinen Tool [[media:Bitdreher.zip | Bitdreher]] umwandeln. Dabei wird die Bitverdrehung vorher durchgeführt. Die Daten können damit ohne zusätzliche Verdrehung schnell ins FPGA geschrieben werden.&lt;br /&gt;
* Ponyprog starten, EEPROM Familie &amp;quot;IC Bus 16bit eeprom&amp;quot; auswählen, den jeweiligen Typ auch auswählen (25C128, 24C256, 24C512).&lt;br /&gt;
* Die Bin-Datei laden und &amp;quot;Write Device&amp;quot; ausführen.&lt;br /&gt;
* Das erfolgreiche Programmieren und Verifizieren wird von Ponyprog angezeigt.&lt;br /&gt;
 &lt;br /&gt;
Wenn die FPGA-Konfiguration grösser als ein EEPROM ist, muss die Datei in mehrere Stücke aufgeteilt werden. Das kann man mit IMPACT machen oder &#039;&#039;&#039;promgen&#039;&#039;&#039; direkt von der Kommandozeile aufrufen. Die Option &#039;&#039;-s &amp;lt;size&amp;gt;&#039;&#039; erlaubt das Aufteilen der Konfigurationsdaten in kleinere Dateien. Beachtet werden muss dabei, dass die einzelnen Blöcke exakt so gross sein müssen wie ein einzelner EEPROM. Ausser natürlich der letzte Block, dessen Länge ergibt sich aus (Dateigrösse MODULO EEPROM-Grösse). Die einzelnen Dateien können dann einfach per Ponyprog in die EEPROMs geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung!&#039;&#039;&#039;&lt;br /&gt;
*Dabei muss man aufpassen, dass die Reihenfolge nicht verwechselt wird! Der erste Block muss in den EEPROM mit Adresse 0, der zweite in den mit Adresse 1 usw.&lt;br /&gt;
* Wenn man mit Ponyprog mehrere EEPROMs an einem Bus programmieren will, muss die Adresse der EEPROMs manuell in der Datei &#039;&#039;PONYPROG2000.INI&#039;&#039; in der Zeile&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        I2CBaseAddress=0xA0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
: eingetragen werden (0xA0, 0xA2, 0xA4, 0xA6, 0xA8, 0xAA, 0xAC, 0xAE). Nach jeder Änderung muss Ponyprog neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
== Leistung ==&lt;br /&gt;
&lt;br /&gt;
Auf einem Tiny12 mit voll aufgedrehtem RC-Oszillator (ca. 2 MHz) und einer Online Bitverdrehung (bitreversal=1) erreicht man eine Geschwindigkeit von ca. 8,5kB/s, d.h. der im Test verwendete FPGA vom Typ XC2S30 mit 42096 Bytes Konfigurationsspeicher wird in ca. 5s konfiguriert. Nicht gerade berauschend, aber ausreichend. Der Grund dafür liegt nicht nur in der begrenzten Geschwindigkeit des I2C Busses (400kHz), sondern in einer Merkwürdigkeit der Konfigurationssoftware von Xilinx. Diese verdreht nämlich die Bits innerhalb der Bytes aus fadenscheinigen Gründen (Bit 0&amp;lt;-&amp;gt;7, Bit 1&amp;lt;-&amp;gt;6, etc.). Damit muss aber immer zunächst ein Byte vollständig gelesen werden (MSB zuerst) und dananch in umgekehrter Reihenfolge ausgegeben werden (LSB zuerst). Das kostet einiges an Zeit. Damit werden bei 2 MHz nur etwa 15% der maximalen Geschwindigkeit erreicht, dementsprechend sind die Konfigurationszeiten etwa sechs mal so lang wie in der Tabelle oben angegeben. Mit dem Parameter bitreversal=0 und der Bearbeitung der Konfigurationsdaten mit dem Tool [[media:Bitdreher.zip | Bitdreher]] erreicht man eine Konfigurationszeit von ca 3s, 40% schneller! Die erreichbaren Konfigurationszeiten sind in nachfolgender Tabelle exemplarisch angegeben, mit dem in Klammern angegebenen Faktor kann man direkt in die zweite Tabelle gehen und die reale Konfigurationszeit ausrechnen. Bei höherem Prozessortakt werden längere Pausen eingefügt, sodass die minimalen Pulszeiten für 400kHz auf dem I2C-Bus eingehalten werden. Dies wird mit dem schönen, leistungsfähigen Makro &#039;&#039;delay&#039;&#039; erreicht.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; | Takt [MHz]  &lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; | Konfigurationszeit [s] (Faktor)&lt;br /&gt;
|-&lt;br /&gt;
! bitreversal=0 || bitreversal=1   &lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2  &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3,0 (3,8)&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4,8 (6)&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5  &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1,2 (1,5)&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2,1 (2,6)&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 10 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0,9 (1,1)&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1,4 (1,8)&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
== Zukunftsaussichten ==&lt;br /&gt;
&lt;br /&gt;
Für grössere FPGAs werden die seriellen EEPROMs irgendwann zu klein und zu langsam. Hier müssen andere Datenträger her. SD-Karten sind klein, billig und weit verbreitet. Auch wenn der Aufwand zu deren Ansteuerung plus Minimalfunktionalität für FAT12/FAT16 um einiges höher liegt, ist dies ein interessanter Ansatzpunkt, der in Zukunft einmal umgesetzt werden kann.&lt;br /&gt;
&lt;br /&gt;
Als Zwischenlösung bieten sich Flashbausteine mit [[SPI]] im SO-8 Gehäuse an, die  gibt es bis zu unglaublichen 32 Mbit zum Spottpreis, z.b. bei [[Elektronikversender#csd-electronics | CSD]]. Allerdings muss dann ein AVR mit zwei zusätzlichen Pins her, hier muss man dann auf ein 20 poliges Gehäuse wechseln. Enthusiasten nehmen das platzsparende MLF20 ;-).&lt;br /&gt;
&lt;br /&gt;
Alternativ könnte geprüft werden, ob der Dataflash eines [[AVR_Butterfly]] ausreicht. Siehe: [[FPGA_Konfiguration_mit_AVR_Butterfly]]&lt;br /&gt;
&lt;br /&gt;
== Diskussion im Forum ==&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/79844 Programm auf Spartan 3A laden]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/83026 FPGA synthetisierung]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/80275 Einsteigerfreundlicher FPGA]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/78362 Spartan 3E mit SPI-Flash]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/75954 Spartan 3e: Anfägerhilfe bei Flashspeicherung]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/39941 Programmier-Hardware Altera Cyclone-II /EPCS4]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/39947 FPGA und CPLD programmieren]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.xilinx.com FPGAs von Xilinx]&lt;br /&gt;
* [http://www.lancos.com PonyProg]&lt;br /&gt;
* [http://www.atmel.com/products/serial/default.asp Serielle EEPROMs bei Atmel]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc3301.pdf Configuring High-density FPGAs using Atmel’s Serial DataFlash® and an AVR® Microcontroller (2003)]&lt;br /&gt;
* [http://www.xilinx.com/publications/xcellonline/xcell_55/xc_pdf/xc_spi55.pdf XC-SPI55 Program SPI Serial Flash from Xilinx FPGAs and CPLDs (2005)]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp445.pdf XAPP445 Configuring Spartan-3E FPGAs with SPI Flash Memories (2007)]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp693.pdf XAPP693 CPLD-Based Configuration...for Xilinx Platform Flash PROMs and FPGAs (2005)]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp176.pdf XAPP176 Configuration and Readback of the Spartan-II and Spartan-IIE Families (2002)]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp098.pdf XAPP098 The Low-Cost, Efficient Serial Configuration of Spartan FPGAs (1998)]&lt;br /&gt;
&lt;br /&gt;
[[Category:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Horstsch</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=FPGA_Konfiguration_mit_AVR_Butterfly&amp;diff=67042</id>
		<title>FPGA Konfiguration mit AVR Butterfly</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=FPGA_Konfiguration_mit_AVR_Butterfly&amp;diff=67042"/>
		<updated>2012-06-26T21:40:58Z</updated>

		<summary type="html">&lt;p&gt;Horstsch: initial version&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
Dieses Projekte stellt gewissermaßen eine Ergänzung zu [[Low_Cost_FPGA_Konfiguration]] dar.&lt;br /&gt;
Hier wurde ein [[AVR Butterfly]] genutzt, um einen FPGA Xilinx Spartan-3-1000 via [[JTAG]] zu konfigurieren. &lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
Da die Pins CCLK, Din und Done nicht zugänglich sind, mußte der Weg über die [[JTAG]]-Schnittstelle gegangen werden. Es wurde ein kleines Trägerboard für den Butterfly entwickelt, um alle benötigten Schnittstellen bequem unterzubringen.&lt;br /&gt;
[[Bild:carrierboard_butterfly_xapp058.png]]&lt;br /&gt;
&lt;br /&gt;
Der Dataflash auf dem Butterfly-Board hat eine Größe von 512 kByte. Da passen die ca. 402 kByte Konfigurationsdaten [http://www.xilinx.com/support/documentation/user_guides/ug332.pdf] für den der Spartan-3-1000 gut rein. Wer einen größeren FPGA konfigurieren möchte, braucht also auch den passenden Speicher dafür.&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:schematic_butterfly_xapp058.png]]&lt;br /&gt;
&lt;br /&gt;
Der Butterfly wird mit einer externen Betriebsspannung von 3,3 V versorgt. Damit ergeben sich 3,3 V Pegel für die JTAG-Schnittstelle. Achtung, bei neueren FPGAs liegt die JTAG-Spannung bei 2,5 V oder 1,8 V. Die Referenzspannung der Zielhardware kann per Software geprüft werden.&lt;br /&gt;
&lt;br /&gt;
Das eigentliche Programmiergerät kann an JTAG_IN angeschlossen werden. Auf den in XAPP058 angegebenen Multiplexer zum Umschalten der JTAG-Quelle kann verzichtet werden, da der Mikrocontroller seine Ausgänge (ebenso wie das Programmiergerät) bei Nichtgebrauch hochohmig schaltet. Man darf natürlich nicht gleichzeitig mit dem Programmer und dem AVR per JTAG auf das FPGA zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
Als Grundgerüst für die Butterfly-Software wurde die gcc-Portiertung der Butterfly-Demo [http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#bf_app] verwendet.&lt;br /&gt;
Um die Daten sicher in den Dataflash zu bekommen, wird das XMODEM-Protokoll verwendet. Dazu gibt es von Atmel die Application Note AVR350 [http://www.atmel.com/Images/doc1472.pdf]. Und um letztendlich den FPGA zu konfigurieren wurde von Xilinx die Application Note XAPP058 [http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf] benutzt.&lt;br /&gt;
 &lt;br /&gt;
Damit das alles in den 16 kByte Flash des ATmega169 passt, wurde der Democode entschlackt.&lt;br /&gt;
Dann erfolgt die Anpassung des Xilinx-Codes: MAX_LEN (lenval.h) muß rigeros verringert werden, damit die Datenstrukturen von Xilinx in den Speicher von 1 kByte passen. Ich habe 128 gewählt. Das ist auch die maximale Größe, die Impact für die Konfigurationshäppchen verwendet. Außerdem muß noch die Kompression deaktiviert werden: XSVF_SUPPORT_COMPRESSION (micro.c). Damit schrumpft die Variable xsvfInfo auf 546 Byte.&lt;br /&gt;
&lt;br /&gt;
Alle Funktionen können bequem über das Bedienpanel des Butterfly abgerufen werden:&lt;br /&gt;
&lt;br /&gt;
=== Menüstruktur ===&lt;br /&gt;
[[Bild:menu_struktur.png]]&lt;br /&gt;
&lt;br /&gt;
== Workflow ==&lt;br /&gt;
Im Allgemeinen wird sich der folgende Workflow ergeben:&lt;br /&gt;
* XSVF-Daten generieren&lt;br /&gt;
* Download&lt;br /&gt;
* Konfigurieren des FPGA&lt;br /&gt;
&lt;br /&gt;
=== XSVF-Daten generieren ===&lt;br /&gt;
Die XSVF-Dateien können inzwischen direkt durch Xilinx-Impact erstellt werden.&lt;br /&gt;
Ich nutze dafür dieses kleine Skript (bit2xsvf.cmd):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setmode -bs&lt;br /&gt;
setCable -port xsvf -file &amp;quot;design.xsvf&amp;quot;&lt;br /&gt;
addDevice -p 1 -file &amp;quot;design.bit&amp;quot;&lt;br /&gt;
program -p 1&lt;br /&gt;
closeCable&lt;br /&gt;
quit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Durch &amp;lt;pre&amp;gt;$ impact -batch bit2xsvf.cmd&amp;lt;/pre&amp;gt; wird die XSVF-Datei auf der Kommandozeile erstellt.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
Für den Download der XSVF-Datei in den Dataflash wird die serielle Schnittstelle auf 115200 Baud eingestellt und die Datei per XMODEM transferiert.&lt;br /&gt;
Mit der Linux-Kommandozeile geht das z.B. so:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ stty -F /dev/ttyS0 115200&lt;br /&gt;
$ sz --xmodem design.xsvf &amp;gt; /dev/ttyS0 &amp;lt; /dev/ttyS0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zur Kontrolle, kann der Inhalt des Dataflash auf der seriellen Schnittstelle ausgegeben werden (dump):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Page: 0&lt;br /&gt;
0x0000: 0x07 0x00 0x13 0x00 0x14 0x00 0x12 0x00 0x12 0x01 0x04 0x00 0x00 0x00 0x00 0x02 ................&lt;br /&gt;
0x0010: 0x06 0x09 0x08 0x00 0x00 0x00 0x20 0x01 0x0F 0xFF 0xFF 0xFF 0x09 0x00 0x00 0x00 ...... .........&lt;br /&gt;
0x0020: 0x00 0xF1 0x42 0x80 0x93 0x02 0x06 0x09 0x09 0x00 0x00 0x00 0x00 0xF1 0x42 0x80 ..B...........B.&lt;br /&gt;
0x0030: 0x93 0x02 0x06 0x3F 0x02 0x06 0x0B 0x04 0x00 0x00 0x36 0xB0 0x02 0x06 0x05 0x04 ...?......6.....&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Konfigurieren des FPGA ===&lt;br /&gt;
Die eigentliche Konfiguration des FPGA erfolgt mit dem Menüpunkt &amp;quot;Program FPGA&amp;quot;.&lt;br /&gt;
Wenn alles geklappt hat steht nach kurzer Zeit &amp;quot;done&amp;quot; im Display, sonst erhält man eine entsprechende Fehlermeldung.&lt;br /&gt;
&lt;br /&gt;
== Optimierungen ==&lt;br /&gt;
In der ersten funktionierenden Implementation benötigte das Programm ca. 400 Sekunden um das FPGA zu konfigurieren. Das entspricht einer Datentransferrate von 1,1 kByte/s. Völlig unakzeptabel.&lt;br /&gt;
&lt;br /&gt;
Also musste optimiert werden. Der RC-Oszillator des AVR wird beim Startup auf 1 MHz Taktfrequenz kalibriert. Wenn man den Takteiler von 8 auf 1 stellt, läuft der AVR schon mit 8 MHz. Durch Programmieren des OSCCAL-Registers mit 0x7F ließ sich mein ATmega auf 15 MHz beschleunigen. Damit ließ sich die Konfigurationszeit auf 25 Sekunden (17 kByte/s) verringern. Schon besser.&lt;br /&gt;
&lt;br /&gt;
Damit sich die Zeit für den XMODEM-Transfer ebenfalls verkürzt, wird die Baudrate der seriellen Schnittstelle auf 115200 eingestellt. Der ATmega läuft nur für die Konfiguration mit der vollen Geschwindigkeit. Für eine fehlerfreie serielle Datenübertragung wird der RC-Oszillator auf eine Taktfrequenz von 11,0592 MHz kalibriert.&lt;br /&gt;
Bei wem das nicht klappen sollte, der muß eine kleinere Taktfrequenz im Makefile (F_CPU) einstellen. Laut ATmega169-Datenblatt müßten 8 MHz +/-10 Prozent immer funktionieren.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Geschwindigkeitssteigerung konnte durch die Nutzung des USI-Moduls erreicht werden. Normalerweise werden TDI, TDO, TCK und TMS durch Bitbanging erzeugt. Xilinx hat diese Funktionen in ports.c schön gekapselt. Sehr portabel, aber nicht schnell.&lt;br /&gt;
Durch direkten Aufruf der USI-Register in der Funktion xsvfShiftOnly konnte eine weitere wesentliche Beschleunigung erreicht werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin ist die Reihenfolge der Bits in den JTAG-Daten (LSB...MSB) nicht passend für das USI-Datenregister. Es müssen also alle Bytes gespiegelt werden. Am schnellsten geht dies mit einer Tabelle, die leider etwas Speicher kostet. Außerdem wurde die Zählerbreite lNumBits von 32 auf 16 Bit reduziert.&lt;br /&gt;
&lt;br /&gt;
Damit ergibt sich letztendlich eine akzeptable Konfigurationszeit von 5,6 Sekunden und damit eine Transferrate von 75 kByte/s. Der Flash des ATmega169 ist mit 12 kByte gut gefüllt, läßt aber noch etwas Luft für Erweiterungen.&lt;br /&gt;
&lt;br /&gt;
== Ausblick ==&lt;br /&gt;
Um die folgenden Features könnte das Projekt noch erweitert werden:&lt;br /&gt;
* Lesen der Konfiguration von SD-Karte&lt;br /&gt;
* direkte Interpretation von .bit-Dateien&lt;br /&gt;
* Unterstützung von komprimierten Daten&lt;br /&gt;
&lt;br /&gt;
== Download ==&lt;br /&gt;
[[media:butterfly_xapp058.zip]]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/user_guides/ug332.pdf UG332 Spartan-3 Generation Configuration User Guide]&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#bf_app AVR Butterfly Application code port to avr-gcc]&lt;br /&gt;
* [http://www.atmel.com/Images/doc1472.pdf AVR350: Xmodem CRC Receive Utility for AVR]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf XAPP058 Xilinx In-System Programming Using an Embedded Microcontroller]&lt;br /&gt;
&lt;br /&gt;
[[Category:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>Horstsch</name></author>
	</entry>
</feed>