Forum: FPGA, VHDL & Co. Problem bei AC97-Codec Ansteuerung (LM4550)


von Benjamin K. (halunke86)


Lesenswert?

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

1
----------------------------------------------------------------------------------
2
-- Company: 
3
-- Engineer: 
4
-- 
5
-- Create Date:    10:28:53 03/06/2012 
6
-- Design Name: 
7
-- Module Name:    ac97controller - Behavioral 
8
-- Project Name: 
9
-- Target Devices: 
10
-- Tool versions: 
11
-- Description: 
12
--
13
-- Dependencies: 
14
--
15
-- Revision: 
16
-- Revision 0.01 - File Created
17
-- Additional Comments: 
18
--
19
----------------------------------------------------------------------------------
20
library IEEE;
21
use IEEE.STD_LOGIC_1164.ALL;
22
23
-- Uncomment the following library declaration if using
24
-- arithmetic functions with Signed or Unsigned values
25
--use IEEE.NUMERIC_STD.ALL;
26
27
-- Uncomment the following library declaration if instantiating
28
-- any Xilinx primitives in this code.
29
--library UNISIM;
30
--use UNISIM.VComponents.all;
31
32
entity ac97controller is
33
    Port ( clk :           in   STD_LOGIC;
34
        res_n :        in   STD_LOGIC;
35
        ac97_bitclk :     in    STD_LOGIC;
36
           ac97_sdata_in :   in    STD_LOGIC;
37
        ac97vol :       in   STD_LOGIC_VECTOR(4 downto 0);
38
           ac97_sync :       out    STD_LOGIC;
39
           ac97_sdata_out :   out    STD_LOGIC;
40
           ac97_reset :     out    STD_LOGIC;
41
        
42
        sintest_out :     out   STD_LOGIC;
43
        led1 :         out   STD_LOGIC;
44
        led2 :         out   STD_LOGIC;
45
        led3 :         out   STD_LOGIC;
46
        led4 :         out   STD_LOGIC;
47
        
48
        
49
        cnt_out:         out  integer
50
        );
51
end ac97controller;
52
53
architecture Behavioral of ac97controller is
54
55
type state_type is (reset, slot0, slot1, slot2, slot3, slot4, slotrest);
56
57
signal current_state: state_type := reset;
58
signal sin_test   : std_logic_vector(19 downto 0);
59
60
signal bit_cnt   : natural := 0;
61
signal res_cnt   : natural := 0;
62
signal sin_cnt    : natural := 0;
63
64
signal volcontrol : natural := 0;
65
signal holddata : std_logic_vector(19 downto 0);
66
67
68
begin
69
  
70
  cnt_out <= res_cnt;
71
  sintest_out <= sin_test(19);
72
73
  cold_reset: process (clk, res_n)
74
  begin
