<?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=TheMason</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=TheMason"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/TheMason"/>
	<updated>2026-04-06T06:35:55Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Benutzer:TheMason&amp;diff=23183</id>
		<title>Benutzer:TheMason</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Benutzer:TheMason&amp;diff=23183"/>
		<updated>2007-08-06T15:36:19Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Über mich==&lt;br /&gt;
&lt;br /&gt;
Ich interessiere mich seit meiner Kindheit für Elektronik und Computer, und habe aus diesem Grund auch Elektrotechnik studiert.&lt;br /&gt;
Ich bin seit 2005 in diesem Forum, und beschäftige mich mit uC&#039;s, SW Design, VHDL Design und Platinen Design.&lt;br /&gt;
&lt;br /&gt;
==Beiträge==&lt;br /&gt;
&lt;br /&gt;
Die Audio-Platform mit dem Spartan 3 [[Audio-DSP_mit_Spartan_3-FPGA]] &amp;lt;br&amp;gt;&lt;br /&gt;
Der Audio-Codec TLV320AIC23b [[Audio_Codec_Board]]&lt;br /&gt;
&lt;br /&gt;
==Leute gesucht==&lt;br /&gt;
&lt;br /&gt;
Ich suche noch Leute die Lust und Zeit haben an dem Audio-Projekt mitzuwirken.&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio_Codec_Board_mit_TLV320AIC23b&amp;diff=22676</id>
		<title>Audio Codec Board mit TLV320AIC23b</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio_Codec_Board_mit_TLV320AIC23b&amp;diff=22676"/>
		<updated>2007-07-14T18:52:37Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Version von TheMason */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Überlegungen zu Audio-Erweiterungsplatine mit TLV320AIC23b ([http://focus.ti.com/lit/ds/symlink/tlv320aic23b.pdf Datenblatt])&lt;br /&gt;
&lt;br /&gt;
* Codec&lt;br /&gt;
* 12 MHz Quarz&lt;br /&gt;
* Analogbeschaltung wie in Eval-Board-Schaltplan&lt;br /&gt;
* 2x Cinch oder 1x Klinkenbuchse für Line In&lt;br /&gt;
* 2x Cinch oder 1x Klinkenbuchse für Line Out&lt;br /&gt;
* Klinkenbuchse für Kopfhörer&lt;br /&gt;
* Stiftleiste für I2S &amp;amp; I2C/SPI&lt;br /&gt;
* Jumper für MODE&lt;br /&gt;
* Jumper für Quarz/externe MCLK&lt;br /&gt;
&lt;br /&gt;
Layout:&lt;br /&gt;
* getrennte Masseflächen für AGND und DGND, nur eine Verbindung? Wahrscheinlich mehr Aufwand als Nutzen.&lt;br /&gt;
* Masseflächen auf bottom layer&lt;br /&gt;
* siehe Hinweise in http://focus.ti.com/lit/ds/symlink/tlv320aic20k.pdf&lt;br /&gt;
&lt;br /&gt;
==Version von TheMason==&lt;br /&gt;
&lt;br /&gt;
Die Vorschläge sind tlw. realisiert. Z.B. Widerstandsbrücken statt Jumper, Masseflächen nicht getrennt sondern nur eine auf der Unterseite.&lt;br /&gt;
&lt;br /&gt;
Schaltung in Anlehnung an das Referenz-Design von TI.&lt;br /&gt;
&lt;br /&gt;
[[Media:Codec_eagle_dateien.zip|Codec_eagle_dateien.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Schaltplan als PNG : &lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_sch.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Board Oberseite :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_top.png]]&lt;br /&gt;
&lt;br /&gt;
Board Unterseite :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_btm.png]]&lt;br /&gt;
&lt;br /&gt;
Bauteile Platzierung :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_partlocs.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fertige Platine (leider sehr unscharf) :&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec-board-top.jpg|thumb|pix=300|Oberseite]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec-board-btn.jpg|thumb|pix=300|Unterseite]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Es wurden 2 Boards (einer als Master, der andere als Slave) aufgebaut und tlw. getestet (Mikrofon und Headphone noch nicht getestet). Line In/Out und Konfig. funktionieren.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Kleiner Wermutstropfen : Die 220uF Elkos für den Kopfhörer haben das falsche Shape und sind zu klein. &amp;lt;br&amp;gt;&lt;br /&gt;
Auf dem Bild sind auch statt 0.47uF Elkos 470nF Kerkos verbaut. Passen sollten die 0.47uF aber schon, denn die 1uF sind ja schon recht klein.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bauteile Liste :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_bom.zip]]&lt;br /&gt;
&lt;br /&gt;
==SVN-Repository==&lt;br /&gt;
&lt;br /&gt;
svn co svn://mikrocontroller.net/audiodsp&lt;br /&gt;
&lt;br /&gt;
Ein automatisch aktualisiertes Paket mit den Daten aus dem Repository gibt es unter http://www.mikrocontroller.net/download/audiodsp-snapshot.tar.gz. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Audio]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio_Codec_Board_mit_TLV320AIC23b&amp;diff=22675</id>
		<title>Audio Codec Board mit TLV320AIC23b</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio_Codec_Board_mit_TLV320AIC23b&amp;diff=22675"/>
		<updated>2007-07-14T18:48:43Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Version von TheMason */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Überlegungen zu Audio-Erweiterungsplatine mit TLV320AIC23b ([http://focus.ti.com/lit/ds/symlink/tlv320aic23b.pdf Datenblatt])&lt;br /&gt;
&lt;br /&gt;
* Codec&lt;br /&gt;
* 12 MHz Quarz&lt;br /&gt;
* Analogbeschaltung wie in Eval-Board-Schaltplan&lt;br /&gt;
* 2x Cinch oder 1x Klinkenbuchse für Line In&lt;br /&gt;
* 2x Cinch oder 1x Klinkenbuchse für Line Out&lt;br /&gt;
* Klinkenbuchse für Kopfhörer&lt;br /&gt;
* Stiftleiste für I2S &amp;amp; I2C/SPI&lt;br /&gt;
* Jumper für MODE&lt;br /&gt;
* Jumper für Quarz/externe MCLK&lt;br /&gt;
&lt;br /&gt;
Layout:&lt;br /&gt;
* getrennte Masseflächen für AGND und DGND, nur eine Verbindung? Wahrscheinlich mehr Aufwand als Nutzen.&lt;br /&gt;
* Masseflächen auf bottom layer&lt;br /&gt;
* siehe Hinweise in http://focus.ti.com/lit/ds/symlink/tlv320aic20k.pdf&lt;br /&gt;
&lt;br /&gt;
==Version von TheMason==&lt;br /&gt;
&lt;br /&gt;
Die Vorschläge sind tlw. realisiert. Z.B. Widerstandsbrücken statt Jumper, Masseflächen nicht getrennt sondern nur eine auf der Unterseite.&lt;br /&gt;
&lt;br /&gt;
Schaltung in Anlehnung an das Referenz-Design von TI.&lt;br /&gt;
&lt;br /&gt;
[[Media:Codec_eagle_dateien.zip|Codec_eagle_dateien.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Schaltplan als PNG : &lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_sch.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Board Oberseite :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_top.png]]&lt;br /&gt;
&lt;br /&gt;
Board Unterseite :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_btm.png]]&lt;br /&gt;
&lt;br /&gt;
Bauteile Platzierung :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_partlocs.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fertige Platine (leider sehr unscharf) :&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec-board-top.jpg|thumb|pix=300|Oberseite]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec-board-btn.jpg|thumb|pix=300|Unterseite]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec-board-btn.jpg|thumb|pix=300|Unterseite]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Es wurden 2 Boards (einer als Master, der andere als Slave) aufgebaut und tlw. getestet (Mikrofon und Headphone noch nicht getestet). Line In/Out und Konfig. funktionieren.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Kleiner Wermutstropfen : Die 220uF Elkos für den Kopfhörer haben das falsche Shape und sind zu klein. &amp;lt;br&amp;gt;&lt;br /&gt;
Auf dem Bild sind auch statt 0.47uF Elkos 470nF Kerkos verbaut. Passen sollten die 0.47uF aber schon, denn die 1uF sind ja schon recht klein.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==SVN-Repository==&lt;br /&gt;
&lt;br /&gt;
svn co svn://mikrocontroller.net/audiodsp&lt;br /&gt;
&lt;br /&gt;
Ein automatisch aktualisiertes Paket mit den Daten aus dem Repository gibt es unter http://www.mikrocontroller.net/download/audiodsp-snapshot.tar.gz. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Audio]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio_Codec_Board_mit_TLV320AIC23b&amp;diff=22674</id>
		<title>Audio Codec Board mit TLV320AIC23b</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio_Codec_Board_mit_TLV320AIC23b&amp;diff=22674"/>
		<updated>2007-07-14T18:48:19Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Version von TheMason */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Überlegungen zu Audio-Erweiterungsplatine mit TLV320AIC23b ([http://focus.ti.com/lit/ds/symlink/tlv320aic23b.pdf Datenblatt])&lt;br /&gt;
&lt;br /&gt;
* Codec&lt;br /&gt;
* 12 MHz Quarz&lt;br /&gt;
* Analogbeschaltung wie in Eval-Board-Schaltplan&lt;br /&gt;
* 2x Cinch oder 1x Klinkenbuchse für Line In&lt;br /&gt;
* 2x Cinch oder 1x Klinkenbuchse für Line Out&lt;br /&gt;
* Klinkenbuchse für Kopfhörer&lt;br /&gt;
* Stiftleiste für I2S &amp;amp; I2C/SPI&lt;br /&gt;
* Jumper für MODE&lt;br /&gt;
* Jumper für Quarz/externe MCLK&lt;br /&gt;
&lt;br /&gt;
Layout:&lt;br /&gt;
* getrennte Masseflächen für AGND und DGND, nur eine Verbindung? Wahrscheinlich mehr Aufwand als Nutzen.&lt;br /&gt;
* Masseflächen auf bottom layer&lt;br /&gt;
* siehe Hinweise in http://focus.ti.com/lit/ds/symlink/tlv320aic20k.pdf&lt;br /&gt;
&lt;br /&gt;
==Version von TheMason==&lt;br /&gt;
&lt;br /&gt;
Die Vorschläge sind tlw. realisiert. Z.B. Widerstandsbrücken statt Jumper, Masseflächen nicht getrennt sondern nur eine auf der Unterseite.&lt;br /&gt;
&lt;br /&gt;
Schaltung in Anlehnung an das Referenz-Design von TI.&lt;br /&gt;
&lt;br /&gt;
[[Media:Codec_eagle_dateien.zip|Codec_eagle_dateien.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Schaltplan als PNG : &lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_sch.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Board Oberseite :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_top.png]]&lt;br /&gt;
&lt;br /&gt;
Board Unterseite :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_btm.png]]&lt;br /&gt;
&lt;br /&gt;
Bauteile Platzierung :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_partlocs.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fertige Platine (leider sehr unscharf) :&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec-board-top.jpg|thumb|pix=300|Oberseite]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec-board-btn.jpg|thumb|pix=300|Unterseite]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec-board-btn.jpg|thumb|pix=300|Unterseite]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Es wurden 2 Boards (einer als Master, der andere als Slave) aufgebaut und tlw. getestet (Mikrofon und Headphone noch nicht getestet). Line In/Out und Konfig. funktionieren.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Kleiner Wermutstropfen : Die 220uF Elkos für den Kopfhörer haben das falsche Shape und sind zu klein. &amp;lt;br&amp;gt;&lt;br /&gt;
Auf dem Bild sind auch statt 0.47uF Elkos 470nF Kerkos verbaut. Passen sollten die 0.47uF aber schon, denn die 1uF sind ja schon recht klein.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==SVN-Repository==&lt;br /&gt;
&lt;br /&gt;
svn co svn://mikrocontroller.net/audiodsp&lt;br /&gt;
&lt;br /&gt;
Ein automatisch aktualisiertes Paket mit den Daten aus dem Repository gibt es unter http://www.mikrocontroller.net/download/audiodsp-snapshot.tar.gz. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Audio]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Codec_bom.zip&amp;diff=22673</id>
		<title>Datei:Codec bom.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Codec_bom.zip&amp;diff=22673"/>
		<updated>2007-07-14T18:39:57Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio_Codec_Board_mit_TLV320AIC23b&amp;diff=22672</id>
		<title>Audio Codec Board mit TLV320AIC23b</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio_Codec_Board_mit_TLV320AIC23b&amp;diff=22672"/>
		<updated>2007-07-14T18:38:06Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Version von TheMason */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Überlegungen zu Audio-Erweiterungsplatine mit TLV320AIC23b ([http://focus.ti.com/lit/ds/symlink/tlv320aic23b.pdf Datenblatt])&lt;br /&gt;
&lt;br /&gt;
* Codec&lt;br /&gt;
* 12 MHz Quarz&lt;br /&gt;
* Analogbeschaltung wie in Eval-Board-Schaltplan&lt;br /&gt;
* 2x Cinch oder 1x Klinkenbuchse für Line In&lt;br /&gt;
* 2x Cinch oder 1x Klinkenbuchse für Line Out&lt;br /&gt;
* Klinkenbuchse für Kopfhörer&lt;br /&gt;
* Stiftleiste für I2S &amp;amp; I2C/SPI&lt;br /&gt;
* Jumper für MODE&lt;br /&gt;
* Jumper für Quarz/externe MCLK&lt;br /&gt;
&lt;br /&gt;
Layout:&lt;br /&gt;
* getrennte Masseflächen für AGND und DGND, nur eine Verbindung? Wahrscheinlich mehr Aufwand als Nutzen.&lt;br /&gt;
* Masseflächen auf bottom layer&lt;br /&gt;
* siehe Hinweise in http://focus.ti.com/lit/ds/symlink/tlv320aic20k.pdf&lt;br /&gt;
&lt;br /&gt;
==Version von TheMason==&lt;br /&gt;
&lt;br /&gt;
Die Vorschläge sind tlw. realisiert. Z.B. Widerstandsbrücken statt Jumper, Masseflächen nicht getrennt sondern nur eine auf der Unterseite.&lt;br /&gt;
&lt;br /&gt;
Schaltung in Anlehnung an das Referenz-Design von TI.&lt;br /&gt;
&lt;br /&gt;
[[Media:Codec_eagle_dateien.zip|Codec_eagle_dateien.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Schaltplan als PNG : &lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_sch.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Board Oberseite :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_top.png]]&lt;br /&gt;
&lt;br /&gt;
Board Unterseite :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_btm.png]]&lt;br /&gt;
&lt;br /&gt;
Bauteile Platzierung :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_partlocs.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fertige Platine (leider sehr unscharf) :&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec-board-top.jpg|thumb|pix=300|Oberseite]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec-board-btn.jpg|thumb|pix=300|Unterseite ]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Es wurden 2 Boards (einer als Master, der andere als Slave) aufgebaut und tlw. getestet (Mikrofon und Headphone noch nicht getestet). Line In/Out und Konfig. funktionieren.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Kleiner Wermutstropfen : Die 220uF Elkos für den Kopfhörer haben das falsche Shape und sind zu klein. &amp;lt;br&amp;gt;&lt;br /&gt;
Auf dem Bild sind auch statt 0.47uF Elkos 470nF Kerkos verbaut. Passen sollten die 0.47uF aber schon, denn die 1uF sind ja schon recht klein.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==SVN-Repository==&lt;br /&gt;
&lt;br /&gt;
svn co svn://mikrocontroller.net/audiodsp&lt;br /&gt;
&lt;br /&gt;
Ein automatisch aktualisiertes Paket mit den Daten aus dem Repository gibt es unter http://www.mikrocontroller.net/download/audiodsp-snapshot.tar.gz. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Audio]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Codec-board-top.jpg&amp;diff=22671</id>
		<title>Datei:Codec-board-top.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Codec-board-top.jpg&amp;diff=22671"/>
		<updated>2007-07-14T18:29:01Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Codec-board-btn.jpg&amp;diff=22670</id>
		<title>Datei:Codec-board-btn.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Codec-board-btn.jpg&amp;diff=22670"/>
		<updated>2007-07-14T18:28:53Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=22669</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=22669"/>
		<updated>2007-07-14T18:28:11Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Fotos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshaper&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im aktuellen Schaltplan wird auf einen Mikroprozessor verzichtet. Dieser diente im System erstmal nur zu Initialisierung der Codecs. Dieser Vorgang kann nun vom PC aus gesteuert werden, da in der neuen ISE 6.2 Version 4 Leitungen herausgeführtz wurden, welche per RS232 gesetzt und gelöscht werden. &lt;br /&gt;
