Forum: FPGA, VHDL & Co. Merkwürdiges Verhalten eines Flipflops bei der Simulation


von ti6wb (Gast)


Angehängte Dateien:

Lesenswert?

Moinsen,
ich habe schnell mal eben im Xilinx Project-Navigator ein D-FlipFlop in 
VHDL beschrieben (siehe dff.vhd) Und eine Testbench erzeugen lassen 
(siehe dff_tb.vhd). Soweit so gut. Beschreibe ich meine Clock und meinen 
Stimulus in der Testbench wie folgt:

   clock_process: process
   begin
      while not stop_the_clock loop
         clock <= '0', '1' after clock_period / 2;
         wait for clock_period;
      end loop;
      wait;
   end process;

   stim_proc: process
   begin
      wait for 3*clock_period/2;
      d <= '1';
      wait for clock_period;
      d <= '0';
      wait;
   end process;
END;

so ist die Simulation in Ordnung und liefert das erwartete Ergebnis 
(siehe DFF1.png)

Beschreibe ich meine Clock aber auf folgende Weise:

   clock_process :process
   begin
      clock <= '0';
      wait for clock_period/2;
      clock <= '1';
      wait for clock_period/2;
   end process;

bekomme ich ein völlig anderes und meiner Meinung nach auch falsches 
Verhalten im Simulator (ISIM (Win und Linux) und auch bei GHDL/GtkWave 
angezeigt (siehe DFF2.vhd).

Vielleicht kann mir jemand erklären, warum sich die beiden verschiedenen 
Clock Beschreibungen im Simulator so unterschiedlich verhalten.

Gruß Wolfgang

von Georg A. (Gast)


Lesenswert?

Klingt nach einem Delta-Cycle-Problem, das ist so das 
Setup/Hold-Equivalent der Simulatoren... Das "'1' after clock_period / 
2;" macht die Zuweisung nicht vom Takt-Signal abhängig, sondern direkt 
von der Zeit. D.h. Clk und Data wird wirklich gleichzeitig geändert, der 
FF-Prozess wird erst dann simuliert, wenn sich das stabilisiert hat. 
Damit sieht er schon die geänderten Daten und die Taktflanke, die Werte 
scheinen "durchzurutschen".

Du musst die Testdatenerzeugung echt synchron zum Taktsignal machen, 
d.h. auch ein wait until oder rising_edge. Dann stimmt die Kausalität 
wieder.

Ähnliche Effekte gibt es übrigens, wenn man Takte per Signalzuweisung 
weiterreicht. In der Realität ein Draht, im Simulator aber 
Verzögerungsleitungen mit infinitesimal kurzem Delay, der aber >0 ist.

von berndl k. (bernd_l)


Lesenswert?

ti6wb schrieb:
> clock_process :process
>    begin
>       clock <= '0';
>       wait for clock_period/2;
>       clock <= '1';
>       wait for clock_period/2;
>    end process;

ich mache das so (tut auch mit GHDL):
1
   clk_process : process
2
   begin
3
      loop
4
         clk <= '1';
5
         wait for clk_period/2;
6
         clk <= '0';
7
         wait for clk_period/2;
8
         exit when end_of_sim = '1';
9
      end loop;
10
      wait;
11
   end process;
Unterschied zu deiner Version: loop-statement und exit condition...

von Georg A. (Gast)


Lesenswert?

Das löst das Problem des Threaderstellers aber nur zufällig (Takt 
startet invertiert).

von Klaus Falser (Gast)


Lesenswert?

ti6wb schrieb:
> stim_proc: process
>    begin
>       wait for 3*clock_period/2;
>       d <= '1';
>       wait for clock_period;
>       d <= '0';
>       wait;
>    end process;

Das solltest Du besser so schreiben :
1
    begin
2
        wait until clk = '1'; -- wartet auf steigende Flanke !
3
        wait until clk = '1';
4
        d <= '1';
5
        wait until clk = '1';
6
        d <= '0';
7
       wait;
8
    end process;

Dies garantiert, dass das Signal d kurz NACH der Taktflanke gesetzt 
wird.

von Klaus (Gast)


Lesenswert?

Klaus Falser schrieb:
> Das solltest Du besser so schreiben :    begin
>         wait until clk = '1'; -- wartet auf steigende Flanke !
>         wait until clk = '1';
>         d <= '1';
>         wait until clk = '1';
>         d <= '0';
>        wait;
>     end process;

Steh ich gerade auf dem Schlauch, oder sollte es nicht am besten so 
heißen (so richtig old school synchron halt):
1
begin
2
  wait until rising_edge(clk);  -- wartet auf steigende Flanke !
3
  d <= '1';
4
  wait until rising_edge(clk);
5
  d <= '0';
6
  wait;
7
end process;

von Joe (Gast)


Lesenswert?

Gehüpft wie gesprungen.

von Duke Scarring (Gast)


Lesenswert?

Ich mag den folgenden Einzeiler für die Takterzeugung:
1
signal   simulation_run  : boolean   := true;
2
3
constant tb_clock_period : time      := (1 sec / 50_000_000); -- 50 MHz
4
signal   tb_clock        : std_logic := '0';           -- vordefinieren
5
6
...
7
 
8
tb_clock <= not tb_clock after tb_clock_period / 2 when simulation_run;
9
10
...
11
process
12
begin
13
  ...
14
  simulation_run <= false;
15
  report "simulation end" severity note;
16
  wait;
17
end process;

Mit simulation_run müssen dann alle Takt-/Signalquellen abgeschaltet 
werden. So kommt man ohne den häßlichen failure aus der Simulation 
raus.

Duke

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


Lesenswert?

ti6wb schrieb:
> bekomme ich ein völlig anderes und meiner Meinung nach auch falsches
> Verhalten im Simulator
Lustigerweise beschreibst du mit der ganz am Anfang gezeigten Erzeugung 
von 'd' im stim_proc genau das, was an/in einem FPGA zu Metastabilität 
führen wird: die Eingangsdaten (hier 'd') ändern sich nicht WEGEN des 
Takts sondern GENAU GLEICHZEITIG zum Takt.
Und damit ist bei der steigenden Flanke an 'clock' auch schon der "neue" 
Pegel an 'd' zu finden. Das Stichwort hat Georg schon dazu geliefert.

So gesehen sind beide Simulationsergebnisse RICHTIG, denn mit genau 
diesem D-FF und dieser Beschreibung der FPGA-Umgebung können auch beide 
Waveforms in der Realität herauskommen...  :-o

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.