mikrocontroller.net

Forum: FPGA, VHDL & Co. Signal im gleichen Takt zweimal ändern?


Autor: Markus Zingg (bitdigger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jan M. (mueschel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Manuel S (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jan hat recht, genau so ist es

Die letzte durchgeführte Zuweisung im Prozess gewinnt

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Markus Zingg (bitdigger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jan M. (mueschel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die default initialisierung ist gängig
ich mach das auch gerne
process
begin
    wait until rising_edge(clk);
    (a,b,c) <= std_logic_vector'("000");
    case current_state is
      when Astate => a <= '1';
      when Bstate => b <= '1';
      when Cstate => c <= '1';
    end case;
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

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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;


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 =>

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Nephilim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: bitdigger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Manuel S (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>@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...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.