Wer das System nachbauen möchte kann entweder die TLV320AIC23B Codecs, aber auch beliebige andere Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Die Initialisierung dieser Codecs muß dann aber separat vorgenommen werden (wobei man dann wahrscheinlich nicht um einen uC drum herum kommt). Um das System zu Testen (Programme und Koeffizienten in den DAP einzuspielen) wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Zur Auswahl der verwendeten Schnittstelle (RS232 oder SPI) wird Pin 13 des B1-Connectors benutzt. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]] (noch die alte Version -&amp;gt; Kein Delay, Kein Lesen und vor allem : Kein Initialisieren der Codecs)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In dem unten angegebenen Repository ist eine Version (ohne Speicheranbindung des Util-Cores) die auf dem Nexys Board lauffähig ist. Der verwendete Codec ist wie schon im bisherigen Projekt der TLV320AIC23B. Dieser wird via RS232 (6-pin Port A des Nexys Boards) über die GPO Leitungen (6-pin Port D des Nexys Boards) initialisiert. Die eigentlichen Datenleitungen des Codecs liegen an Port B (BCLK, LRCLK, DIN, DOUT).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nexys Board==&lt;br /&gt;
&lt;br /&gt;
Im SVN Repository (s.u.) gibt es eine Version des DAPs für das Nexys Board.&lt;br /&gt;
Diese ist voll SW-Kompatibel zum alten Spartan 3 Board (allerdings z.Z. nur über RS232 steuerbar). Neu bei der Version ist das das Speicherinterface generisch ausgelegt wurde und ein einfacher SRAM-Controller für das Nexys Board PSDRAM geschrieben wurde. Durch das generische Interface ist es möglich andere Speicherarten anzubinden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Download des DAP als MCS-File für das Nexys-1000 Board : [[Media:Nexys_dap.zip]]&lt;br /&gt;
&lt;br /&gt;
Diese Version ist voll lauffähig (wurde mit den Demos getestet).&lt;br /&gt;
Die Pin Belegung für die RS232 und den Audio-Codec ist wie folgt :&lt;br /&gt;
&lt;br /&gt;
Header A : RS232 Schnittstelle&amp;lt;br&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Pin 1 : RxD von MAX232&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 2 : TxD von MAX232&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 3 : -&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 4 : -&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 5 : GND&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 6 : VCC (3.3V/5V für MAX232/MAX3232)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Header B : I2S Schnittstelle für 1 Codec&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pin 1 : BitClk&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 2 : L/R Clk&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 3 : SDIN&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 4 : SDOUT&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 5 : GND&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 6 : VCC (3.3V für den Codec)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Header D : Codec-Konfiguration via SPI&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pin 1 : Codec 2 CS&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 2 : Codec 1 CS&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 3 : Codec SPI Data&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 4 : Codec SPI Clk&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 5 : GND&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 6 : VCC&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left|Spartan3 Board und Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left|Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:dap_nexys_v1.jpg|thumb|300px|left|Nexys Board mit 1 Audio-Codec]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Nexys-board-gesamt.jpg|thumb|300px|left|Nexys Board mit Lochraster-Board und 2 Audio-Codec-Boards (siehe Artikel &amp;quot;Audio-Codec-Board&amp;quot;)]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Nexys-board-codecs-1.jpg|thumb|300px|left|2 Audio-Codec-Boards (siehe Artikel &amp;quot;Audio-Codec-Board&amp;quot;)]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
Der DAP als Synth. Der DAP wird komplett vom PC aus gesteuert (Hüllkurve, Sequencer und Filterberechnung werden im PC gemacht). PC Programm und Source folgen&lt;br /&gt;
&lt;br /&gt;
[[Media:synthdemo1.wav.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MC505 Demos ===&lt;br /&gt;
&lt;br /&gt;
Die folgenden Demos stammen von meiner Roland-MC505 Groovebox. Es wird einfach nur ein Werkspreset abgespielt und durch den DAP gejagt.&lt;br /&gt;
&lt;br /&gt;
* [[Media:mc505-eq-demo.wav.zip|EQ-Demo]]&lt;br /&gt;
* [[Media:mc505-filter-demo.wav.zip|Filter-Demo (Tiefpass/Hochpass/Notch)]]&lt;br /&gt;
* [[Media:mc505-delay-demo.wav.zip|Delay-Demo (137BPM [657ms &amp;amp; 876 ms]/Chorus)]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen. &lt;br /&gt;
Nachtrag zum Konfigurieren des Codecs : Prinzipiell funktioniert es, allerdings ist das mit häßlichen Nebengeräuschen verbunden, da ich bei jeder Änderung der Lautstärke im Codec, diesen auch Resetten muß, da sonst immer beide Codecs beschrieben werden, was unschön ist. Warum dies so ist kann ich leider nicht sagen, da ich keine Möglichkeit habe die SPI-Leitungen mitzusniffen (bräuchte dafür einen kleinen LA, den ich nicht habe). &lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Quellcodes für das EQ-Demo, das Filter-Demo und das Delay-Demo : [[Media:dap_demos_plus_delphi_source.zip]]&lt;br /&gt;
&lt;br /&gt;
Es folgen noch der Quellcode für den Mischer (hab ich gerade nicht zur Hand) und weitere Demos (ein Synthesizer und eine 4x4 Patchbay mit EQ und was mir sonst noch einfällt. Dann natürlich mit Source-Codes).&lt;br /&gt;
Anhand dieser Beispiele wird auch eine grobe Doku erstellt.&lt;br /&gt;
&lt;br /&gt;
== SVN-Repository ==&lt;br /&gt;
&lt;br /&gt;
 svn co svn://mikrocontroller.net/audiodsp&lt;br /&gt;
&lt;br /&gt;
Ein automatisch aktualisiertes Paket mit den Daten aus dem Repository gibt es unter http://www.mikrocontroller.net/download/audiodsp-snapshot.tar.gz.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
- Update 12.07.2007 :&lt;br /&gt;
&lt;br /&gt;
Es wurde ein generisches Speicherinterfaces welches Wartezyklen im DAP erlaubt implementiert. Dadurch kann man auf die jeweilgen Speicher des Boards eingehen. Z.Z. ist nur ein einfaches Speicherinterface für den asynchronen Betrieb des PSDRAM des Nexys Boards implementiert. Das Interface ermögicht es einen RAM Controller anzuschließen welcher z.B. ein quasi-Multiport RAM darstellt.&lt;br /&gt;
Getestet wurde der Stand mit dem Nexys-1000 Board.&lt;br /&gt;
&lt;br /&gt;
==To do ...==&lt;br /&gt;
&lt;br /&gt;
--nähere Zukunft--&lt;br /&gt;
* Einen Konfigurationsdialog in die Demo-Programme einarbeiten mit denen man mit den Codecs etwas spielen kann (Line-In Level, Mikrofon-Level, Bypass, Head-Phone Volume) tlw. erledigt. Funktioniert aber nicht richtig, und daher noch nicht eingebaut. Quellcodes dazu sind vorhanden.&lt;br /&gt;
* Doku anhand der Demo-Programme erstellen&lt;br /&gt;
* C-Code schnipsel erstellen&lt;br /&gt;
&lt;br /&gt;
--fernere Zukunft--&lt;br /&gt;
* Front-End des DAPs machen, mit dem sich DAP-Programme erstellen lassen, der Koeffizienten-, Daten- und Wellenform-Speicher beschrieben und gelesen werden kann, der Mikro-Code editierbar gemacht wird und noch ein paar Sachen mehr machbar sind&lt;br /&gt;
* Synthesizer realisieren (in Verbindung mit uC, MSP430 oder ARM7)&lt;br /&gt;
* weitere Module für den Rahmen (HDD-Core, weitere Routing-Möglichkeiten innerhalb der bisherigen Cores SDSP und Util)&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
* http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]] [[Category:DSP]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Nexys-board-codecs-1.jpg&amp;diff=22668</id>
		<title>Datei:Nexys-board-codecs-1.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Nexys-board-codecs-1.jpg&amp;diff=22668"/>
		<updated>2007-07-14T18:23:15Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Nexys-board-gesamt.jpg&amp;diff=22667</id>
		<title>Datei:Nexys-board-gesamt.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Nexys-board-gesamt.jpg&amp;diff=22667"/>
		<updated>2007-07-14T18:22:51Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio_Codec_Board_mit_TLV320AIC23b&amp;diff=22629</id>
		<title>Audio Codec Board mit TLV320AIC23b</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio_Codec_Board_mit_TLV320AIC23b&amp;diff=22629"/>
		<updated>2007-07-13T11:42:34Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Überlegungen zu Audio-Erweiterungsplatine mit TLV320AIC23b ([http://focus.ti.com/lit/ds/symlink/tlv320aic23b.pdf Datenblatt])&lt;br /&gt;
&lt;br /&gt;
* Codec&lt;br /&gt;
* 12 MHz Quarz&lt;br /&gt;
* Analogbeschaltung wie in Eval-Board-Schaltplan&lt;br /&gt;
* 2x Cinch oder 1x Klinkenbuchse für Line In&lt;br /&gt;
* 2x Cinch oder 1x Klinkenbuchse für Line Out&lt;br /&gt;
* Klinkenbuchse für Kopfhörer&lt;br /&gt;
* Stiftleiste für I2S &amp;amp; I2C/SPI&lt;br /&gt;
* Jumper für MODE&lt;br /&gt;
* Jumper für Quarz/externe MCLK&lt;br /&gt;
&lt;br /&gt;
Layout:&lt;br /&gt;
* getrennte Masseflächen für AGND und DGND, nur eine Verbindung&lt;br /&gt;
* Masseflächen auf bottom layer&lt;br /&gt;
* siehe Hinweise in http://focus.ti.com/lit/ds/symlink/tlv320aic20k.pdf&lt;br /&gt;
&lt;br /&gt;
==Version von TheMason==&lt;br /&gt;
&lt;br /&gt;
Die Vorschläge sind tlw. realisiert. Z.B. WIderstandsbrücken statt Jumper, Masseflächen nicht getrennt sondern nur eine auf der Unterseite.&lt;br /&gt;
&lt;br /&gt;
Schaltung in Anlehnung an das Referenz-Design von TI.&lt;br /&gt;
&lt;br /&gt;
[[Media:Codec_eagle_dateien.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Schaltplan als PNG : &lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_sch.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Board Oberseite :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_top.png]]&lt;br /&gt;
&lt;br /&gt;
Board Unterseite :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_btm.png]]&lt;br /&gt;
&lt;br /&gt;
Bauteile Platzierung :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codec_brd_partlocs.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weitere Bilder des fertigen Codec Boards folgen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==SVN-Repository==&lt;br /&gt;
&lt;br /&gt;
svn co svn://mikrocontroller.net/audiodsp&lt;br /&gt;
&lt;br /&gt;
Ein automatisch aktualisiertes Paket mit den Daten aus dem Repository gibt es unter http://www.mikrocontroller.net/download/audiodsp-snapshot.tar.gz. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Audio]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Codec_brd_partlocs.png&amp;diff=22628</id>
		<title>Datei:Codec brd partlocs.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Codec_brd_partlocs.png&amp;diff=22628"/>
		<updated>2007-07-13T11:38:37Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Codec_brd_top.png&amp;diff=22627</id>
		<title>Datei:Codec brd top.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Codec_brd_top.png&amp;diff=22627"/>
		<updated>2007-07-13T11:38:31Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Codec_brd_btm.png&amp;diff=22626</id>
		<title>Datei:Codec brd btm.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Codec_brd_btm.png&amp;diff=22626"/>
		<updated>2007-07-13T11:38:25Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Codec_sch.png&amp;diff=22625</id>
		<title>Datei:Codec sch.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Codec_sch.png&amp;diff=22625"/>
		<updated>2007-07-13T11:37:11Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Codec_eagle_dateien.zip&amp;diff=22624</id>
		<title>Datei:Codec eagle dateien.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Codec_eagle_dateien.zip&amp;diff=22624"/>
		<updated>2007-07-13T11:35:54Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=22623</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=22623"/>
		<updated>2007-07-13T11:05:47Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Nexys Board */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshaper&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im aktuellen Schaltplan wird auf einen Mikroprozessor verzichtet. Dieser diente im System erstmal nur zu Initialisierung der Codecs. Dieser Vorgang kann nun vom PC aus gesteuert werden, da in der neuen ISE 6.2 Version 4 Leitungen herausgeführtz wurden, welche per RS232 gesetzt und gelöscht werden. &lt;br /&gt;
Wer das System nachbauen möchte kann entweder die TLV320AIC23B Codecs, aber auch beliebige andere Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Die Initialisierung dieser Codecs muß dann aber separat vorgenommen werden (wobei man dann wahrscheinlich nicht um einen uC drum herum kommt). Um das System zu Testen (Programme und Koeffizienten in den DAP einzuspielen) wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Zur Auswahl der verwendeten Schnittstelle (RS232 oder SPI) wird Pin 13 des B1-Connectors benutzt. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]] (noch die alte Version -&amp;gt; Kein Delay, Kein Lesen und vor allem : Kein Initialisieren der Codecs)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In dem unten angegebenen Repository ist eine Version (ohne Speicheranbindung des Util-Cores) die auf dem Nexys Board lauffähig ist. Der verwendete Codec ist wie schon im bisherigen Projekt der TLV320AIC23B. Dieser wird via RS232 (6-pin Port A des Nexys Boards) über die GPO Leitungen (6-pin Port D des Nexys Boards) initialisiert. Die eigentlichen Datenleitungen des Codecs liegen an Port B (BCLK, LRCLK, DIN, DOUT).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nexys Board==&lt;br /&gt;
&lt;br /&gt;
Im SVN Repository (s.u.) gibt es eine Version des DAPs für das Nexys Board.&lt;br /&gt;
Diese ist voll SW-Kompatibel zum alten Spartan 3 Board (allerdings z.Z. nur über RS232 steuerbar). Neu bei der Version ist das das Speicherinterface generisch ausgelegt wurde und ein einfacher SRAM-Controller für das Nexys Board PSDRAM geschrieben wurde. Durch das generische Interface ist es möglich andere Speicherarten anzubinden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Download des DAP als MCS-File für das Nexys-1000 Board : [[Media:Nexys_dap.zip]]&lt;br /&gt;
&lt;br /&gt;
Diese Version ist voll lauffähig (wurde mit den Demos getestet).&lt;br /&gt;
Die Pin Belegung für die RS232 und den Audio-Codec ist wie folgt :&lt;br /&gt;
&lt;br /&gt;
Header A :&amp;lt;br&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Pin 1 : RxD von MAX232&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 2 : TxD von MAX232&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 3 : -&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 4 : -&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 5 : GND&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 6 : VCC (3.3V/5V für MAX232/MAX3232)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Header B :&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pin 1 : BitClk&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 2 : L/R Clk&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 3 : SDIN&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 4 : SDOUT&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 5 : GND&amp;lt;br&amp;gt;&lt;br /&gt;
Pin 6 : VCC (3.3V für den Codec)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left|Spartan3 Board und Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left|Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:dap_nexys_v1.jpg|thumb|300px|left|Nexys Board mit 1 Audio-Codec]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
Der DAP als Synth. Der DAP wird komplett vom PC aus gesteuert (Hüllkurve, Sequencer und Filterberechnung werden im PC gemacht). PC Programm und Source folgen&lt;br /&gt;
&lt;br /&gt;
[[Media:synthdemo1.wav.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MC505 Demos ===&lt;br /&gt;
&lt;br /&gt;
Die folgenden Demos stammen von meiner Roland-MC505 Groovebox. Es wird einfach nur ein Werkspreset abgespielt und durch den DAP gejagt.&lt;br /&gt;
&lt;br /&gt;
* [[Media:mc505-eq-demo.wav.zip|EQ-Demo]]&lt;br /&gt;
* [[Media:mc505-filter-demo.wav.zip|Filter-Demo (Tiefpass/Hochpass/Notch)]]&lt;br /&gt;
* [[Media:mc505-delay-demo.wav.zip|Delay-Demo (137BPM [657ms &amp;amp; 876 ms]/Chorus)]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen. &lt;br /&gt;
Nachtrag zum Konfigurieren des Codecs : Prinzipiell funktioniert es, allerdings ist das mit häßlichen Nebengeräuschen verbunden, da ich bei jeder Änderung der Lautstärke im Codec, diesen auch Resetten muß, da sonst immer beide Codecs beschrieben werden, was unschön ist. Warum dies so ist kann ich leider nicht sagen, da ich keine Möglichkeit habe die SPI-Leitungen mitzusniffen (bräuchte dafür einen kleinen LA, den ich nicht habe). &lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Quellcodes für das EQ-Demo, das Filter-Demo und das Delay-Demo : [[Media:dap_demos_plus_delphi_source.zip]]&lt;br /&gt;
&lt;br /&gt;
Es folgen noch der Quellcode für den Mischer (hab ich gerade nicht zur Hand) und weitere Demos (ein Synthesizer und eine 4x4 Patchbay mit EQ und was mir sonst noch einfällt. Dann natürlich mit Source-Codes).&lt;br /&gt;
Anhand dieser Beispiele wird auch eine grobe Doku erstellt.&lt;br /&gt;
&lt;br /&gt;
== SVN-Repository ==&lt;br /&gt;
&lt;br /&gt;
 svn co svn://mikrocontroller.net/audiodsp&lt;br /&gt;
&lt;br /&gt;
Ein automatisch aktualisiertes Paket mit den Daten aus dem Repository gibt es unter http://www.mikrocontroller.net/download/audiodsp-snapshot.tar.gz.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
- Update 12.07.2007 :&lt;br /&gt;
&lt;br /&gt;
Es wurde ein generisches Speicherinterfaces welches Wartezyklen im DAP erlaubt implementiert. Dadurch kann man auf die jeweilgen Speicher des Boards eingehen. Z.Z. ist nur ein einfaches Speicherinterface für den asynchronen Betrieb des PSDRAM des Nexys Boards implementiert. Das Interface ermögicht es einen RAM Controller anzuschließen welcher z.B. ein quasi-Multiport RAM darstellt.&lt;br /&gt;
Getestet wurde der Stand mit dem Nexys-1000 Board.&lt;br /&gt;
&lt;br /&gt;
==To do ...==&lt;br /&gt;
&lt;br /&gt;
--nähere Zukunft--&lt;br /&gt;
* Einen Konfigurationsdialog in die Demo-Programme einarbeiten mit denen man mit den Codecs etwas spielen kann (Line-In Level, Mikrofon-Level, Bypass, Head-Phone Volume) tlw. erledigt. Funktioniert aber nicht richtig, und daher noch nicht eingebaut. Quellcodes dazu sind vorhanden.&lt;br /&gt;
* Doku anhand der Demo-Programme erstellen&lt;br /&gt;
* C-Code schnipsel erstellen&lt;br /&gt;
&lt;br /&gt;
--fernere Zukunft--&lt;br /&gt;
* Front-End des DAPs machen, mit dem sich DAP-Programme erstellen lassen, der Koeffizienten-, Daten- und Wellenform-Speicher beschrieben und gelesen werden kann, der Mikro-Code editierbar gemacht wird und noch ein paar Sachen mehr machbar sind&lt;br /&gt;
* Synthesizer realisieren (in Verbindung mit uC, MSP430 oder ARM7)&lt;br /&gt;
* weitere Module für den Rahmen (HDD-Core, weitere Routing-Möglichkeiten innerhalb der bisherigen Cores SDSP und Util)&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
* http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]] [[Category:DSP]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=22618</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=22618"/>
		<updated>2007-07-13T10:59:30Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Fotos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshaper&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im aktuellen Schaltplan wird auf einen Mikroprozessor verzichtet. Dieser diente im System erstmal nur zu Initialisierung der Codecs. Dieser Vorgang kann nun vom PC aus gesteuert werden, da in der neuen ISE 6.2 Version 4 Leitungen herausgeführtz wurden, welche per RS232 gesetzt und gelöscht werden. &lt;br /&gt;
Wer das System nachbauen möchte kann entweder die TLV320AIC23B Codecs, aber auch beliebige andere Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Die Initialisierung dieser Codecs muß dann aber separat vorgenommen werden (wobei man dann wahrscheinlich nicht um einen uC drum herum kommt). Um das System zu Testen (Programme und Koeffizienten in den DAP einzuspielen) wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Zur Auswahl der verwendeten Schnittstelle (RS232 oder SPI) wird Pin 13 des B1-Connectors benutzt. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]] (noch die alte Version -&amp;gt; Kein Delay, Kein Lesen und vor allem : Kein Initialisieren der Codecs)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In dem unten angegebenen Repository ist eine Version (ohne Speicheranbindung des Util-Cores) die auf dem Nexys Board lauffähig ist. Der verwendete Codec ist wie schon im bisherigen Projekt der TLV320AIC23B. Dieser wird via RS232 (6-pin Port A des Nexys Boards) über die GPO Leitungen (6-pin Port D des Nexys Boards) initialisiert. Die eigentlichen Datenleitungen des Codecs liegen an Port B (BCLK, LRCLK, DIN, DOUT).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nexys Board==&lt;br /&gt;
&lt;br /&gt;
Im SVN Repository (s.u.) gibt es eine Version des DAPs für das Nexys Board.&lt;br /&gt;
Diese ist voll SW-Kompatibel zum alten Spartan 3 Board (allerdings z.Z. nur über RS232 steuerbar). Neu bei der Version ist das das Speicherinterface generisch ausgelegt wurde und ein einfacher SRAM-Controller für das Nexys Board PSDRAM geschrieben wurde. Durch das generische Interface ist es möglich andere Speicherarten anzubinden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Download des DAP als MCS-File für das Nexys-1000 Board : [[Media:Nexys_dap.zip]]&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left|Spartan3 Board und Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left|Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:dap_nexys_v1.jpg|thumb|300px|left|Nexys Board mit 1 Audio-Codec]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
Der DAP als Synth. Der DAP wird komplett vom PC aus gesteuert (Hüllkurve, Sequencer und Filterberechnung werden im PC gemacht). PC Programm und Source folgen&lt;br /&gt;
&lt;br /&gt;
[[Media:synthdemo1.wav.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MC505 Demos ===&lt;br /&gt;
&lt;br /&gt;
Die folgenden Demos stammen von meiner Roland-MC505 Groovebox. Es wird einfach nur ein Werkspreset abgespielt und durch den DAP gejagt.&lt;br /&gt;
&lt;br /&gt;
* [[Media:mc505-eq-demo.wav.zip|EQ-Demo]]&lt;br /&gt;
* [[Media:mc505-filter-demo.wav.zip|Filter-Demo (Tiefpass/Hochpass/Notch)]]&lt;br /&gt;
* [[Media:mc505-delay-demo.wav.zip|Delay-Demo (137BPM [657ms &amp;amp; 876 ms]/Chorus)]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen. &lt;br /&gt;
Nachtrag zum Konfigurieren des Codecs : Prinzipiell funktioniert es, allerdings ist das mit häßlichen Nebengeräuschen verbunden, da ich bei jeder Änderung der Lautstärke im Codec, diesen auch Resetten muß, da sonst immer beide Codecs beschrieben werden, was unschön ist. Warum dies so ist kann ich leider nicht sagen, da ich keine Möglichkeit habe die SPI-Leitungen mitzusniffen (bräuchte dafür einen kleinen LA, den ich nicht habe). &lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Quellcodes für das EQ-Demo, das Filter-Demo und das Delay-Demo : [[Media:dap_demos_plus_delphi_source.zip]]&lt;br /&gt;
&lt;br /&gt;
Es folgen noch der Quellcode für den Mischer (hab ich gerade nicht zur Hand) und weitere Demos (ein Synthesizer und eine 4x4 Patchbay mit EQ und was mir sonst noch einfällt. Dann natürlich mit Source-Codes).&lt;br /&gt;
Anhand dieser Beispiele wird auch eine grobe Doku erstellt.&lt;br /&gt;
&lt;br /&gt;
== SVN-Repository ==&lt;br /&gt;
&lt;br /&gt;
 svn co svn://mikrocontroller.net/audiodsp&lt;br /&gt;
&lt;br /&gt;
Ein automatisch aktualisiertes Paket mit den Daten aus dem Repository gibt es unter http://www.mikrocontroller.net/download/audiodsp-snapshot.tar.gz.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
- Update 12.07.2007 :&lt;br /&gt;
&lt;br /&gt;
Es wurde ein generisches Speicherinterfaces welches Wartezyklen im DAP erlaubt implementiert. Dadurch kann man auf die jeweilgen Speicher des Boards eingehen. Z.Z. ist nur ein einfaches Speicherinterface für den asynchronen Betrieb des PSDRAM des Nexys Boards implementiert. Das Interface ermögicht es einen RAM Controller anzuschließen welcher z.B. ein quasi-Multiport RAM darstellt.&lt;br /&gt;
Getestet wurde der Stand mit dem Nexys-1000 Board.&lt;br /&gt;
&lt;br /&gt;
==To do ...==&lt;br /&gt;
&lt;br /&gt;
--nähere Zukunft--&lt;br /&gt;
* Einen Konfigurationsdialog in die Demo-Programme einarbeiten mit denen man mit den Codecs etwas spielen kann (Line-In Level, Mikrofon-Level, Bypass, Head-Phone Volume) tlw. erledigt. Funktioniert aber nicht richtig, und daher noch nicht eingebaut. Quellcodes dazu sind vorhanden.&lt;br /&gt;
* Doku anhand der Demo-Programme erstellen&lt;br /&gt;
* C-Code schnipsel erstellen&lt;br /&gt;
&lt;br /&gt;
--fernere Zukunft--&lt;br /&gt;
* Front-End des DAPs machen, mit dem sich DAP-Programme erstellen lassen, der Koeffizienten-, Daten- und Wellenform-Speicher beschrieben und gelesen werden kann, der Mikro-Code editierbar gemacht wird und noch ein paar Sachen mehr machbar sind&lt;br /&gt;
* Synthesizer realisieren (in Verbindung mit uC, MSP430 oder ARM7)&lt;br /&gt;
* weitere Module für den Rahmen (HDD-Core, weitere Routing-Möglichkeiten innerhalb der bisherigen Cores SDSP und Util)&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
* http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]] [[Category:DSP]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Dap_nexys_v1.jpg&amp;diff=22617</id>
		<title>Datei:Dap nexys v1.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Dap_nexys_v1.jpg&amp;diff=22617"/>
		<updated>2007-07-13T10:58:39Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=22599</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=22599"/>
		<updated>2007-07-13T00:25:33Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* To do ... */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshaper&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im aktuellen Schaltplan wird auf einen Mikroprozessor verzichtet. Dieser diente im System erstmal nur zu Initialisierung der Codecs. Dieser Vorgang kann nun vom PC aus gesteuert werden, da in der neuen ISE 6.2 Version 4 Leitungen herausgeführtz wurden, welche per RS232 gesetzt und gelöscht werden. &lt;br /&gt;
Wer das System nachbauen möchte kann entweder die TLV320AIC23B Codecs, aber auch beliebige andere Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Die Initialisierung dieser Codecs muß dann aber separat vorgenommen werden (wobei man dann wahrscheinlich nicht um einen uC drum herum kommt). Um das System zu Testen (Programme und Koeffizienten in den DAP einzuspielen) wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Zur Auswahl der verwendeten Schnittstelle (RS232 oder SPI) wird Pin 13 des B1-Connectors benutzt. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]] (noch die alte Version -&amp;gt; Kein Delay, Kein Lesen und vor allem : Kein Initialisieren der Codecs)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In dem unten angegebenen Repository ist eine Version (ohne Speicheranbindung des Util-Cores) die auf dem Nexys Board lauffähig ist. Der verwendete Codec ist wie schon im bisherigen Projekt der TLV320AIC23B. Dieser wird via RS232 (6-pin Port A des Nexys Boards) über die GPO Leitungen (6-pin Port D des Nexys Boards) initialisiert. Die eigentlichen Datenleitungen des Codecs liegen an Port B (BCLK, LRCLK, DIN, DOUT).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nexys Board==&lt;br /&gt;
&lt;br /&gt;
Im SVN Repository (s.u.) gibt es eine Version des DAPs für das Nexys Board.&lt;br /&gt;
Diese ist voll SW-Kompatibel zum alten Spartan 3 Board (allerdings z.Z. nur über RS232 steuerbar). Neu bei der Version ist das das Speicherinterface generisch ausgelegt wurde und ein einfacher SRAM-Controller für das Nexys Board PSDRAM geschrieben wurde. Durch das generische Interface ist es möglich andere Speicherarten anzubinden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Download des DAP als MCS-File für das Nexys-1000 Board : [[Media:Nexys_dap.zip]]&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left|Spartan3 Board und Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left|Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
Der DAP als Synth. Der DAP wird komplett vom PC aus gesteuert (Hüllkurve, Sequencer und Filterberechnung werden im PC gemacht). PC Programm und Source folgen&lt;br /&gt;
&lt;br /&gt;
[[Media:synthdemo1.wav.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MC505 Demos ===&lt;br /&gt;
&lt;br /&gt;
Die folgenden Demos stammen von meiner Roland-MC505 Groovebox. Es wird einfach nur ein Werkspreset abgespielt und durch den DAP gejagt.&lt;br /&gt;
&lt;br /&gt;
* [[Media:mc505-eq-demo.wav.zip|EQ-Demo]]&lt;br /&gt;
* [[Media:mc505-filter-demo.wav.zip|Filter-Demo (Tiefpass/Hochpass/Notch)]]&lt;br /&gt;
* [[Media:mc505-delay-demo.wav.zip|Delay-Demo (137BPM [657ms &amp;amp; 876 ms]/Chorus)]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen. &lt;br /&gt;
Nachtrag zum Konfigurieren des Codecs : Prinzipiell funktioniert es, allerdings ist das mit häßlichen Nebengeräuschen verbunden, da ich bei jeder Änderung der Lautstärke im Codec, diesen auch Resetten muß, da sonst immer beide Codecs beschrieben werden, was unschön ist. Warum dies so ist kann ich leider nicht sagen, da ich keine Möglichkeit habe die SPI-Leitungen mitzusniffen (bräuchte dafür einen kleinen LA, den ich nicht habe). &lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Quellcodes für das EQ-Demo, das Filter-Demo und das Delay-Demo : [[Media:dap_demos_plus_delphi_source.zip]]&lt;br /&gt;
&lt;br /&gt;
Es folgen noch der Quellcode für den Mischer (hab ich gerade nicht zur Hand) und weitere Demos (ein Synthesizer und eine 4x4 Patchbay mit EQ und was mir sonst noch einfällt. Dann natürlich mit Source-Codes).&lt;br /&gt;
Anhand dieser Beispiele wird auch eine grobe Doku erstellt.&lt;br /&gt;
&lt;br /&gt;
== SVN-Repository ==&lt;br /&gt;
&lt;br /&gt;
 svn co svn://mikrocontroller.net/audiodsp&lt;br /&gt;
&lt;br /&gt;
Ein automatisch aktualisiertes Paket mit den Daten aus dem Repository gibt es unter http://www.mikrocontroller.net/download/audiodsp-snapshot.tar.gz.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
- Update 12.07.2007 :&lt;br /&gt;
&lt;br /&gt;
Es wurde ein generisches Speicherinterfaces welches Wartezyklen im DAP erlaubt implementiert. Dadurch kann man auf die jeweilgen Speicher des Boards eingehen. Z.Z. ist nur ein einfaches Speicherinterface für den asynchronen Betrieb des PSDRAM des Nexys Boards implementiert. Das Interface ermögicht es einen RAM Controller anzuschließen welcher z.B. ein quasi-Multiport RAM darstellt.&lt;br /&gt;
Getestet wurde der Stand mit dem Nexys-1000 Board.&lt;br /&gt;
&lt;br /&gt;
==To do ...==&lt;br /&gt;
&lt;br /&gt;
--nähere Zukunft--&lt;br /&gt;
* Einen Konfigurationsdialog in die Demo-Programme einarbeiten mit denen man mit den Codecs etwas spielen kann (Line-In Level, Mikrofon-Level, Bypass, Head-Phone Volume) tlw. erledigt. Funktioniert aber nicht richtig, und daher noch nicht eingebaut. Quellcodes dazu sind vorhanden.&lt;br /&gt;
* Doku anhand der Demo-Programme erstellen&lt;br /&gt;
* C-Code schnipsel erstellen&lt;br /&gt;
&lt;br /&gt;
--fernere Zukunft--&lt;br /&gt;
* Front-End des DAPs machen, mit dem sich DAP-Programme erstellen lassen, der Koeffizienten-, Daten- und Wellenform-Speicher beschrieben und gelesen werden kann, der Mikro-Code editierbar gemacht wird und noch ein paar Sachen mehr machbar sind&lt;br /&gt;
* Synthesizer realisieren (in Verbindung mit uC, MSP430 oder ARM7)&lt;br /&gt;
* weitere Module für den Rahmen (HDD-Core, weitere Routing-Möglichkeiten innerhalb der bisherigen Cores SDSP und Util)&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
* http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]] [[Category:DSP]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=22598</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=22598"/>
		<updated>2007-07-13T00:24:40Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* SVN-Repository */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshaper&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im aktuellen Schaltplan wird auf einen Mikroprozessor verzichtet. Dieser diente im System erstmal nur zu Initialisierung der Codecs. Dieser Vorgang kann nun vom PC aus gesteuert werden, da in der neuen ISE 6.2 Version 4 Leitungen herausgeführtz wurden, welche per RS232 gesetzt und gelöscht werden. &lt;br /&gt;
Wer das System nachbauen möchte kann entweder die TLV320AIC23B Codecs, aber auch beliebige andere Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Die Initialisierung dieser Codecs muß dann aber separat vorgenommen werden (wobei man dann wahrscheinlich nicht um einen uC drum herum kommt). Um das System zu Testen (Programme und Koeffizienten in den DAP einzuspielen) wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Zur Auswahl der verwendeten Schnittstelle (RS232 oder SPI) wird Pin 13 des B1-Connectors benutzt. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]] (noch die alte Version -&amp;gt; Kein Delay, Kein Lesen und vor allem : Kein Initialisieren der Codecs)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In dem unten angegebenen Repository ist eine Version (ohne Speicheranbindung des Util-Cores) die auf dem Nexys Board lauffähig ist. Der verwendete Codec ist wie schon im bisherigen Projekt der TLV320AIC23B. Dieser wird via RS232 (6-pin Port A des Nexys Boards) über die GPO Leitungen (6-pin Port D des Nexys Boards) initialisiert. Die eigentlichen Datenleitungen des Codecs liegen an Port B (BCLK, LRCLK, DIN, DOUT).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nexys Board==&lt;br /&gt;
&lt;br /&gt;
Im SVN Repository (s.u.) gibt es eine Version des DAPs für das Nexys Board.&lt;br /&gt;
Diese ist voll SW-Kompatibel zum alten Spartan 3 Board (allerdings z.Z. nur über RS232 steuerbar). Neu bei der Version ist das das Speicherinterface generisch ausgelegt wurde und ein einfacher SRAM-Controller für das Nexys Board PSDRAM geschrieben wurde. Durch das generische Interface ist es möglich andere Speicherarten anzubinden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Download des DAP als MCS-File für das Nexys-1000 Board : [[Media:Nexys_dap.zip]]&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left|Spartan3 Board und Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left|Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
Der DAP als Synth. Der DAP wird komplett vom PC aus gesteuert (Hüllkurve, Sequencer und Filterberechnung werden im PC gemacht). PC Programm und Source folgen&lt;br /&gt;
&lt;br /&gt;
[[Media:synthdemo1.wav.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MC505 Demos ===&lt;br /&gt;
&lt;br /&gt;
Die folgenden Demos stammen von meiner Roland-MC505 Groovebox. Es wird einfach nur ein Werkspreset abgespielt und durch den DAP gejagt.&lt;br /&gt;
&lt;br /&gt;
* [[Media:mc505-eq-demo.wav.zip|EQ-Demo]]&lt;br /&gt;
* [[Media:mc505-filter-demo.wav.zip|Filter-Demo (Tiefpass/Hochpass/Notch)]]&lt;br /&gt;
* [[Media:mc505-delay-demo.wav.zip|Delay-Demo (137BPM [657ms &amp;amp; 876 ms]/Chorus)]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen. &lt;br /&gt;
Nachtrag zum Konfigurieren des Codecs : Prinzipiell funktioniert es, allerdings ist das mit häßlichen Nebengeräuschen verbunden, da ich bei jeder Änderung der Lautstärke im Codec, diesen auch Resetten muß, da sonst immer beide Codecs beschrieben werden, was unschön ist. Warum dies so ist kann ich leider nicht sagen, da ich keine Möglichkeit habe die SPI-Leitungen mitzusniffen (bräuchte dafür einen kleinen LA, den ich nicht habe). &lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Quellcodes für das EQ-Demo, das Filter-Demo und das Delay-Demo : [[Media:dap_demos_plus_delphi_source.zip]]&lt;br /&gt;
&lt;br /&gt;
Es folgen noch der Quellcode für den Mischer (hab ich gerade nicht zur Hand) und weitere Demos (ein Synthesizer und eine 4x4 Patchbay mit EQ und was mir sonst noch einfällt. Dann natürlich mit Source-Codes).&lt;br /&gt;
Anhand dieser Beispiele wird auch eine grobe Doku erstellt.&lt;br /&gt;
&lt;br /&gt;
== SVN-Repository ==&lt;br /&gt;
&lt;br /&gt;
 svn co svn://mikrocontroller.net/audiodsp&lt;br /&gt;
&lt;br /&gt;
Ein automatisch aktualisiertes Paket mit den Daten aus dem Repository gibt es unter http://www.mikrocontroller.net/download/audiodsp-snapshot.tar.gz.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
- Update 12.07.2007 :&lt;br /&gt;
&lt;br /&gt;
Es wurde ein generisches Speicherinterfaces welches Wartezyklen im DAP erlaubt implementiert. Dadurch kann man auf die jeweilgen Speicher des Boards eingehen. Z.Z. ist nur ein einfaches Speicherinterface für den asynchronen Betrieb des PSDRAM des Nexys Boards implementiert. Das Interface ermögicht es einen RAM Controller anzuschließen welcher z.B. ein quasi-Multiport RAM darstellt.&lt;br /&gt;
Getestet wurde der Stand mit dem Nexys-1000 Board.&lt;br /&gt;
&lt;br /&gt;
==To do ...==&lt;br /&gt;
&lt;br /&gt;
--nähere Zukunft--&lt;br /&gt;
* Eine neue 9.1&#039;er ISE Version uploaden die dann alle fehlenden Features (Delay, Lesen, Codecs initialisieren) gegenüber der 6.2&#039;er ISE Version enthält. (sofern es mit ISE 9.1 machbar bzw. compilierbar ist)&lt;br /&gt;
* Einen Konfigurationsdialog in die Demo-Programme einarbeiten mit denen man mit den Codecs etwas spielen kann (Line-In Level, Mikrofon-Level, Bypass, Head-Phone Volume) tlw. erledigt. Funktioniert aber nicht richtig, und daher noch nicht eingebaut. Quellcodes dazu sind vorhanden.&lt;br /&gt;
* Ein einfaches Synth Demo (Oszillatoren und Filter)&lt;br /&gt;
* Doku anhand der Demo-Programme erstellen&lt;br /&gt;
* C-Code schnipsel erstellen&lt;br /&gt;
&lt;br /&gt;
--fernere Zukunft--&lt;br /&gt;
* Front-End des DAPs machen, mit dem sich DAP-Programme erstellen lassen, der Koeffizienten-, Daten- und Wellenform-Speicher beschrieben und gelesen werden kann, der Mikro-Code editierbar gemacht wird und noch ein paar Sachen mehr machbar sind&lt;br /&gt;
* Synthesizer realisieren (in Verbindung mit uC, MSP430 oder ARM7)&lt;br /&gt;
* weitere Module für den Rahmen (HDD-Core, weitere Routing-Möglichkeiten innerhalb der bisherigen Cores SDSP und Util)&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
* http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]] [[Category:DSP]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=22597</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=22597"/>
		<updated>2007-07-13T00:18:23Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* ISE6.2 vs. ISE9.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshaper&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im aktuellen Schaltplan wird auf einen Mikroprozessor verzichtet. Dieser diente im System erstmal nur zu Initialisierung der Codecs. Dieser Vorgang kann nun vom PC aus gesteuert werden, da in der neuen ISE 6.2 Version 4 Leitungen herausgeführtz wurden, welche per RS232 gesetzt und gelöscht werden. &lt;br /&gt;
Wer das System nachbauen möchte kann entweder die TLV320AIC23B Codecs, aber auch beliebige andere Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Die Initialisierung dieser Codecs muß dann aber separat vorgenommen werden (wobei man dann wahrscheinlich nicht um einen uC drum herum kommt). Um das System zu Testen (Programme und Koeffizienten in den DAP einzuspielen) wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Zur Auswahl der verwendeten Schnittstelle (RS232 oder SPI) wird Pin 13 des B1-Connectors benutzt. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]] (noch die alte Version -&amp;gt; Kein Delay, Kein Lesen und vor allem : Kein Initialisieren der Codecs)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In dem unten angegebenen Repository ist eine Version (ohne Speicheranbindung des Util-Cores) die auf dem Nexys Board lauffähig ist. Der verwendete Codec ist wie schon im bisherigen Projekt der TLV320AIC23B. Dieser wird via RS232 (6-pin Port A des Nexys Boards) über die GPO Leitungen (6-pin Port D des Nexys Boards) initialisiert. Die eigentlichen Datenleitungen des Codecs liegen an Port B (BCLK, LRCLK, DIN, DOUT).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nexys Board==&lt;br /&gt;
&lt;br /&gt;
Im SVN Repository (s.u.) gibt es eine Version des DAPs für das Nexys Board.&lt;br /&gt;
Diese ist voll SW-Kompatibel zum alten Spartan 3 Board (allerdings z.Z. nur über RS232 steuerbar). Neu bei der Version ist das das Speicherinterface generisch ausgelegt wurde und ein einfacher SRAM-Controller für das Nexys Board PSDRAM geschrieben wurde. Durch das generische Interface ist es möglich andere Speicherarten anzubinden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Download des DAP als MCS-File für das Nexys-1000 Board : [[Media:Nexys_dap.zip]]&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left|Spartan3 Board und Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left|Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
Der DAP als Synth. Der DAP wird komplett vom PC aus gesteuert (Hüllkurve, Sequencer und Filterberechnung werden im PC gemacht). PC Programm und Source folgen&lt;br /&gt;
&lt;br /&gt;
[[Media:synthdemo1.wav.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MC505 Demos ===&lt;br /&gt;
&lt;br /&gt;
Die folgenden Demos stammen von meiner Roland-MC505 Groovebox. Es wird einfach nur ein Werkspreset abgespielt und durch den DAP gejagt.&lt;br /&gt;
&lt;br /&gt;
* [[Media:mc505-eq-demo.wav.zip|EQ-Demo]]&lt;br /&gt;
* [[Media:mc505-filter-demo.wav.zip|Filter-Demo (Tiefpass/Hochpass/Notch)]]&lt;br /&gt;
* [[Media:mc505-delay-demo.wav.zip|Delay-Demo (137BPM [657ms &amp;amp; 876 ms]/Chorus)]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen. &lt;br /&gt;
Nachtrag zum Konfigurieren des Codecs : Prinzipiell funktioniert es, allerdings ist das mit häßlichen Nebengeräuschen verbunden, da ich bei jeder Änderung der Lautstärke im Codec, diesen auch Resetten muß, da sonst immer beide Codecs beschrieben werden, was unschön ist. Warum dies so ist kann ich leider nicht sagen, da ich keine Möglichkeit habe die SPI-Leitungen mitzusniffen (bräuchte dafür einen kleinen LA, den ich nicht habe). &lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Quellcodes für das EQ-Demo, das Filter-Demo und das Delay-Demo : [[Media:dap_demos_plus_delphi_source.zip]]&lt;br /&gt;
&lt;br /&gt;
Es folgen noch der Quellcode für den Mischer (hab ich gerade nicht zur Hand) und weitere Demos (ein Synthesizer und eine 4x4 Patchbay mit EQ und was mir sonst noch einfällt. Dann natürlich mit Source-Codes).&lt;br /&gt;
Anhand dieser Beispiele wird auch eine grobe Doku erstellt.&lt;br /&gt;
&lt;br /&gt;
== SVN-Repository ==&lt;br /&gt;
&lt;br /&gt;
 svn co svn://mikrocontroller.net/audiodsp&lt;br /&gt;
&lt;br /&gt;
Ein automatisch aktualisiertes Paket mit den Daten aus dem Repository gibt es unter http://www.mikrocontroller.net/download/audiodsp-snapshot.tar.gz.&lt;br /&gt;
&lt;br /&gt;
==To do ...==&lt;br /&gt;
&lt;br /&gt;
--nähere Zukunft--&lt;br /&gt;
* Eine neue 9.1&#039;er ISE Version uploaden die dann alle fehlenden Features (Delay, Lesen, Codecs initialisieren) gegenüber der 6.2&#039;er ISE Version enthält. (sofern es mit ISE 9.1 machbar bzw. compilierbar ist)&lt;br /&gt;
* Einen Konfigurationsdialog in die Demo-Programme einarbeiten mit denen man mit den Codecs etwas spielen kann (Line-In Level, Mikrofon-Level, Bypass, Head-Phone Volume) tlw. erledigt. Funktioniert aber nicht richtig, und daher noch nicht eingebaut. Quellcodes dazu sind vorhanden.&lt;br /&gt;
* Ein einfaches Synth Demo (Oszillatoren und Filter)&lt;br /&gt;
* Doku anhand der Demo-Programme erstellen&lt;br /&gt;
* C-Code schnipsel erstellen&lt;br /&gt;
&lt;br /&gt;
--fernere Zukunft--&lt;br /&gt;
* Front-End des DAPs machen, mit dem sich DAP-Programme erstellen lassen, der Koeffizienten-, Daten- und Wellenform-Speicher beschrieben und gelesen werden kann, der Mikro-Code editierbar gemacht wird und noch ein paar Sachen mehr machbar sind&lt;br /&gt;
* Synthesizer realisieren (in Verbindung mit uC, MSP430 oder ARM7)&lt;br /&gt;
* weitere Module für den Rahmen (HDD-Core, weitere Routing-Möglichkeiten innerhalb der bisherigen Cores SDSP und Util)&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
* http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]] [[Category:DSP]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Nexys_dap.zip&amp;diff=22596</id>
		<title>Datei:Nexys dap.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Nexys_dap.zip&amp;diff=22596"/>
		<updated>2007-07-13T00:17:51Z</updated>

		<summary type="html">&lt;p&gt;TheMason: ZIP File des MCS-Files für den DAP auf dem Nexys-1000 Board&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ZIP File des MCS-Files für den DAP auf dem Nexys-1000 Board&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=21162</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=21162"/>
		<updated>2007-04-20T20:27:09Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* To do ... */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im aktuellen Schaltplan wird auf einen Mikroprozessor verzichtet. Dieser diente im System erstmal nur zu Initialisierung der Codecs. Dieser Vorgang kann nun vom PC aus gesteuert werden, da in der neuen ISE 6.2 Version 4 Leitungen herausgeführtz wurden, welche per RS232 gesetzt und gelöscht werden. &lt;br /&gt;
Wer das System nachbauen möchte kann entweder die TLV320AIC23B Codecs, aber auch beliebige andere Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Die Initialisierung dieser Codecs muß dann aber separat vorgenommen werden (wobei man dann wahrscheinlich nicht um einen uC drum herum kommt). Um das System zu Testen (Programme und Koeffizienten in den DAP einzuspielen) wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Zur Auswahl der verwendeten Schnittstelle (RS232 oder SPI) wird Pin 13 des B1-Connectors benutzt. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]] (noch die alte Version -&amp;gt; Kein Delay, Kein Lesen und vor allem : Kein Initialisieren der Codecs)&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left|Spartan3 Board und Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left|Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
Der DAP als Synth. Der DAP wird komplett vom PC aus gesteuert (Hüllkurve, Sequencer und Filterberechnung werden im PC gemacht). PC Programm und Source folgen&lt;br /&gt;
&lt;br /&gt;
[[Media:synthdemo1.wav.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MC505 Demos ===&lt;br /&gt;
&lt;br /&gt;
Die folgenden Demos stammen von meiner Roland-MC505 Groovebox. Es wird einfach nur ein Werkspreset abgespielt und durch den DAP gejagt.&lt;br /&gt;
&lt;br /&gt;
* [[Media:mc505-eq-demo.wav.zip|EQ-Demo]]&lt;br /&gt;
* [[Media:mc505-filter-demo.wav.zip|Filter-Demo (Tiefpass/Hochpass/Notch)]]&lt;br /&gt;
* [[Media:mc505-delay-demo.wav.zip|Delay-Demo (137BPM [657ms &amp;amp; 876 ms]/Chorus)]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen. &lt;br /&gt;
Nachtrag zum Konfigurieren des Codecs : Prinzipiell funktioniert es, allerdings ist das mit häßlichen Nebengeräuschen verbunden, da ich bei jeder Änderung der Lautstärke im Codec, diesen auch Resetten muß, da sonst immer beide Codecs beschrieben werden, was unschön ist. Warum dies so ist kann ich leider nicht sagen, da ich keine Möglichkeit habe die SPI-Leitungen mitzusniffen (bräuchte dafür einen kleinen LA, den ich nicht habe). &lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Quellcodes für das EQ-Demo, das Filter-Demo und das Delay-Demo : [[Media:dap_demos_plus_delphi_source.zip]]&lt;br /&gt;
&lt;br /&gt;
Es folgen noch der Quellcode für den Mischer (hab ich gerade nicht zur Hand) und weitere Demos (ein Synthesizer und eine 4x4 Patchbay mit EQ und was mir sonst noch einfällt. Dann natürlich mit Source-Codes).&lt;br /&gt;
Anhand dieser Beispiele wird auch eine grobe Doku erstellt.&lt;br /&gt;
&lt;br /&gt;
==To do ...==&lt;br /&gt;
&lt;br /&gt;
--nähere Zukunft--&lt;br /&gt;
* Eine neue 9.1&#039;er ISE Version uploaden die dann alle fehlenden Features (Delay, Lesen, Codecs initialisieren) gegenüber der 6.2&#039;er ISE Version enthält. (sofern es mit ISE 9.1 machbar bzw. compilierbar ist)&lt;br /&gt;
* Einen Konfigurationsdialog in die Demo-Programme einarbeiten mit denen man mit den Codecs etwas spielen kann (Line-In Level, Mikrofon-Level, Bypass, Head-Phone Volume) tlw. erledigt. Funktioniert aber nicht richtig, und daher noch nicht eingebaut. Quellcodes dazu sind vorhanden.&lt;br /&gt;
* Ein einfaches Synth Demo (Oszillatoren und Filter)&lt;br /&gt;
* Doku anhand der Demo-Programme erstellen&lt;br /&gt;
* C-Code schnipsel erstellen&lt;br /&gt;
&lt;br /&gt;
--fernere Zukunft--&lt;br /&gt;
* Front-End des DAPs machen, mit dem sich DAP-Programme erstellen lassen, der Koeffizienten-, Daten- und Wellenform-Speicher beschrieben und gelesen werden kann, der Mikro-Code editierbar gemacht wird und noch ein paar Sachen mehr machbar sind&lt;br /&gt;
* Synthesizer realisieren (in Verbindung mit uC, MSP430 oder ARM7)&lt;br /&gt;
* weitere Module für den Rahmen (HDD-Core, weitere Routing-Möglichkeiten innerhalb der bisherigen Cores SDSP und Util)&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
* http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=21161</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=21161"/>
		<updated>2007-04-20T20:26:13Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Audio Demos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im aktuellen Schaltplan wird auf einen Mikroprozessor verzichtet. Dieser diente im System erstmal nur zu Initialisierung der Codecs. Dieser Vorgang kann nun vom PC aus gesteuert werden, da in der neuen ISE 6.2 Version 4 Leitungen herausgeführtz wurden, welche per RS232 gesetzt und gelöscht werden. &lt;br /&gt;
Wer das System nachbauen möchte kann entweder die TLV320AIC23B Codecs, aber auch beliebige andere Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Die Initialisierung dieser Codecs muß dann aber separat vorgenommen werden (wobei man dann wahrscheinlich nicht um einen uC drum herum kommt). Um das System zu Testen (Programme und Koeffizienten in den DAP einzuspielen) wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Zur Auswahl der verwendeten Schnittstelle (RS232 oder SPI) wird Pin 13 des B1-Connectors benutzt. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]] (noch die alte Version -&amp;gt; Kein Delay, Kein Lesen und vor allem : Kein Initialisieren der Codecs)&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left|Spartan3 Board und Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left|Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
Der DAP als Synth. Der DAP wird komplett vom PC aus gesteuert (Hüllkurve, Sequencer und Filterberechnung werden im PC gemacht). PC Programm und Source folgen&lt;br /&gt;
&lt;br /&gt;
[[Media:synthdemo1.wav.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MC505 Demos ===&lt;br /&gt;
&lt;br /&gt;
Die folgenden Demos stammen von meiner Roland-MC505 Groovebox. Es wird einfach nur ein Werkspreset abgespielt und durch den DAP gejagt.&lt;br /&gt;
&lt;br /&gt;
* [[Media:mc505-eq-demo.wav.zip|EQ-Demo]]&lt;br /&gt;
* [[Media:mc505-filter-demo.wav.zip|Filter-Demo (Tiefpass/Hochpass/Notch)]]&lt;br /&gt;
* [[Media:mc505-delay-demo.wav.zip|Delay-Demo (137BPM [657ms &amp;amp; 876 ms]/Chorus)]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen. &lt;br /&gt;
Nachtrag zum Konfigurieren des Codecs : Prinzipiell funktioniert es, allerdings ist das mit häßlichen Nebengeräuschen verbunden, da ich bei jeder Änderung der Lautstärke im Codec, diesen auch Resetten muß, da sonst immer beide Codecs beschrieben werden, was unschön ist. Warum dies so ist kann ich leider nicht sagen, da ich keine Möglichkeit habe die SPI-Leitungen mitzusniffen (bräuchte dafür einen kleinen LA, den ich nicht habe). &lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Quellcodes für das EQ-Demo, das Filter-Demo und das Delay-Demo : [[Media:dap_demos_plus_delphi_source.zip]]&lt;br /&gt;
&lt;br /&gt;
Es folgen noch der Quellcode für den Mischer (hab ich gerade nicht zur Hand) und weitere Demos (ein Synthesizer und eine 4x4 Patchbay mit EQ und was mir sonst noch einfällt. Dann natürlich mit Source-Codes).&lt;br /&gt;
Anhand dieser Beispiele wird auch eine grobe Doku erstellt.&lt;br /&gt;
&lt;br /&gt;
==To do ...==&lt;br /&gt;
&lt;br /&gt;
--nähere Zukunft--&lt;br /&gt;
* Eine neue 9.1&#039;er ISE Version uploaden die dann alle fehlenden Features (Delay, Lesen, Codecs initialisieren) gegenüber der 6.2&#039;er ISE Version enthält. (sofern es mit ISE 9.1 machbar bzw. compilierbar ist)&lt;br /&gt;
* Einen Kofigurationsdialog in die Demo-Programme einarbeiten mit denen man mit den Codecs etwas spielen kann (Line-In Level, Mikrofon-Level, Bypass, Head-Phone Volume) tlw. erledigt. Funktioniert aber nicht richtig, und daher noch nicht eingebaut. Quellcodes dazu sind vorhanden.&lt;br /&gt;
* Ein einfaches Synth Demo (Oszillatoren und Filter)&lt;br /&gt;
* Doku anhand der Demo-Programme erstellen&lt;br /&gt;
* C-Code schnipsel erstellen&lt;br /&gt;
&lt;br /&gt;
--fernere Zukunft--&lt;br /&gt;
* Front-End des DAPs machen, mit dem sich DAP-Programme erstellen lassen, der Koeffizienten-, Daten- und Wellenform-Speicher beschrieben und gelesen werden kann, der Mikro-Code editierbar gemacht wird und noch ein paar Sachen mehr machbar sind&lt;br /&gt;
* Synthesizer realisieren (in Verbindung mit uC, MSP430 oder ARM7)&lt;br /&gt;
* weitere Module für den Rahmen (HDD-Core, weitere Routing-Möglichkeiten innerhalb der bisherigen Cores SDSP und Util)&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
* http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Synthdemo1.wav.zip&amp;diff=21160</id>
		<title>Datei:Synthdemo1.wav.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Synthdemo1.wav.zip&amp;diff=21160"/>
		<updated>2007-04-20T20:24:38Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=21091</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=21091"/>
		<updated>2007-04-17T19:52:46Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* To do ... */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im aktuellen Schaltplan wird auf einen Mikroprozessor verzichtet. Dieser diente im System erstmal nur zu Initialisierung der Codecs. Dieser Vorgang kann nun vom PC aus gesteuert werden, da in der neuen ISE 6.2 Version 4 Leitungen herausgeführtz wurden, welche per RS232 gesetzt und gelöscht werden. &lt;br /&gt;
Wer das System nachbauen möchte kann entweder die TLV320AIC23B Codecs, aber auch beliebige andere Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Die Initialisierung dieser Codecs muß dann aber separat vorgenommen werden (wobei man dann wahrscheinlich nicht um einen uC drum herum kommt). Um das System zu Testen (Programme und Koeffizienten in den DAP einzuspielen) wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Zur Auswahl der verwendeten Schnittstelle (RS232 oder SPI) wird Pin 13 des B1-Connectors benutzt. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]] (noch die alte Version -&amp;gt; Kein Delay, Kein Lesen und vor allem : Kein Initialisieren der Codecs)&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left|Spartan3 Board und Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left|Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MC505 Demos ===&lt;br /&gt;
&lt;br /&gt;
Die folgenden Demos stammen von meiner Roland-MC505 Groovebox. Es wird einfach nur ein Werkspreset abgespielt und durch den DAP gejagt.&lt;br /&gt;
&lt;br /&gt;
* [[Media:mc505-eq-demo.wav.zip|EQ-Demo]]&lt;br /&gt;
* [[Media:mc505-filter-demo.wav.zip|Filter-Demo (Tiefpass/Hochpass/Notch)]]&lt;br /&gt;
* [[Media:mc505-delay-demo.wav.zip|Delay-Demo (137BPM [657ms &amp;amp; 876 ms]/Chorus)]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen. &lt;br /&gt;
Nachtrag zum Konfigurieren des Codecs : Prinzipiell funktioniert es, allerdings ist das mit häßlichen Nebengeräuschen verbunden, da ich bei jeder Änderung der Lautstärke im Codec, diesen auch Resetten muß, da sonst immer beide Codecs beschrieben werden, was unschön ist. Warum dies so ist kann ich leider nicht sagen, da ich keine Möglichkeit habe die SPI-Leitungen mitzusniffen (bräuchte dafür einen kleinen LA, den ich nicht habe). &lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Quellcodes für das EQ-Demo, das Filter-Demo und das Delay-Demo : [[Media:dap_demos_plus_delphi_source.zip]]&lt;br /&gt;
&lt;br /&gt;
Es folgen noch der Quellcode für den Mischer (hab ich gerade nicht zur Hand) und weitere Demos (ein Synthesizer und eine 4x4 Patchbay mit EQ und was mir sonst noch einfällt. Dann natürlich mit Source-Codes).&lt;br /&gt;
Anhand dieser Beispiele wird auch eine grobe Doku erstellt.&lt;br /&gt;
&lt;br /&gt;
==To do ...==&lt;br /&gt;
&lt;br /&gt;
--nähere Zukunft--&lt;br /&gt;
* Eine neue 9.1&#039;er ISE Version uploaden die dann alle fehlenden Features (Delay, Lesen, Codecs initialisieren) gegenüber der 6.2&#039;er ISE Version enthält. (sofern es mit ISE 9.1 machbar bzw. compilierbar ist)&lt;br /&gt;
* Einen Kofigurationsdialog in die Demo-Programme einarbeiten mit denen man mit den Codecs etwas spielen kann (Line-In Level, Mikrofon-Level, Bypass, Head-Phone Volume) tlw. erledigt. Funktioniert aber nicht richtig, und daher noch nicht eingebaut. Quellcodes dazu sind vorhanden.&lt;br /&gt;
* Ein einfaches Synth Demo (Oszillatoren und Filter)&lt;br /&gt;
* Doku anhand der Demo-Programme erstellen&lt;br /&gt;
* C-Code schnipsel erstellen&lt;br /&gt;
&lt;br /&gt;
--fernere Zukunft--&lt;br /&gt;
* Front-End des DAPs machen, mit dem sich DAP-Programme erstellen lassen, der Koeffizienten-, Daten- und Wellenform-Speicher beschrieben und gelesen werden kann, der Mikro-Code editierbar gemacht wird und noch ein paar Sachen mehr machbar sind&lt;br /&gt;
* Synthesizer realisieren (in Verbindung mit uC, MSP430 oder ARM7)&lt;br /&gt;
* weitere Module für den Rahmen (HDD-Core, weitere Routing-Möglichkeiten innerhalb der bisherigen Cores SDSP und Util)&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
* http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=21090</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=21090"/>
		<updated>2007-04-17T19:51:53Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Delphi Tools */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im aktuellen Schaltplan wird auf einen Mikroprozessor verzichtet. Dieser diente im System erstmal nur zu Initialisierung der Codecs. Dieser Vorgang kann nun vom PC aus gesteuert werden, da in der neuen ISE 6.2 Version 4 Leitungen herausgeführtz wurden, welche per RS232 gesetzt und gelöscht werden. &lt;br /&gt;
Wer das System nachbauen möchte kann entweder die TLV320AIC23B Codecs, aber auch beliebige andere Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Die Initialisierung dieser Codecs muß dann aber separat vorgenommen werden (wobei man dann wahrscheinlich nicht um einen uC drum herum kommt). Um das System zu Testen (Programme und Koeffizienten in den DAP einzuspielen) wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Zur Auswahl der verwendeten Schnittstelle (RS232 oder SPI) wird Pin 13 des B1-Connectors benutzt. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]] (noch die alte Version -&amp;gt; Kein Delay, Kein Lesen und vor allem : Kein Initialisieren der Codecs)&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left|Spartan3 Board und Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left|Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MC505 Demos ===&lt;br /&gt;
&lt;br /&gt;
Die folgenden Demos stammen von meiner Roland-MC505 Groovebox. Es wird einfach nur ein Werkspreset abgespielt und durch den DAP gejagt.&lt;br /&gt;
&lt;br /&gt;
* [[Media:mc505-eq-demo.wav.zip|EQ-Demo]]&lt;br /&gt;
* [[Media:mc505-filter-demo.wav.zip|Filter-Demo (Tiefpass/Hochpass/Notch)]]&lt;br /&gt;
* [[Media:mc505-delay-demo.wav.zip|Delay-Demo (137BPM [657ms &amp;amp; 876 ms]/Chorus)]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen. &lt;br /&gt;
Nachtrag zum Konfigurieren des Codecs : Prinzipiell funktioniert es, allerdings ist das mit häßlichen Nebengeräuschen verbunden, da ich bei jeder Änderung der Lautstärke im Codec, diesen auch Resetten muß, da sonst immer beide Codecs beschrieben werden, was unschön ist. Warum dies so ist kann ich leider nicht sagen, da ich keine Möglichkeit habe die SPI-Leitungen mitzusniffen (bräuchte dafür einen kleinen LA, den ich nicht habe). &lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Quellcodes für das EQ-Demo, das Filter-Demo und das Delay-Demo : [[Media:dap_demos_plus_delphi_source.zip]]&lt;br /&gt;
&lt;br /&gt;
Es folgen noch der Quellcode für den Mischer (hab ich gerade nicht zur Hand) und weitere Demos (ein Synthesizer und eine 4x4 Patchbay mit EQ und was mir sonst noch einfällt. Dann natürlich mit Source-Codes).&lt;br /&gt;
Anhand dieser Beispiele wird auch eine grobe Doku erstellt.&lt;br /&gt;
&lt;br /&gt;
==To do ...==&lt;br /&gt;
&lt;br /&gt;
--nähere Zukunft--&lt;br /&gt;
* Eine neue 9.1&#039;er ISE Version uploaden die dann alle fehlenden Features (Delay, Lesen, Codecs initialisieren) gegenüber der 6.2&#039;er ISE Version enthält. (sofern es mit ISE 9.1 machbar bzw. compilierbar ist)&lt;br /&gt;
* Einen Kofigurationsdialog in die Demo-Programme einarbeiten mit denen man mit den Codecs etwas spielen kann (Line-In Level, Mikrofon-Level, Bypass, Head-Phone Volume)&lt;br /&gt;
* Ein einfaches Synth Demo (Oszillatoren und Filter)&lt;br /&gt;
* Sources der Demo-Programme uploaden&lt;br /&gt;
* Doku anhand der Demo-Programme erstellen&lt;br /&gt;
* C-Code schnipsel erstellen&lt;br /&gt;
&lt;br /&gt;
--fernere Zukunft--&lt;br /&gt;
* Front-End des DAPs machen, mit dem sich DAP-Programme erstellen lassen, der Koeffizienten-, Daten- und Wellenform-Speicher beschrieben und gelesen werden kann, der Mikro-Code editierbar gemacht wird und noch ein paar Sachen mehr machbar sind&lt;br /&gt;
* Synthesizer realisieren (in Verbindung mit uC, MSP430 oder ARM7)&lt;br /&gt;
* weitere Module für den Rahmen (HDD-Core, weitere Routing-Möglichkeiten innerhalb der bisherigen Cores SDSP und Util)&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
* http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Dap_demos_plus_delphi_source.zip&amp;diff=21089</id>
		<title>Datei:Dap demos plus delphi source.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Dap_demos_plus_delphi_source.zip&amp;diff=21089"/>
		<updated>2007-04-17T19:46:01Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20770</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20770"/>
		<updated>2007-04-04T17:47:22Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Audio Demos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im aktuellen Schaltplan wird auf einen Mikroprozessor verzichtet. Dieser diente im System erstmal nur zu Initialisierung der Codecs. Dieser Vorgang kann nun vom PC aus gesteuert werden, da in der neuen ISE 6.2 Version 4 Leitungen herausgeführtz wurden, welche per RS232 gesetzt und gelöscht werden. &lt;br /&gt;
Wer das System nachbauen möchte kann entweder die TLV320AIC23B Codecs, aber auch beliebige andere Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Die Initialisierung dieser Codecs muß dann aber separat vorgenommen werden (wobei man dann wahrscheinlich nicht um einen uC drum herum kommt). Um das System zu Testen (Programme und Koeffizienten in den DAP einzuspielen) wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Zur Auswahl der verwendeten Schnittstelle (RS232 oder SPI) wird Pin 13 des B1-Connectors benutzt. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]] (noch die alte Version -&amp;gt; Kein Delay, Kein Lesen und vor allem : Kein Initialisieren der Codecs)&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left|Spartan3 Board und Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left|Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
MC505 Demos.&lt;br /&gt;
&lt;br /&gt;
Die folgenden Demos stammen von meiner Roland-MC505 Groovebox. Es wird einfach nur ein Werkspreset abgespielt und durch den DAP gejagt.&lt;br /&gt;
&lt;br /&gt;
[[Media:mc505-eq-demo.wav.zip|EQ-Demo]]&lt;br /&gt;
&lt;br /&gt;
[[Media:mc505-filter-demo.wav.zip|Filter-Demo (Tiefpass/Hochpass/Notch)]]&lt;br /&gt;
&lt;br /&gt;
[[Media:mc505-eq-demo.wav.zip|Delay-Demo (137BPM [657ms &amp;amp; 876 ms]/Chorus)]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen.&lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
==To do ...==&lt;br /&gt;
&lt;br /&gt;
--nähere Zukunft--&lt;br /&gt;
* Eine neue 9.1&#039;er ISE Version uploaden die dann alle fehlenden Features (Delay, Lesen, Codecs initialisieren) gegenüber der 6.2&#039;er ISE Version enthält. (sofern es mit ISE 9.1 machbar bzw. compilierbar ist)&lt;br /&gt;
* Einen Kofigurationsdialog in die Demo-Programme einarbeiten mit denen man mit den Codecs etwas spielen kann (Line-In Level, Mikrofon-Level, Bypass, Head-Phone Volume)&lt;br /&gt;
* Ein einfaches Synth Demo (Oszillatoren und Filter)&lt;br /&gt;
* Sources der Demo-Programme uploaden&lt;br /&gt;
* Doku anhand der Demo-Programme erstellen&lt;br /&gt;
* C-Code schnipsel erstellen&lt;br /&gt;
&lt;br /&gt;
--fernere Zukunft--&lt;br /&gt;
* Front-End des DAPs machen, mit dem sich DAP-Programme erstellen lassen, der Koeffizienten-, Daten- und Wellenform-Speicher beschrieben und gelesen werden kann, der Mikro-Code editierbar gemacht wird und noch ein paar Sachen mehr machbar sind&lt;br /&gt;
* Synthesizer realisieren (in Verbindung mit uC, MSP430 oder ARM7)&lt;br /&gt;
* weitere Module für den Rahmen (HDD-Core, weitere Routing-Möglichkeiten innerhalb der bisherigen Cores SDSP und Util)&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
* http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Mc505-filter-demo.wav.zip&amp;diff=20769</id>
		<title>Datei:Mc505-filter-demo.wav.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Mc505-filter-demo.wav.zip&amp;diff=20769"/>
		<updated>2007-04-04T17:45:22Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Mc505-delay-demo.wav.zip&amp;diff=20768</id>
		<title>Datei:Mc505-delay-demo.wav.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Mc505-delay-demo.wav.zip&amp;diff=20768"/>
		<updated>2007-04-04T17:43:53Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Mc505-eq-demo.wav.zip&amp;diff=20767</id>
		<title>Datei:Mc505-eq-demo.wav.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Mc505-eq-demo.wav.zip&amp;diff=20767"/>
		<updated>2007-04-04T17:43:12Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20633</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20633"/>
		<updated>2007-04-01T19:52:16Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* In Kürze ... */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im aktuellen Schaltplan wird auf einen Mikroprozessor verzichtet. Dieser diente im System erstmal nur zu Initialisierung der Codecs. Dieser Vorgang kann nun vom PC aus gesteuert werden, da in der neuen ISE 6.2 Version 4 Leitungen herausgeführtz wurden, welche per RS232 gesetzt und gelöscht werden. &lt;br /&gt;
Wer das System nachbauen möchte kann entweder die TLV320AIC23B Codecs, aber auch beliebige andere Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Die Initialisierung dieser Codecs muß dann aber separat vorgenommen werden (wobei man dann wahrscheinlich nicht um einen uC drum herum kommt). Um das System zu Testen (Programme und Koeffizienten in den DAP einzuspielen) wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Zur Auswahl der verwendeten Schnittstelle (RS232 oder SPI) wird Pin 13 des B1-Connectors benutzt. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]] (noch die alte Version -&amp;gt; Kein Delay, Kein Lesen und vor allem : Kein Initialisieren der Codecs)&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left|Spartan3 Board und Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left|Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
Es wurde nur ein Rosa Rauschen auf den Eingang gegeben und das EQ-Demo gestartet. Dann auf &amp;quot;MoveIt!&amp;quot; klicken und é voilá ...&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen.&lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
==To do ...==&lt;br /&gt;
&lt;br /&gt;
--nähere Zukunft--&lt;br /&gt;
* Eine neue 9.1&#039;er ISE Version uploaden die dann alle fehlenden Features (Delay, Lesen, Codecs initialisieren) gegenüber der 6.2&#039;er ISE Version enthält. (sofern es mit ISE 9.1 machbar bzw. compilierbar ist)&lt;br /&gt;
* Einen Kofigurationsdialog in die Demo-Programme einarbeiten mit denen man mit den Codecs etwas spielen kann (Line-In Level, Mikrofon-Level, Bypass, Head-Phone Volume)&lt;br /&gt;
* Ein einfaches Synth Demo (Oszillatoren und Filter)&lt;br /&gt;
* Sources der Demo-Programme uploaden&lt;br /&gt;
* Doku anhand der Demo-Programme erstellen&lt;br /&gt;
* C-Code schnipsel erstellen&lt;br /&gt;
&lt;br /&gt;
--fernere Zukunft--&lt;br /&gt;
* Front-End des DAPs machen, mit dem sich DAP-Programme erstellen lassen, der Koeffizienten-, Daten- und Wellenform-Speicher beschrieben und gelesen werden kann, der Mikro-Code editierbar gemacht wird und noch ein paar Sachen mehr machbar sind&lt;br /&gt;
* Synthesizer realisieren (in Verbindung mit uC, MSP430 oder ARM7)&lt;br /&gt;
* weitere Module für den Rahmen (HDD-Core, weitere Routing-Möglichkeiten innerhalb der bisherigen Cores SDSP und Util)&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
* http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20628</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20628"/>
		<updated>2007-04-01T19:28:39Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* ISE6.2 vs. ISE9.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im aktuellen Schaltplan wird auf einen Mikroprozessor verzichtet. Dieser diente im System erstmal nur zu Initialisierung der Codecs. Dieser Vorgang kann nun vom PC aus gesteuert werden, da in der neuen ISE 6.2 Version 4 Leitungen herausgeführtz wurden, welche per RS232 gesetzt und gelöscht werden. &lt;br /&gt;
