Op 6 november 2007 16:04:35 schreef free_electron:
in verilog dan maar :p



module debounce(input clock,reset,in,
                output reg out);

parameter threshold = 4'd9; // deze mag niet hoger zijn dan 4 bit ! ik zet hem op 9 voorloopig
reg [4:0] bounce;

always @(posedge clk,posedge reset)
if (reset) begin
   bounce <=4'b0;
   out <=0;
   end
else begin
   if (in and (bounce <>threshold)) bounce <= bounce +1;
   if (!in and (bounce <>0)) bounce <= bounce-1;
   if (bounce=0) out <=0;
   if (bounce=threshold) out <=1;
end
endmodule

dit ding is een symmetrische debouncer.
het is eigenlijk niks anders dan een up/down counter die gelimiteerd is tussen '0' en de waarde van 'threshold'

bij elke clockpuls wordt de ingang gesampled. als die hoog is gaat de teller omhoog. als di laag is gaat de teller omlaag.
als de teller nul bereikt schakelt de uitgang laag.
als de teller 'threshold' bereikt gaat de uitgang hoog.

je kan de 'gevoeligheid' instellen door de waarde van threshold aan te passen

Verdikkie Free dat is een leuke methode daar. :)

je weg en weer looplichtje :

Op 6 november 2007 16:34:11 schreef MagicBox:
[...]

Verdikkie Free dat is een leuke methode daar. :)

het probleem van de meeste debouncers is dat ze maar reageren op de eerste edge alleen. bij het terug verbreken van het conatct ontdenderen ze niet. en dan krijg je vodden.
boveniden gaat ook de pulsduur om zeep.

stel je hebt dit soort signaal


  _   ____   _   ________________________   _     __
_| |_|    |_| |_|                        |_| |___|  |___

de meeste debouncers maken er dit van


  _   ____   _   ____________________   _     ___
_| |_|    |_| |_|                    |_| |___|   |___
                _____________________           _
_______________|                     |_________| |____

de counter methode maakt er dit van


  _   ____   _   _________________   _      ___
_| |_|    |_| |_|                 |_| |____|   |___
           ________________________________   
__________|                                |______

tis moeilijk te tekenen maar dat ding 'integreert' eigenlijk de dendering. als je een dendertrein bekijkt dan zie je dat daar een bepaald verloop in zit.
de pulslengte wordt uitgemiddeld.

schakelbare 2 deler


module div2 (input clk,reset,select,
             output out);
reg ticktock;

always @(posedge clk,posedge reset)
   if (reset) ticktock <=0;
   else ticktock <= !ticktock;

always 
    if (select) out = ticktock;
    else out = clk; 

endmodule

Op 6 november 2007 16:47:39 schreef free_electron:
schakelbare 2 deler

Mwhaaaaaah, de clk in de combinatoriek gebruiken, hij doet het weer! Ik vind het nog steeds een slechte gewoonte. Ik doe het zo:


module div2 (input clk,reset,select,
             output out);
reg div2_en;

always @(posedge clk,posedge rst)
   if (rst) div2_en <= 0;
   else div2_en <= !div2_en;

always @(posedge clk,posedge rst)
    if (rst) out <= 0;
    else begin
       // doe hier alles wat op clk moet
       if (div2_en) begin
           //doe hier alles wat op clk/2 moet;\
       end
    end
endmodule

ipv

Je hebt nu maar een clk waar alle FFs op lopen.

Kan je dat eens schrijven in VHDL versta geen Virolog

Hmm, ik hoop dat je dat uitgang signaal dat niet gebruikt als klok voor andere flip-flops, anders maakt het natuurlijk nog niks uit of je nu synchroon of asynchroon de klok deelt.

Als je een klok wil vertragen gebruik je of meerdere klok-domeinen ( Moet je wel weten wat je doet, en alles synchronizeren), of je gebruikt een klok enable.

Dit voorkomt ook al die mooie gated-clock waarschuwingen van je synthesizer.

