Forum: FPGA, VHDL & Co. Monoflop mit Spartan 3 und VHDL


von Markus (Gast)


Lesenswert?

Hallo Leute,

ich gerade am verzweifeln. Ich versuche seit Stunden, ein Monoflop in 
VHDL zu programmieren, aber habe leider bisher keinen Erfolg. Hat jemand 
von euch sowas schon mal gemacht und kann mir vielleicht einen Beispiel 
Code geben, damit ich wenigstens die grobe Richtung weiß wo ich hin 
muss. Vielen Dank jetzt shcon mal.

Gruß Markus

von thomas (Gast)


Lesenswert?

Hmm Monoflop ... Ausgang für eine bestimmte Zeit auf High legen und dann 
kippt er von alleine wieder auf Low ...

Mein Tip: Prozess, der einen Counter hochzählt, je nach gewünschter 
Länge des High Pegels.
Wenn logisch 1 am Eingang anliegt wird der Ausgang auf 1 gesetzt und der 
Counter gestartet bis dieser den gewünschten Wert überschreitet. Ausgang 
wird wieder 0 gesetzt und Counter wird gestoppt.

Wenn Du es bis morgen nicht hinbekommst und keiner Dir ein Beispiel 
postet, dann mach ich mich mal dran ... geh jetzt aber erstmal ein wenig 
schlafen ^^

von thomas (Gast)


Lesenswert?

So, das wäre mein Vorschlag für dein Problem. Das ganze ist ein nicht 
nachtriggerbares Monoflop.
1
port(
2
  clk     : in std_logic;
3
  trigger : in std_logic;
4
  d_out   : out std_logic
5
);
6
7
8
process(clk,trigger)
9
  variable aktiv : std_logic := '0';
10
  variable counter : integer range 0 to ??? ; --such dir eine größe aus, je nach takt
11
begin
12
  if rising_edge(clk) then
13
    if trigger = '1' and aktiv = '0' then
14
      aktiv = '1';
15
      counter := ???;
16
    elsif aktiv = '1' then
17
      d_out <= '1';
18
      counter := counter - 1;
19
      if counter = 0 then
20
        aktiv := '0';
21
      end if;
22
    else
23
      d_out <= '0';
24
    end if;
25
  end if;
26
end;

von Markus (Gast)


Lesenswert?

Vielen Dank Thomas,

ich werde mich gleich mal ran machen und deinen Code ausprobieren.

Gruß Markus

von Markus (Gast)


Lesenswert?

Hallo Thomas,

hab deinen Code gerade getestet, aber tut nicht das was ich erwartet 
hätte, ich wollte z.B. auf eine Taste drücken und danach geht für eine 
bestimmte Zeit eine LED an und danach wieder aus. Aber entweder sie ist 
immer an oder geht gar nicht an. Aber dein Code müßte funktionieren, bin 
eigentlich alles Schritt für Schritt durhgegangen, naja ich versuchs 
noch etwas. Werde dann nochmal meinen Code posten.

Gruß Markus

von Mark (Gast)


Lesenswert?

Hi Markus,

bitte nicht den Code unverändert übernehmen. Und das Verhalten ist so, 
dass bei gedrückter Taste (Trigger = 1) der Ausgang für 1 Takt auf 0 
geht und dann gleich wieder auf 1. D.h. es gibt keine Flankentriggerung.
Die Variablen sind hier auch ungünstig.
Ich würde folgendes vorschlagen:

constant MONO_DELAY : integer := 20; -- Bsp.

signal cnt_q : integer range 0 to MONO_DELAY;
signal trig0_q : std_logic;
signal trig1_q : std_logic;

process(clk)
begin
   if rising_edge(clk) then
      trig0_q <= trigger;
      trig1_q <= trig0_q;

      if cnt_q > 0 then
         dout <= '1';
         cnt_q <= cnt_q -1;
      else
         dout <= '0';

         if trig0_q ='1' and trig1_q='0' then -- rising_edge trigger
            cnt_q <= MONO_DELAY;
         end if;
      end if;
   end if;
end process;

von thomas (Gast)


Lesenswert?

Guter Hinweis Mark, es lag wirklich nur an den Variablen bei mir. 
Signale drauß gemacht und schon ging es ohne Probleme.

von Gast (Gast)


Lesenswert?

Könntest auch ein RC-Kombination simulieren.

von David (Gast)


Lesenswert?

Hi, I am interested to know how trig1_q is updated in the code:

process(clk)
begin
   if rising_edge(clk) then
      trig0_q <= trigger;
      trig1_q <= trig0_q;

      if cnt_q > 0 then
         dout <= '1';
         cnt_q <= cnt_q -1;
      else
         dout <= '0';

         if trig0_q ='1' and trig1_q='0' then -- rising_edge trigger
            cnt_q <= MONO_DELAY;
         end if;
      end if;
   end if;
end process;

Thanks

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


Lesenswert?

David schrieb:
> Hi, I am interested to know how trig1_q is updated in the code:
1
   if rising_edge(clk) then
2
      trig0_q <= trigger;
3
      trig1_q <= trig0_q;
4
      :
trig1_q gets the value of trig0_q at the rising edge of clk.
With the same rising edge trig0_q gets the value of trigger.

This whole thing is a 2 bit shift register:
1
            ______  trig0_q  _____  trig1_q
2
trigger ---| D   Q|---------|D   Q|-------
3
           |      |         |     |   
4
      clk--|>_____|    clk--|>____|


You can write the above code also this way with absolutely no change in 
functionality:
1
   if rising_edge(clk) then
2
      trig1_q <= trig0_q;
3
      trig0_q <= trigger;
4
      :

von David (Gast)


Lesenswert?

Hi again,
I thought the code after the sensitivity list is sequential, therefore 
if trigger = 1 then trig0_q = 1 and triq1_q = 1.

So (if trig0_q ='1' and trig1_q='0' then) will never be true.

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


Lesenswert?

> therefore if trigger = 1 then trig0_q = 1 and triq1_q = 1.
This assumption is wrong.

The process is calculated each time clk changes its state. And only if 
the change is a rising edge, the value of the signals will be evaluated. 
After finishing this process the last assigned value will be transferred 
to the signal. Throughout the evaluation the value of signal itself 
doesn't change.

So if trig0_q = 1 and triq1_q = 1 and trigger is 0, after processing the 
signals will be trig0_q = 0 and triq1_q = 1. With the next rising edge 
of clk this will change to trig0_q = 0 and triq1_q = 0.
So, the behaviour is like a shift register.

> therefore if trigger = 1 then trig0_q = 1 and triq1_q = 1.
Variables change their value immediately with the assignment.
Singals change their value after evaluating the whole process.

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.