Wer das System nachbauen möchte kann entweder die TLV320AIC23B Codecs, aber auch beliebige andere Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Die Initialisierung dieser Codecs muß dann aber separat vorgenommen werden (wobei man dann wahrscheinlich nicht um einen uC drum herum kommt). Um das System zu Testen (Programme und Koeffizienten in den DAP einzuspielen) wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Zur Auswahl der verwendeten Schnittstelle (RS232 oder SPI) wird Pin 13 des B1-Connectors benutzt. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]] (noch die alte Version -&amp;gt; Kein Delay, Kein Lesen und vor allem : Kein Initialisieren der Codecs)&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left|Spartan3 Board und Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left|Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
Es wurde nur ein Rosa Rauschen auf den Eingang gegeben und das EQ-Demo gestartet. Dann auf &amp;quot;MoveIt!&amp;quot; klicken und é voilá ...&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen.&lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
==In Kürze ...==&lt;br /&gt;
&lt;br /&gt;
... werde ich noch die geänderten PC-Demos hochladen, damit man alles vom PC aus machen kann. Die neue ISE 6.2&#039;er Version unterstützt das Ansteuern der Codecs.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
... werde ich eine neue 9.1&#039;er ISE Version uploaden die dann alle Features der 6.2&#039;er ISE Version enthält. (sofern es mit ISE 9.1 machbar bzw. compilierbar ist)&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
* http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20627</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20627"/>
		<updated>2007-04-01T19:27:43Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Hardware */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im aktuellen Schaltplan wird auf einen Mikroprozessor verzichtet. Dieser diente im System erstmal nur zu Initialisierung der Codecs. Dieser Vorgang kann nun vom PC aus gesteuert werden, da in der neuen ISE 6.2 Version 4 Leitungen herausgeführtz wurden, welche per RS232 gesetzt und gelöscht werden. &lt;br /&gt;
