mikrocontroller.net

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


Autor: Schwabe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Andreas D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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“.)

Autor: Schwabe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
 library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity anwendung is

    Port ( takt, reset  : in  STD_LOGIC;
                      t_north  :       in STD_LOGIC;
                      t_south  :       in STD_LOGIC;
                      t_west   :       in STD_LOGIC;
                      t_east   :       in STD_LOGIC;
                      sw_0     :       in STD_LOGIC;
                      sw_1     :       in STD_LOGIC;
                      sw_2     :       in STD_LOGIC;
                      sw_3     :       in STD_LOGIC;
                      led_array     :  out STD_LOGIC_VECTOR (7 downto 0);
                      einer, zehner, Hdt, Tsd, Z_tsd, H_Tsd: out STD_LOGIC_VECTOR(3 downto 0));
end anwendung;


architecture Behavioral of anwendung is
-- Deklaration der Signale --------------------------------------------
-- Taktsignale ---------------------------------------------------------

        signal takt_temp: STD_LOGIC_VECTOR (31 downto 0) := x"00000000";
        signal takt_temp_2: STD_LOGIC_VECTOR (31 downto 0) := x"00000000":
        signal takt_temp_3: STD_LOGIC_VECTOR (31 downto 0) := x"00000000";
        signal sec_clk: STD_LOGIC := '0';
        signal entprell_clk: STD_LOGIC := '0';
        signal ton_clk: STD_LOGIC := '0';

-- Register ------------------------------------------------------------
-- High ----------------------------------------------------------------

        signal RH : STD_LOGIC_VECTOR (3 downto 0) := "0000";
        signal RHH: STD_LOGIC_VECTOR (3 downto 0) := "1001";

-- Low -----------------------------------------------------------------
 
        signal RL : STD_LOGIC_VECTOR (3 downto 0) := "0000";
        signal RLL: STD_LOGIC_VECTOR (3 downto 0) := "1001";

-- Überträge -----------------------------------------------------------
-- Einer ---------------------------------------------------------------

        signal co_e : STD_LOGIC := '0';
      
-- Zehner --------------------------------------------------------------

        signal co_z : STD_LOGIC := '0';
 
-- Zustände ------------------------------------------------------------

     type ZUSTAENDE is (A, B, C, D, E);
       signal ZUSTAND, FOLGEZUSTAND : ZUSTAENDE;
     
begin

-- Frequenzteiler ------------------------------------------------------
-- Von 50MHz auf 1Hz ---------------------------------------------------
sek_counter : process (takt, reset, takt_temp_2)

begin
                  if reset = '1' then
                     takt_temp_2 <= x"00000000";
                  elsif rising_edge(takt) then
                        if takt_temp_2 >= 25000000
                then sec_clk <= not(sec_clk);
                takt_temp_2 <= x"00000000";
                        else takt_temp_2 <= takt_temp_2 + 1;
                        end if;
                  else
                       takt_temp_2 <= takt_temp_2;
                  end if;
end process sek_counter;

-- Von 50MHz auf 1kHz --------------------------------------------------
ton_counter : process (takt, reset, takt_temp_3)

begin
                if reset = '1' then
                   takt_temp_3 <= x"00000000";
                elsif rising_edge(takt) then
                       if takt_temp_3 >= 25000 then
                          ton_clk <= not(ton_clk);
                          takt_temp_3 <= x"00000000";
                       else
                          takt_temp_3 <= takt_temp_3 + 1;
                       end if;
                else 
           takt_temp_3 <= takt_temp_3;
                end if;
end process ton_counter;

-- Von 50MHz auf 100Hz (entprellen) ------------------------------------
entprell_counter : process (takt, reset, takt_temp)

begin
               if reset = '1' then 
             takt_temp <= x"00000000";
                  entprell_clk <= '0';
-- asynchrones Rücksetzen
               elsif rising_edge(takt) then
                     if takt_temp >= 250000 then
              -- sychrones Zaehlen
                        entprell_clk <= not(entprell_clk);
                        takt_temp <= x"00000000";
                     else
                     takt_temp <= takt_temp + 1;
                     end if;
               else
               takt_temp <= takt_temp;
               end if;
end process entprell_counter;

-- Kaskadierbare Zähler (9-0) ------------------------------------------
-- Register Low --------------------------------------------------------
counter_RL: process (sec_clk,reset,ZUSTAND,RL, RH,RHH,sw_0,sw_1,sw_2,sw_3,RLL,co_e, co_z)

begin
-- Asynchrones Rücksetzen
           if reset = '1' then RLL <= RL;
           elsif ZUSTAND = E then
                      if  (sw_3 & sw_2 & sw_1 & sw_0) >= 9  then
                          RL <= "1001";
                      else
                          RL <= sw_3 & sw_2 & sw_1 & sw_0;
                      end if;
-- Synchrone Teil mit carry_in Berücksichtigung
           elsif( rising_edge(sec_clk) and ZUSTAND = B and co_z = '0' ) then
                    if RLL = "0000" then -- Überlaufbedingung zum Rücksetzen
                            RLL <= "1001";
                            co_e <= '1';
                    else
                       co_e <= '0';
                       RLL <= RLL - 1;
                    end if;
           else RLL <= RLL; -- Erhalt des Zählerstandes
           end if;
end process counter_RL;


-- Register High -------------------------------------------------------
counter_RH: process (co_e,reset,ZUSTAND,RH,sw_0,sw_1,sw_2,sw_3,RHH,co_z)

