www.mikrocontroller.net

Forum: FPGA, VHDL & Co. VHDL Text für die Ertönung eines 1 kHz Tons


Autor: Slam Jam (slamjam)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich kenne mich nicht gut aus mit VHDL und bin fast fertig mit meiner 
Synthesis meines VHDL Textes, bis mir grad einfiel, dass ich den Teil 
mit der Ertönung eines 1kHz Tons für eine halbe Sekunde beim Drücken 
einer Taste vergessen habe.

Es handelt sich um ein Xilinx Board der Reihe Spartan3 mit einem 
XC3S700A!

Ich bin für jede Hilfe dankbar!

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zwei Zähler, einen der 2kHz macht und damit Deinen Piepser toggelt und 
den zweiten, der nach einer halben Sekunde den ersten Zähler das enable 
wegnimmt.

Duke

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Platzsparender kann man das Ganze auch in ein paar SRL16E integrieren.

Beispiele hierfür sind auf dieser PDF (Stichwort: Puls-Generator):
http://www.xilinx.com/support/documentation/white_...

Gruß Marc

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

Bewertung
0 lesenswert
nicht lesenswert
> Platzsparender ...
Bei Teilern von z.B. 50MHz nach 2kHz (=25000) und dann von 1ms nach 
500ms (=500) würde ich das so nicht sagen. Das wird für einen kleinen 
Teiler von 260 in dem WP271 in Frage gestellt. Allerdings sei so eine 
Schieberegister-Lösung eventuell einfacher und praktischer:
This solution is larger than the counter-based pulse generator, 
but the simplicity of this technique makes it practical.

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast Recht, der Multi-stage Divider im Beispiel ist vorallem für 
kleine Divisionen gut geeignet. Da hier aber nur ein Summer angesteuert 
werden soll und Synkronität mit den 50MHz am Ausgang vernachlässigt 
werden kann, ist es möglich diesen so umzuformen, dass er in diese 
Anwendung genau hineinpasst.
Dein Zitat stammt übrigens aus dem Hot-Counter (viele FF in einer 
Schleife). Den meinte ich nicht.

Um auf dein Beispiel einzugehen:

 50 MHz / 25  =>  2 SRL16
  2 MHz / 10  =>  1 SRL16
200 KHz / 10  =>  1 SRL16
 20 KHz / 10  =>  1 SRL16
  2 KHz

Beispiel-Code:
entity Div_25k is
    Port ( CLK_IN : in  STD_LOGIC;
           CLK_OUT : buffer STD_LOGIC);
end Div_25k;

architecture Behavioral of Div_25k is
  signal Stage_1 : std_logic_vector(24 downto 0) := "0000000000000000000000001";
  signal Stage_2 : std_logic_vector(9 downto 0) := "0000011111";
  signal Stage_3 : std_logic_vector(9 downto 0) := "0000011111";
  signal Stage_4 : std_logic_vector(9 downto 0) := "0000011111";
begin

  process(CLK_IN,Stage_1(24),Stage_2(9),Stage_3(9))
  begin
    if rising_edge(CLK_IN) then
      Stage_1 <= Stage_1(23 downto 0) & Stage_1(24);
    end if;
    if rising_edge(Stage_1(24)) then
      Stage_2 <= Stage_2(8 downto 0) & Stage_2(9);
    end if;
    if rising_edge(Stage_2(9)) then
      Stage_3 <= Stage_3(8 downto 0) & Stage_3(9);
    end if;
    if rising_edge(Stage_3(9)) then
      Stage_4 <= Stage_4(8 downto 0) & Stage_4(9);
    end if;
  end process;
  
  CLK_OUT <= Stage_4(9);

end Behavioral;

Verbrauch: 5 SRL16 ~ 4 SLICEs nach Synthese (natürlich mit Warnung auf 
skew)

Hab mal probehalber den selben Divider mit einen normalen Counter ( + 
Compare ) syntetisiert und kahm allein hierfür auf 13 SLICEs.

Der Divider von 1 KHz auf 500 Hz braucht in beiden Fällen nur 1 LUT.

Platzsparender ... ?
Antwort: JA, man muss aber bedenken, dass diese Art von Divider nicht
             für alles geeignet ist und auch einige Probleme mit sich
             bringen kann.

Ob man das Ganze noch als einfach und praktisch ansehen kann, ist die 
andere Frage ;-)

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

Bewertung
0 lesenswert
nicht lesenswert
> Ob man das Ganze noch als einfach und praktisch ansehen kann, ist die
> andere Frage ;-)
So einen asynchronen Zähler würde ich bestenfalls machen, wenn ich 
wirklich kein einziges FF mehr freihabe.. :-o


