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!
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
> 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:
1
This solution is larger than the counter-based pulse generator,
2
but the simplicity of this technique makes it practical.
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:
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 ;-)
> 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) ;-)
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.
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:
> 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 ^_^
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
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?
@ 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...
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.