begin
-- Asynchrones Rücksetzen
                if reset = '1' then RHH <= RH;
                elsif ZUSTAND = D then
                        if  (sw_3 & sw_2 & sw_1 & sw_0) >= 9  then
                               RH <= "1001";
                        else
                               RH <= sw_3 & sw_2 & sw_1 & sw_0;
                        end if;
-- Synchrone Teil mit carry_in Berücksichtigung
               elsif( rising_edge(co_e)and ZUSTAND = B) then
                        if RHH = "0000" and RLL = "0000" then -- Überlaufbedingung zum Rücksetzen
                           co_z <= '1';
               elsif
                      RHH = "0000" then RHH <= "1001"; --???? RHH soll bei 0 auch 0 bleiben
               else
                      RHH <= RHH - 1;
                      co_z <= '0';
               end if;
               else
               RHH <= RHH ;      -- Erhalt des Zählerstandes
            end if;
      end process counter_RH;
-- carry_out Erzeugung


-- Betriebsartenumschaltung --------------------------------------------
zustandsaktualisierung: process (entprell_clk,reset)

 begin
        if reset = '1' then
               ZUSTAND <=A;
        elsif rising_edge(entprell_clk) then
               ZUSTAND <= FOLGEZUSTAND;
        end if;

  end process zustandsaktualisierung;


-- Folgezustandsberechnung ---------------------------------------------
-- Betriebsarten:
-- B:     Normaler Count-Down-Modus
-- C:     Programmiermodus

folgezustandsberechnung: process (t_east, t_west, t_south, t_north, ZUSTAND, co_z, FOLGEZUSTAND)

 begin
       case ZUSTAND is


-- COUNT-DOWN-MODUS -------------------------------------------------------------------
               when A => if t_west = '1' then FOLGEZUSTAND <= C;
                          elsif t_east = '1' then FOLGEZUSTAND <= B;
-- Start Countdown
                          else FOLGEZUSTAND <= A;
                          end if;
               when B => if co_z = '1' then FOLGEZUSTAND <= A;
                          else FOLGEZUSTAND <= B;
                          end if;

 
-- PROGRAMMIERMODUS --------------------------------------------------------------------
                 when C => if t_west = '1' then FOLGEZUSTAND <= A;
                         elsif t_south = '1' then FOLGEZUSTAND <= E;
                         elsif t_north = '1' then FOLGEZUSTAND <= D;
                         else FOLGEZUSTAND <= C;
                         end if;
                 when D => if ZUSTAND = D then FOLGEZUSTAND <= C;
                         end if;
                 when E => if ZUSTAND = E then FOLGEZUSTAND <= C;
                         end if;
        end case;
        end process folgezustandsberechnung;

 
-- Ausgänge zuweisen ---------------------------------------------------

-- LCD-Anzeige

        einer   <= RLL;
        zehner  <= RHH;
        Hdt     <= "1111";
        Tsd     <= "1111";
        Z_tsd   <= RL;
        H_tsd   <= RH;



-- LED-Anzeige

        led_array(0) <= sw_0;
        led_array(1) <= sw_1;
        led_array(2) <= sw_2;
        led_array(3) <= sw_3;
        led_array(4) <= '1' when ZUSTAND = E else '0';
        led_array(5) <= '1' when ZUSTAND = D else '0';
        led_array(6) <= '1' when ZUSTAND = C else '0';
        led_array(7) <= '1' when ZUSTAND = B else '0';







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

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar, kannst Du mal bitte Deinen Textbaustein einstellen?

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und außerdem: Wo ist denn jetz die Testbench?

Duke

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

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

Hier isser:
Ein Design (insbesondere ein Anfängerdesign) hat genau 1 Takt, 
der immer auf dieselbe Flanke aktiv ist. 
Es gibt keinen (und schon gleich gar keinen asynchronen oder 
gar kombinatorischen) Reset.
Externe Signale werden über 2 Flipflops einsynchronisiert.
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:
                  elsif rising_edge(takt) then
:
elsif( rising_edge(co_e)and ZUSTAND = B) then
:
        elsif rising_edge(entprell_clk) then


Asynchrones und sogar kombinatorisches Rücksetzen mit nicht 
einsynchronisierten Signalen:
-- Asynchrones Rücksetzen
                if reset = '1' then RHH <= RH;
                elsif ZUSTAND = D then
                        if  (sw_3 & sw_2 & sw_1 & sw_0) >= 9  then
                               RH <= "1001";
                        else
                               RH <= sw_3 & sw_2 & sw_1 & sw_0;
                        end if;
-- Synchrone Teil mit carry_in Berücksichtigung
               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:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
:
:
        signal en_sec: std_logic := '0';  -- Enable-Signal 1 sec
        signal cnt_sec: integer range 0 to 49999999 := 0;
:
:

-- Sekunden-Enable erzeugen
process (takt) begin
       if rising_edge(takt) then
          if pre_sec < 49999999 then
             pre_sec <= pre_sec+1;
             en_sec <= '0';
          else
             pre_sec <= 0;
             en_sec <= '1';
         end if;
      end if;
end process sek_counter;

-- Verwendung des Enable Signals
process (takt) begin
   if rising_edge(takt) then -- es kann nur einen geben!
      if en_sec =n '1' then
         if (cnt_sec > 0) then 
            cnt_sec <= cnt_sec -1;
            ton_ausgeben <= '0';
         else
            cnt_sec <= '0';
            ton_ausgeben <= '1';
         end if;
      end if;
end process;

:
:

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

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht 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 ...

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Mathias Jt (mjpdx)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Mathias Jt (mjpdx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wurde notiert, danke ;-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.