Wer das System nachbauen möchte kann entweder die TLV320AIC23B Codecs, aber auch beliebige andere Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Die Initialisierung dieser Codecs muß dann aber separat vorgenommen werden (wobei man dann wahrscheinlich nicht um einen uC drum herum kommt). Um das System zu Testen (Programme und Koeffizienten in den DAP einzuspielen) wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Zur Auswahl der verwendeten Schnittstelle (RS232 oder SPI) wird Pin 13 des B1-Connectors benutzt. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left|Spartan3 Board und Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left|Expansion Board]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
Es wurde nur ein Rosa Rauschen auf den Eingang gegeben und das EQ-Demo gestartet. Dann auf &amp;quot;MoveIt!&amp;quot; klicken und é voilá ...&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen.&lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
==In Kürze ...==&lt;br /&gt;
&lt;br /&gt;
... werde ich noch die geänderten PC-Demos hochladen, damit man alles vom PC aus machen kann. Die neue ISE 6.2&#039;er Version unterstützt das Ansteuern der Codecs.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
... werde ich eine neue 9.1&#039;er ISE Version uploaden die dann alle Features der 6.2&#039;er ISE Version enthält. (sofern es mit ISE 9.1 machbar bzw. compilierbar ist)&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
* http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20575</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20575"/>
		<updated>2007-04-01T10:49:47Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* In Kürze ... */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im hier vorgestellten Schaltplan ist ein MSP430 enthalten der allerdings nur die Initialisierung und Konfiguration der Codecs übernimmt. Wer das System nachbauen möchte kann beliebige Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Um das System zu Testen wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Ansonsten benötigt das System nur den Pin 13 des B1-Connectors. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Spartan3 Board und Expansion Board&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
