Forum: FPGA, VHDL & Co. Countdown-Zähler mit anschließender Tonausgabe


von Schwabe (Gast)


Lesenswert?

Hallo Leute

Ich habe ein Problem, ich erstelle gerade einen Countdown-Zähler der von 
maximal 99 runterzählen soll. Die Zahl ist einstellbar. Nun es tut sich 
schon etwas, nur es gibt noch einige kleine Probleme z.B. mit der 
Tonausgabe und ich denke auch mit den Zuständen. Wäre cool wenn sich 
jemand melden würde, den Quelltext und die Aufgabenstellung kann ich 
euch dann zukommen lassen, wenn ihr Zeit habt  mal drüberzuschauen...

PS: Ich benutze das Spartan3a Starterkit.

von Duke Scarring (Gast)


Lesenswert?

Schwabe schrieb:
> nur es gibt noch einige kleine Probleme z.B. mit der
> Tonausgabe und ich denke auch mit den Zuständen
Ah. Tolle Fehlerbeschreibung :-)

Hast Du schon eine Testbench?

Duke

von Andreas D. (Gast)


Lesenswert?

Ohne den Code kann man leider dazu gar nix sagen. Wäre also schlau 
gewesen wenn du ihn (bzw. den entsprechenden Ausschnitt) gleich 
angehängt hättest. (Dafür gibt es extra das Feld „Dateianhang“.)

von Schwabe (Gast)


Lesenswert?

1
 library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
7
entity anwendung is
8
9
    Port ( takt, reset  : in  STD_LOGIC;
10
                      t_north  :       in STD_LOGIC;
11
                      t_south  :       in STD_LOGIC;
12
                      t_west   :       in STD_LOGIC;
13
                      t_east   :       in STD_LOGIC;
14
                      sw_0     :       in STD_LOGIC;
15
                      sw_1     :       in STD_LOGIC;
16
                      sw_2     :       in STD_LOGIC;
17
                      sw_3     :       in STD_LOGIC;
18
                      led_array     :  out STD_LOGIC_VECTOR (7 downto 0);
19
                      einer, zehner, Hdt, Tsd, Z_tsd, H_Tsd: out STD_LOGIC_VECTOR(3 downto 0));
20
end anwendung;
21
22
23
architecture Behavioral of anwendung is
24
-- Deklaration der Signale --------------------------------------------
25
-- Taktsignale ---------------------------------------------------------
26
27
        signal takt_temp: STD_LOGIC_VECTOR (31 downto 0) := x"00000000";
28
        signal takt_temp_2: STD_LOGIC_VECTOR (31 downto 0) := x"00000000":
29
        signal takt_temp_3: STD_LOGIC_VECTOR (31 downto 0) := x"00000000";
30
        signal sec_clk: STD_LOGIC := '0';
31
        signal entprell_clk: STD_LOGIC := '0';
32
        signal ton_clk: STD_LOGIC := '0';
33
34
-- Register ------------------------------------------------------------
35
-- High ----------------------------------------------------------------
36
37
        signal RH : STD_LOGIC_VECTOR (3 downto 0) := "0000";
38
        signal RHH: STD_LOGIC_VECTOR (3 downto 0) := "1001";
39
40
-- Low -----------------------------------------------------------------
41
 
42
        signal RL : STD_LOGIC_VECTOR (3 downto 0) := "0000";
43
        signal RLL: STD_LOGIC_VECTOR (3 downto 0) := "1001";
44
45
-- Überträge -----------------------------------------------------------
46
-- Einer ---------------------------------------------------------------
47
48
        signal co_e : STD_LOGIC := '0';
49
      
50
-- Zehner --------------------------------------------------------------
51
52
        signal co_z : STD_LOGIC := '0';
53
 
54
-- Zustände ------------------------------------------------------------
55
56
     type ZUSTAENDE is (A, B, C, D, E);
57
       signal ZUSTAND, FOLGEZUSTAND : ZUSTAENDE;
58
     
59
begin
60
61
-- Frequenzteiler ------------------------------------------------------
62
-- Von 50MHz auf 1Hz ---------------------------------------------------
63
sek_counter : process (takt, reset, takt_temp_2)
64
65
begin
66
                  if reset = '1' then
67
                     takt_temp_2 <= x"00000000";
68
                  elsif rising_edge(takt) then
69
                        if takt_temp_2 >= 25000000
70
                then sec_clk <= not(sec_clk);
71
                takt_temp_2 <= x"00000000";