75
    if (clk'event and clk = '1') then
76
      if res_n = '0' then
77
        ac97_reset <= '0';
78
        res_cnt <= 0;
79
      elsif res_cnt < 1000 then
80
        ac97_reset <= '0';
81
        res_cnt <= res_cnt + 1;
82
      else
83
        ac97_reset <= '1';    
84
      end if;
85
    end if;
86
  end process cold_reset;
87
    
88
    
89
  f: process (ac97_bitclk) is
90
  begin
91
    holddata <= sin_test;
92
    if res_n = '0' then
93
      current_state <= reset;
94
      ac97_sdata_out <= '0';
95
      ac97_sync <= '0';
96
      bit_cnt <= 0;
97
    elsif ac97_bitclk'event and ac97_bitclk = '1' then
98
      case current_state is
99
          when reset =>  current_state <= slot0;
100
                    ac97_sync <= '1';
101
                    bit_cnt <= 0;
102
          when slot0 =>   case bit_cnt is                      --  bit_cnt : 0 .. 15
103
                      when 0      => ac97_sdata_out <= '1';     -- Valid data bit
104
                                  ac97_sync <= '1';
105
                      when 1       => ac97_sdata_out <= '1';     -- Valid control address in slot1 
106
                                  ac97_sync <= '1';
107
                      when 2       => ac97_sdata_out <= '1';     -- Valid control data in slot2
108
                                  ac97_sync <= '1';                    
109
                      when 3       => ac97_sdata_out <= '1';    -- Valid PCM Data in Slot 3 (Left channel audio)
110
                                  ac97_sync <= '1';
111
                      when 4       => ac97_sdata_out <= '1';    -- Valid PCM Data in Slot 4 (Right channel audio)
112
                                  ac97_sync <= '1';
113
                      when 15      => ac97_sync <= '0';
114
                      when others    => ac97_sdata_out <= '0';    -- 
115
                                  ac97_sync <= '1';
116
                    end case;
117
                    if bit_cnt < 15 then 
118
                      current_state <= slot0;
119
                    else
120
                      current_state <= slot1;
121
                    end if;
122
          when slot1 =>   if volcontrol = 1 then                    -- !toggler -> master vol. reg
123
                      case bit_cnt is                        --  bit_cnt : 16 .. 35
124
                        when 16        => ac97_sdata_out <= '0';     -- write
125
                        when 22        => ac97_sdata_out <= '1';     -- master volume register 02h
126
                        when others     => ac97_sdata_out <= '0';
127
                      end case;
128
                    elsif volcontrol = 0 then
129
                      case bit_cnt is                        --  bit_cnt : 16 .. 35
130
                        when 16        => ac97_sdata_out <= '0';     -- write
131
                        when 21        => ac97_sdata_out <= '1';     -- headphone volume register 04h
132
                        when others     => ac97_sdata_out <= '0';
133
                      end case;
134
            --        else
135
            --          case bit_cnt is
136
            --            when 16         => ac97_sdata_out <= '0';
137
            --            when 21         => ac97_sdata_out <= '1';
138
            --            when 23         => ac97_sdata_out <= '1';    -- mono volume register
139
            --            when others     => ac97_sdata_out <= '0';
140
            --          end case;
141
                    end if;
142
                    if bit_cnt < 35 then 
143
                      current_state <= slot1;
144
                    else
145
                      current_state <= slot2;
146
                      if volcontrol < 1 then 
147
                        volcontrol <= volcontrol + 1;
148
                      end if;
149
                    end if;                              
150
          when slot2 => --  if toggler = false then                      --  bit_cnt : 36 .. 55
151
                    --  ac97_sdata_out <= '0';                    --  unmute + 0dB attention
152
                    --else
153
                      case bit_cnt is
154
                        when 36         => ac97_sdata_out <= '0';    -- unmute
155
                        when 37        => ac97_sdata_out <= ac97vol(4);
156
                        when 38        => ac97_sdata_out <= ac97vol(3);
157
                        when 39        => ac97_sdata_out <= ac97vol(2);
158
                        when 40        => ac97_sdata_out <= ac97vol(1);
159
                        when 41        => ac97_sdata_out <= ac97vol(0);
160
                        when others     => ac97_sdata_out <= '0';  
161
                      end case;
162
                    --end if;
163
                    if bit_cnt < 55 then                     
164
                      current_state <= slot2;
165
                    else
166
                      current_state <= slot3;
167
--                      toggler <= not toggler;
168
                    end if;
169
          when slot3 =>   ac97_sdata_out <= holddata(75 - bit_cnt);        --  bit_cnt : 56 .. 75
170
                    ac97_sync <= '0';        
171
                    if bit_cnt < 75 then 
172
                      current_state <= slot3;
173
                    else
174
                      current_state <= slot4;
175
                    end if;
176
          when slot4 =>   ac97_sdata_out <= holddata(95 - bit_cnt);        --  bit_cnt : 76 .. 95
177
                    ac97_sync <= '0';
178
                    if bit_cnt < 95 then 
179
                      current_state <= slot4;
180
                    else
181
                      current_state <= slotrest;
182
                    end if;
183
          when slotrest =>                                   -- bit_cnt : 96 .. 255
184
                    ac97_sdata_out <= '0';
185
                    ac97_sync <= '0';
186
                    if bit_cnt < 255 then 
187
                      current_state <= slotrest;
188
                    else
189
                      ac97_sync <= '1';
190
                      current_state <= slot0;
191
                    end if;
192
      end case;
193
      
194
      if current_state /= reset and res_n = '1' and bit_cnt < 255 then
195
        bit_cnt <= bit_cnt + 1;
196
      else
197
        bit_cnt <= 0;
198
      end if;
199
    end if;
200
  end process;
201
202
  --Testsignal
203
  process(ac97_bitclk) is
204
  begin
205
    if ac97_bitclk'event and ac97_bitclk = '1' then
206
      if sin_cnt <= 12288 then
207
        sin_test <= "11111111111111111100";
208
        sin_cnt <= sin_cnt + 1;
209
      elsif sin_cnt < 24576 then
210
        sin_test <= "00000000000000000000";
211
        sin_cnt <= sin_cnt + 1;
212
      else
213
        sin_cnt <= 0;
214
      end if;
215
    end if;
216
  end process;
217
218
end Behavioral;

von M. J. (manfred-64)


Lesenswert?

Hi,

nur mal so, da man sich öfters mal bei den einfacheren Dingen vertut.
Bist Du sichre das Du die HP und nicht ne LIN Buchse erwischt hast?

von Benjamin K. (halunke86)


Lesenswert?

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

von Benjamin K. (halunke86)


Lesenswert?

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 ;)

