Forum: FPGA, VHDL & Co. VHDL Problem mit IF


von Kaffeetasse (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich bin noch relativ neu im Thema VHDL und habe offenbar ein Problem mit 
der IF Anweisung. Mein Erzeugter Code sieht folgendermaßen aus:

LIBRARY IEEE ;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL ;
USE IEEE.STD_LOGIC_UNSIGNED.ALL ;

ENTITY ampel IS
PORT (r: OUT STD_LOGIC;
      ge: OUT STD_LOGIC;
      g: OUT STD_LOGIC;
      q_a: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
      stsig: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
      clk: IN STD_LOGIC);
END ampel;

ARCHITECTURE behav OF ampel IS
BEGIN

  p1 : PROCESS (clk, stsig)
  BEGIN

    IF (clk'EVENT AND clk'LAST_VALUE='0' AND clk='1') THEN
    ELSIF (stsig<="0000") THEN r<='0'; ge<='0'; g<='0';
    ELSIF (stsig<="0001") THEN r<='1'; ge<='0'; g<='0';
    ELSIF (stsig<="0010") THEN r<='1'; ge<='1'; g<='0';
    ELSIF (stsig<="0011") THEN r<='0'; ge<='0'; g<='1';
    ELSIF (stsig<="0100") THEN r<='0'; ge<='1'; g<='0';
    ELSIF (stsig<="0101" AND q_a<="1001") THEN r<='0'; ge<='1'; g<='0';
    ELSIF (stsig<="0101" AND q_a<="0000") THEN r<='0'; ge<='0'; g<='0';
    END IF;

  END PROCESS p1 ;

END behav;

Dieser funktioniert soweit auch in der Simulation mit ModelSim bis auf 
die letzten beiden ELSIF-Anweisungen in denen das g-Signale je nach Wert 
des q_a Signals umgeschalten werden soll. Das Problem ist das "g" 
einfach auf '1' bleibt und das Umschalten nicht funktioniert (siehe 
Anhang Bild)....

Folgende Force File verwende ich:
force clk 0  0 ns, 1 100 ns -repeat 200 ns;
force stsig 2#0000 0;
force stsig 2#0001 500;
force stsig 2#0010 1000;
force stsig 2#0011 1500;
force stsig 2#0100 2000;
force stsig 2#0000 2400;
force stsig 2#0101 3000;
force q_a 2#0000 0;
force q_a 2#1001 3000;
force q_a 2#0000 3500;
force q_a 2#1001 4000;
force q_a 2#0000 4500;

Hat evtl. jemand eine Idee woran das liegen könnte? Offenbar 
funktioniert die "AND"-Verknüpfung innerhalb der ELSIF nicht!?

Vielen Dank!

LG K.

von dden (Gast)


Lesenswert?

von demhier mal abgesehen
-----------------------------------------------------------
 IF (clk'EVENT AND clk'LAST_VALUE='0' AND clk='1') THEN

???? und was machst du mit der clock hier ????

    ELSIF (stsig<="0000") THEN r<='0'; ge<='0'; g<='0';
-----------------------------------------------------------
hast du eine if abfrage kleiner =, wie soll das so funktionieren?
probiers mal mit einem case statment in der clock
also

if rising_edge(clk) then
  case xy is
    when "0000" =>
      r<='1';
    when "" =>
    when others =>
  end case;
end if;

von Kaffeetasse (Gast)


Lesenswert?

@dden
Also wenn ich deine antwort richtig verstehe meinst du mit "kleiner =" 
das: "<="...
ich verstehe aber in diesem fall eine Wertzuweisung für Signalpegel (<=) 
darunter....
diese Zeile:
"IF (clk'EVENT AND clk'LAST_VALUE='0' AND clk='1')"
soll sicherstellen das immer wenn clk-signal von low auf high wechselt 
das darunter stehende abgearbeitet werden soll...
das gibt funktioniert auch alles wie geschrieben mein prob liegt hier:
    ELSIF (stsig<="0101" AND q_a<="1001") THEN r<='0'; ge<='1'; g<='0';
    ELSIF (stsig<="0101" AND q_a<="0000") THEN r<='0'; ge<='0'; g<='0';

...thx...

von dden (Gast)


Lesenswert?

also das deine simulation funktioniert liegt daran das du stsig mit in 
die sensitive liste aufgenommen hast, das mit dem clk ist heutzutage ein 
eher seltenes konstrukt, da du die IEEE.STD_LOGIC_1164 eingebunden hast 
nutze doch einfach die rising_edge funktion.
Und sowas hier kann nicht funktionieren
  IF (clk'EVENT AND clk'LAST_VALUE='0' AND clk='1') THEN
    >>>> hier ist die clk action <<<<
  ELSIF xxx then

  end if;

In einer IF THEN abfrage kannste nix zuweisen!

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


Lesenswert?

dden schrieb:
> von demhier mal abgesehen
> -----------------------------------------------------------
>  IF (clk'EVENT AND clk'LAST_VALUE='0' AND clk='1') THEN
> ???? und was machst du mit der clock hier ????
Andere schreiben rising_edge() statt dessen...

dden schrieb:
> Und sowas hier kann nicht funktionieren
>   IF (clk'EVENT AND clk'LAST_VALUE='0' AND clk='1') THEN
>     >>>> hier ist die clk action <<<<
>   ELSIF xxx then
Das ist auch schlichtweg falsch, denn in der eigentlichen Taktabfrage 
wird nichts gemacht:
1
IF (clk'EVENT AND clk'LAST_VALUE='0' AND clk='1') THEN
2
 -- nichts zu tun hier?
3
ELSIF (stsig<="0000") THEN r<='0'; ge<='0'; g<='0';
4
ELSIF (stsig<="0001") THEN r<='1'; ge<='0'; g<='0';
Das erste elsif sollte wohl ein if sein...

Kaffeetasse schrieb:
> Folgende Force File verwende ich:
Du kannst doch VHDL. Warum schreibst du nicht einfach eine 
herstellerunabhängige Testbench, statt diese krude ModelSim 
Force-Geschichte zu nehmen?



Leute, nehmt bitte die [ vhdl ] und [ /vhdl ] Tags um den VHDL Quelltext 
(ohne die Leerzeichen in den Klammern), dann wird der VHDL-Text sinnvoll 
formatiert und eingefärbt.

: Bearbeitet durch Moderator
von Kaffeetasse (Gast)


Lesenswert?

@dden
das heist "<=" ist falsch? könnte man da stattdessen schreiben 
stsig="XXXX"???
ich hatte angedacht die ganzen ELSIF-Funktionen als "clk action" zu 
schreiben... das geht also auch nicht ???

ich hab meien code jz so abgeändert:
ARCHITECTURE behav OF ampel IS
BEGIN

  p1 : PROCESS (clk)
  BEGIN

    IF (clk'EVENT AND clk'LAST_VALUE='0' AND clk='1') THEN
    ELSIF (stsig="0000") THEN r<='0'; ge<='0'; g<='0';
    ELSIF (stsig="0001") THEN r<='1'; ge<='0'; g<='0';
    ELSIF (stsig="0010") THEN r<='1'; ge<='1'; g<='0';
    ELSIF (stsig="0011") THEN r<='0'; ge<='0'; g<='1';
    ELSIF (stsig="0100") THEN r<='0'; ge<='1'; g<='0';
    ELSIF (stsig="0101" AND q_a="1001") THEN r<='0'; ge<='1'; g<='0';
    ELSIF (stsig="0101" AND q_a="0000") THEN r<='0'; ge<='0'; g<='0';
    END IF;

  END PROCESS p1 ;

END behav;

jz simuliert es zumindest so wie es soll - also es funktioniert...
ist das fachlich trotzdem falsch???


zum clk, meinst du so:

 RISING_EDGE(clk) THEN XXX ???

...thx...

von dden (Gast)


Lesenswert?

Sorry Lothar,
wollte im zweiten Bsp. eigentlich ausdrücken das das mit dem elsif nicht 
funktionieren kann und in die if rising_edge(clk) kein else welcher form 
auch immer darf.
Trotzdem hat er eine eher unlogische abfrage von stsig.
Nochmal mein vorschlag stattdessen:
vhdl
if rising_edge(clk) then
  case stsig is
    when "0000" =>
      r<='1';
    when "0101" =>
      if q_a="0000" then
        r<='0';
        ge<='0';
        g<='0';
      elsif q_a="0101" then
        r<='0';
        ge<='1';
        g<='0';
      end if;
    when others =>

  end case;
end if;
/vhdl

von Schlumpf (Gast)


Lesenswert?

Deine ganzen Zuweisungen "funktionieren" nur, wenn gerade keine 
steigende Flanke auf dem Taktsignal ist..
Lothar hat´s ja auch schon gesagt. Du schreibst:

Wenn steigende Taktflanke, dann mache NICHTS und sonst mache diese 
ganzen anderen ELSIFs.

Denke nicht, dass du mit deinem Code genau das ausdrücken wolltest, was 
ich oben hingeschrieben habe :-)

