Forum: FPGA, VHDL & Co. Wie programmiert mann dass?


von Matze (Gast)


Lesenswert?

Hallo,

Ich frage mich wie ein auf 1-Setzen eines Signals 'A' programmiert 
werden kann, welches vom Zustand eines anderen Signals 'B' abhängig ist.

Dabei soll das auf 1 zu setzende Signal 'A' nur 1 Clk, nach setzen des 
Signals 'B' wieder rückgesetzt werden.

--> Wie z.b. im Userguide UG586 des MIG Version 2.4 auf Seite 162, 
Figure 1-74.

Hier wird ein Signal 'A' gesetzt, während gleichzeitig ein Signal 'B' 
rückgesetzt wird.
Nach Setzen des Signals 'B' ist dass Signal 'A' lediglich noch 1 Clk 
lang auf 1.

Mir fällt nur diese Lösung ein:
Initialisierung :
wdf_rdy <= 1;
wdf_rdy_merk <= 0;
1
if rising_edge(SYS_clk) then
2
                    wdf_rdy_merk <= wdf_rdy;
3
                    if wdf_rdy_merk = '1' then  --Daten übernommen
4
                        wdf_wren <= '0';
5
                        state <= idle;
6
                    else                        --Kommando anlegen
7
                        wdf_wren <= '1';
8
                    end if;
9
end if;

Es scheint denkbar, dass im 1. Clk, der wdf_rdy_merk sowie wdf_wren auf 
1 gesetzt werden.

Beim 2. Clk ist wdf_rdy_merk = '1', folglich wird wdf_wren = 0.

Warum ist wdf_wren nun > 1 CLK lang auf 1?

von Staubfänger (Gast)


Lesenswert?

Ich denke Dein Code zeigt ein häufig auftretendes Mißverständnis: 
Nämlich, dass der Code, genau wie ein imperatives Programm zu 
interpretieren ist. Du siehst eine Folge von:

wdf_rdy_merk <= wdf_rdy;
if wdf_rdy_merk = '1' then  --Daten übernommen

und nimmst an, dass die Bedingung des if (im Kontext mit dem früher 
geschriebenen wdf_rdy <= 1;) wahr sein müsste, weil ja wdf_rdy_merk eine 
1 zugewiesen wurde.

Das aber ist so nicht richtig.
Vielmehr beschreibst Du in VHDL Strukturen. Die "Zuweisung" wdf_rdy_merk 
<= 1 ist eine Struktur. Die "if-Anweisung" ist eine Struktur. Beide sind 
unabhängig voneinander und sind nicht kausal verbunden. (Jedenfalls in 
einem anderen Sinne, als Du das annimmst).

Das ist der tiefere Sinn, des hier so oft zu lesenden Einwurfs: In VHDL 
schreibt man keine Programme sondern man beschreibt Strukturen.

von FPGA-Polizei (Gast)


Lesenswert?

Nun, in diesem Fall sind die Signale allerdings sehr wohl kausal 
verbunden, da unbedingt. Sie sind nur nicht datensynchron im selben 
Takt.

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


Angehängte Dateien:

Lesenswert?

Matze schrieb:
> Hier wird ein Signal 'A' gesetzt, während gleichzeitig ein Signal 'B'
> rückgesetzt wird.
Ist das Setzen des zweiten Signals nicht eher eine Folge des gesetzten 
ersten Signals? Denn "gleichzeitig" gibt es nicht in der Hardware. 
Sondern es gibt eine Taktflanke und einen Zustand davor, der zu einem 
Zustand danach führt. Und dann kommt wieder eine Taktflanke... usf...

> Ich frage mich wie ein auf 1-Setzen eines Signals 'A' programmiert
> werden kann, welches vom Zustand eines anderen Signals 'B' abhängig ist.
>
> Dabei soll das auf 1 zu setzende Signal 'A' nur 1 Clk, nach setzen des
> Signals 'B' wieder rückgesetzt werden.
> --> Wie z.b. im Userguide UG586
Du hättest da einfach einen Screenshot anhängen können...
Wie auch immer: was dort zu sehen ist, ist stinknormales synchrones 
Design ohne jegliche Merker oder sonstwas. Der Code für diese Reaktion 
ist einfach sowas:
1
 if rising_edge(SYS_clk) then
2
       :
3
       :
4
       if app_rdy = '1' then
5
           app_en <= '0';
6
       end if;
7
       :
8
       :
9
 end if;

Matze schrieb:
1
 if rising_edge(SYS_clk) then
2
                     wdf_rdy_merk <= wdf_rdy;
3
                     if wdf_rdy_merk = '1' then  --Daten übernommen
4
                         wdf_wren <= '0';
5
                         state <= idle;
6
                     else                        --Kommando anlegen
7
                         wdf_wren <= '1';
8
                     end if;
9
 end if;
Du kannst diesen Code übrigens ohne jegliche Änderung im 
Syntheseergebnis(!!!) auch so schreiben:
1
if rising_edge(SYS_clk) then
2
                    if wdf_rdy_merk = '1' then  --Daten übernommen
3
                        wdf_wren <= '0';
4
                        state <= idle;
5
                    else                        --Kommando anlegen
6
                        wdf_wren <= '1';
7
                    end if;
8
                    wdf_rdy_merk <= wdf_rdy;