72
                        else takt_temp_2 <= takt_temp_2 + 1;
73
                        end if;
74
                  else
75
                       takt_temp_2 <= takt_temp_2;
76
                  end if;
77
end process sek_counter;
78
79
-- Von 50MHz auf 1kHz --------------------------------------------------
80
ton_counter : process (takt, reset, takt_temp_3)
81
82
begin
83
                if reset = '1' then
84
                   takt_temp_3 <= x"00000000";
85
                elsif rising_edge(takt) then
86
                       if takt_temp_3 >= 25000 then
87
                          ton_clk <= not(ton_clk);
88
                          takt_temp_3 <= x"00000000";
89
                       else
90
                          takt_temp_3 <= takt_temp_3 + 1;
91
                       end if;
92
                else 
93
           takt_temp_3 <= takt_temp_3;
94
                end if;
95
end process ton_counter;
96
97
-- Von 50MHz auf 100Hz (entprellen) ------------------------------------
98
entprell_counter : process (takt, reset, takt_temp)
99
100
begin
101
               if reset = '1' then 
102
             takt_temp <= x"00000000";
103
                  entprell_clk <= '0';
104
-- asynchrones Rücksetzen
105
               elsif rising_edge(takt) then
106
                     if takt_temp >= 250000 then
107
              -- sychrones Zaehlen
108
                        entprell_clk <= not(entprell_clk);
109
                        takt_temp <= x"00000000";
110
                     else
111
                     takt_temp <= takt_temp + 1;
112
                     end if;
113
               else
114
               takt_temp <= takt_temp;
115
               end if;
116
end process entprell_counter;
117
118
-- Kaskadierbare Zähler (9-0) ------------------------------------------
119
-- Register Low --------------------------------------------------------
120
counter_RL: process (sec_clk,reset,ZUSTAND,RL, RH,RHH,sw_0,sw_1,sw_2,sw_3,RLL,co_e, co_z)
121
122
begin
123
-- Asynchrones Rücksetzen
124
           if reset = '1' then RLL <= RL;
125
           elsif ZUSTAND = E then
126
                      if  (sw_3 & sw_2 & sw_1 & sw_0) >= 9  then
127
                          RL <= "1001";
128
                      else
129
                          RL <= sw_3 & sw_2 & sw_1 & sw_0;
130
                      end if;
131
-- Synchrone Teil mit carry_in Berücksichtigung
132
           elsif( rising_edge(sec_clk) and ZUSTAND = B and co_z = '0' ) then
133
                    if RLL = "0000" then -- Überlaufbedingung zum Rücksetzen
134
                            RLL <= "1001";
135
                            co_e <= '1';
136
                    else
137
                       co_e <= '0';
138
                       RLL <= RLL - 1;
139
                    end if;
140
           else RLL <= RLL; -- Erhalt des Zählerstandes
141
           end if;
142
end process counter_RL;
143
144
145
-- Register High -------------------------------------------------------
146
counter_RH: process (co_e,reset,ZUSTAND,RH,sw_0,sw_1,sw_2,sw_3,RHH,co_z)
147
148
begin
149
-- Asynchrones Rücksetzen
150
                if reset = '1' then RHH <= RH;
151
                elsif ZUSTAND = D then
152
                        if  (sw_3 & sw_2 & sw_1 & sw_0) >= 9  then
153
                               RH <= "1001";
154
                        else
155
                               RH <= sw_3 & sw_2 & sw_1 & sw_0;
156
                        end if;
157
-- Synchrone Teil mit carry_in Berücksichtigung
158
               elsif( rising_edge(co_e)and ZUSTAND = B) then
159
                        if RHH = "0000" and RLL = "0000" then -- Überlaufbedingung zum Rücksetzen
160
                           co_z <= '1';
161
               elsif
162
                      RHH = "0000" then RHH <= "1001"; --???? RHH soll bei 0 auch 0 bleiben
163
               else
164
                      RHH <= RHH - 1;
165
                      co_z <= '0';
166
               end if;
167
               else
168
               RHH <= RHH ;      -- Erhalt des Zählerstandes
169
            end if;
170
      end process counter_RH;
171
-- carry_out Erzeugung
172
173
174
-- Betriebsartenumschaltung --------------------------------------------
175
zustandsaktualisierung: process (entprell_clk,reset)
176
177
 begin
178
        if reset = '1' then
179
               ZUSTAND <=A;
180
        elsif rising_edge(entprell_clk) then