Op 6 november 2007 16:44:05 schreef free_electron:
[...]

het probleem van de meeste debouncers is dat ze maar reageren op de eerste edge alleen. bij het terug verbreken van het conatct ontdenderen ze niet. en dan krijg je vodden.
boveniden gaat ook de pulsduur om zeep.

De code die ik postte doet precies dat. Ontdenderen bij de opgaande flank en ontdenderen bij de neergaande flank.
De aangevoerde klok moet ongeveer 1 kHz zijn.

Bart

Kan je eens een ontdender routine schrijven door gebruik van een Timer want ik moet starten van een clock van 50MHz en het ontdenderen is 20 ms

Ik heb al zitten zoeken hoe je dat moet doen maar vind het niet direct

Ik weet dat we bij de stijgende flank een timer moeten starten en deze stoppen als we een dalende flank detecteren maar hoe doe je dat in VHDL?

Waar moet ik nu eigenlijk de pinnen programmeren van die drukknop, die fysieke pinnen weet ik wel

Graag een berichtje terug

Kan je ook eens zeggen hoe ik 2 snelheden kan maken als je drukt op eerste knopje moet hij naar links lopen en met ander knopje naar rechts?

Gewoon principe van bvb een 4 LEDS looplicht

Op 6 november 2007 20:26:53 schreef Stephane1976:
Kan je dat eens schrijven in VHDL versta geen Virolog

