Forum: FPGA, VHDL & Co. VHDL Prozess nur "anstupsen"


von Mark W. (kram) Benutzerseite


Lesenswert?

Hallo,

ich baue mir gerade einen Prozess, womit ich einen 
Initialisierungsvorgang realisieren moechte.
Nun weiss ich nicht, wie ich den Prozess kontrolliert starten kann. Ich 
moechte, dass er bei einer Flanke anlaeuft und einmal durchlaeft und 
dann stehen bleibt. Ich frage mich ob ich das in dem Prozess realisieren 
kann, oder ob ich eine externe Schalung benoetige, die mir aus eine 
Flanke ein Dauersignal generiert und das dann als Enable verwendet wird. 
Was passieren soll wenn die Flanke waerend des Prozesses kommt, ist 
erstmal egal, kann neu anlaufen oder auch ignoriert werden waerend der 
Laufzeit des Prozesses.

1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity TESTPROCESS is
6
  port(  CLK, RST : in std_logic;
7
      Y   : out std_logic;
8
      Z   : out std_logic
9
  );
10
end TESTPROCESS;
11
12
architecture BEHAVIORAL of TESTPROCESS is
13
14
signal c : integer :=0;
15
constant t1 : integer :=0;
16
constant t2 : integer :=10;
17
constant t3 : integer :=20;
18
constant t4 : integer :=30;
19
20
begin
21
22
process(CLK)
23
begin
24
  if(rising_edge(CLK)) then
25
    if c = t1 then
26
      Y <= '0';
27
      Z <= '0';
28
    elsif c = t2 then
29
      Y <= '0';
30
      Z <= '1';
31
    elsif c = t3 then
32
      Y <= '1';
33
      Z <= '0';
34
    elsif c = t4 then
35
      Y <= '1';
36
      Z <= '1';
37
    end if;
38
    if c < 200 then
39
    c <= c+1;
40
    end if;
41
  end if;
42
end process;
43
44
end BEHAVIORAL;

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


Lesenswert?

Mark W. schrieb:
> Nun weiss ich nicht, wie ich den Prozess kontrolliert starten kann. Ich
> moechte, dass er bei einer Flanke anlaeuft und einmal durchlaeft und
> dann stehen bleibt.
Du denkst zu sehr wie ein "Softwareprogrammierer" (auch die Beschreibung 
in diesem Prozess sieht ganz danach aus...)
Ein "Prozess" in VHDL beschreibt eine Hardware, die in LUTs und 
Flipflops realisiert wird und immer da ist. Die FSM, die deine 
Beschreibung darstellt, wird nach dem Laden des FPGAs, bei dem der 
Zähler sowie wahrscheinlich auch X und Y mit 0 initialisert werden (das 
darf der Synthesizer laut deiner Beschreibung aber handhaben wie er 
will, denn du definierst X und Y erst ab dem 11. Takt). Dann zählt der 
Zähler mit jedem Takt eins hoch und die  Vergleicher lösen bei 
bestimmten Zählerständen bestimmte Aktionen aus. Ab dem 31. Takt bleiben 
X und Y dann auf '1' stehen.

> waerend der Laufzeit des Prozesses.
Die "Laufzeit" eines Prozesses (also ab Aktivierung durch eine 
Signaländerung in der Sensitivliste) ist theoretisch 0. In der Praxis 
kommt der Takt, dann herrscht Hektik in der Logik, die rechtzeitig vor 
dem nächsten Tkat beendet sein muss.

> Was passieren soll wenn die Flanke waerend des Prozesses kommt
Weil die Laufzeit des Prozesses 0 ist (die simulationszeit bleibt 
einfach stehen), kann keine zweite Flanke während der Berechnung des 
Prozesses auftreten...


BTW: was hat die gepostete Code Beschreibung eigentlich mit deiner 
Aufgabe zu tun?

von Mark W. (kram) Benutzerseite


Lesenswert?

Lothar M. schrieb:
>
> BTW: was hat die gepostete Code Beschreibung eigentlich mit deiner
> Aufgabe zu tun?
Das ist ein Prototyp meiner Ablaufsteuerung. :-)
Funktioniert auch schon halbwegs. Ich moechte verschiedene Signale 
setzen um andere Hardware zu initialisieren.
Also:
Enable Signale setzen
Reset Signale setzen
Addressdaten setzen
usw.
Und das in einer bestimmten zeitlichen Abfolge. Deswegen der 
Zaehlprozess. Es genuegt wenn ich die Zahlstufen als Taktzyklen 
bestimme, denn ich weiss immer wan ich welche Signale setzen muss. Das 
muss einmal bei einem Tastendruck durchlaufen und stehen bleiben.

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