181
               ZUSTAND <= FOLGEZUSTAND;
182
        end if;
183
184
  end process zustandsaktualisierung;
185
186
187
-- Folgezustandsberechnung ---------------------------------------------
188
-- Betriebsarten:
189
-- B:     Normaler Count-Down-Modus
190
-- C:     Programmiermodus
191
192
folgezustandsberechnung: process (t_east, t_west, t_south, t_north, ZUSTAND, co_z, FOLGEZUSTAND)
193
194
 begin
195
       case ZUSTAND is
196
197
198
-- COUNT-DOWN-MODUS -------------------------------------------------------------------
199
               when A => if t_west = '1' then FOLGEZUSTAND <= C;
200
                          elsif t_east = '1' then FOLGEZUSTAND <= B;
201
-- Start Countdown
202
                          else FOLGEZUSTAND <= A;
203
                          end if;
204
               when B => if co_z = '1' then FOLGEZUSTAND <= A;
205
                          else FOLGEZUSTAND <= B;
206
                          end if;
207
208
 
209
-- PROGRAMMIERMODUS --------------------------------------------------------------------
210
                 when C => if t_west = '1' then FOLGEZUSTAND <= A;
211
                         elsif t_south = '1' then FOLGEZUSTAND <= E;
212
                         elsif t_north = '1' then FOLGEZUSTAND <= D;
213
                         else FOLGEZUSTAND <= C;
214
                         end if;
215
                 when D => if ZUSTAND = D then FOLGEZUSTAND <= C;
216
                         end if;
217
                 when E => if ZUSTAND = E then FOLGEZUSTAND <= C;
218
                         end if;
219
        end case;
220
        end process folgezustandsberechnung;
221
222
 
223
-- Ausgänge zuweisen ---------------------------------------------------
224
225
-- LCD-Anzeige
226
227
        einer   <= RLL;
228
        zehner  <= RHH;
229
        Hdt     <= "1111";
230
        Tsd     <= "1111";
231
        Z_tsd   <= RL;
232
        H_tsd   <= RH;
233
234
235
236
-- LED-Anzeige
237
238
        led_array(0) <= sw_0;
239
        led_array(1) <= sw_1;
240
        led_array(2) <= sw_2;
241
        led_array(3) <= sw_3;
242
        led_array(4) <= '1' when ZUSTAND = E else '0';
243
        led_array(5) <= '1' when ZUSTAND = D else '0';
244
        led_array(6) <= '1' when ZUSTAND = C else '0';
245
        led_array(7) <= '1' when ZUSTAND = B else '0';
246
247
248
249
250
251
252
253
end Behavioral;

Also der Ton soll 1Hz-Ton sein und nachdem der Zähler auf 0 ist, soll 5 
sekunden lang der Ton ausgegeben werden. RLL ist der Wert der 
runtergezählt wird und RL der wert des Registers...

von Duke Scarring (Gast)


Lesenswert?

Lothar, kannst Du mal bitte Deinen Textbaustein einstellen?

von Duke Scarring (Gast)


Lesenswert?

Und außerdem: Wo ist denn jetz die Testbench?

Duke

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


Lesenswert?

Duke Scarring schrieb:
> Lothar, kannst Du mal bitte Deinen Textbaustein einstellen?
Moment, ich suche nach Postulat....

Hier isser:
1
Ein Design (insbesondere ein Anfängerdesign) hat genau 1 Takt, 
2
der immer auf dieselbe Flanke aktiv ist. 
3
Es gibt keinen (und schon gleich gar keinen asynchronen oder 
4
gar kombinatorischen) Reset.
5
Externe Signale werden über 2 Flipflops einsynchronisiert.
6
Jede Abweichung von diesen Regeln muß fundiert begründet werden können.

Und kaum zu glauben: jeder einzelne Fehler wurde gemacht und sehr oft 
gemacht...

Zum Takt:
1
                  elsif rising_edge(takt) then
2
:
3
elsif( rising_edge(co_e)and ZUSTAND = B) then
4
:
5
        elsif rising_edge(entprell_clk) then


Asynchrones und sogar kombinatorisches Rücksetzen mit nicht 
einsynchronisierten Signalen:
1
-- Asynchrones Rücksetzen
2
                if reset = '1' then RHH <= RH;
3
                elsif ZUSTAND = D then
4
                        if  (sw_3 & sw_2 & sw_1 & sw_0) >= 9  then
5
                               RH <= "1001";
6
                        else
