Forum: FPGA, VHDL & Co. Synchroner Reset in der Testbench


von Hans-werner M. (hanswerner)


Lesenswert?

Ich habe in meinem VHDL-Programm die asynchronen Resets in synchrone 
Resets geändert. Leider funktioniert es nun nicht mehr.
Was ist die Ursache ?
Hier der ganz normale Clock in der Testbench.
1
clock_process:proces
2
begin
3
  clock <= '0';
4
  wait for clock_period/2;
5
  clock <= '1';
6
  wait for clock_period/2;
7
end process;
Danach der Stimulus.
1
stim_proc:process
2
begin
3
  wait until clock = '1';
4
  reset <= '1';
5
  wait for clock_period;
6
  reset <= '0';
7
  -- Weitere Zeilen
8
  --
9
end process;
Das Reset-Signal wird (Synchron) so nicht erkannt.
Ein asynchrones Reset funktioniert.
Es funktioniert ebenfalls wenn ich das Reset-Signal länger anlege also 
"wait for 2*clock_period" hineinschreibe.
Ob ich "wait until clock = '1'" oder "wait until rising_edge(clock)" 
schreibe macht hier keinen Unterschied.
Funktioniert der synchrone Reset in der Testbench nur wenn ich das 
Reset-Signal in einem eigenen Prozess formuliere ?

Simuliert mit Xilinx ISE 11.1

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Hans-werner M. schrieb:
> Das Reset-Signal wird (Synchron) so nicht erkannt.
Der Reset muß VOR der Taktflanke bereits seinen Wert haben wie bei 
allen anderen Signalen auch!
1
stim_proc:process
2
begin
3
  reset <= '1';
4
  wait until clock = '1';
5
  reset <= '0';
6
  wait for clock_period;
7
    -- Weitere Zeilen
8
  --
9
end process;

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


Lesenswert?

> Ob ich "wait until clock = '1'" oder "wait until rising_edge(clock)"
> schreibe macht hier keinen Unterschied.
Weil es keinen Unterscheid gibt.

> clock_period/2;
Was ist denn dein Clock? Kann es da Rundungsfehler geben?
So z.B. dass gelten könnte
   2*(clock_period/2) < clock_period

Wenn du dich wirklich synchron an den Takt hängen willst solltest du es 
auch nur vom Takt abhängig machen:
1
stim_proc:process
2
begin
3
  wait until clock = '1';
4
  reset <= '1';
5
  wait until clock = '1';
6
  reset <= '0';
7
  -- Weitere Zeilen
8
  --
9
end process;

von SuperWilly (Gast)


Lesenswert?

Hallo,

was passiert mit folgender Variante ?
1
stim_proc:process
2
begin
3
  wait until clock = '1';
4
  reset <= '1';
5
  wait for clock_period;
6
  reset <= '0';
7
  -- Weitere Zeilen
8
  --
9
wait;                                    -- !!!
10
end process;

Gruß,
SuperWilly

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


Lesenswert?

Nachtrag zu meinem vorigen Post:
Um unvorbereitete Zeitgenossen nicht zu überraschen, empfiehlt sich 
trotzdem diese Schreibweise:
1
stim_proc:process
2
begin
3
  wait until rising_edge(clock);
4
  reset <= '1';
5
  wait until rising_edge(clock);
6
  reset <= '0';
7
  -- Weitere Zeilen
8
  --
9
end process;

BTW:
Welche Reset-Quelle soll denn damit simuliert werden? Ich kenne keine, 
die genau 1 Taktzyklus lang aktiv ist.

Mein Vorschlag:
Mach den Reset ganz raus. Du brauchst ihn nicht.
(Diese Aussage trifft in 99% der Fälle zu).

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


Angehängte Dateien:

Lesenswert?

Zum Thema Rundungsfehler nehmen wir mal folgende Testbench an
(mit einer Simulationssuflösung von 1 ps):
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity Clk_Period_Error is
6
end Clk_Period_Error;
7
8
architecture Behavioral of Clk_Period_Error is
9
  signal clk2 :  std_logic := '0';
