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


von Markus Z. (bitdigger)


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

von Jan M. (mueschel)


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.

von Manuel S (Gast)


Lesenswert?

Jan hat recht, genau so ist es

Die letzte durchgeführte Zuweisung im Prozess gewinnt

von Karl (Gast)


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.

von Markus Z. (bitdigger)


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

von Jan M. (mueschel)


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.

von daniel (Gast)


Lesenswert?

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

von Gast (Gast)


Lesenswert?

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

von Gast (Gast)


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

von Nephilim (Gast)


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.

von bitdigger (Gast)


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

von Manuel S (Gast)


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.

von Karl (Gast)


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

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.