Hallo, habe hier ein sonderbares Problem. Ich werte einen 4bit-Vektor aus (TR_IN), und zwar jeweils 2 bits zusammen (also bit 3 und 2 und bit 1 und 0). Dies hatte ich ursprünglich so gemacht: --------------- if (TR_IN (1 downto 0) = "01") OR (TR_IN (1 downto 0) = "10") then tr_imp_k1_tmp <= '1'; count_tr_of_k1 <= count_tr_of_k1 + 1; end if; if (TR_IN (3 downto 2) = "01") OR (TR_IN (3 downto 2) = "10") then tr_imp_k2_tmp <= '1'; count_tr_of_k2 <= count_tr_of_k2 + 1; end if; if (TR_IN (1 downto 0) = "01") then ef_1 <= '1'; end if; if (TR_IN (3 downto 2) = "01") then ef_2 <= '1'; end if; ---------------- Dieser Code verursachte im ganzen Projekt große Fehler. Daraufhin habe ich nach langer Fehlersuche eine case-Anweisung daraus gemacht, in der alle möglichen Konstellationen von TR_IN enthalten sind: ---------------- case TR_IN is when "0001" => tr_imp_k1_tmp <= '1'; count_tr_of_k1 <= count_tr_of_k1 + 1; ef_1 <= '1'; when "0010" => tr_imp_k1_tmp <= '1'; count_tr_of_k1 <= count_tr_of_k1 + 1; when "0100" => tr_imp_k2_tmp <= '1'; count_tr_of_k2 <= count_tr_of_k2 + 1; ef_2 <= '1'; when "1000" => tr_imp_k2_tmp <= '1'; count_tr_of_k2 <= count_tr_of_k2 + 1; when "0101" => tr_imp_k1_tmp <= '1'; count_tr_of_k1 <= count_tr_of_k1 + 1; ef_1 <= '1'; tr_imp_k2_tmp <= '1'; count_tr_of_k2 <= count_tr_of_k2 + 1; ef_2 <= '1'; when "0110" => tr_imp_k1_tmp <= '1'; count_tr_of_k1 <= count_tr_of_k1 + 1; tr_imp_k2_tmp <= '1'; count_tr_of_k2 <= count_tr_of_k2 + 1; ef_2 <= '1'; when "1001" => tr_imp_k1_tmp <= '1'; count_tr_of_k1 <= count_tr_of_k1 + 1; tr_imp_k2_tmp <= '1'; count_tr_of_k2 <= count_tr_of_k2 + 1; ef_1 <= '1'; when "1010" => tr_imp_k1_tmp <= '1'; count_tr_of_k1 <= count_tr_of_k1 + 1; tr_imp_k2_tmp <= '1'; count_tr_of_k2 <= count_tr_of_k2 + 1; when others => null; end case; -------------------- Und diese Anweisung funktioniert tadellos. Damit ist ja eigentlich alles klar und schön, nur hätte ich sehr gerne verstanden, was an den obigen IFs falsch ist. Sieht oder weiß da jemand was?
ich denke, es fehlen einfach die else-Zweige in den if-statements, die Signale werden nur gesetzt. Jörg
Ausserdem scheint in beiden Versionen die Flankenauswertung für die Zähler zu fehlen (rising_edge ode so) Gruß Jörg
>ich denke, es fehlen einfach die else-Zweige in den if-statements, die >Signale werden nur gesetzt. Das gleiche passiert ja auch bei der Case-Anweisung. Die Signale werden anderswo zurückgesetzt. >Ausserdem scheint in beiden Versionen die Flankenauswertung für die >Zähler zu fehlen (rising_edge ode so) Das rundherum habe ich jetzt aus Platzgründen weggelassen, ich habe nur das wesentliche reinkopiert. Wie schon geschrieben funktioniert der Code mit der Case-Anweisung 100%ig. Mich wurmt nur, dass ich nicht weiß, warum das mit den ifs nicht klappt.
Hat keiner 'ne Idee?
Was meckert der Compiler denn an?
Gast
#499101
Würd auch sagen, dass es an den fehlenden else liegt. Dann werden evtl. Latches synthetisiert. Versuchs doch einfach mal mit den else, ist ja nicht so aufwendig. Oder aber, du setzt in dem Prozess ganz am Anfang Standardwerte für die Signale, die in den ifs Werte bekommen (alle auf 0 zum Beispiel).
Gast
#499332
So wie es aussieht, werden in beiden Beschreibungen Laches erzeugt. Und das ist grundsätzlich schonmal schlecht. Versuch entweder in allen Bedingugen alle Singale zuzuweisen oder mach den Prozess getaktet und register deine Signale.
Gast
#499373
Wenn keiner eine prompte Lösung hat, dann weil das problem in der fragestellung nicht sichtbar ist. #Dieser Code verursachte im ganzen Projekt große Fehler. Was sind für Dich große Fehler? Brechen die Tools ab? Ist das Verhalten ein anderes? Was verhält sich anders als erwartet? Ohne diese Antworten können wir den Code nur auf unpraktische Schreibweise durchsuchen. Oder ich rate: Multiple sources?; X im in der simu? #Das rundherum habe ich jetzt aus Platzgründen weggelassen, #ich habe nur das wesentliche reinkopiert. Wie schon geschrieben #funktioniert Packe reinkopierten code zwischen vhdl und /vhdl in eckigen Klammern und benutze den Vorschaue-Button, dann sieht der Code besser aus wie hier:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
Ich habe vor dem Code eine Zeile mit vhdl in [ ] geschrieben und danach eine mit /vhdl auch in [ ]. Und du kannst den Code in einer Datei an Deine Anfrage anhängen. Dein Problem wird zu 50% die "Rücksetzbedingung woanders im Code" sein. Da kommt nur Murks raus. Das muss im selben prozess stehen, es muß nicht unbedingt eine Else oder ein Elsif sein, aber wenn du ein FliFlop habe willst dann muß in einem Prozess das Setzen und das Rücksetzten beschrieben sein. Beispiel
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
Wohlgemerkt das Rücksetzten muss im selben prozess beschrieben sein, das signal das das Rücksetzen auslöst kann irgendwo anders stehen. Die anderen 50% deines Problems, warum das case tut und das If nicht, ist sicherlich der Others Zweig mit dem Null. IMHO heisst das, das die Signale nicht vom Prozess getrieben werden, wenn die When bedingungen nicht erfüllt werden. Du kannst ja mal schreiben
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
Dann könnte das Case-Konstrukt genauso wirken wie das If. Oder du schreibst:
1 | |
2 | |
3 | |
4 | |
5 | |
Aber das ist mE nur Dein verständnisproblem, dein Designproblem ist die "Rücksetzbedingung sonstwo". Das ist nicht C, das ist eine Hardware-beschreibungssprache. Und falls due ein FF willst, musst du in einem Prozess, setzen und Rücksetzten beschreiben, aber nicht die eine Hälfte in diesem Prozess und die andere in einem Zweiten. Und dann vielleicht noch mit unterschiedlichen Takt(-flanken) }:-0 das geht nicht! Aber ohne kompletten Code und Fehlerbeschreibung können wir nur weiter raten. Aber schau mal nach was eine null zuweisung oder null in VHDL tut.
Gast
#499376
Ich hab ein paar ; vergessen, auch anderswo können Tippfühler im Syntax stecken.
Hallo, erstmal vielen Dank für die reichlichen Antworten. Ok, hier ist zweimal der gesamte Prozess, in dem die Anweisungen von oben stehen, zuerst mit IF (der "Böse"), und dann mit Case:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
So, das sollte schonmal einige der Punkte von euch klären. Sorry, dass ich nicht gleich den ganzen Prozess geschickt habe, aber ich wollte nicht einen endlos langen Thread machen. :) So, zuerst zu den Fehlern. Also der Prozess ist Teil eines relativ großen Designs. Keine der beiden Varianten macht beim Synthetisieren Probleme, das Design macht auf dem FPGA Probleme, und zwar in einem ganz anderen Teil, der diesem Prozess vorgeschaltet ist (dort wird das TR_IN erzeugt) und auch kein Feedback von diesem Prozess hier bekommt. >Würd auch sagen, dass es an den fehlenden else liegt. Dann werden evtl. >Latches synthetisiert. >So wie es aussieht, werden in beiden Beschreibungen Laches erzeugt. Und >das ist grundsätzlich schonmal schlecht. Also das ganze Design ist eigentlich streng getaktet, das TR_IN wird getaktet erzeugt und kommt so rein. Oder verstehe ich das jetzt falsch, also Latches sind doch NICHTtaktgesteuerte Register, oder (Wie heißen taktgesteuerte eigentlich)? >Aber schau mal nach was eine null zuweisung oder null in VHDL tut. Öhm, also in meinen Büchern steht prinzipiell "Nichts". Also es macht nichts. Und das soll es hier ja auch. Aber hier besteht (bei mir) durchaus noch Klärungsbedarf, also bitte belehrt mich. :) Habe ich das jetzt richtig verstanden, dass das ganze laufen sollte, wenn ich bei den IFs jeweils schreibe "else NULL;" ? Weil ich dachte, dass das sowieso nix macht, wenn da nur IF sowieso steht. IF Q = '1' then A = '1' heißt doch, wenn Q 1 ist, setze A auch auf 1. Und wenn nicht, also wenn Q nicht 1 ist, mach bitte nix. Oder verstehe ich das falsch?
Gast
#499507
Hm, also Null schaltet den Signaltreiber ab, ansosnsten treibt er den
vorhergehenden wert.
Also
(1)die bedingung zum setzten wird erfüllt dann wird eine '1' getrieben
(2)keine bedingung wird erfüllt, aber vorher war die setzbedingung wird
erfüllt -> es wird immer noch eine '1' getrieben
(3) es wird Null gesagt (wie auch immer) dann bleibt die eins wenn kein
andere Quelle das signal treibt, ansosonsten gewinnt das andere Signal
(4) es wird eine '1' getrieben (weil (1) oder (2) und wg. einer anderen
bedingung wird eine '0' getrieben, dann kommt X raus.
Also Null heisst nicht das nix passiert, es heisst das von dieser stelle
nix neues passiert (signaltreiber abgeschaltet), von anderen stellen
kann was passieren. Wenn zwei stellen treiben dann geht es durch die
resolution funktion also bei std_logic:
stelle 1 stelle2 Ergebnis
'1' '0' X
'1' 'Z' 1
'1' '1' 1 (?), ich bion mir nicht sicher eventuell auch X
'1' null '1'
'0' null '0'
'1' 'u' 'u' oder 'X'
u heisst unassigned, also wert wurde noch nie zugewiesen, nicht zu
wechseln mit 'X' -> unknown -unbekannt (z.B. wg. crash('1' und '0'von
zwei Quellen ))?
#IF Q = '1' then A = '1' heißt doch, wenn Q 1 ist, setze A auch auf 1.
#Und wenn nicht, also wenn Q nicht 1 ist, mach bitte nix.
#Oder verstehe ich das falsch?
wahrscheinlich, es heisst wenn Q nicht 1 dann ÄNDERE nix also der alte
Wert wird getrieben -> typ. VBerhalten eines FF.
Ändere Nix ist nicht da selbe wie MACH nix. Mach nix heisst Null
(Signaltreiber abschalten).
Vielleicht kann man sagen, mach nix gibt es im FPGA nicht und daher im
synthetisierbaren VHDL auch nicht. IM Fpga gibt es Änderen oder nicht
ändern, aber gemacht wird immer was. (schlecht zu beschreiben das ist)
Ok, das hab ich soweit verstanden. Mach nix heißt in dem Fall dann halt nur "lass es so, wie es ist". Ist dann dieses null gleichzusetzen mit einer Tristate-Konstruktion, also wie z.B. bei einem bidirektionalen Datenbus, den ich so steuere:
1 | |
2 | |
Kann man sowas auch mit "null" machen? Ich habe jetzt mal probehalber in der IF-Version bei allen verzweigungen "else null;" eingefügt, der Fehler bleibt aber der gleiche...
Gast
#499526
Ich glaube man muß unterscheiden zwischen dem NULL statement oder der NULL Zuweisung. if Q = '1' then A <= '1'; else null; end if; bewirkt daß A sich nicht ändert. Aber if Q = '1' then A <= '1'; else A <= null; end if; schaltet den Driver ab. Wird nicht sehr oft verwendet, mir war die null Zuweisung jedenfalls unbekannt und kann für die Synthese sicher nicht verwendet werden.
Gast
#499533
Zur Ergänzung : Das NULL statement in : if Q = '1' then A <= '1'; else null; end if; ist natürlich überflüssig !!
Gast
#499598
Also der erste sichtbare Unterschied den ich sehe ist das Null statement, sonst ist alles gleich. wenn null nicht dasselbe macht wie <= null (warum auch); da liege ich natürlich mit meiner vermutung falsch. Und es kann nicht darin liegen. Ein anderer Unterschied ist das when eigentlich mit if elsif übersetzt wird. Also so wie du dein If schreibst, passt kein elsif, da sehe ich also (noch) kein Problem. Sowie es klingt, verhalten sich die synthetisierten designs unterschiedlich, also wird wohl der (eigentlich funktional identische) Code unterschiedlich übersetzt. Da könnt was im synthesereport stehen (Xilinx: *.syr).
Naja, ich behandele das TR_IN ja schon unterschiedlich, bei den IFs frage ich die ersten und letzten beiden Bits getrennt ab, wogegen ich bei dem Case-Statement alle möglichen auftretenden Fälle abhandele.
Gast
#499642
In einem getakteten Prozess kann es nicht an Latches liegen und du kannst die else weglassen, das stimmt, aber das konnte man aus deinem ersten Post ja nicht ablesen. Die Frage, die ich mal in den Raum stellen würde ist, ob dein Code überhaupt das gleiche macht? Mit den if fragst du nur den folgende Fälle ab, in denen was passiert: "0101","0110","1001","1010" Im case-statement wird z.B. auch bei "0001" was ausgeführt...? Wie das?
Gast
#499653
Achso, entschuldige, durch die einzelnen if-Anweisungen werden natürlich auch die anderen Fälle abgefagt.
Gast
#499658
Aber was passiert z.B bei "1101"? Bei deiner if-Anweisung kommt eine Zuweisung, im case nicht.
Diese Konstellation wird nicht auftreten, die beiden Bitpaare von TR_IN können nur 00,01 oder 10 sein, nicht aber 11.
Gast
#499682
wer glaubt's, wird selig ;)
Gast
#499684
Vielleicht solltest du mal ein paar Differenzen der Simulationsergebnisse posten, dann würde eine Analyse wesentlich besser funktionieren. Oder funktioniert die Simulation gleich und nur direkt der Test auf dem FPGA macht Probleme?
Gast
#499685
@Christian:
>können nur 00,01 oder 10 sein, nicht aber 11
Das weißt aber nur Du und nicht der Compiler. Änder doch mal den letzten
case -Fall, dass Du 10 und 11 zu "when others" zusammenfasst.
Rick
Gast
#507228
Ich vermute mal, dass deine großen Probleme darin liegen, dass das Design so in etwa läuft, aber manchmal (jede Sekunde, jede Minute, jede Stunde, einmal am Tag) nicht so richtig tut. Das sind die wirklich großen Probleme. And now ladies and gentlemen, we proudly present: -->> Der kombinatorische asynchrone Reset <<--
1 | |
2 | |
3 | |
Ich hatte da auch mal so ein Design, da waren in der Rücksetz-Bedingung so ähnliche Konstrukte. Das lief, solange die Steuerung kalt war, aber nach einer Stunde wars vorbei. Dann habe ich irgendwas im Code geändert, und dann hat sich irgendwas im Verhalten der Steuerung geändert. 1) So einen kombinatorischen Reset darf es nicht geben (es sei denn man liebt Probleme) 2) in die Process-Sensitivity-List gehören maximal Reset und Takt, besser noch: nur der Takt (Reset ist dann synchron) Es ist eben so: wenn eines der Rücksetz-Signale z.B. von einem Zähler kommt und/oder sonstwoher kombinatorisch erzeugt wird, gibt es einen kurzen Glitch und ein paar der FFs werden zurückgesetzt (aber eben nicht alle und noch fieser: nicht immer die selben). Probiers doch mal eher so:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
Jetzt nur noch etwas aufpassen mit der Latency. Lothar
@Lothar: Vielen Dank für deine Antwort! Erstmal nur ganz schnell: das "böse" Reset habe ich doch aber auch in der anderen Variante, und dort läuft das Design tadellos?!
Gast
#507294
@Christian: Ja, wie gesagt, es läuft schon, meistens. Aber du darfst so ein Design nicht großartig ändern (z.B. auch andere Zielhardware), denn sonst ändert sich das FPGA-interne Layout, damit das Timing und: RUMMS. Wirklich transportabel und reproduzierbar ist nur ein komplett synchrones Design: alle Zustände ändern sich ausschliesslich mit dem Takt, einzige Ausnahme: der (oft unnötige [aber das ist eine andere Sache]) externe asynchrone Reset. Wobei ich immer auch so einen Reset erst mal synchronisiere und dann im FPGA intern verwende.
Gast
#509414
@Christian: Hat sich schon was getan? Läuft dein Design? Ich lerne gerne noch dazu: Was war die Ursache für den Fehler?
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.