7
                               RH <= sw_3 & sw_2 & sw_1 & sw_0;
8
                        end if;
9
-- Synchrone Teil mit carry_in Berücksichtigung
10
               elsif( rising_edge(co_e)and ZUSTAND = B) then

> nur es gibt noch einige kleine Probleme
Das sehe ich nicht so.
Dein Design ist absolut zufällig im Verhalten.
Das kann gehen, du kannst aber bestenfalls eine Wahrscheinlichkeit 
angeben (sozusagen eine MTBF), denn ein Fehler muß hier früher oder 
später passieren...

BTW: mit Vektoren rechnet man nicht!
Nimm für deine Zähler einfach den Typ unsigned oder noch besser integer 
aus der numeric_std:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.numeric_std.all;
4
:
5
:
6
        signal en_sec: std_logic := '0';  -- Enable-Signal 1 sec
7
        signal cnt_sec: integer range 0 to 49999999 := 0;
8
:
9
:
10
11
-- Sekunden-Enable erzeugen
12
process (takt) begin
13
       if rising_edge(takt) then
14
          if pre_sec < 49999999 then
15
             pre_sec <= pre_sec+1;
16
             en_sec <= '0';
17
          else
18
             pre_sec <= 0;
19
             en_sec <= '1';
20
         end if;
21
      end if;
22
end process sek_counter;
23
24
-- Verwendung des Enable Signals
25
process (takt) begin
26
   if rising_edge(takt) then -- es kann nur einen geben!
27
      if en_sec =n '1' then
28
         if (cnt_sec > 0) then 
29
            cnt_sec <= cnt_sec -1;
30
            ton_ausgeben <= '0';
31
         else
32
            cnt_sec <= '0';
33
            ton_ausgeben <= '1';
34
         end if;
35
      end if;
36
end process;
37
38
:
39
:

EDIT: sieh dir mal den Beitrag "vhdl-richtlinien f. synthese?" an...

von Duke Scarring (Gast)


Lesenswert?

Lothar Miller schrieb:
> Und kaum zu glauben: jeder einzelne Fehler wurde gemacht und sehr oft
> gemacht...

Wahrscheinlich sollten wir doch mal ein Buch machen und an die 
Multiplikatoren der Universitäten, Hochschulen und Schulen(?) verteilen. 
Nur wer finanziert das?

Duke

von Klaus F. (kfalser)


Lesenswert?

Duke Scarring schrieb:
> Wahrscheinlich sollten wir doch mal ein Buch machen und an die
> Multiplikatoren der Universitäten, Hochschulen und Schulen(?) verteilen.

Bücher gibt's schon, FAQ gibt's schon, aber lesen tut niemand mehr.
Vielleicht einmal eine Hör-CD oder ein Video, zum runterladen auf den 
MP3 Player ...

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


Lesenswert?

Klaus Falser schrieb:
> ein Video, zum runterladen auf den MP3 Player ...
Aber maximal 6:48 lang... :-o

Duke Scarring schrieb:
> Wahrscheinlich sollten wir doch mal ein Buch machen ...
Am besten ein E-Book, dann könnte man einfach da draus hierher kopieren.
Das Problem ist eigentlich, dass alles über VHDL schon geschrieben 
wurde. Und das bisschen, das im Zusammenhang von VHDL mit FPGAs zu 
beachten ist, das passt locker auf ein Faltblatt...

> an die Multiplikatoren ... verteilen.
An welche?

von Mathias J. (mjpdx)


Lesenswert?

>Wahrscheinlich sollten wir doch mal ein Buch machen und an die
>Multiplikatoren der Universitäten, Hochschulen
 verteilen!

Bitte!

Das man nicht mit Vektoren rechnet wurde mir nie mitgeteilt, geschweige 
denn kritisiert!! Es ging ja immer...

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


Lesenswert?

Mathias Jt schrieb:
> Das man nicht mit Vektoren rechnet wurde mir nie mitgeteilt, geschweige
> denn kritisiert!! Es ging ja immer...
Ja, aber ein Zähler von 0..999 wird im Simulator nicht angemeckert 
werden können, denn der nächste Überlauf des 10-Bit-Vektors findet bei 
1023 statt.

Aus diesem Grund (von der einfacheren Schreibweise abgesehen) Zähler 
immmer mit eingeschränkten Integern (z.B. range 0 to 999) machen.

von Mathias J. (mjpdx)


Lesenswert?

Wurde notiert, danke ;-)

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.