von Stefan H. (Firma: dm2sh) (stefan_helmert)


Lesenswert?


von Benjamin K. (halunke86)


Lesenswert?

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....

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Benjamin K. schrieb:
1
 f: process (ac97_bitclk) is
2
   begin
3
     holddata <= sin_test;  
4
     if res_n = '0' then
5
             :
6
     elsif ac97_bitclk'event and ac97_bitclk = '1' then
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...

von Benjamin K. (halunke86)


Lesenswert?

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

von ergher (Gast)


Lesenswert?

> 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...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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
    if ac97_bitclk'event and ac97_bitclk = '1' then
4
      sin_cnt <= sin_cnt + 1;  -- auf jeden Fall beim Takt hochzählen
5
      if sin_cnt <= 12288 then
6
        sin_test <= "11111111111111111100";
7
      elsif sin_cnt < 24576 then
8
        sin_test <= "00000000000000000000";
9
      else
10
        sin_cnt <= 0;
11
      end if;
12
    end if;
13
  end process;

von Benjamin K. (halunke86)


Lesenswert?

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

von Benjamin K. (halunke86)


Lesenswert?

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)

von Benjamin K. (halunke86)


Lesenswert?

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.
1
----------------------------------------------------------------------------------
2
-- Company: 
3
-- Engineer: 
4
-- 
5
-- Create Date:    10:28:53 03/06/2012 
6
-- Design Name: 
7
-- Module Name:    ac97controller - Behavioral 
8
-- Project Name: 
9
-- Target Devices: 
10
-- Tool versions: 
11
-- Description: 
12
--
13
-- Dependencies: 
14
--
15
-- Revision: 
16
-- Revision 0.01 - File Created
17
-- Additional Comments: 
18
--
19
----------------------------------------------------------------------------------
20
library IEEE;
21
use IEEE.STD_LOGIC_1164.ALL;
22
23
-- Uncomment the following library declaration if using
24
-- arithmetic functions with Signed or Unsigned values
25
use IEEE.NUMERIC_STD.ALL;
26
27
-- Uncomment the following library declaration if instantiating
28
-- any Xilinx primitives in this code.
29
--library UNISIM;
30
--use UNISIM.VComponents.all;
31
32
entity ac97controller is
33
    Port ( clk :           in   STD_LOGIC;
34
        res_n :        in   STD_LOGIC;
35
        ac97_bitclk :     in    STD_LOGIC;
36
           ac97_sdata_in :   in    STD_LOGIC;
37
        ac97vol :       in   STD_LOGIC_VECTOR(4 downto 0);
38
           ac97_sync :       out    STD_LOGIC;
39
           ac97_sdata_out :   out    STD_LOGIC;
40
           ac97_reset :     out    STD_LOGIC;
41
        
42
        sintest_out :     out   STD_LOGIC;
43
        led1 :         out   STD_LOGIC;
44
        led2 :         out   STD_LOGIC;
45
        led3 :         out   STD_LOGIC;
46
        led4 :         out   STD_LOGIC
47
        );