Lesenswert?

Mark W. schrieb:
> Und das in einer bestimmten zeitlichen Abfolge.
Ich würde das anders machen. Mit einer FSM und einem Zähler/Timer, der 
für den jeweils nächsten Zustand neu geladen wird. Den Zuständen in der 
FSM kann man sprechende Namen geben und muss nicht mit "Magic Numbers" 
herumhantieren.

Denn dann könnte ich neben dem stupiden geradlinigen zeitlichen Ablauf 
auch leicht eine Reaktion auf ein anderes z.B. von aussen kommendes 
Signal (z.B. ein Endschalter) in diese FSM einbauen. So könnte ich ganz 
leicht in den Ablauf des Kaffeeautomaten mit der Beschreibung FSM0b aus 
dem Beitrag "Re: Hilfe für Code - VHDL" eine Wartezeit 
einbauen.

Oder ich kann mit dieser FSM ganz einfach eine Zeit mittendrin um 5 
Takte verlängern, ohne alle nachfolgenden Zeiten entsprechend anpassen 
zu müssen...

von wendelsberg (Gast)


Lesenswert?

Mark W. schrieb:

> Also:
> Enable Signale setzen
> Reset Signale setzen
> Addressdaten setzen
> usw.
>
Warum tut man sich das an, das mit Logik machen zu wollen? Zeitkritisch, 
sehr schnell oder was fuer Gruende sprechen dafuer?

wendelsberg

von Mark W. (kram) Benutzerseite


Lesenswert?

wendelsberg schrieb:
> Mark W. schrieb:
>
>> Also:
>> Enable Signale setzen
>> Reset Signale setzen
>> Addressdaten setzen
>> usw.
>>
> Warum tut man sich das an, das mit Logik machen zu wollen? Zeitkritisch,
> sehr schnell oder was fuer Gruende sprechen dafuer?

Naja, ich habe mir erst ueberlegt eine CPU oder sowas zu nehemn, aber 
das habe ich dann schnell aufgegeben, ist vermutlich ovekill.
Dann habe ich es mit einer FSM gemacht, hat auch funktioniert.
Dann habe ich mir gedacht, man kann die "case when" ja auch rausnehemn 
um die Sache zu vereinfachen.
Jetzt will ich nur noch den Startimpuls einbauen und nach einmaligem 
Durchlaufen zuruecksetzen.
Wenn das nicht klappt, gehe ich wieder zurueck zur FSM.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Mark W. schrieb:
> Nun weiss ich nicht, wie ich den Prozess kontrolliert starten kann. Ich
> moechte, dass er bei einer Flanke anlaeuft und einmal durchlaeft und
> dann stehen bleibt.
1
-- läuft einmal, bleibt dann stehen
2
process(clk)
3
variable state : integer range 0 to 2 := 0; -- default 0
4
begin
5
  if rising_edge(clk) then
6
    if reset='1' then
7
      -- irgendwas resetten falls notwendig
8
      state:=0;
9
    else
10
      case state is
11
        when 0 =>
12
          if trigger='1' then
13
            state:=1;
14
          end if;
15
        when 1 =>
16
          -- einmalig irgendwas machen
17
          state:= 2;
18
        when 2 =>
19
          -- bleibt für immer in 2
20
        when others =>
21
          state:=0;
22
      end case;
23
    end if;
24
  end if;
25
end if;

oder sowas:
1
-- läuft einmal, bleibt dann stehen
2
process(clk)
3
variable flag : std_logic := '0';
4
begin
5
  if rising_edge(clk) then
6
    if reset='1' then
7
      -- irgendwas resetten falls notwendig
8
      flag:='0';
9
    else
10
      if trigger='1' and flag='0' then
11
        -- einmalig irgendwas machen
12
        flag:='1';
13
      end if;
14
    end if;
15
  end if;
16
end if;

Die erste Version ist halt eine Statemachine - muss man entscheiden, 
welche Variante man eher braucht.

du kannst statt Variablen auch Signale verwendet - Variablen werden ja 
von Leuten, die damit nicht umgehen können, verteufelt ;-)

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


Lesenswert?