von dden (Gast)


Lesenswert?

so jetzt aber
1
if rising_edge(clk) then
2
  case stsig is
3
    when "0000" =>
4
      r<='1';
5
    when "0101" =>
6
      if q_a="0000" then
7
        r<='0';
8
        ge<='0';
9
        g<='0';
10
      elsif q_a="0101" then
11
        r<='0';
12
        ge<='1';
13
        g<='0';
14
      end if;
15
    when others =>
16
17
  end case;
18
end if;

deine simulation ist falsch und bildet nicht die wirklichkeit ab.

von Kaffeetasse (Gast)


Lesenswert?

oki ich verstehe glaube wo das prob lag - die erste elsif muss ein if 
sein, dann müsste es stimmen!
so geändert...
1
ARCHITECTURE behav OF ampel IS 
2
BEGIN
3
4
  p1 : PROCESS (clk) 
5
  BEGIN
6
    
7
    IF (clk'EVENT AND clk'LAST_VALUE='0' AND clk='1') THEN 
8
    IF (stsig="0000") THEN r<='0'; ge<='0'; g<='0';
9
    ELSIF (stsig="0001") THEN r<='1'; ge<='0'; g<='0';
10
    ELSIF (stsig="0010") THEN r<='1'; ge<='1'; g<='0';
