Hallo,
ich experimentiere zur Zeit mit dem AC97-Standard. Hierfür verwende ich
das Digilent-Genesys-Virtex5-Evalboard (mit dem LM4550).
Als erstes wollte ich mir ein Testsignal an der Lautsprecherbuchse
(genauer gesagt: Headphone) ausgeben lassen. Hierfür setze ich in jedem
Frame das Master + Headphone Volume auf einen (über Schiebeschalter)
einstellbaren Wert (dies sind auch die einzigen Einstellungen, welche
ich in den Registern für den AC97Codec vornehme). Das Testsignal
schreibe ich dann in Slot3&4 (PCM-Data), sodass an meiner Buchse am Ende
ein Monosignal entstehen sollte.
Wenn ich nun Kopfhörer an die HP OUT Buchse anschließe, höre ich zwar
prinzipiell einen Ton (welcher von der Frequenz mit meinem Testsignal
übereinstimmt und sich auch variieren lässt), dessen Lautstärke sich
auch dämpfen lässt, jedoch ist dieser sehr sehr leise.
Ich kann aus den oben geschilderten Beobachtungen schließen, dass ich
mit den Timings richtig liegen sollte (ansonsten käme weder ein Ton noch
würde ich die Lautstärke regeln können).
Muss ich noch zusätzliche Einstellungen als die oben genannten Treffen
oder hat jemand eine Idee, was das Verhalten erklären könnte?
Im Anhang habe ich mal noch den VHDL-Code, falls das jemandem
weiterhilft (bitte nicht wundern falls es an der ein oder anderen Stelle
etwas unübersichtlich ist, ich experimentiere jetzt schon eine Weile
damit rum ; da dies meine erstes größeres Projekt in VHDL ist bin ich
über Hinweise bzgl. des "Programmierstils" auch sehr dankbar)
Vielen Dank schonmal im Voraus.
Gruß Benny
Jup, bin mir sicher....
Auch die Kopfhörer habe ich als Fehlerquelle ausschließen können, wenn
ich hochohmig mit dem Oszilloskop messe kann ich kein Signal - mal
abgesehn vom Rauschen - erkennen (interessant dass ich überhaupt etwas
höre ;) )
Gruß Benny
Oh, mein letzter Beitrag klingt ein wenig wirr, wollte schreiben dass
ich die Kopfhörer als Fehlerquelle ausschließen kann und dass es mich
wundert, dass ich mit dem Oszilloskop kein Signal messen kann ;)
Hallo Stefan,
deine Antwort klang so vielversprechend, jedoch bekommme ich mit
"00000000000000000000" und "00000000000000000100" immer noch keinen
lauteren Ton heraus...
Werden die PCM-Daten eigentlich als Signed oder Unsigned interpretiert?
Habe dazu bisher auch noch keine fundierte Aussage gefunden...(ich habe
es auch schon mit den Werten "00000000000000000100" und
"10000000000000000100" versucht, jedoch auch ohne Erfolg...)
Interessant ist auch, dass in der Codec-Beschreibung kein Wort vom
Zweierkomplement gemacht wird und ich erst nach deinem Hinweis erste
Suchergebnisse gefunden habe, wo dies erwähnt wird....
Was fehlt da wohl alles in der Sensitivliste?
Benjamin K. schrieb:> deine Antwort klang so vielversprechend, jedoch bekommme ich mit> "00000000000000000000" und "00000000000000000100" immer noch keinen> lauteren Ton heraus...
Funktioniert die Kommunikastion grundsätzlich?
Was sagt denn deine Simulation?
BTW:
Auch wenn dieses Design mal läuft, wirst du immer wieder mal Prbleme
bekommen, weil da munter Signale über Taktdomänengrenzen hin+her
verdrahtet sind...
Woher kommen diese Takte?
Und schon der asynchrone Reset kann dazu führen, dass das Design nach
dem Start mal läuft und mal nicht...
Dies liegt daran dass ich mit 2 verschiedenen Clocks arbeiten muss.
Während eines Resets bzw. nach dem Einschalten des Boards muss der
AC97Codec erst einmal "gebootet" werden, weshalb ich hier über den
FPGA-Clk arbeite.
Danach stellt der Codec einen eigenen Bitclk zur Verfügung, mit welchem
ich dann arbeite, um die Frames zu übertragen...
Du hast natürlich recht dass meine Sensivity-Liste unvollständig ist,
ich habe viel herumexperimentiert weshalb noch das ein oder andere
Artefakt im Code vorhanden ist...
Muss aber zu meiner Verteidigung sagen dass sich bisher keine
Auffälligkeiten nach einem manuellen Reset gezeigt haben....
Gruß Benny
> jedoch bekommme ich mit "00000000000000000000" und "00000000000000000100"> immer noch keinen lauteren Ton heraus...
kein Wunder, liegt ja auch nicht besonders weit auseinander - Versuch
mal 000000000000 und 011111111111111...
Benjamin K. schrieb:> Dies liegt daran dass ich mit 2 verschiedenen Clocks arbeiten muss.
Wenn du das WEISST, dann kannst du ja was gegen potentielle Fehler tun
und solche Taktdomänenübergänge per Synchronisation entschärfen.
> Muss aber zu meiner Verteidigung sagen dass sich bisher keine> Auffälligkeiten nach einem manuellen Reset gezeigt haben....
Ja, irgendwann ist immer das erste Mal... ;-)
Ich kenne deinen Baustein nicht, und weiß daher auch nicht, was
tatsächlich klemmt, aber weil du gefragt hast:
Benjamin K. schrieb:> bin ich über Hinweise bzgl. des "Programmierstils" auch sehr dankbar)
In diesem letzten Prozess sind die Zähler in den if-Abfragen ungünstig
aufgehoben. Denn wenn du in 4 Wochen noch ein if dazuhängst, aber
vergisst, den Zähler mit reinzubauen, dann belibt der stehen. Besser
wäre es, den Zähler auf jeden Fall hochzuzählen, und bei Bedarf
zurückzusetzen:
1
process(ac97_bitclk)is
2
begin
3
ifac97_bitclk'eventandac97_bitclk='1'then
4
sin_cnt<=sin_cnt+1;-- auf jeden Fall beim Takt hochzählen
ergher schrieb:>> jedoch bekommme ich mit "00000000000000000000" und "00000000000000000100">> immer noch keinen lauteren Ton heraus...>> kein Wunder, liegt ja auch nicht besonders weit auseinander - Versuch> mal 000000000000 und 011111111111111...
Wenn der Codec es als Zweierkomplement interpretiert, habe ich einmal
"0..0" und einmal "11111111111111111011" + 1 = "1111111111111111100"
(also wenn ich es als VZ-lose Zahl interpretiere)
So nah beieinander liegen die Werte doch gar nicht....
@Lothar:
thx für die Tips, werde sie im Hinterkopf behalten ;)
Gruß Benny
So,
ich habe inzwischen einen Fehler entdecken können:
Bei den Adressregistern (Slot1) habe ich mich - was meinen bitcnt angeht
- um 1 Bit vertan (siehe unten). Wenn ich diesen Fehler jedoch
korrigiere, höre ich überhaupt nichts mehr.
Kann mir jemand mal die Bereiche des bitcnt mit den jeweiligen Zuständen
bestätigen (also slot0 geht von 0..15, slot1 von 16..35 usw) bzw.
widerlegen?
Gruß Benny
Anhang (zu den Adress-Reg's):
Das Master Vol. Register hat die Adresse 02h = "00000010", das Headphone
Vol. Reg die Adresse 04h = "00000100". Das erste Bit in Slot1 gibt an,
ob gelesen (=1) oder geschrieben(=0) wird.
Will man also ins Master-Vol-Reg schreiben, sieht slot1 folgendermaßen
aus:
"00000001000000000000" (bitcnt = 23)
Für das HP-Vol-Reg ergibt sich "00000010000000000000" (bitcnt = 22)
So, neues Statusupdate, habe den Fehler nun endgültig gefunden:
Es gibt noch ein PCM Out Volume Register, welches mir bisher nicht
aufgefallen ist, da es in der Register Map unter "Input Volume"
beschrieben wird. Dieses ist defaultmäßig auf Mute, weshalb der Testton
so stark gedämpft klang (interessant dass überhaupt ein Ton
herausgegeben wird)...
An dieser Stelle möchte ich noch die Aussage meines letzten Beitrags
korrigieren, habe nicht berücksichtigt dass der Adressvektor die Länge 7
hat. Aus diesem Grund ist die Zuordnung aus dem ersten Beispiel doch
korrekt gewesen.
Abschließend noch einmal der überarbeitete Code, welcher mit Sicherheit
programmiertechnisch noch nicht einwandfrei ist, jedoch ein
funktionierendes Ergebnis erbringt.
Vielen Dank nochmal an alle, die hier mitdiskutiert haben.
res_n ist in der Sensitivliste nicht nötig.
Dieser Prozess ist incl. Reset komplett synchron.
Warum hast du das beim zweiten Prozess nicht auch so gemacht?
1
process(clk)is
2
begin
3
casecurrent_stateis
4
whenreset=>led1<='1';
clk ist in der Sensitivliste nicht nötig, weil er im Prozess gar nicht
verwendet wird. Korrekterweise müsste aber current_state da rein.
Aber: zum Glück macht das der Synthesizer automatisch... ;-)
Nur: die Hardware und die Simulation passen nicht zueinander... :-o
Lothar Miller schrieb:> Warum hast du das beim zweiten Prozess nicht auch so gemacht?
In dem Moment, wo der Reset-Button gedrückt wird, hört mein Bitclk auf
und wird auf low gezogen. Ist jetzt der Bitclk just im Moment des Resets
auf '0', wird der Prozess doch nicht darauf reagieren, oder?
Gruß Benny
Benjamin K. schrieb:> In dem Moment, wo der Reset-Button gedrückt wird
Brauchst du tatsächlich einen Reset-Knopf?
Und wenn: kannst du mit dem nicht auch gleich das FPGA neu laden?
Dann wäre nämlich ohne Reset alles im Urzustand...
Lies mal den Beitrag "Xilinx und die Resets"
Und das darin erwähnte WP272 von Xilinx.
Ich habe auch den LM4550 drauf und musste feststellen, dass das ein
ziemliches Tier ist. Kann alles bis zum 3D Sound ist aber nicht so
einfach zu programmieren. Momentan hapert es auch ein bischen an meinem
Verständnis für die zu übertragenden Audiodaten:
Laut Beschreibung handelt es sich um PCM Daten. Das heisst für mich, ich
muss meinen analogen Datenstrom (kommt bei mir mit 96kHz) erst noch in
PCM wandeln, um ihn in die Slots einzufügen. (?)
Abgesehen davon, dass ich keinen Core dafür habe, verwirrt mich die
Aussage in diesem Thema, dass es / ob es sich um signed/unsigned PCM
handelt:
Beitrag "Re: AC97 Audio Codec, Ansteuerung mit VHDL"
Leider finde ich auf der dort verlinkten Seite keinen Beispiel-Code.
Etwas dazu gibt es wohl noch hier:
Beitrag "AC97-VHDL-Sourcecode"Beitrag "Richtige Ansteuerung des AC97-Chips?"
aber auch das ist nicht so durchsichtig.
Warum wird der Codec eigentlich überhaupt mit PCM gefahren, statt mit
seriellen digitalen Daten?
> Laut Beschreibung handelt es sich um PCM Daten. Das heisst für mich, ich> muss meinen analogen Datenstrom (kommt bei mir mit 96kHz) erst noch in> PCM wandeln, um ihn in die Slots einzufügen. (?)
Das sollte eigentlich Aufgabe des Codes sein, meine ich. PCM ist doch
1-Bit Daten und beschrieben wird sicher parallel.
> Abgesehen davon, dass ich keinen Core dafür habe, verwirrt mich die> Aussage in diesem Thema, dass es / ob es sich um signed/unsigned PCM> handelthttp://www.wiki.multimedia.cx/index.php?title=PCM
Hallo,
wenn bei diesem Codec PCM das hier
(http://de.wikipedia.org/wiki/Puls-Code-Modulation) ist, dann frage ich
mich, wo denn bitteschön das Problem ist? Das ist ja dann einfacher wie
ein serieller Datenstrom (da keine Bit-Alignment Detektion erforderlich
ist).
Hobbymusiker schrieb:> (kommt bei mir mit 96kHz)
Das heißt, dass du mit 96 KHz nach der AD-Wandlung, also alle ~10,417us,
einen n bit breiten Wert von deinem Audiosignal bekommst. Dieses Signal
muss du nach meinem Verständnis in einem Slot vom AC-LINK-Interface
packen und fertig. Die AC-LINK Schnittstelle scheint mir ein
deterministisches Verhalten zu haben, also es sendet nacheinander immer
diesselbe Information in einer festen Reihenfolge in einer festen
Frequenz. (Keine Garantie auf Richtigkeit, da ich das Datenblatt nur
überflogen habe und es selber nocht nicht implementiert habe). Das
schreit förmlich nach einer Lösung mit einer FSM!
Grüße
pcm schrieb:> Hobbymusiker schrieb:>> (kommt bei mir mit 96kHz)
Nur der Vollständigkeit halber:
Ich hatte das nicht geschrieben sondern nur zitiert.
> Das heißt, dass du mit 96 KHz nach der AD-Wandlung, also alle ~10,417us,> einen n bit breiten Wert von deinem Audiosignal bekommst.
Auch hier nur eine kleine Anmerkung:
Der Codec arbeit mit wesentlich höherem Takt, als die Samplerate und
liefert alles seriell ab.
> Die AC-LINK Schnittstelle scheint mir ein> deterministisches Verhalten zu haben, also es sendet nacheinander immer> diesselbe Information in einer festen Reihenfolge in einer festen> Frequenz.
Der Codec liefert ein Synch Signal, das die Position der Bits = Slots
angibt.
Die Frage von Rolf war aber wohl die nach der Art der Daten. Aus meiner
Sicht muss man da nichts wandeln sondern Daten seriell in die slots
einfügen.
Hobbyorganist schrieb:> Die Frage von Rolf war aber wohl die nach der Art der Daten. Aus meiner> Sicht muss man da nichts wandeln sondern Daten seriell in die slots> einfügen.
So scheint es zu sein, und dann machte auch die Fragestellung nach dem
signed wieder Sinn. Bin jetzt das Dokument nochmals durchgegangen und
finde immer noch nichts. Momentan tönt es sehr nach Übersteuerung.
Rolf S. schrieb:> Hobbyorganist schrieb:>> Die Frage von Rolf war aber wohl die nach der Art der Daten. Aus meiner>> Sicht muss man da nichts wandeln sondern Daten seriell in die slots>> einfügen.> So scheint es zu sein, und dann machte auch die Fragestellung nach dem> signed wieder Sinn. Bin jetzt das Dokument nochmals durchgegangen und> finde immer noch nichts. Momentan tönt es sehr nach Übersteuerung.
Könnte der Unterschied zwischen Offsetcodierung und 2er Komplement sein.
Invertiere mal das MSB.
Lothar Miller schrieb:> Benjamin K. schrieb:>> Dies liegt daran dass ich mit 2 verschiedenen Clocks arbeiten muss.> Wenn du das WEISST, dann kannst du ja was gegen potentielle Fehler tun> und solche Taktdomänenübergänge per Synchronisation entschärfen.>>> Muss aber zu meiner Verteidigung sagen dass sich bisher keine>> Auffälligkeiten nach einem manuellen Reset gezeigt haben....> Ja, irgendwann ist immer das erste Mal... ;-)>> Ich kenne deinen Baustein nicht, und weiß daher auch nicht, was> tatsächlich klemmt, aber weil du gefragt hast:> Benjamin K. schrieb:>> bin ich über Hinweise bzgl. des "Programmierstils" auch sehr dankbar)> In diesem letzten Prozess sind die Zähler in den if-Abfragen ungünstig> aufgehoben. Denn wenn du in 4 Wochen noch ein if dazuhängst, aber> vergisst, den Zähler mit reinzubauen, dann belibt der stehen. Besser> wäre es, den Zähler auf jeden Fall hochzuzählen, und bei Bedarf> zurückzusetzen:>
1
>process(ac97_bitclk)is
2
>begin
3
>ifac97_bitclk'eventandac97_bitclk='1'then
4
>sin_cnt<=sin_cnt+1;-- auf jeden Fall beim Takt hochzählen
5
>ifsin_cnt<=12288then
6
>sin_test<="11111111111111111100";
7
>elsifsin_cnt<24576then
8
>sin_test<="00000000000000000000";
9
>else
10
>sin_cnt<=0;
11
>endif;
12
>endif;
13
>endprocess;
14
>
Schreib den mal um und zwar so hier wie folgt:
process(ac97_bitclk) is
begin
if ac97_bitclk'event and ac97_bitclk = '1' then
sin_cnt <= sin_cnt + 1; -- auf jeden Fall beim Takt hochzählen
if sin_cnt <= 12233 then
sin_test <= "11101110111111001100";
elsif sin_cnt < 24576 then
sin_test <= "00000100100000010001";
else
sin_cnt <= 1;
end if;
end if;
end process;
Nun erscheint dein Lautsärkewert in abgewandelter Prozessstruktur und du
kannst die Laustsärke bis hochdrehen..
Ist aus änlichem Projekt, aber selber Quellcode.
Tux
Ich habe jetzt meinen Codec aktiv und es ist in der Tat signed integer,
was er haben will. Alles andere produziert Störung. Ich habe aber ein
neues Problem:
Bevor ich meinen Ausgang auf den Codec ausgebe, führe ich noch eine
Multilpikation mit 16 Bit durch und den Ausgangs zu skalieren. Die
Lautstärke lässt sich damit wie erwartet eistellen, jedoch habe ich den
bemerksenswerten Effekt, dass additiv zum Klang ein kleines Sirren hinzu
tönt, das in der Tonhöhe mit der Lautstärke korreliert ist: Je höher die
Luatstärkeeinstellung, desto höher (nicht lauter) ist der Störton.
Was könnte das sein?
Die Multiplikation sieht in etwa so aus:
ausgang_temp <= std__logic_vector (signed(quelle) * signed (ampli));
ausgang <= ausgang_temp(31 downto 16);
ampli ist dabei immer positiv zwischen 1024 und 32767.
quelle ist immer zwischen -32499 und 32499
Einen Üerlauf kann es ja nicht geben. Woher kommt das?
In der Simulation ist nichts Ungewähnliches zu erblicken.