Mampf F. schrieb:
> Variablen werden ja von Leuten, die damit nicht umgehen können,
> verteufelt ;-)
Ich nehme gerne Variablen. Nur Anfänger fallen damit gern auf die Nase, 
weil sich diese Variable eben wie eine VHDL-Variable, und somit nicht 
wie von ihnen erwartet verhält... ?

: Bearbeitet durch Moderator
von Mark W. (kram) Benutzerseite


Angehängte Dateien:

Lesenswert?

Ich habe jetzt eine SM genommen und bin jetzt soweit, dass es 
funktioniert wie ich mir das vorgestellt habe. Jedenfalls in der 
Simulation erstmal.
Alles States werden durchlaufen und in der letzten State wird auf das 
Startsignal gewartet.
Wenn das kommt, geht es wieder von vorne los.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Lothar M. schrieb:
> Mampf F. schrieb:
>> Variablen werden ja von Leuten, die damit nicht umgehen können,
>> verteufelt ;-)
> Ich nehme gerne Variablen. Nur Anfänger fallen damit gern auf die Nase,
> weil sich diese Variable eben wie eine VHDL-Variable, und somit nicht
> wie von ihnen erwartet verhält... ?

Ach und weil man sich - bei suboptimaler Verwendung - recht schnell das 
Timing kaputt machen kann, weil man zuviel in einen Clock-Cycle packen 
kann^^ :)

von Mark W. (kram) Benutzerseite


Lesenswert?

Mampf F. schrieb:
> Lothar M. schrieb:
>> Mampf F. schrieb:
>>> Variablen werden ja von Leuten, die damit nicht umgehen können,
>>> verteufelt ;-)
>> Ich nehme gerne Variablen. Nur Anfänger fallen damit gern auf die Nase,
>> weil sich diese Variable eben wie eine VHDL-Variable, und somit nicht
>> wie von ihnen erwartet verhält... ?
>
> Ach und weil man sich - bei suboptimaler Verwendung - recht schnell das
> Timing kaputt machen kann, weil man zuviel in einen Clock-Cycle packen
> kann^^ :)
Danke fuer Eure Tips, werde mit Variablen vorsichtig umgehen. :-)

VHDL soll ja eine Sprache fuer Hardware sein, dafuer sind die Elemente 
aber sehr an Software angelehnt.
Beispiel: Process
Ein Prozess ist ja gerade etwas, was T>0 braucht, sonst waere es ja kein 
Prozess. Man haette vielleicht unit oder design unit fuer parallele 
Ausfuehrung nehmen koennen und process fuer zeitliche Abfolgen.

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


Lesenswert?

Mark W. schrieb:
> dass es funktioniert wie ich mir das vorgestellt habe.
Mir erscheint das Handling des Zählers jetzt unnötig umständlich. Warum 
muss der immer mal wieder zwischendurch anhalten, wenn der Zustand 
weitergeschaltet wird? Damit hast du wieder blitzartig so einen 
"Off-Bay-One" Effekt an der Backe (die Zustände werden jetzt jeweils für 
11 Takte gehalten, obwohl die Zahlen 10,20,30 etwas anderes vermuten 
lassen...).

Mein Ansatz wäre so:
1
:
2
:
3
signal c : integer range 0 to 9 := 9;
4
type state_type is (Idle, S1, S2, S3);
5
signal state : state_type := S1;
6
7
begin
8
9
process(CLK) -- nur CLK relevant
10
begin
11
  if rising_edge(CLK) then
12
    if c>0 then
13
      c <= c-1;
14
    end if;
15
    case next_state is
16
      when Idle =>
17
        if c=0 and ST='1' then
18
          next_state <= S1;
19
          Y <= '0';
20
          Z <= '0';
21
          c <= 9;
22
        end if;
23
      when S1 =>
24
        if c=0 then
25
          next_state <= S2;
26
          Y <= '0';
27
          Z <= '1';
28
          c <= 9;
29
        end if;
30
      when S2 =>
31
        if c=0 then
32
          next_state <= S3;
33
          Y <= '1';
34
          Z <= '0';
35
          c <= 9;
36
        end if;
37
      when S3 =>
38
        if c=0 then
39
          next_state <= Idle;
40
          Y <= '1';
41
          Z <= '1';
42
          c <= 9;
43
        end if;
44
    end case;
45
  end if;
46
end process;
47
:
48
:

Und dann gäbe es noch die von mir bevorzugte Variante, die einfach einen 
Zähler hochzählt und über den Index die Werte abbildet:
1
:
2
:
3
signal c  : integer range 0 to 9 := 9; -- bei Integern immer den Bereich angeben, sonst kann der Simulator bei einem Überlauf nicht meckern
4
signal ci : integer range 0 to 3 := 0;
5
type pattern_t is array (0 to 3) of std_logic_vector(1 downto 0); 
6
signal pattern : pattern_t := ("00","01","10","11");
7
8
begin
9
10
  process begin
11
    wait until rising_edge(CLK);
12
    if c>0 then 
13
      c <= c-1;
14
    else
15
      if ci<3 then       -- Index hochzählen
16
        ci <= ci+1;
17
        c  <= 9;
18
      elsif ST='1' then  -- auf Index 3 warten bis Neustart
19
        ci <= 0;
20
        c  <= 9;
21
      end if;
22
    end if;
23
  end process;
24
25
  X <= pattern(ci)(0);
26
  Y <= pattern(ci)(1);
27
:
28
:

Wenn man da unterschiedliche Zeiten für die einzelnen Zyklen will, dann 
kann man das mit einem zweiten Array erschlagen:
1
:
2
:
3
signal c  : integer range 0 to 9 := 9; -- bei Integern immer den Bereich angeben, sonst kann der Simulator bei einem Überlauf nicht meckern
4
signal ci : integer range 0 to 3 := 0;
5
type pattern_t is array (0 to 3) of std_logic_vector(1 downto 0); 
6
type delay_t is array (0 to 3) of ingeger range 0 to 9;
7
8
signal pattern : pattern_t := ("00","01","10","11");
9
signal delay   : delay_t :=   (  10,   5,   7,   4);
10
11
begin
12
13
  process begin
14
    wait until rising_edge(CLK);
15
    if c>0 then 
16
      c <= c-1;
17
    else
18
      if ci<3 then       -- Index hochzählen
19
        c  <= delay(ci+1)-1;
20
        ci <= ci+1;
21
      elsif ST='1' then  -- bei Index 3 warten bis Neustart
22
        c  <= delay(0)-1;
23
        ci <= 0;
24
      end if;
25
    end if;
26
  end process;
27
28
  X <= pattern(ci)(0);
29
  Y <= pattern(ci)(1);
30
:
31
:

Mark W. schrieb:
> VHDL soll ja eine Sprache fuer Hardware sein
VHDL ist eine Hardware-Beschreibungs-Sprache.

> dafuer sind die Elemente aber sehr an Software angelehnt.
Nur für den, der vorher Software gemacht hat.

> Beispiel: Process
> Ein Prozess ist ja gerade etwas, was T>0 braucht, sonst waere es ja kein
> Prozess.
??? Mir erschließt sich die Logik nicht...

Die Anweisungen in einem Prozess werden vom simulator per Definition 
in der Zeit 0 berechnet. Denn das Hauptproblem von 
Softwareprogrammierern ist, zu meinen, ein Prozess würde wie ein 
Programm Schritt für Schritt "durchlaufen" und "abgearbeitet". Dem ist 
aber nicht so.

> Man haette vielleicht unit oder design unit fuer parallele
> Ausfuehrung nehmen koennen und process fuer zeitliche Abfolgen.
Es gibt keine zeitlichen Abfolgen. Jeder zeitliche Ablauf muss in einen 
Zustandsautomaten gepackt werden. Und dann gibt es einen Takt, der dafür 
sorgt, dass der Zustandsautomat weitergeschaltet wird (auch ein simpler 
Zähler für ein Delay ist ein Zustandsautomat).
Und jeder Zustand des Prozesses samt nachgeschalteter Logik ist 
"parallel" auf dem FPGA vorhanden. Nur eben ggfs. nicht aktiv. Insofern 
ist diese Unterscheidung "parallele Hardware" und "zeitlicher Ablauf" 
nur in deinem Kopf. Im FPGA sind das alles nur LUTs und Flipflops. Mehr 
"Bauteile" hast du für deine Hardware-Beschreibung nicht zur 
Verfügung...

: Bearbeitet durch Moderator
von Mark W. (kram) Benutzerseite


Lesenswert?

Lothar M. schrieb:
...
Die Zahlen 10, 20, 30 sind nur beispielhaft, genau wie die Ausgaenge Y 
und Z, um die Sache gering und einfach zu halten. Sie sollten aber 
variabel einstellbar sein.