11
    ELSIF (stsig="0011") THEN r<='0'; ge<='0'; g<='1';
12
    ELSIF (stsig="0100") THEN r<='0'; ge<='1'; g<='0';
13
    ELSIF (stsig="0101" AND q_a="1001") THEN r<='0'; ge<='1'; g<='0';
14
    ELSIF (stsig="0101" AND q_a="0000") THEN r<='0'; ge<='0'; g<='0';  
15
    END IF; 
16
    END IF;  
17
  END PROCESS p1 ; 
18
19
END behav;

@dden:
also dein code sieht auch gut aus, mit case anweisung habe ich noch nix 
gemacht (nur gelesen) ... deswegen noch net so richtig ran getraut^^

: Bearbeitet durch Moderator
von Schlumpf (Gast)


Lesenswert?

dden schrieb:
> deine simulation ist falsch und bildet nicht die wirklichkeit ab.

Du weisst doch gar nicht, was seine "Wirklichkeit" ist? Also was er 
beschreiben wollte....

Die Simulation bildet genau das ab, was er beschrieben hat.

Sein Problem ist, dass er seinen Prozess nur mit "clk" in der 
Sensitivity-List "triggert". Daher reagiert der Prozess nur bei Änderung 
von Clock.
Seine ganzen Zuweisungen macht er aber nur dann, wenn der Takt gerade 
KEINE STEIGENDE FLANKE aufweist.

Alles, was bei den ELSIFs zugewiesen wird, wird also immer nur dann 
zugewiesen, wenn eine fallende Taktflanke auftritt.

Das ist eine total krautige Darstellung und wahrscheinlich nichtmal 
synthetisierbar. Jedenfalls entsteht dabei kein Register.