10
  signal clk  :  std_logic := '0';
11
   constant clk_period : time := (1 sec / 300000000); -- 300MHz Takt
12
begin
13
   clk2 <= not clk2 after clk_period/2;
14
   clk  <= not clk  after clk_period;
15
end Behavioral;
Und sehen uns nach 3,333 ns an, was passiert ist (Screenshot).

Ganz klar ist zu sehen, dass
(3,333ns)/2 + (3,333ns)/2 = 1,6665 ns + 1,6665 ns
wegen der Simulationsauflösung (1 ps) zu
1,666 ns + 1,666 ns = 3,332 ns
zurückgeschnitten werden.
Und das ist natürlich weniger als 3,333 ns.
Fazit: clk2 schaltet 1 ps früher als clk.

von Hans-werner M. (hanswerner)


Lesenswert?

Hallo Läubi,

du hast ja sowas von Recht.

Der Reset muß VOR der Taktflanke bereits seinen Wert haben wie bei
allen anderen Signalen auch!

Habe aber noch Schwierigkeiten mit dem "Vor". "Vor" meint doch hier 
"zeitlich vor". Wie erklärt sich denn der Zeitunterschied ?
Zu welchem Zeitpunkt wird denn "reset <= '1'" ausgeführt ?

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


Lesenswert?

Hans-werner M. schrieb:
> Zu welchem Zeitpunkt wird denn "reset <= '1'" ausgeführt ?
Bezogen auf deinen ersten Post?
Gleichzeitig mit der steigenden Flanke von clock.
Aber eben als Reaktion auf die steigende Flanke...

EDIT:
> Hallo Läubi,
> du hast ja sowas von Recht.
Sieh dir doch mal das Timing an. Ausgehend von einem Defaultwert von '0' 
auf clock hast du mit Läubis Variante 1,5 Takte lang deinen Reset 
anliegen :-o

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


Lesenswert?

Ich habe das nochmal durchgeknetet.

Mit einer restlos durch 2 teilbaren Taktfrequenz wird beim Originalcode
1
   clock_process: process begin
2
     clk <= '0';
3
     wait for clock_period/2;
4
     clk <= '1';
5
     wait for clock_period/2;
6
   end process;
7
   
8
9
   stim_proc: process begin
10
     wait until clk = '1';
11
     reset <= '1';
12
     wait for clock_period;
13
     reset <= '0';
14
     :
15
   end process;
der Reset genau zur steigenden Flanke von clk inaktiv. Der Prozess, 
der clk auswertet, sieht dann bereits eine '0' und wird den reset 
nicht mehr bearbeiten.

Mit 1 ps mehr
1
   stim_proc: process begin
2
     :
3
     reset <= '1';
4
     wait for clock_period + 1 ps;
5
     reset <= '0';
6
     :
7
   end process;
ist der reset bei der Flanke noch aktiv und er wird ausgeführt.

Mit einer ungeraden Taktfrequenz ergibt sich der oben beschriebene 
Effekt
1
2*(clock_period/2) < clock_period
allerdings mit dem Vorteil, dass clock_period dadurch automatisch 1 ps 
länger ist, und damit der Reset erkannt wird.

Funktionieren würde also
1.
1
   stim_proc: process begin
2
     wait until clk = '1';
3
     reset <= '1';
4
     wait for clock_period + 1 ps;
5
     reset <= '0';
6
     :
7
   end process;
2.
1
   stim_proc: process begin
2
     wait until clk = '1';
3
     reset <= '1';
4
     wait until clk = '1';
5
     reset <= '0';
6
     :
7
   end process;
3.
1
   stim_proc: process begin
2
     wait until clk = '0';
3
     reset <= '1';
4
     wait for clock_period;
5
     reset <= '0';
6
     :
7
   end process;
Wobei die 3. Lösung einen Takt Latency ins Spiel bringt. Am saubersten 
und formal richtig ist in einem synchronen Design die 2. Lösung.

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.