Expansion Board&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
Es wurde nur ein Rosa Rauschen auf den Eingang gegeben und das EQ-Demo gestartet. Dann auf &amp;quot;MoveIt!&amp;quot; klicken und é voilá ...&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen.&lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
==In Kürze ...==&lt;br /&gt;
&lt;br /&gt;
... werde ich noch die geänderten PC-Demos hochladen, damit man alles vom PC aus machen kann. Die neue ISE 6.2&#039;er Version unterstützt das Ansteuern der Codecs.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
... werde ich eine neue 9.1&#039;er ISE Version uploaden die dann alle Features der 6.2&#039;er ISE Version enthält. (sofern es mit ISE 9.1 machbar bzw. compilierbar ist)&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20573</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20573"/>
		<updated>2007-04-01T10:48:31Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* ISE6.2 vs. ISE9.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im hier vorgestellten Schaltplan ist ein MSP430 enthalten der allerdings nur die Initialisierung und Konfiguration der Codecs übernimmt. Wer das System nachbauen möchte kann beliebige Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Um das System zu Testen wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Ansonsten benötigt das System nur den Pin 13 des B1-Connectors. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Ise6.2_gpo.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Spartan3 Board und Expansion Board&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
Expansion Board&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
Es wurde nur ein Rosa Rauschen auf den Eingang gegeben und das EQ-Demo gestartet. Dann auf &amp;quot;MoveIt!&amp;quot; klicken und é voilá ...&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen.&lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
==In Kürze ...==&lt;br /&gt;
&lt;br /&gt;
... werde ich noch eine kleine Erweiterung des DAP einbauen, die es erlaubt die Codecs vom PC aus zu konfigurieren. Dadurch entfällt der uC, und ich hoffe dadurch mehr Leute zum ausprobieren dieses Projekts zu bringen.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
... werde ich eine neue 9.1&#039;er ISE Version uploaden die dann alle Features der 6.2&#039;er ISE Version enthält.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Ise6.2_gpo.zip&amp;diff=20572</id>
		<title>Datei:Ise6.2 gpo.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Ise6.2_gpo.zip&amp;diff=20572"/>
		<updated>2007-04-01T10:47:57Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20571</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20571"/>
		<updated>2007-04-01T10:47:08Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Fotos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im hier vorgestellten Schaltplan ist ein MSP430 enthalten der allerdings nur die Initialisierung und Konfiguration der Codecs übernimmt. Wer das System nachbauen möchte kann beliebige Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Um das System zu Testen wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Ansonsten benötigt das System nur den Pin 13 des B1-Connectors. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Dap Ise6.2.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Spartan3 Board und Expansion Board&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt_wo_uc.jpg|thumb|300px|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
