www.mikrocontroller.net

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


Autor: Hans-werner M. (hanswerner)
Datum:

Bewertung
0 lesenswert
nicht 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.
clock_process:proces
begin
  clock <= '0';
  wait for clock_period/2;
  clock <= '1';
  wait for clock_period/2;
end process;
Danach der Stimulus.
stim_proc:process
begin
  wait until clock = '1';
  reset <= '1';
  wait for clock_period;
  reset <= '0';
  -- Weitere Zeilen
  --
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

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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!
stim_proc:process
begin
  reset <= '1';
  wait until clock = '1';
  reset <= '0';
  wait for clock_period;
    -- Weitere Zeilen
  --
end process;

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
stim_proc:process
begin
  wait until clock = '1';
  reset <= '1';
  wait until clock = '1';
  reset <= '0';
  -- Weitere Zeilen
  --
end process;

Autor: SuperWilly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

was passiert mit folgender Variante ?

stim_proc:process
begin
  wait until clock = '1';
  reset <= '1';
  wait for clock_period;
  reset <= '0';
  -- Weitere Zeilen
  --
wait;                                    -- !!!
end process;



Gruß,
SuperWilly

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachtrag zu meinem vorigen Post:
Um unvorbereitete Zeitgenossen nicht zu überraschen, empfiehlt sich 
trotzdem diese Schreibweise:
stim_proc:process
begin
  wait until rising_edge(clock);
  reset <= '1';
  wait until rising_edge(clock);
  reset <= '0';
  -- Weitere Zeilen
  --
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).

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Zum Thema Rundungsfehler nehmen wir mal folgende Testbench an
(mit einer Simulationssuflösung von 1 ps):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity Clk_Period_Error is
end Clk_Period_Error;

architecture Behavioral of Clk_Period_Error is
  signal clk2 :  std_logic := '0';
  signal clk  :  std_logic := '0';
   constant clk_period : time := (1 sec / 300000000); -- 300MHz Takt
begin
   clk2 <= not clk2 after clk_period/2;
   clk  <= not clk  after clk_period;
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.

Autor: Hans-werner M. (hanswerner)
Datum:

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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe das nochmal durchgeknetet.

Mit einer restlos durch 2 teilbaren Taktfrequenz wird beim Originalcode
   clock_process: process begin
     clk <= '0';
     wait for clock_period/2;
     clk <= '1';
     wait for clock_period/2;
   end process;
   

   stim_proc: process begin
     wait until clk = '1';
     reset <= '1';
     wait for clock_period;
     reset <= '0';
     :
   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
   stim_proc: process begin
     :
     reset <= '1';
     wait for clock_period + 1 ps;
     reset <= '0';
     :
   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
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.
   stim_proc: process begin
     wait until clk = '1';
     reset <= '1';
     wait for clock_period + 1 ps;
     reset <= '0';
     :
   end process;
2.
   stim_proc: process begin
     wait until clk = '1';
     reset <= '1';
     wait until clk = '1';
     reset <= '0';
     :
   end process;
3.
   stim_proc: process begin
     wait until clk = '0';
     reset <= '1';
     wait for clock_period;
     reset <= '0';
     :
   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.

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.