Danke fuer das Beispiel, ich werde es mir mal ansehen und ausprobieren.

von Mark W. (kram) Benutzerseite


Lesenswert?

Lothar M. schrieb:

>> Beispiel: Process
>> Ein Prozess ist ja gerade etwas, was T>0 braucht, sonst waere es ja kein
>> Prozess.
> ??? Mir erschließt sich die Logik nicht...

Meinem Verstaendniss nach ist eine Prozess eine zeitliche Abfolge von 
Schritten. Ich brauchte einen Prozess, eine Art Ablaufsteuerung, 
aehnlich wie bei einer SPS oder Aehnlichem.
Also genau das was eine FSM macht mit Hilfe des Taktes und Bedingungen.
Zuerst tue dies, dann jenes und zum Schluss warte...
So langsam erschliesst es sich mir, aber nur sehr langsam. :-)

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


Lesenswert?

Mark W. schrieb:
> Meinem Verstaendniss nach ist eine Prozess eine zeitliche Abfolge von
> Schritten. Ich brauchte einen Prozess, eine Art Ablaufsteuerung,
> aehnlich wie bei einer SPS oder Aehnlichem.
Du darfst nicht versuchen, allgemeine Begriffe aus irgendwelchen anderen 
Welten (SPS oder ähmlichen) auf ein völlig neues Tätigkeitsfeld 
(Hardwarebeschreibung) zu übertragen.

Mark W. schrieb:
> Ich brauchte einen Prozess, eine Art Ablaufsteuerung, aehnlich wie bei
> einer SPS oder Aehnlichem.
Abläufe werden mit FSM gesteuert. Auch in der SPS. Nur heißen die dort 
"Schrittketten", die Zustände werden mit "Merkern" abgebildet usw. usf.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Mark W. schrieb:
> Meinem Verstaendniss nach ist eine Prozess eine zeitliche Abfolge von
> Schritten. Ich brauchte einen Prozess, eine Art Ablaufsteuerung,
> aehnlich wie bei einer SPS oder Aehnlichem.
> Also genau das was eine FSM macht mit Hilfe des Taktes und Bedingungen.
> Zuerst tue dies, dann jenes und zum Schluss warte...
> So langsam erschliesst es sich mir, aber nur sehr langsam. :-)

Nope ...

Es gibt auch kombinatorische Prozesse:
1
process(a, b)
2
begin
3
  c <= a and b;
4
end process;

das wird einfach in eine und-Verknüpfung umgesetzt.

genauso ginge auch
1
c <= a and b;

Prozesse können eine andere Syntax nutzen, aber die gleiche Hardware 
erzeugen.

Beispiel:
1
-- klar, ist ein trivial-beispiel^^
2
c <= '1' when a='0' else '0';
3
4
process(a)
5
begin
6
  if a='0' then
7
    c <= '1';
8
  else
9
    c <= '0';
10
  end if;
11
end process;

if-then-else oder case funktionieren nur in Prozessen zB.

zu 99% verwende ich Prozesse nur für getaktete Logik ´ala
1
process(clk)
2
begin
3
  if rising_edge(clk) then
4
    if reset='1' then
5
      ...
6
    else
7
      ...
8
    end if;
9
  end if;
10
end process;

und zu 99.99999999% nur 'clk' in der Sensitivity-List der Prozesse (löst 
schonmal viele Probleme^^).

Kombinatorisches Zeugs ohne Prozess - außer die anderen 
Syntax-Möglichkeiten bringen mir Vorteile. Das ist aber eher selten der 
Fall.

Beispiel hier:
1
    process(curl_mid_state_low, curl_mid_state_high)
2
    begin
3
        for I in 0 to HASH_LENGTH-1 loop
4
            curl_hash((I*2)/32)((I*2) mod 32) <= curl_mid_state_low(I);
5
            curl_hash((I*2)/32)((I*2) mod 32 + 1) <= curl_mid_state_high(I);
6
        end loop;            
7
    end process;

Da ist ein Prozess für das 'for-loop' schön ... Ginge mit 'generate' 
auch ohne ... aber mei, Geschmackssache^^

Das ist eigentlich so der Brain-F**k, den man bei VHDL nie so wirklich 
los bekommt ... welche Syntax sind innerhalb Prozesse erlaubt, welche 
Außerhalb xD

: Bearbeitet durch User
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.