48
end ac97controller;
49
50
architecture Behavioral of ac97controller is
51
52
type state_type is (reset, slot0, slot1, slot2, slot3, slot4, slotrest);
53
54
signal current_state: state_type := reset;
55
signal sin_test   : std_logic_vector(19 downto 0);
56
57
signal bit_cnt   : natural range 0 to 255;
58
signal res_cnt   : natural := 0;
59
signal sin_cnt    : natural := 0;
60
61
signal volcontrol : natural := 0;
62
63
signal volume : std_logic_vector(15 downto 0);
64
65
constant REG_MASTERVOL : std_logic_vector(6 downto 0) := "0000010";
66
constant REG_HPVOL : std_logic_vector(6 downto 0) := "0000100";
67
constant REG_PCMOUTVOL : std_logic_vector(6 downto 0) := "0011000";
68
constant PCMOUTVOL : std_logic_vector (15 downto 0) := "0001111100011111";
69
70
-- VZ-behaftet, Zweierkomplement
71
constant HIGHVAL   : std_logic_vector(19 downto 0) := "01111111111111111100";     -- Zweierkomplement: "1000000000000000100"
72
constant LOWVAL   : std_logic_vector(19 downto 0) := "00000000000000000000";    -- Zweierkomplement: "0111111111111111000"
73
--constant LOWVAL   : std_logic_vector(19 downto 0) := "00000000000000000000";
74
75
-- nicht VZ-behaftet, Zweierkomplement
76
--constant HIGHVAL   : std_logic_vector(19 downto 0) := "00000000000000000000";
77
--constant LOWVAL   : std_logic_vector(19 downto 0) := "00000000000000000100";
78
79
-- nicht VZ-behaftet
80
--constant HIGHVAL   : std_logic_vector(19 downto 0) := "00000000000000000000";
81
--constant LOWVAL   : std_logic_vector(19 downto 0) := "11111111111111111100";
82
83
84
begin
85
86
  volume <= "000" & ac97vol & "000" & ac97vol;
87
88
  cold_reset: process (clk, res_n)
89
  begin