blijkbaar versta je geen vhdl ook ...
50MHz en je moet 20mS kunnen vangen. 1mS is 1 khz. 20 mS is dus 50 Hz ... dus je hebt al in ieder geval een 1 miljoen deler nodig ....
je zou dan een 2 teller kunnen maken. 00 0`1 doen niks maar 10 is uitgang hoog .. en 00 is uitgang laag.

dus met 2 flifplops ben je er.

je probleme heeft niks te maken met verilog of vhdl. desnoods maak je dat met TTL of CMOS citjes , een schema of met losse transistoren als het moet. het punt is dat je de opgave niet snapt en zolang je niet begrijpt wat je moet doen kan je het niet in code gieten. eerst TTL en dan VHDL... tzal veel beter gaan.

analyseer de opgave eens.

uw 20mS heb ik al opgelost.

een debouncer heb ik ook al gegeven. ik heb uitgelegd hoe je met een up.down counter een debouncer kan maken.

je weg en weer lopen : gebruik een drukknop om een t-flipflop te laten omkippen. afhankelijk van de stand van die t-flipflop schakel je ene counter in upcount of downcount. en 2 snelheden is kwestie van de clocksnelheid van die counter aan te passen.

Op 6 november 2007 20:26:53 schreef Stephane1976:
Kan je dat eens schrijven in VHDL versta geen Virolog

In VHDL is het bijna precies zo. Je moet alleen de "always @" vervangen door een


process(clk, rst) begin
  if (rst='1') bla bla
  elsif (clk'event and clk='1') bla bla
  end if;
end process;

pfew, m'n VHDL is nogal stroef na een paar jaar :-)

Verilog en VHDL verschillen niet zoveel als je het principe van FE's schakeling snapt.

Dat blijkt ook uit uw signatuur ;)

Slordig. Maar scherp opgelet!

Tot mijn grote verbazing heb ik laatst een projectje gedaan waarbij ik gewoon op 1kHz de schakelaar sample, en gewoon op iedere (opgaande) flank reageer. Aangezien er niet alleen een ledje aan en uit moest, maar een teller door de gebruiker op de juiste waarde moet worden ingesteld, is het voor de gebruiker belangrijk dat ie niet 2, 3 of 4 flanken ziet als je op het knopje drukt. Het lijkt toch prima te werken. :-) Kortom ontdenderen was niet nodig. Kost alleen maar code. Doen we wel als het WEL nodig is...

kost geen code ... dendersysteem past in 2 of 3 LE's... als je er 15000 hebt. no problemo...

Op 6 november 2007 22:01:35 schreef Stephane1976:
Bart

Kan je eens een ontdender routine schrijven door gebruik van een Timer want ik moet starten van een clock van 50MHz en het ontdenderen is 20 ms

Ik heb al zitten zoeken hoe je dat moet doen maar vind het niet direct

Ik weet dat we bij de stijgende flank een timer moeten starten en deze stoppen als we een dalende flank detecteren maar hoe doe je dat in VHDL?

Waar moet ik nu eigenlijk de pinnen programmeren van die drukknop, die fysieke pinnen weet ik wel

Graag een berichtje terug

Kan je ook eens zeggen hoe ik 2 snelheden kan maken als je drukt op eerste knopje moet hij naar links lopen en met ander knopje naar rechts?

Gewoon principe van bvb een 4 LEDS looplicht

Wat je het beste kunt maken is een clokced event. In de kop staat dan altijd:

IF sample'EVENT and sample = '1' THEN

Daaronder kun je alles plaatsen wat je maar wilt.
In het geval van een deler vanuit 50 MHz, kun je het beste een teller ontwerpen zoals je zou doen in software. Je wilt dan bijv. naar 1 kHz.
Je wilt de klok dus delen door 50000.

Dat is dus een 16 bits teller die je elke klok verhoogd. Op 0 maak je de uigang laag en op 25000 maak je de uitgang hoog. Op 50000 reset je de teller.

Die module of process kun je dan koppelen aan de ontdender shakeling.

Wat de voorbeeldcode doet is reageren op de ingang.
Als de ingang '1' is dan wordt een teller verhoogd. Als de waarde van de teller bijv. 15 of 20 is (na 20ms dus) dan wordt de ingang doorgezet.
De truuk is om de teller door te laten lopen tot het dubbele van die waarde, tot 30 of 40 dus.
Als de ingang '0' is wordt de teller weer verlaagd.
Als de tellerwaarde onder de 15 of 20 komt, dan wordt e uitgang '0'.

Je hebt dus 2 modules nodig:

1. om je klok te delen naar een frequentie van 1 kHz.
2. een teller om de ingang te ontdenderen.

Je hoeft dus geen timer te starten op de opgaande flank. Je 'sampelt' 1000x per seconde de ingang en zo bepaal je of de schakelaar gedrukt is of niet.

De werking is hetzelfde.

Voor je uiteindelijke schakeling (looplicht) heb je nog wel wat meer modules nodig. Als je met modules werkt, dan hoef je de code maar eenmaal te schrijven.

Even een oud topic oprakelen, maar ik ben me in de VHDL aan het storten, en ik kon deze even niet volgen:

Op 6 november 2007 13:58:48 schreef Bart Hiddink:


    IF ffa > 0 THEN
      ffa <= ffa - 1 ;
    ELSIF ffa > 15 THEN -- de_bounce_length = 16
      ffa <= 31; -- de_bounce_lenght *2
    END IF;

Na die eerste IF komt hij toch alleen bij de ELSIF op het moment dat ffa > 0 niet waar is? Dus dan heeft die ffa > 15 conditie toch geen enkele nut, immers, als ffa > 0 niet waar is, dan moet ffa wel kleiner-of-gelijk zijn aan 0.

Ik zie overigens wel in waarom de code gewoon werkt * , ben zelfs niet helemaal zeker van de bedoeling van die stuk code wat m.i. nooit uitgevoerd zal worden. Een soort hysterese inbouwen ofzo? Iemand die mij dit kan uitleggen? (Bart zelf??)

edit
* Nee, ik zie op het eind de conditie


IF ffa > 15 THEN -- de_bounce_length = 15
	out_put <= '1';
ELSE
	out_put <= '0';
END IF;

dus hij kan alsnog gaan klapperen. Die rare ELSIF zal dus toch iets moeten gaan doen lijkt het, maar ik heb het gevoel dat dit stuk code niet helemaal zuiver is.

zondagavond-schoppie


IF sample'EVENT and sample = '1' THEN
	IF in_put = '1' THEN
		IF ffa < 31 THEN -- de_bounce_length*2
			ffa <= ffa + 1 ;
		END IF;
	ELSE
		IF ffa > 0 THEN
			ffa <= ffa - 1 ;
		ELSIF ffa > 15 THEN -- de_bounce_length = 16
			ffa <= 31; -- de_bounce_lenght *2
		END IF;
	END IF;
END IF;

als de ingang hoog is : en de teller is kleinre dan 31 : tel op.
die teller loopt dus tot 31.

als deingang laag is:
als de teller groter is dan 0 : aftellen.
als de teller groter is dan 15 .. laden met 31 ...

daar is inderdaad iets niet juist ...
da werkt niet.

Hm, gelukkig; ben ik dus toch niet gek. (Nee, niet inkoppen ;)) Ik heb inmiddels wat herschreven, maar vind het er nog niet optimaal uitzien na synthese.

Free, ik zou jouw code graag met de RTL viewer bekijken, maar krijg errors bij het compilen en kan zelf geen Verilog:

Error (10170): Verilog HDL syntax error at temp_debounce_test.v(13) near text "and";  expecting ")", or "?", or binary operator
Error (10170): Verilog HDL syntax error at temp_debounce_test.v(14) near text "and";  expecting ")", or "?", or binary operator
Error (10170): Verilog HDL syntax error at temp_debounce_test.v(15) near text "="
Error (10170): Verilog HDL syntax error at temp_debounce_test.v(16) near text "="

[Bericht gewijzigd door Jochem op (65%)]

verdikke. ik zat zeker nog half te slapen ..



module debounce(input clock,reset,in,
                output reg out);

parameter threshold = 4'd9; // deze mag niet hoger zijn dan 4 bit ! ik zet hem op 9 voorloopig
reg [4:0] bounce;

always @(posedge clk,posedge reset)
if (reset) begin
   bounce <=4'b0;
   out <=0;
   end
else begin
   if (in & (bounce <>threshold)) bounce <= bounce +1;
   if (!in & (bounce <>0)) bounce <= bounce-1;
   if (bounce=0) out <=0;
   if (bounce=threshold) out <=1;
end
endmodule

vervang die 'and' door & en tis opgelost

Ik kwam toevallig in dit topic terecht en heb geen kennis van VHDL. Ik gebruik al wel een tijdje heel succesvol een debounce algorithme wat is afgeleid uit dit artikel pagina 21. Roep gewoon debounce aan in een loop met 5ms vertraging, dit geeft een responsetijd van 50 a 60 ms. Je kunt in kritische gevallen ook een interrupt genereren die elke zoveel ms een check doet en actie onderneemt als er een toets is ingedrukt.

@animal64 : we zijn dus wel met hardware bezig he ... geen software ! Dit draait niet op een processor maar is gemaakt in hardware

je kan om te beginnen geen loops maken. alles gebeurt simultaan. tis een gans andere wereld.

funny, ik vond het RTL resultaat van die VHDL-code van mij (aangepaste versie van het idee van bart, lijkt nu behoorlijk op dat van jou free) een beetje groot en onhandig eruit zien, maar ik heb nu die verilog code werkend (moest nog wat erui vissen, maar lijkt erop dat verilog geen <> kent, maar != wel) en de resultaten zijn praktisch gelijk aan elkaar

Op 8 november 2007 16:15:58 schreef free_electron:
kost geen code ... dendersysteem past in 2 of 3 LE's... als je er 15000 hebt. no problemo...

Dat geldt dus niet voor de code zoals jij 'm gaf... daarom dacht ik dat mijn VHDL code omslachtig was... ik heb zeker 10 LE's, maar jij dus ook blijkt :)

het hangt er vanaf hoe groot je de teller maakt en wat hoeveel flipflops en luts er in ene ld zitten natuurlijk.