Expansion Board&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Codecs.jpg|thumb|300px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
Es wurde nur ein Rosa Rauschen auf den Eingang gegeben und das EQ-Demo gestartet. Dann auf &amp;quot;MoveIt!&amp;quot; klicken und é voilá ...&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen.&lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
==In Kürze ...==&lt;br /&gt;
&lt;br /&gt;
... werde ich noch eine kleine Erweiterung des DAP einbauen, die es erlaubt die Codecs vom PC aus zu konfigurieren. Dadurch entfällt der uC, und ich hoffe dadurch mehr Leute zum ausprobieren dieses Projekts zu bringen.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
... werde ich eine neue 9.1&#039;er ISE Version uploaden die dann alle Features der 6.2&#039;er ISE Version enthält.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20570</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20570"/>
		<updated>2007-04-01T10:46:32Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Hardware */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Fpga_ext_board_schematic_no_uc.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im hier vorgestellten Schaltplan ist ein MSP430 enthalten der allerdings nur die Initialisierung und Konfiguration der Codecs übernimmt. Wer das System nachbauen möchte kann beliebige Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Um das System zu Testen wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Ansonsten benötigt das System nur den Pin 13 des B1-Connectors. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
*19 GPO 3 - Chip-Select Codec 2&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 2 - Chip-Select Codec 1&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 1 - SPI-Data out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
*19 GPO 0 - SPI-Clock Out&lt;br /&gt;
*20 N.C.&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Dap Ise6.2.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Spartan3 Board und Expansion Board&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt.jpg|thumb|300px|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
Expansion Board&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:exp-board1.jpg|thumb|300px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
Es wurde nur ein Rosa Rauschen auf den Eingang gegeben und das EQ-Demo gestartet. Dann auf &amp;quot;MoveIt!&amp;quot; klicken und é voilá ...&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen.&lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
==In Kürze ...==&lt;br /&gt;
&lt;br /&gt;
... werde ich noch eine kleine Erweiterung des DAP einbauen, die es erlaubt die Codecs vom PC aus zu konfigurieren. Dadurch entfällt der uC, und ich hoffe dadurch mehr Leute zum ausprobieren dieses Projekts zu bringen.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
... werde ich eine neue 9.1&#039;er ISE Version uploaden die dann alle Features der 6.2&#039;er ISE Version enthält.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Fpga_ext_board_schematic_no_uc.JPG&amp;diff=20569</id>
		<title>Datei:Fpga ext board schematic no uc.JPG</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Fpga_ext_board_schematic_no_uc.JPG&amp;diff=20569"/>
		<updated>2007-04-01T10:44:25Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Codecs.jpg&amp;diff=20568</id>
		<title>Datei:Codecs.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Codecs.jpg&amp;diff=20568"/>
		<updated>2007-04-01T10:44:00Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Gesamt_wo_uc.jpg&amp;diff=20567</id>
		<title>Datei:Gesamt wo uc.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Gesamt_wo_uc.jpg&amp;diff=20567"/>
		<updated>2007-04-01T10:43:46Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20566</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20566"/>
		<updated>2007-04-01T10:42:55Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Übersicht */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