90
    if (clk'event and clk = '1') then
91
      if res_n = '0' then
92
        ac97_reset <= '0';
93
        res_cnt <= 0;
94
      elsif res_cnt < 1000 then
95
        ac97_reset <= '0';
96
        res_cnt <= res_cnt + 1;
97
      else
98
        ac97_reset <= '1';    
99
      end if;
100
    end if;
101
  end process cold_reset;
102
    
103
    
104
  f: process (ac97_bitclk, res_n) is
105
  begin
106
    if res_n = '0' then
107
      current_state <= reset;
108
      ac97_sdata_out <= '0';
109
      ac97_sync <= '0';
110
      bit_cnt <= 0;
111
      sin_cnt <= 0;
112
    elsif ac97_bitclk'event and ac97_bitclk = '1' then
113
      case current_state is
114
          when reset =>  ac97_sync <= '1';
115
                    bit_cnt <= 0;
116
                    sin_cnt <= 0;
117
                    if res_cnt < 1000 then
118
                      current_state <= reset;
119
                    else
120
                      current_state <= slot0;
121
                    end if;
122
          when slot0 =>   case bit_cnt is                      --  bit_cnt : 0 .. 15
123
                      when 0      => ac97_sdata_out <= '1';     -- Valid data bit
124
                                  ac97_sync <= '1';
125
                      when 1       => ac97_sdata_out <= '1';     -- Valid control address in slot1 
126
                                  ac97_sync <= '1';
127
                      when 2       => ac97_sdata_out <= '1';     -- Valid control data in slot2
128
                                  ac97_sync <= '1';                    
129
                      when 3       => ac97_sdata_out <= '1';    -- Valid PCM Data in Slot 3 (Left channel audio)
130
                                  ac97_sync <= '1';
131
                      when 4       => ac97_sdata_out <= '1';    -- Valid PCM Data in Slot 4 (Right channel audio)
132
                                  ac97_sync <= '1';
133
                      when 15      => ac97_sync <= '0';
134
                      when others    => ac97_sdata_out <= '0';    -- 
135
                                  ac97_sync <= '1';
136
                    end case;
137
                    if bit_cnt < 15 then 
138
                      current_state <= slot0;
139
                    else
140
                      current_state <= slot1;
141
                    end if;
142
          when slot1 =>   if bit_cnt = 16 then                        -- bitcnt : 16..35
143
                      ac97_sdata_out <= '0';                    -- write
144
                    elsif bit_cnt < 24 then
145
                      if volcontrol = 0 then                    -- pcmout volume register
146
                        ac97_sdata_out <= REG_PCMOUTVOL(23-bit_cnt);    
147
                      elsif volcontrol = 1 then                  -- master volume register
148
                        ac97_sdata_out <= REG_MASTERVOL(23-bit_cnt);    
149
                      else                                -- headphone volume register
150
                        ac97_sdata_out <= REG_HPVOL(23-bit_cnt);      
151
                      end if;
152
                    else
153
                      ac97_sdata_out <= '0';
154
                    end if;
155
                    
156
                    if bit_cnt < 35 then 
157
                      current_state <= slot1;
158
                    else
159
                      current_state <= slot2;
160
                    end if;                              
161
          when slot2 =>  if bit_cnt < 52 then
162
                      if volcontrol = 0 then
163
                        ac97_sdata_out <= PCMOUTVOL(52 - bit_cnt);
164
                      else
165
                        ac97_sdata_out <= volume(52 - bit_cnt);        -- bitcnt : 36 .. 55  
166
                      end if;
167
                    else
168
                      ac97_sdata_out <= '0';
169
                    end if;
170
                    if bit_cnt < 55 then                     
171
                      current_state <= slot2;
172
                    else
173
                      if volcontrol < 2 then 
174
                        volcontrol <= volcontrol + 1;
175
                      else 
176
                        volcontrol <= 1;
177
                      end if;
178
                      current_state <= slot3;
179
                    end if;
180
          when slot3 =>  ac97_sync <= '0';                          --  bit_cnt : 56 .. 75
181
                    if sin_cnt < 24 then
182
                      ac97_sdata_out <= HIGHVAL(75 - bit_cnt);  
183
                    else
184
                      ac97_sdata_out <= LOWVAL(75 - bit_cnt);
185
                    end if;
186
                    
187
                    if bit_cnt < 75 then 
188
                      current_state <= slot3;
189
                    else
190
                      current_state <= slot4;
191
                    end if;
192
          when slot4 =>   ac97_sync <= '0';                          --  bit_cnt : 76 .. 95
193
                    if sin_cnt < 24 then
194
                      ac97_sdata_out <= HIGHVAL(95 - bit_cnt);        
195
                    else
196
                      ac97_sdata_out <= LOWVAL(95 - bit_cnt);        
197
                    end if;
198
                    
199
                    if bit_cnt < 95 then 
200
                      current_state <= slot4;
201
                    else
202
                      if sin_cnt < 48 then
203
                        sin_cnt <= sin_cnt + 1;
204
                      else
205
                        sin_cnt <= 0;
206
                      end if;
207
                      current_state <= slotrest;
208
                    end if;
209
          when slotrest =>                                   -- bit_cnt : 96 .. 255
210
                    ac97_sdata_out <= '0';
211
                    ac97_sync <= '0';
212
                    if bit_cnt < 255 then 
213
                      current_state <= slotrest;
214
                    else
215
                      ac97_sync <= '1';
216
                      current_state <= slot0;
217
                    end if;
218
      end case;
219
      
220
      if current_state /= reset and res_n = '1' and bit_cnt < 255 then
221
        bit_cnt <= bit_cnt + 1;
222
      else
223
        bit_cnt <= 0;
224
      end if;
225
    end if;
226
  end process;
227
228
    
229
  process(clk) is
230
  begin 
231
    case current_state is
232
      when reset =>   led1 <= '1';
233
                led2 <= '0';
234
                led3 <= '0';
235
                led4 <= '0';
236
      when slot0 => 
237
                led1 <= '0';
238
                led2 <= '1';
239
                led3 <= '0';
240
                led4 <= '0';
241
      when slot1 =>   led1 <= '0';
242
                led2 <= '0';
243
                led3 <= '1';
244
                led4 <= '0';
245
      when slot2 =>   led1 <= '0';
246
                led2 <= '0';
247
                led3 <= '0';
248
                led4 <= '1';
249
      when others => led1 <= '0';
250
                led2 <= '0';
251
                led3 <= '0';
252
                led4 <= '0';
253
    end case;
254
  end process;
255
256
end Behavioral;

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Benjamin K. schrieb:
1
 cold_reset: process (clk, res_n)
2
   begin
3
     if (clk'event and clk = '1') then
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
    case current_state is
4
      when reset =>   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

von Benjamin K. (halunke86)


Lesenswert?

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

von Rolf S. (audiorolf)


Lesenswert?

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?

von Hobbymusiker (Gast)


Lesenswert?

> 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
> handelt
http://www.wiki.multimedia.cx/index.php?title=PCM

von pcm (Gast)


Lesenswert?

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

von Hobbyorganist (Gast)


Lesenswert?

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.

von Rolf S. (audiorolf)


Lesenswert?

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.

von Lattice User (Gast)


Lesenswert?

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.

von Tux(Programmierer) (Gast)


Lesenswert?

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
>     if ac97_bitclk'event and ac97_bitclk = '1' then
4
>       sin_cnt <= sin_cnt + 1;  -- auf jeden Fall beim Takt hochzählen
5
>       if sin_cnt <= 12288 then
6
>         sin_test <= "11111111111111111100";
7
>       elsif sin_cnt < 24576 then
8
>         sin_test <= "00000000000000000000";
9
>       else
10
>         sin_cnt <= 0;
11
>       end if;
12
>     end if;
13
>   end process;
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

von Rolf S. (audiorolf)


Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.