9
end if;
Denn ein jedes Signal übernimmt den "neuen" Wert erst am Ende eines 
Prozesses oder beim nächsten wait...

Matze schrieb:
> Ich frage mich wie ein auf 1-Setzen eines Signals 'A' programmiert
> werden kann
Warum heißt es VHDL und nicht VHPL? Weil es eine "Description Language" 
und keine "Programming Language" ist. Du musst also deine Hardware 
beschreiben. Und dazu musst du dir erst mal vorstellen, wie diese 
Hardware aussehen soll. Das tust du nicht, sondern du "programmierst" 
einfach mal drauf los...

: Bearbeitet durch Moderator
von Matze (Gast)


Angehängte Dateien:

Lesenswert?

Zu einem Zeitpunkt x wird wdf_wren = 1 gesetzt.

Zum Zeitpunkt x+1,
soll für den fall dass wdf_rdy zu Zeitpunkt x = 1 war, wdf_wren = 0 
werden.
falls wdf_rdy zu Zeitpunkt x = 0 war, so soll wdf_wren = 1 bleiben.

--> wdf_wren soll so lange auf 1 bleiben.
--> Bis festgestellt wird dass wdf_rdy im unmittelbar vorhergehenden 
Zustand --> 1 war.

Meine Variante braucht 2 Zyklen, um wdf_wren = 0 zu setzen, nachdem 
wfd_rdy = 1 ist.
Denn im Takt 4 wird der Merker erst mit 1 beschrieben.
Bis wdf_wren = 0 wird, braucht es noch einen Takt.

Ist der beigefügte Ablauf korrekt?

Und wenn ja, wie kann ein Rücksetzen von wdf_wren zum Takt 4 erfolgen?

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


Lesenswert?

Matze schrieb:
> Zum Zeitpunkt x+1, soll für den fall dass wdf_rdy zu Zeitpunkt x = 1
> war, wdf_wren = 0 werden.
> falls wdf_rdy zu Zeitpunkt x = 0 war, so soll wdf_wren = 1 bleiben.
Wenn ich nur das und genau das umsetzen soll und keine weiteren 
Forderungen bestehen, dann könnte ich das so beschreiben:
1
 if rising_edge(SYS_clk) then
2
       wdf_wren <= not wdf_rdy;
3
 end if;

Matze schrieb:
> --> wdf_wren soll so lange auf 1 bleiben.
> --> Bis festgestellt wird dass wdf_rdy im unmittelbar vorhergehenden
> Zustand --> 1 war.
Ok, dann diese Beschreibung:
1
 if rising_edge(SYS_clk) then
2
       :
3
       :
4
       if wdf_rdy = '1' then
5
           wdf_wren <= '0';
6
       end if;
7
       :
8
       :
9
 end if;
Kommt dir das bekannt vor? Ja, ich hatte es schon mal gepostet...
Dort steht: wenn zur steigenden Flanke vom Takt wdf_rdy high ist, dann 
wird als Folge das Flipflop wdf_wren auf low gesetzt.

von Staubfänger (Gast)


Lesenswert?

Nun, dann lass doch den Merker einfach weg. Dessen setzen führt erst die 
Verzögerung ein. Ein gedankliches Problem dabei ist auch oft, ab wann 
man die Takte zählt, bzw. ob man einen Zustand bei der Flanke betrachtet 
(das ist ja die Aussage des Codes) oder ob man eine Änderung während der 
Zeit zwischen zwei Flanken betrachtet.


In Deinem Code kommt etwas wie "state <= idle" vor. Du benutzt also 
vermutlich ohnehin eine Zustandsmaschine. Das kannst Du ja nutzen, in 
dem ein Zustand auch ein "Merker" ist.

Setzen wir voraus, Du kommst von einem Zustand "Initiate-Command" in 
einen Zustand "Enabled-Wait-Ready" in dem wren bei Übergang dahin auf 1 
gesetzt wurde und in dem Du auf 'ready' wartest. Etwa so:

state

Initiate-Command       wdf_wren <= '1'; state <= Enabled-Wait-Ready;

Enabled-Wait-Ready     if wdf_rdy = '1' then state <= Ready; else state 
<= Enabled-Wait-Ready;

Ready                  wdf_wren <= '0'; -- rdy war im vorherigen Takt 1
                       state <= Following-State;

Following-State


Dieser Zwischenzustand Enabled-Wait-Ready sorgt dafür, dass noch ein 
weiterer Takt vergehen muss, ehe wren wieder auf 0 gesetzt wird.

Das wäre wörtlich, das Verhalten, dass Du mit dem Satz: "soll für den 
fall dass wdf_rdy zu Zeitpunkt x = 1 war, wdf_wren = 0
werden." beschreibst.

Falls aber wren bei dem nächsten Takt gesetzt werden soll, nachdem rdy = 
1 geworden ist, dann lässt Du den Zwischenzustand einfach weg.


state

Initiate-Command       wdf_wren <= '1'; state <= Enabled-Wait-Ready;

Enabled-Wait-Ready     if wdf_rdy = '1' then wdf_wren <= '0'; state <= 
Following-State; else state    <= Enabled-Wait-Ready;

Following-State

von Matze (Gast)


Lesenswert?

Danke, für eure Ausführungen,

habs nun mit einem Zwischenzustand gelöst.

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.