Hallo, Als VHDL Neuling bin ich über folgenden fremden Code gestolpert den ich hier auf das wesentliche reduziert wiedergebe: process (clk, reset) begin if (reset = '1') then signal <= '0'; isc_state <= IDLE; elsif rising_edge(clk) then case (state) is when IDLE => -- nicht relevant ; when FILL => signal <= '0'; if (fifo_empty = '0') then signal <= '1'; end if; when others => state <= IDLE; end case; end if; end process; Ich finde dass in "when FILL" signal nicht korrekt behandelt wird. Ich dachte immer dass Signale nur EINMAL Zyklus verändert werden können. Falls aber die Bedingung if(fifo_emtpy = '0' ) war ist, wirds kompliziert. Gewisse Quellen sagen das Verhalten sei nicht definiert, andere sagen die Letzte Zuweisung "gewinne". Selbst wenn letzteres war wäre, wäre dies ja nur bei Erfüllter Bedingung so. Was würde dann mit "signal" passieren wenn die Bedingung nicht erfüllt ist??? Ist dieser Code unschön, normal, oder falsch? Will heissen gibt das bei der Synthese eventuell ein Verhalten welches dem erwarteten Ergebnis wiederspricht (dass signal bei (fifo_empty = '0') '1' ist und sonst '0' ? Danke für eure Meinungen! Markus
Der Code ist vollkommen korrekt. In jedem Takt wird der komplette Prozess einmal durchlaufen. Für jedes Signal wird die letzte gültige Zuweisung gesucht, und genau dieser Wert wird dem Signal zugewiesen. Ist der fifo nicht leer, so ist die letzte ausgeführte Anweiung signal <= '1'; Ist er aber leer, ist die if-Bedingung falsch, die letzte Anweisung wird nicht ausgeführt, also bleibt signal <= '0' als letzte Zuweisung stehen.
Jan hat recht, genau so ist es Die letzte durchgeführte Zuweisung im Prozess gewinnt
Was man anmeckern könnte ist, dass die Ausgänge nicht nur vom Zustand abhängen. Kann unter Umständen zu langsamer Schaltung führen.
Ok, danke mal soweit. Wie schauts denn aber mit folgendem Code aus? process (clk, reset) begin if (reset = '1') then state <= IDLE; elsif rising_edge(clk) then case (state) is when IDLE => -- nicht relevant ; when FILL => counter <= counter + 1; -- weiterer Code hier if (counter = '11') then -- weiterer Code auch hier end if; when others => state <= IDLE; end case; end if; end process; Ist das denn auch ok? Ich meine, die if Zeile, enthält denn counter dort noch den Wert VOR der Inkrementierung, und selbst wenn, gilt das denn noch als "sauber" ? TIA Markus
Auch das ist vollkommen korrekt - der Vergleich enthält den Wert des counters vor dem inkrementieren. Der neue Wert wird dem Signal ja erst nach dem durchlaufen des kompletten Prozesses zugewiesen. @Karl: Naja, das ist ja erstmal kein Fehler, sondern nur eine Frage des zugrundeliegenden Designs. In modernen FPGAs ist das aber sicher kein großes Problem - Jeder counter braucht länger als diese zusätzliche Abfrage des empty-Signals.
die default initialisierung ist gängig ich mach das auch gerne
1 | process
|
2 | begin
|
3 | wait until rising_edge(clk); |
4 | (a,b,c) <= std_logic_vector'("000"); |
5 | case current_state is |
6 | when Astate => a <= '1'; |
7 | when Bstate => b <= '1'; |
8 | when Cstate => c <= '1'; |
9 | end case; |
10 | end process; |
für mich sieht das "einfacher" zu verstehen als die variante bei der für jeden zustand die zuweisungen an alle signale voll ausgeführt ist. grüsse, daniel
1 | process (clk, reset) |
2 | begin
|
3 | if (reset = '1') then |
4 | state <= IDLE; |
5 | elsif rising_edge(clk) then |
6 | |
7 | case (state) is |
8 | |
9 | when IDLE => |
10 | -- nicht relevant
|
11 | ;
|
12 | when FILL => |
13 | counter <= counter + 1; |
14 | -- weiterer Code hier
|
15 | if (counter = '11') then |
16 | -- weiterer Code auch hier
|
17 | end if; |
18 | |
19 | when others => |
20 | state <= IDLE; |
21 | |
22 | end case; |
23 | |
24 | end if; |
25 | end process; |
Für mich ist diese Code wenn auch syntaktisch korrekt, denoch total Unsinn. Der Zustand state wird im reset Zweig auf IDLE gesetzt. Im wenn others Zweig ebenfalls. nirgendwo wird er auf FILL gestezt. Deshalb wird der FILL Zweig nie ausgeführt. Eine ordentliche Synthese optimiert dir den ganzen Code weg. Gruß Gast ps: Wenn im IDLE Zweig nichts gemacht werden soll schreibt man normalerweise when IDLE =>
Ups, da hab ich zu früh absenden gedrückt ;-). Wollte schreiben: ps: Wenn im IDLE Zweig nichts gemacht werden soll schreibt man normalerweise when IDLE => null; Gruß Gast
im IDLE Zweig wird aber was gemacht, es ist nur im moment als unrelevant auskommentiert. ich schätze mal das dort im normalfall irgendwas abgefragt wird wodurch dann der STATE auf FILL gesetzt wird und schon gehts los. es wurde doch nur zur übersichtlichkeit rausgenommen.
Yep, war genau so gemeint. Beispiele sind gekürzt um aufs Wesentliche zu reduzieren. Mir geht es eigentlich darum besser zu verstehen wie so mit Signalen codiert werden soll. Meiner Meinung nach (aber die ist ja nicht wirklich so relevant als Anfänger) sind diese Beispiele schlechter Stil und unübersichtlich. Im ersten Fall würde eine else Konstruckt in welchem "signal" auf '0' gesetzt wird Klarheit schaffen. Im Zweiten Fall - naja, etwas andere Logik und für Counter eine Variable einsetzen? Denn, wird der Code etwas umfangreicher ist diese Hinterherhinkerei der Zustände doch irgendwie ein Alptraum fürs Verständnis. Markus
Das mit dem Alptraum kommt drauf an von welcher Seite du es betrachtest. Wenn du daran denkst wie die Schaltung später nach der Synthese rauskommt, bzw. wie du sie mit "alter" Digitaltechnik aufbauen würdest macht das durchaus Sinn.
>@Karl: Naja, das ist ja erstmal kein Fehler, sondern nur eine Frage des >zugrundeliegenden Designs. In modernen FPGAs ist das aber sicher kein >großes Problem - Jeder counter braucht länger als diese zusätzliche >Abfrage des empty-Signals. Hab ja nicht behauptet, dass es ein Fehler ist. Schonmal was von Moore und Mealy gehört? Der geneigte Leser kann ja googeln...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.