> Der Divider von 1 KHz auf 500 Hz braucht in beiden Fällen nur 1 LUT.
Es ging ursprünglich um 1ms (= 1kHz) und 500ms (= Piepdauer)  ;-)

Autor: Slam Jam (slamjam)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Danke erst mal für die Tips!

Ich weiß jetzt nicht genau, ob ich das Prellen meines Schalters (in dem 
Fall der Taste "south") mitberücksichtigen muß. Die Prellzeit beträgt 
200ms.


Für das Prellen habe ich:



FOLGEZUSTANDSBERECHNUNG: process (taste,ZUSTAND)
  begin
    case ZUSTAND is
    when A => if A = '1' THEN FOLGEZUSTAND <= B;
      else FOLGEZUSTAND <= A;
      end if ;
      F <= '0', ci <= '0';
    when B => if co = '1' THEN FOLGEZUSTAND <= C;
      else FOLGEZUSTAND <= B;
      end if;
      F <= '0', ci <= '1';
    when C => THEN FOLGEZUSTAND <= D;
      F <= '1', ci <= '1';
    when D => A = '0' THEN FOLGEZUSTAND <= E;
      else FOLGEZUSTAND <= D;
      end if ;
      F <= '0', ci <= '0';
    when E => if co = '1' THEN FOLGEZUSTAND <= F;
      else FOLGEZUSTAND <= E;
      end if ;
      F <= '0', ci <= '1';
    when F => THEN FOLGEZUSTAND <= A;
      F <= '0',ci <= '1';
    end case;
  end process FOLGEZUSTANDSBERECHNUNG;

FOLGEZUSTANDSBERECHNUNG: process (taste,ZUSTAND)
  begin
    case ZUSTAND is
    when A => if B = '1' THEN FOLGEZUSTAND <= B;
      else FOLGEZUSTAND <= A;
      end if ;
      F <= '0', ci <= '0';
    when B => if co = '1' THEN FOLGEZUSTAND <= C;
      else FOLGEZUSTAND <= B;
      end if;
      F <= '0', ci <= '1';
    when C => THEN FOLGEZUSTAND <= D;
      F <= '1', ci <= '1';
    when D => B = '0' THEN FOLGEZUSTAND <= E;
      else FOLGEZUSTAND <= D;
      end if ;
      F <= '0', ci <= '0';
    when E => if co = '1' THEN FOLGEZUSTAND <= F;
      else FOLGEZUSTAND <= E;
      end if ;
      F <= '0', ci <= '1';
    when F => THEN FOLGEZUSTAND <= A;
      F <= '0',ci <= '1';
    end case;
  end process FOLGEZUSTANDSBERECHNUNG;


ZUSTANDSAUSGABE: process (ZUSTAND)
  begin
    CASE ZUSTAND is
      when A => STATE <= "000";
      when B => STATE <= "001";
      when C => STATE <= "010";
      when D => STATE <= "100";
      when E => STATE <= "101";
      when F => STATE <= "110";
    end case;
  end process ZUSTANDSAUSGABE;


Irgendwelche Anmerkungen oder Tips?

 Wie gesagt soll beim Drücken der Taste south für eine halbe Sekunde ein 
1kHz-Ton ertönen.

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

Bewertung
0 lesenswert
nicht lesenswert
 FOLGEZUSTANDSBERECHNUNG: process (taste,ZUSTAND)
Unvollständige Sensitivliste, B und co fehlen --> fehlerhafte Simulation

Aber das ist nicht so schlimm. Schlimm ist der Aufwand, den du treibst. 
Eine Abfrage auf eine steigende bzw. fallende Flanke geht ganz einfach 
mit einem Schieberegister:
http://www.lothar-miller.de/s9y/categories/5-Entprellung