so käme man der Sache schon näher (ohne Korrektur sonstiger "unüblicher" 
Beschreibungsweisen:
1
    IF (clk'EVENT AND clk'LAST_VALUE='0' AND clk='1') THEN
2
      IF (stsig<="0000") THEN r<='0'; ge<='0'; g<='0';
3
      ELSIF (stsig<="0001") THEN r<='1'; ge<='0'; g<='0';
4
      ELSIF (stsig<="0010") THEN r<='1'; ge<='1'; g<='0';
5
      ELSIF (stsig<="0011") THEN r<='0'; ge<='0'; g<='1';
6
      ELSIF (stsig<="0100") THEN r<='0'; ge<='1'; g<='0';
7
      ELSIF (stsig<="0101" AND q_a<="1001") THEN r<='0'; ge<='1'; g<='0';
8
      ELSIF (stsig<="0101" AND q_a<="0000") THEN r<='0'; ge<='0'; g<='0';
9
      END IF;
10
    END IF;

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


Lesenswert?

Kaffeetasse schrieb:
> oki ich verstehe glaube wo das prob lag -
> die erste elsif muss ein if sein, dann müsste es stimmen!
Korrekt. Allerdings hast du eher ein grundlegendes Problem: du 
programmierst anstatt Hardware zu beschreiben. Nun ist VHDL aber 
eine Beschreibungssprache, keine Programmiersprache. Du musst dir also 
eine Hardware vorstellen, und die dann mit VHDL beschreiben. Hast du 
eine Vorstellung, wie deine Hardware aussieht, und was bei der Synthese 
herauskommen muss? Nein? Dann sieh dir ab&zu mal den RTL-Schaltplan 
deiner Beschreibung an...

> so geändert...
Noch die Leerzeichen in den eckigen Klammern der [ vhdl ] Tags weg, und 
den Code sinnvoll und übersichtlich eingerückt, dann passt das.

: Bearbeitet durch Moderator
von dden (Gast)


Lesenswert?

naja ich denke er wollte die werte gleichwertig entsprechend stsig bei 
steigender Flanke übernehmen.
Und ich würde sagen das die simulation so wie es im ersten posting stand 
faktisch einen kombinatorischen prozess sieht da die if clk abfrage ja 
immer flasch ist ausser wenn eine steigende flanke kommt und er auch auf 
veränderung von stsig triggert.

von dden (Gast)


Lesenswert?

@ Lothar
wasn da nicht ordentlich eingrückt ??
Davon mal abgesehen das es ein unvollständiges Beispiel sein sollte, um 
ihm mal grob die Richtung zu zeigen.

von Kaffeetasse (Gast)


Lesenswert?

@dden
ich glaueb mit dem einrücken war mein post gemeint...
die simulation so wie es im ersten beitrag steht war dahingehend falsch 
das immer bei fallender flanke die "clk action" war - so wie @Schlumpf 
meinte glaube ich...
jetzt ist die reaktion, wie es soll, auf steigender clk-flanke...
thx für die erläuterungen...

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


Lesenswert?

dden schrieb:
> wasn da nicht ordentlich eingrückt ??
Du warst doch gar nicht gemeint...
Das da war gemeint:
1
    IF (clk'EVENT AND clk'LAST_VALUE='0' AND clk='1') THEN 
2
    IF (stsig="0000") THEN r<='0'; ge<='0'; g<='0';
3
    ELSIF (stsig="0001") THEN r<='1'; ge<='0'; g<='0';
Eine Verschärfung, die jetzt noch denkbar wäre, ist dass alles vorn am 
Zeilenanfang beginnt:
1
IF (clk'EVENT AND clk'LAST_VALUE='0' AND clk='1') THEN 
2
IF (stsig="0000") THEN r<='0'; ge<='0'; g<='0';
3
ELSIF (stsig="0001") THEN r<='1'; ge<='0'; g<='0';
Oder dass die Einrückungen gar nichts mit der Struktur zu tun haben:
1
    IF (clk'EVENT AND clk'LAST_VALUE='0' AND clk='1') THEN 
2
  IF (stsig="0000") THEN r<='0'; ge<='0'; g<='0';
3
      ELSIF (stsig="0001") THEN r<='1'; ge<='0'; g<='0';

: Bearbeitet durch Moderator
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.