* GPO (General Purpose Outputs) zur Konfiguration der Codecs&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview_wo_uc.jpg|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen, sonst hat das System keine Audio-Clocks, da diese nicht vom FPGA generiert werden)&lt;br /&gt;
Die Initialisierung des Codecs wird vom PC aus gemacht. Dazu dienen die 4 GPO Leitungen auf dem B1- Connector. Da der Codec nur &amp;quot;halbes&amp;quot; SPI unterstüzt (man kann nur schreiben, nicht lesen) gestaltet sich die Initialisierung recht einfach.&lt;br /&gt;
Die 4 GPO-Leitungen teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* Chip-Select Codec 2&lt;br /&gt;
* Chip-Select Codec 1&lt;br /&gt;
* SPI Data Out&lt;br /&gt;
* SPI Clock&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Schematic.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im hier vorgestellten Schaltplan ist ein MSP430 enthalten der allerdings nur die Initialisierung und Konfiguration der Codecs übernimmt. Wer das System nachbauen möchte kann beliebige Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Um das System zu Testen wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Ansonsten benötigt das System nur den Pin 13 des B1-Connectors. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Dap Ise6.2.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Spartan3 Board und Expansion Board&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt.jpg|thumb|300px|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
Expansion Board&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:exp-board1.jpg|thumb|300px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
Es wurde nur ein Rosa Rauschen auf den Eingang gegeben und das EQ-Demo gestartet. Dann auf &amp;quot;MoveIt!&amp;quot; klicken und é voilá ...&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen.&lt;br /&gt;
&lt;br /&gt;
* Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo): [[Media:dap_eq_demo.zip]]&lt;br /&gt;
* Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang: [[Media:dap_mix_demo.zip]]&lt;br /&gt;
* Demo eines Synthesizer-Filters: [[Media:dap_filter_demo.zip]]&lt;br /&gt;
* Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-))): [[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
==In Kürze ...==&lt;br /&gt;
&lt;br /&gt;
... werde ich noch eine kleine Erweiterung des DAP einbauen, die es erlaubt die Codecs vom PC aus zu konfigurieren. Dadurch entfällt der uC, und ich hoffe dadurch mehr Leute zum ausprobieren dieses Projekts zu bringen.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
... werde ich eine neue 9.1&#039;er ISE Version uploaden die dann alle Features der 6.2&#039;er ISE Version enthält.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Overview_wo_uc.jpg&amp;diff=20565</id>
		<title>Datei:Overview wo uc.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Overview_wo_uc.jpg&amp;diff=20565"/>
		<updated>2007-04-01T10:42:07Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20531</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20531"/>
		<updated>2007-03-29T19:09:31Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Übersicht */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features der Audio-Hardware:&lt;br /&gt;
&lt;br /&gt;
* 2 Stereo-Codecs (also 4 Mono Audio-Ein- und Ausgänge)&lt;br /&gt;
* Mikrocontroller (MSP430)&lt;br /&gt;
* MIDI-Interface (noch nicht implementiert)&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview.JPG|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nachbau==&lt;br /&gt;
&lt;br /&gt;
Derjenige der sich dieses System nachbauen möchte benötigt erstmal ein FPGA-Board. Mit dem Spartan 3 Board von Digilent gestaltet sich der Nachbau dadurch einfach, als das die Programmier-Dateien für den FPGA direkt für dieses Board verwendet werden können. Nutzer anderer Boards (Xlinx) müssten zuerst die UCF-Datei für die Pins ihres jeweiligen Boards anpassen, und dieses Projekt neu synthetisieren (compilieren). Nutzer von Altera-Boards hingegen müssen die BlockRAM Instanzen auf die Altera-Architektur anpassen (den Inhalt der RAMs dabei nicht vergessen :-). Vielleicht findet sich ja der eine oder andere der den VHDL Code für Altera-FPGAs portiert.&lt;br /&gt;
Der eigentliche wichtige Teil eines Nachbaus ist der Codec-Teil. Dieses System verwendet zwar zwei Codecs, aber es kann auch mit einem gearbeitet werden. Als Codec kommt der TLV320AIC23B von Texas Instruments zum einsatz. Diesen kann man als kostenloses Sample bei TI direkt bekommen. &lt;br /&gt;
Des weiteren benötigt man noch eine handvoll (oder bei SMD Fingernagelbreite :-) Bauteile wie Kondensatoren, Widerstände und einen Quarz. (Ein Codec MUß als Master laufen)&lt;br /&gt;
Die Initialisierung des Codecs wird momentan zwar noch von einem uC übernommen, aber in Kürze wird eine geänderte Version hochgeladen, mit der der Codec vom PC aus Initialisiert wird, wodurch der Mikroprozessor entfallen kann und den Nachbau deutlich vereinfacht.&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Schematic.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im hier vorgestellten Schaltplan ist ein MSP430 enthalten der allerdings nur die Initialisierung und Konfiguration der Codecs übernimmt. Wer das System nachbauen möchte kann beliebige Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Um das System zu Testen wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Ansonsten benötigt das System nur den Pin 13 des B1-Connectors. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Dap Ise6.2.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Spartan3 Board und Expansion Board&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt.jpg|thumb|300px|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
Expansion Board&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:exp-board1.jpg|thumb|300px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
Es wurde nur ein Rosa Rauschen auf den Eingang gegeben und das EQ-Demo gestartet. Dann auf &amp;quot;MoveIt!&amp;quot; klicken und é voilá ...&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen.&lt;br /&gt;
&lt;br /&gt;
Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo)&lt;br /&gt;
&lt;br /&gt;
[[Media:dap_eq_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang&lt;br /&gt;
&lt;br /&gt;
[[Media:dap_mix_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
Demo eines Synthesizer-Filters&lt;br /&gt;
&lt;br /&gt;
[[Media:dap_filter_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-)))&lt;br /&gt;
&lt;br /&gt;
[[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
==In Kürze ...==&lt;br /&gt;
&lt;br /&gt;
... werde ich noch eine kleine Erweiterung des DAP einbauen, die es erlaubt die Codecs vom PC aus zu konfigurieren. Dadurch entfällt der uC, und ich hoffe dadurch mehr Leute zum ausprobieren dieses Projekts zu bringen.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
... werde ich eine neue 9.1&#039;er ISE Version uploaden die dann alle Features der 6.2&#039;er ISE Version enthält.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20530</id>
		<title>Audio-DSP mit Spartan 3-FPGA</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Audio-DSP_mit_Spartan_3-FPGA&amp;diff=20530"/>
		<updated>2007-03-29T18:50:07Z</updated>

		<summary type="html">&lt;p&gt;TheMason: /* Delphi Tools */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von [[Benutzer:TheMason]]&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projekts ist es, eine FPGA-basierte Plattform aufzubauen mit der es möglich ist Synthesizer, Effektgeräte, Mischpulte  oder gar ein Harddiskrecording-System zu realisieren.&lt;br /&gt;
&lt;br /&gt;
==Update==&lt;br /&gt;
&lt;br /&gt;
Da ich seit geraumer Zeit an diesem Projekt alleine arbeite, ist recht viel Arbeit angefallen und ich versuche diese nun Vorzustellen und zu Gliedern.&lt;br /&gt;
&lt;br /&gt;
==Feature-Liste==&lt;br /&gt;
&lt;br /&gt;
Features der Audio-Hardware:&lt;br /&gt;
&lt;br /&gt;
* 2 Stereo-Codecs (also 4 Mono Audio-Ein- und Ausgänge)&lt;br /&gt;
* Mikrocontroller (MSP430)&lt;br /&gt;
* MIDI-Interface (noch nicht implementiert)&lt;br /&gt;
&lt;br /&gt;
Features des Audio-Prozessors: &lt;br /&gt;
&lt;br /&gt;
* Oszillatoren&lt;br /&gt;
* Biquads (Filter)&lt;br /&gt;
* Addierer, Schalter, Verstärker (Multiplizierer)&lt;br /&gt;
* Delays&lt;br /&gt;
* Steuerung des Audio-Prozessors via SPI oder RS232&lt;br /&gt;
* 4 Mono Ein- und Ausgänge&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
[[Bild:Overview.JPG|thumb|500px]]&lt;br /&gt;
Basis des Audio-Systems ist das Xilinx Spartan 3-Development Board. An diesem Board werden 2 Audio-Codecs angschlossen von denen einer als Master und der andere als Slave agiert. Optional kann noch ein Mikrocontroller angeschlossen werden welcher den FPGA per SPI steuert. Da dieses Projekt mittlerweile recht umfangreich geworden ist, kann ich hier nur einen kurzen Umriss des Systems geben. Dabei beschränke ich mich auf die grobe Funktionsweise des Audio-Prozessors, erläutere das Interface (welches ich als Basis für weitere Projekte bereits nutze) und gebe einen kleinen Überblick über die Hardware.&lt;br /&gt;
&lt;br /&gt;
Das System kann (sofern man 2 Audio-Codecs, von denen einer als Master, der andere als Slave arbeitet, angeschlossen und konfiguriert hat) direkt genutzt werden, da der DAP per RS232 gesteuert werden kann. Der Audio-Prozessor startet mit einem Stereo-Tiefpass-Filter der sich auf den ersten Codec bezieht,&lt;br /&gt;
sodass man ein erstes Demo hat (selbst wenn es etwas unspektakulär ist)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio-Prozessor (DAP)==&lt;br /&gt;
&lt;br /&gt;
[[bild:Overview dap core.JPG|thumb|500px|right]]&lt;br /&gt;
&lt;br /&gt;
Der FPGA beinhaltet in dem gesamten System einen Quasi-DSP. Quasi-DSP deshalb, da die Struktur im Gegensatz zu einem DSP bzw. Mikrocontroller keine Verzweigungen, Interrupts oder ähnliches zulässt. Der Audio-Prozessor besteht im wesentlichen aus 3 Teilen : Einem Rahmen, einem SDSP (Small DSP)-Kern &lt;br /&gt;
sowie einem Utility-Kern. Beide Kerne können theoretisch parallel arbeiten, da jeder Kern eine eigene Statemachine und einen eigenen Mikro-Code Speicher besitzen. Dieses Feature ist allerdings noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Der SDSP-Kern besteht im wesentlichen aus einer MAC-Einheit, einem Speicher für Audio-Daten, einem Koeffizienten-Speicher, einem Adress-Generator und mehreren Muxern, sowie der schon angesprochenen Statemachine und dem Microcode. Weiterhin ist ein Hidden-Write- (bzw. Shadow Register) Mechanismus integriert,&lt;br /&gt;
welcher ein &amp;quot;knackser-freies&amp;quot; Updaten von Koeffizienten ermöglicht. Alle diese Komponenten werden vom MicroCode aus gesteuert (genau wie bei einem Mikrocontroller). Mit diesem Kern ist es möglich, Audio-Signale zu bearbeiten. Zu Den Bearbeitungsmöglichkeiten zählen in erster Linie das Verändern der Lautstärke, Mischen, Filtern (Biquad) sowie Laden und Speichern von &lt;br /&gt;
Audio-Werten.&lt;br /&gt;
&lt;br /&gt;
Der Utility Kern besteht aus einem Akkumulator (für DDS), einem Shaper, einem Adress-Generator, einem Wavetable-Speicher, einem Random-Number Generator, einigen Muxern, (einem Adress-Generator für SRAM, einem SRAM-Controller; diese sind allerdings nur nutzbar wenn man das ganze mit dem ISE 6.2 synthetisiert) &lt;br /&gt;
und der schon angesprochenen Statemachine und dem MicroCode. Der MicroCode steuert (genau wie beim SDSP-Kern) dabei die einzelnen Komponenten des Utility Kerns. Dieser kern ist für das Erzeugen von Audio-Signalen zuständig, und erlaubt ein Audio-Signal zu verzögern, sofern man die ISE-Version 6.2 Verwendet (später dazu mehr). Als Wellenformen stehen Sägezahn, Rechteck (mit veränderbarem Puls/Pausen-Verhältnis), Rauschen sowie benutzderdefinierbare Wellenformen (Wavetable) zur verfügung.&lt;br /&gt;
&lt;br /&gt;
Der Rahmen besteht aus einer Statemachine, einem Programm-Speicher, einigen Muxern, sowie einem doppelten I2S Sender-Empfänger (für 2 Stereo Ein- und Ausgänge). In dem Rahmen werden die beiden Kerne &amp;quot;eingehängt&amp;quot;. Die Kerne werden vom Programmspeicher aus mit Daten versorgt, und von der Statemachine angetriggert. Der Programmspeicher (PMEM) ist als 512x32 Bit organisiert. Das heißt das ein Befehl im Programmspeicher 32 Bit Informationen enthält und der &lt;br /&gt;
Audio-Prozessor max. 512 Befehle umfassen kann.&lt;br /&gt;
&lt;br /&gt;
==Opcodes des DAP==&lt;br /&gt;
&lt;br /&gt;
Diese 32 Bit eines Befehls teilen sich folgendermaßen auf :&lt;br /&gt;
&lt;br /&gt;
* 4 Bit = Opcode (für SDSP und Utility Kern gleich)&lt;br /&gt;
* 2 Bit = noch leer&lt;br /&gt;
* 1 Bit = Core Select (SDSP oder Utility)&lt;br /&gt;
* 1 Bit = Ende des Programms&lt;br /&gt;
* 4 Bit = Eingangs-Routing (Kanal 1 - 4, Ergebnis SDSP Core, Ergebnis Utility Core)&lt;br /&gt;
* 4 Bit = Ausgangs-Routing (SDSP-Ausgang auf Kanal 1-4, Utility Ausgang auf Kanal 1-4)&lt;br /&gt;
* 8 Bit = Adresse 1 (bei SDSP für Audio-Memory, bei Utility Kern für Data Memory)&lt;br /&gt;
* 8 Bit = Adresse 2 (bei SDSP für Koeffizienten-Memory, bei Utility Kern unbenutzt)&lt;br /&gt;
&lt;br /&gt;
Das Eingangsrouting bestimmt mit welchem Signal der gewählte Kern arbeiten soll. Dies können die Eingänge 1-4 sein, aber auch ein vorher berechnetes Ergebnis des SDSP- bzw. Utility-Kerns sein. Das Ausgangsrouting bestimmt von welchem Kern das Signal auf welchen Ausgang geroutet wird.&lt;br /&gt;
&lt;br /&gt;
Die Opcodes des DAPs sind:&lt;br /&gt;
&lt;br /&gt;
SDSP-Kern:&lt;br /&gt;
* Biquad rechnen&lt;br /&gt;
* Audio Wert speichern&lt;br /&gt;
* Audio Wert laden&lt;br /&gt;
* Move eines Wertes im Audio-Speicher&lt;br /&gt;
* Summe resetten&lt;br /&gt;
* Eingang zu Summe addieren&lt;br /&gt;
* Wert aus dem Audio-Speicher zu Summe addieren&lt;br /&gt;
* Eingang zu summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* wert aus dem Audio-Speicher zu Summe mischen (mit Lautstärke Koeffizient)&lt;br /&gt;
* Lautstärke &lt;br /&gt;
&lt;br /&gt;
Utility-Kern:&lt;br /&gt;
* Oszillator (DDS-Teil)&lt;br /&gt;
* Waveshapter&lt;br /&gt;
* Delay&lt;br /&gt;
&lt;br /&gt;
Der Ablauf eines Audio-Programms ist folgender:&lt;br /&gt;
&lt;br /&gt;
Sobald ein neues Sample anliegt, wird die Abarbeitung des Programms von Adresse 0x0000 an im PMEM angestossen. Es wird dabei jeweils ein Befehl geladen und Daten wie Opcode und Adressen liegen dabei an beide Kernen gleichermaßen an. Ist das Programm-Ende Bit nicht gesetzt so wird der jeweilige Kern (mit dem im Opcode angegeben Routing) angetriggert. Legt der betreffende Kern sein Ready Signal auf 1, so wird der nächste Befehl abgearbeitet. Dieses Verhalten (Laden und Verteilen von Opcode-Daten, sowie die Ablaufsteuerung; also das Antriggern des Programms, Antriggern der einzelnen Kerne, warten auf dessen Abarbeitung und das Programm-Ende) wird vom Rahmen übernommen.&lt;br /&gt;
&lt;br /&gt;
==Speicherorganisation==&lt;br /&gt;
&lt;br /&gt;
Alle Speicher die vom DAP angesprochen werden haben eine Wort-Breite von 32 Bit, der Zugriff erfolgt aber ausschließlich über 8 Bit Breite (Interface).&lt;br /&gt;
&lt;br /&gt;
DAP&lt;br /&gt;
* Programmspeicher 	(PMEM)   0x0000 - 0x07ff&lt;br /&gt;
&lt;br /&gt;
SDSP&lt;br /&gt;
* Audio-Speicher   	(AMEM)   von außen nicht zugänglich&lt;br /&gt;
* Koeffizienten-Speciher 	(CMEM)   0x2000 - 0x2023  (man &amp;quot;sieht&amp;quot; nur den Hidden Write -&amp;gt; später mehr dazu)&lt;br /&gt;
* Microcode-Speicher      (MMEM)   0x4000 - 0x47ff&lt;br /&gt;
&lt;br /&gt;
Utility-Core&lt;br /&gt;
* Daten-Speicher          (DMEM)   0x6000 - 0x67ff&lt;br /&gt;
* Wavetable Speicher      (WMEM)   0x8000 - 0x87ff&lt;br /&gt;
* MicroCode-Speicher      (UMEM)   0xa000 - 0xa7ff&lt;br /&gt;
&lt;br /&gt;
==Hidden-Write==&lt;br /&gt;
Um bei Änderung der Koeffizienten &amp;quot;Knackser&amp;quot; zu vermeiden (die dadurch entstehen das der Koeffizient nur teilweise [durch 8 Bit Zugriffe] geändert wird, währenddessen aber Audio trotzdem noch &amp;quot;weiterläuft&amp;quot;, und mit &amp;quot;falschen&amp;quot; Zwischenwerte gerechnet wird) ist ein Mechanismus implementiert der die zu ändernden Koeffizienten im Hintergund in den Speicher schreibt. Um diesen Mechanismus zu nutzen müssen zuerst die Koeffizienten in interne Register&lt;br /&gt;
geschrieben werden. Die Register (es sind 8 32 Bit Register) liegen im Speicherbereich 0x2000 bis 0x201f. Die Speicherstelle 0x2020 gibt die Start-Adresse innerhalb des Koeffizienten Speichers an. Diese Adresse ist nur 8 Bit breit. Die Speicherstelle 0x2021 gibt an wieviele der 8 Register übertragen werden sollen. Die Speicherstelle 0x2022 triggert den Kopier-Vorgang an. Hier reicht es ein Dummy byte zu schreiben. Um den Kopiervorgang zu beenden (MUß GEMACHT WERDEN!!, sonst können keine weiteren Koeffizienten Updates gemacht werden) schreibt man an Speicherstelle 0x2023 ebenfalls ein Dummy Byte.&lt;br /&gt;
&lt;br /&gt;
==I/O Register==&lt;br /&gt;
&lt;br /&gt;
Es gibt noch einen 8-Bit breiten Adress-Bereich innerhalb des DAPs mit dem der I2S-Teil gemutet werden kann. Weiterhin hat man die Möglichkeit die Anzahl der System-Takte pro Sample und die Anzahl der aktiven System-Takte (also die Zeit die der Audio-Prozessor beschäftigt ist) zu ermitteln. Dadurch lässt sich eine Auslastungsanzeige des DAPs realisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Interface==&lt;br /&gt;
&lt;br /&gt;
Um von außen nun ein Programm (bzw. Koeffizienten und Daten) zu laden ist ein Interface implementiert, welches einfach zu handhaben ist und einfach erweitert werden kann. Das Interface kann per RS232 (fest eingestellt auf 115,2kBaud) oder per SPI (wird Hardware-Mässig eingestellt) angesteuert werden. Das Interface in seiner Gesamtheit ist schichtweise aufgebaut und beginnt mit einem Data-Dispatcher. Dieser Data-Dispatcher entscheidet (nach dem dieser selektiert wurde) mit dem ersten Byte, an welches angeschlossene Gerät der weitere Datenstrom geleitet wird.&lt;br /&gt;
&lt;br /&gt;
Als angeschlossene Geräte sind im aktuellen Design ein Gerät namens &amp;quot;StdIO&amp;quot; und der Audio-Prozessor angeschlossen.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;StdIO&amp;quot; Gerät steuert die 7Segment-Anzeige (16-Bit Hexadezimal Anzeige oder 32-Bit Einzelsegment Anzeige), die 8 Leuchtdioden, und erlaubt es die 3 Drucktaster sowie die 8 Schiebeschalter auszulesen.&lt;br /&gt;
&lt;br /&gt;
Der Audio-Prozessor besteht (Interface-seitig gesehen) nur aus einem Speicher-Zugriffs-Interface. Dieses Speicher-Interface entscheidet mit dem ersten Byte (sobald es selektiert wurde) ob in den Speicher geschrieben, von diesem gelesen, ein I/O Schreib oder Lese Zugriff erfolgen soll.&lt;br /&gt;
Die Folgenden 2 Bytes (im Falle eines I/O Zugriffs nur 1 Byte) bestimmen die Adresse und damit den Speicher-Bereich des Audio-Prozessors auf den Zugegriffen werden soll. Das Speicherinterface besitzt einen Autoincrement,&lt;br /&gt;
mit dem fortalufende Bytes einfach hintereinander weggeschrieben werden können, ohne das jedesmal wieder der FPGA, das Gerät und die neue Adresse neu geschrieben werden müssen, was den Zugriff erheblich beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich basierte das System auf einem SPI-Interface. Dabei wurde die Chip-Select Leitung als &amp;quot;globaler&amp;quot; Interface Reset betrachtet, d.h. war die Leitung auf High, war der FPGA Deselektiert und und alle Interface-Statemachines wurden im Reset gehalten. Erst mit dem Setzen dieser Leitung wurde der FPGA angesprochen. (erstes Byte -&amp;gt; Daten-Dispatcher, folgende Bytes gehen an das Gerät, wenn eines ausgewählt wurde). Weiterhin hat SPI die Eigenschaft das mit jedem gesendeten Byte auch eines Emfpangen wurde. Der Umstand das RS232 weder eine Chip-Select Leitung benötigt, noch eine synchrone Übertragung erzwingt führt zu dem Umstand das man bei Nutzung von RS232 einige Befehle zusätzlich benötigt. Diese Befehle werden durch das Zeichen 0x1b (ESC) eingeleitet. Soll statt der &amp;quot;Spezial-Funktion&amp;quot; das Byte 0x1b übertragen werden, so wird dieses einfach erneut gesendet. Soll die Chip-Select leitung gesetzt bzw. gelöscht werden so wird die Sequenz 0x1b 0x00 (Selektieren) bzw.&lt;br /&gt;
0x1b 0x01 (Deselektieren) gesendet. Soll ein zuvor im Ausgangsregister gesetztes Byte gesendet werden so muß die Sequenz 0x1b 0x02 gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
&lt;br /&gt;
0x121b auf dem 7 Segment Display per RS232 Anzeigen:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x00      (Hi Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x12      (Wert 12)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x01      (Lo Byte der 7 Segment Hex Anzeige wählen)&lt;br /&gt;
*- 0x1b 0x1b (Wert 1b -&amp;gt; zu beachten: wenn der Wert 0x1b übertragen werden muß, muß dieser doppelt gesendet werden !!)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Beispiel um in den Programmspeicher des Audio-Prozessors an Adresse 0x0010 das Langwort 0x12233445 zu schreiben:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf1      (DAP Selektieren)&lt;br /&gt;
*- 0x00      (Speicher Schreiben)&lt;br /&gt;
*- 0x00      &lt;br /&gt;
*- 0x10      (Adresse 0x0010 -&amp;gt; PMEM Adresse 0x010)&lt;br /&gt;
*- 0x12	    (Adresse 0x0010 -&amp;gt; 0x12)	&lt;br /&gt;
*- 0x23	    (Adresse 0x0011 -&amp;gt; 0x23, autoincrement)&lt;br /&gt;
*- 0x34      (Adresse 0x0012 -&amp;gt; 0x34, autoincrement)&lt;br /&gt;
*- 0x45      (Adresse 0x0013 -&amp;gt; 0x45, autoincrement)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Auslesen der 8 Schalter:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xf0      (StdIO Selektieren)&lt;br /&gt;
*- 0x04      (Schalter auslesen)&lt;br /&gt;
*- 0x00	    (dummy byte -&amp;gt; überträgt Schalter-Stellung in Ausgabe-Register)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man die 8 Schalterstellungen binär-codiert)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
Der Datendispatcher (welcher mit dem ersten Byte nach dem Selektieren des FPGAs [0x1b 0x00] angesprochen wird) hat weiterhin einige nützliche Funktionen die in Ihrer Gesamtheit allerdings noch nicht ausführlich getestet wurden. Darunter sind Funktionen mit denen Inrformationen über die an den Ports des Daten-Dispatchers angeschlossenen Geräte zu ermitteln. Dieses Feature kann dazu genutuzt werden um zu ermitten welche Geräte im FPGA implementiert sind und an welchen Ports welche Geräte angeschlossen sind.&lt;br /&gt;
&lt;br /&gt;
Anzahl der Ports des Daten Dispatchers liefern:&lt;br /&gt;
&lt;br /&gt;
*- ESC 0x00  (FPGA Selektieren)&lt;br /&gt;
*- 0xed      (Anzahl Ports lesen)&lt;br /&gt;
*- 0x00      (dummy byte -&amp;gt; überträgt Inhalt des Ausgabe-Registers)&lt;br /&gt;
*- ESC 0x02  (Ausgabe Register übertragen, danach empfängt man 0x22)&lt;br /&gt;
*- ESC 0x01  (FPGA Deselektieren)&lt;br /&gt;
&lt;br /&gt;
==DAP-Modul-Schnipsel==&lt;br /&gt;
&lt;br /&gt;
Um mal &amp;quot;eben&amp;quot; mit dem DAP zu spielen, ein paar Schnipsel die sich recht leicht zu kompletten Funktionsblöcken zusammenschließen lassen.&lt;br /&gt;
Es werden hier nur die RS232 Sequenzen mit einer kurzen Erklärung aufgelistet.&lt;br /&gt;
&lt;br /&gt;
*Dual Mono Biquad&lt;br /&gt;
&lt;br /&gt;
*ESC 0x00 - FPGA Selektieren&lt;br /&gt;
*0xF1     - DAP Auswählen&lt;br /&gt;
*0x00 0x00 0x00 - Memory Write (Adresse 0x0000 -&amp;gt; Program Memory)&lt;br /&gt;
*0x10 0x00 0x00 0x08 - Biquad mit Kanal 1 (0) rechnen (AMEM = 0x00;CMEM = 0x08) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x10 0xf0 0x08 0x10 - Biquad mit vorherigem Ergebnis (0xf) rechnen (AMEM = 0x08; CMEM = 0x10) und auf Kanal 1 (0) ausgeben&lt;br /&gt;
*0x01 0x00 0x00 0x00 - Audio Programm Ende (wichtig !!!)&lt;br /&gt;
*ESC 0x01 - DAP &amp;amp; FPGA deselektieren&lt;br /&gt;
&lt;br /&gt;
Erklärung :&lt;br /&gt;
&lt;br /&gt;
Der Aufbau des Opcodes 0x100008 deutet an, das ein Biquad durchgerechnet werden soll. Das Eingangsregister 0 bedeutet das Kanal 1 des 1. Codecs verwendet wird. Das Ausgangsregister welches nach Fertigstellung des Ergebnisses benutzt werden&lt;br /&gt;
ist 0 (-&amp;gt; Kanal 1 des 1. Codecs). Der Teil 0x00 0x08 bedeutet hierbei, das die Biquad-Koeffizienten im CMEM ab Adresse 0x08 stehen. Die Audio-Zwischenwerte werden im Audio-Speicher AMEM ab Adresse 0x00 gelegt.&lt;br /&gt;
Der zweite Opcode (0x10f00810) rechnet ebenfalls ein Biquad durch. Nur das hier statt Kanal 1 des Codecs das voher vom SDSP berechnete Ergebnis verwendet werden soll (Kanal 0xf, wenn man so will). Ausgangsregister ist auch hier wieder Kanal 1. Da dieser Biquad unabhängig vom ersten (d.h. mit anderen Parametern) gerechnet werden soll, sind hier logischerweise auch andere Adressen für AMEM (0x08) und CMEM (0x10) angegeben. Die CMEM-Adresse ist dabei etwas unkritischer, da es ja durchaus sein kann das ein Audio-Signal zweimal mit den selben Biquad-Werten gerechnet werden soll, bzw. unterschiedliche Kanäle mit den selben Biquad-Werten, z.b. bei einem Stereo-Equalizer. Kritischer ist allerdings die Verwendung der AMEM-Adresse. Diese sollte für jede Operation (sofern AMEM denn verwendet wird) unterschiedlich sein, vor allem bei der Berechnung von Biquads. Dies hat den Grund das bei Operationen, die dieselben AMEM Adressen haben die vorher berechneten Werte überschrieben werden. Dies ist bei Biquads gaanz böse (kann u.u. SEHR laut werden), und vom Ergebnis her nicht vorhersagbar.&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
[[bild:Schematic.JPG|thumb|500px]]&lt;br /&gt;
&lt;br /&gt;
Wie Eingangs erwähnt benötigt das System eine (bzw. zwei) Audio-Codecs. Im hier vorgestellten Schaltplan ist ein MSP430 enthalten der allerdings nur die Initialisierung und Konfiguration der Codecs übernimmt. Wer das System nachbauen möchte kann beliebige Codecs verwenden, solange einer als Master und der andere als Slave arbeitet und beide auf den I2S Modus mit 64FS und 20 Bit Wortlänge eingestellt sind. Um das System zu Testen wird lediglich eine serielle Schnittstelle verwendet. Wer will kann aber genausogut den SPI-Modus verwenden und den DAP direkt von einem Mikrocontroller aus steuern. Ansonsten benötigt das System nur den Pin 13 des B1-Connectors. Liegt dieser Pin auf GND so wird der FPGA per RS232 gesteuert. Liegt dieser Pin auf 3.3V so wird der FPGA per SPI gesteuert.&lt;br /&gt;
&lt;br /&gt;
Hier der Schaltplan meines verwendeten Audio-Boards.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch die Pin-Belegung des B1-Expansion Connectors:&lt;br /&gt;
&lt;br /&gt;
Pin&lt;br /&gt;
&lt;br /&gt;
*01 GND&lt;br /&gt;
*02 VCC 5V&lt;br /&gt;
*03 VCC 3.3V&lt;br /&gt;
*04 N.C.&lt;br /&gt;
*05 SPI_CS - Chip Select (von uC nach FPGA)&lt;br /&gt;
*06 N.C.&lt;br /&gt;
*07 SPI_DI - SPI Data In (von uC nach FPGA)&lt;br /&gt;
*08 BCLK - Bit Clock (von Master Codec)&lt;br /&gt;
*09 SPI_CLK - SPI Clock (von uC nach FPGA)&lt;br /&gt;
*10 LRCLK - LR-Clock (von Master Codec)&lt;br /&gt;
*11 SPI_DO - SPI Data Out (von FPGA nach uC)&lt;br /&gt;
*12 SDOUT1 - zum D/A Wandler (Codec) 1&lt;br /&gt;
*13 IF_SEL - Interface Select (GND = RS232; VCC3.3 = SPI)&lt;br /&gt;
*14 SDIN1 - vom A/D Wandler (Codec) 1&lt;br /&gt;
*15 RXD_OUT - RS232 Signal vom MAX232 zum uC&lt;br /&gt;
*16 SDIN2 - vom A/D Wandler (Codec) 2&lt;br /&gt;
*17 TXD_IN - RS232 Signal vom uC zum MAX232&lt;br /&gt;
*18 SDOUT2 - zum D/A Wandler (Codec) 2&lt;br /&gt;
&lt;br /&gt;
==ISE6.2 vs. ISE9.1==&lt;br /&gt;
&lt;br /&gt;
Das Design wurde mit der ISE6.2 Version synthetisiert. Da ich auf eine neuere version umsteigen wollte, ergab sich das Problem das sich das Design nicht vollständig Routen lässt. Erst wenn bestimmte Teile des 6.2&#039;er Designs rausgenommen werden (dazu zählen die Lese-Funktionen des Speichers, des Usage Registers, und die SRAM-Ansteuerung im Utility Kern) damit es sich auf der 9.1&#039;er routen lässt. Nimmt man aber einen Größeren FPGA (XC3S400) so lassen sich auch diese Funktionen implementieren (was allerdings mangels passendem FPGA Board nicht getestet werden konnte).&lt;br /&gt;
&lt;br /&gt;
* Download des DAP für ISE 6.2: [[Media:Dap Ise6.2.zip]]&lt;br /&gt;
* Download des DAP für ISE 9.1: [[Media:Dap Ise9.1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Anmerkung==&lt;br /&gt;
&lt;br /&gt;
Da wie schon gesagt das Projekt komplett auf meinem &amp;quot;Mist&amp;quot; gewachsen ist wird es wohl noch eine Weile dauern bis alles was den DAP betrifft hier in diesem Artikel (und auch in einem Dokumentations-PDF) eingearbeitet ist. Ich werde (sofern ich Zeit dazu habe) noch ein Delphi Programm mit Source-Code einstellen, welche den DAP richtig nutzbar macht und man dann direkt damit &amp;quot;spielen&amp;quot; kann. Eine umfangreiche und vollständige Dokumentation würde momentan einfach zu viel Zeit in Anspruch nehmen und ich möchte langsam das Projekt Vorstellen um Anregung, Kritik und Verbesserungsvorschläge ernten zu können. Ich hoffe noch Leute zu finden um diesem Projekt noch mehr Leben und Möglichkeiten einhauchen zu können.&lt;br /&gt;
&lt;br /&gt;
==Fotos==&lt;br /&gt;
&lt;br /&gt;
Hier mal in paar Fotos (Gemacht mit meiner unscharfen Handy-Kamera :-x) der Hardware.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Spartan3 Board und Expansion Board&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gesamt.jpg|thumb|300px|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
Expansion Board&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:exp-board1.jpg|thumb|300px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Audio Demos==&lt;br /&gt;
&lt;br /&gt;
Ein EQ-Demo mit Rosa Rauschen. Klingt wie eine Meeresbrandung.&lt;br /&gt;
Es wurde nur ein Rosa Rauschen auf den Eingang gegeben und das EQ-Demo gestartet. Dann auf &amp;quot;MoveIt!&amp;quot; klicken und é voilá ...&lt;br /&gt;
&lt;br /&gt;
[[Media:eq_demo1.zip]]&lt;br /&gt;
&lt;br /&gt;
==Delphi Tools==&lt;br /&gt;
&lt;br /&gt;
Um den DAP nutzbar zu machen benötigt man entweder ein uC Programm oder ein PC Programm. Da das verwenden von PC-Programmen einfacher fürs Spielen und Experimentieren ist, werde ich hier im Laufe der Zeit kleine Demo-Programme aber auch komplette Front-Ends für den DAP reinstellen. Die Delphi-Programme sind allesamt in Turbo-Delphi geschrieben und die dazugehörigen Quellcodes werden ebenfalls im Laufe der Zeit geuploaded. Ich werde allerdings zuerst noch das Feature des Konfigurierens der Codecs vom PC aus einbauen.&lt;br /&gt;
&lt;br /&gt;
Demo eines 3 Band Stereo Equalizers. (Der Knopf &amp;quot;MoveIt!&amp;quot; bringt Leben ins Demo)&lt;br /&gt;
&lt;br /&gt;
[[Media:dap_eq_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
Demo eines 4 Kanal Mono Mixers mit Monitor (Vorhör)-Ausgang&lt;br /&gt;
&lt;br /&gt;
[[Media:dap_mix_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
Demo eines Synthesizer-Filters&lt;br /&gt;
&lt;br /&gt;
[[Media:dap_filter_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
Demo eines 2 Kanal Delays (Der Button &amp;quot;MoveIt!&amp;quot; macht daraus einen Chorus :-)))&lt;br /&gt;
&lt;br /&gt;
[[Media:dap_delay_demo.zip]]&lt;br /&gt;
&lt;br /&gt;
==In Kürze ...==&lt;br /&gt;
&lt;br /&gt;
... werde ich noch eine kleine Erweiterung des DAP einbauen, die es erlaubt die Codecs vom PC aus zu konfigurieren. Dadurch entfällt der uC, und ich hoffe dadurch mehr Leute zum ausprobieren dieses Projekts zu bringen.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
... werde ich eine neue 9.1&#039;er ISE Version uploaden die dann alle Features der 6.2&#039;er ISE Version enthält.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Diskussion==&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/65205&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/forum/read-9-238211.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Projekte]] [[Kategorie:Audio]] [[Category:FPGA und Co]]&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Dap_delay_demo.zip&amp;diff=20529</id>
		<title>Datei:Dap delay demo.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Dap_delay_demo.zip&amp;diff=20529"/>
		<updated>2007-03-29T18:49:56Z</updated>

		<summary type="html">&lt;p&gt;TheMason: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>TheMason</name></author>
	</entry>
</feed>