Und die Geschichte mit dem Debuggen über
ZUSTANDSAUSGABE: process (ZUSTAND)
geht auch wesentlich kompakter. Siehe 
http://www.lothar-miller.de/s9y/categories/37-FSM
Also einfach so:
   STATE  <= std_logic_vector(to_unsigned(ZUSTAND'pos(ZUSTAND),3));

Dazu solltest du aber die
use IEEE.numeric_std.ALL;
verwenden, sonst braucht du andere Umwandlungsroutinen von Integer nach 
Vektor.

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Es ging ursprünglich um 1ms (= 1kHz) und 500ms (= Piepdauer)  ;-)

Misst, da haste mich erwicht XD
Hast aber recht, selbst ich verwende solche Sachen nur in 
Ausnahmefällen.

Verkehrt ist es sicherlich nicht, sowas im Hinterkopf zu haben ^_^

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

Bewertung
0 lesenswert
nicht lesenswert
> Wie gesagt soll beim Drücken der Taste south für eine halbe Sekunde
> ein 1kHz-Ton ertönen.
 signal count500us : integer range 0 to 24999; -- bei 50MHz : pro halbe ms --> 25000 Takte
 signal count500ms : integer range 0 to 1000;   

 process begin
    wait until rising_edge(clk);
    if (count500us < 24999) then 
       count500us <= count500us+1; 
    else 
       if (count500ms < 1000) then
           beeper <= not beeper;
           count500ms <= count500ms+1;
       else
           beeper <= '0';
       end if;
    end if;
    if taster_flanke = '1' then 
       count500us <= 0;
       count500ms <= 0; 
    end if;
 end process;

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Setz noch nach dieser Zeile:
if (count500ms < 1000) then
diese Zeile ein:
  count500us <= 0;
Dann dürfte es funktionieren (ein Summer mit 25 MHz funktioniert 
schlecht)


bitte nicht böse sein

Autor: Slam Jam (slamjam)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!


Ich hab deins so übernommen und dann so hingeschrieben:

signal count500us : std_logic_vector range 0 to 24999; -- bei 50MHz : 
pro halbe ms --> 25000 Takte
signal count500ms : std_logic_vector range 0 to 1000;

 process begin
    wait until rising_edge(clk);
    if (count500us < 24999) then
       count500us <= count500us+1;
    else
       if (count500ms < 1000) then
           beeper <= not beeper;
           count500ms <= count500ms+1;
       else
           beeper <= '0';
       end if;
    end if;
    if bcd_south = '1' then
       count500us <= 0;
       count500ms <= 0;
    end if;
 end process;




Synthesize war in Ordnung, nur ein paar Warnungen!


Vielen herzlichen Dank

Autor: Slam Jam (slamjam)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab den Kommentar von Marc erst nach meinem letzten Kommentar gelesen!

Ist das so richtig, meine Marc's Aussage?

Autor: Slam Jam (slamjam)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
signal count500us : std_logic_vector integer range 0 to 24999; -- bei 
50MHz : pro halbe ms --> 25000 Takte
 signal count500ms : std_logic_vector integer range 0 to 1000;

 process begin
    wait until rising_edge(clk);
    if (count500us < 24999) then
       count500us <= count500us+1;
    else
       if (count500ms < 1000) then
           count500us <= 0;
           beeper <= not beeper;
           count500ms <= count500ms+1;
       else
           beeper <= '0';
       end if;
    end if;
    if bcd_south = '1' then
       count500us <= 0;
       count500ms <= 0;
    end if;
 end process;


So in etwa?

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
müsste jetzt so richtig sein

Grüße Mark

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

Bewertung
0 lesenswert
nicht lesenswert
@ Slam Jam
> Ich hab deins so übernommen
Hast du jetzt tatsächlich anderthalb Tage gewartet, bis einer eine 
Lösung hinkritzelt?  :-o

> Ist das so richtig, meine Marc's Aussage?
Wird schon stimmen...  :-o
Aber ich denke, du solltest das einfach mal so ein wenig mental 
nachvollziehen. Warum meint Marc wohl, dass es sinnvoll wäre, beim 
Überlauf den Zähler auch mal zurückzusetzen?

> Synthesize war in Ordnung, nur ein paar Warnungen!
Ja klar, du verwendest ja auch die alten Synopsys-Libs.

@ Marc
Du hast recht, die Zeile fehlt, aber das stimmt nicht:
> ein Summer mit 25 MHz funktioniert schlecht
Denn es ist komplizierter.
Der Zähler count500us wird als 15-Bit Zähler realisiert. Also würde von 
25000 bis 32767 der Beeper mit jedem Takt toggeln, dann aber von 0 bis 
24999 wieder Ruhe geben. Weil bis dahin aber schon längst der count500ms 
fertig ist, ist fast schlagartig nach dem Piepsanfang schon wieder 
Ruhe...

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nicht ganz...

Auch wenn hier ein 15-bit Counter drin steckt, so wird count500us nur 
dann incrementiert, wenn
> count500us < 24999
ist.

d.h.

dein Code wird, sobalt taster_flanke auf '0' fällt, count500us auf 24999 
raufzählen und dann, sobalt er da angekommen ist, den Beeper 1000 mal 
mit voller Geschwindigkeit toggeln.
Eben bis count500ms die 1000 erreicht hat.

Danach ist Ruhe.

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

Bewertung
0 lesenswert
nicht lesenswert
> Danach ist Ruhe.
Gut so ;-)

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
X-D

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.