Forum: FPGA, VHDL & Co. Verilog-Simulation ergibt merkwürdiges Ergebnis


von Frank H. (gowi)


Angehängte Dateien:

Lesenswert?

Hallo,
ich habe ein scheinbar einfaches Verilog-Modul in Quartus II 
geschrieben:
1
module test(CLOCK, RESET, GO, clk_en, DATA, zaehler);
2
3
input CLOCK, RESET, GO, clk_en;
4
input [15:0] DATA;
5
output[15:0] zaehler;
6
7
wire CLOCK, RESET, clk_en, GO;
8
wire [15:0] DATA;
9
reg [15:0] zaehler;
10
reg [3:0] state;
11
12
always @(posedge RESET or posedge CLOCK) begin
13
      if (RESET) begin
14
        zaehler <= 16'b0;
15
        state <= 0;
16
      end else
17
      if (clk_en) begin
18
        if (state == 0 & GO) begin
19
          zaehler <= DATA;
20
          state <= 1;
21
        end
22
      end
23
end
24
endmodule

Der Code ist etwas reduziert, verändert aber das Ergebnis nicht. Im
State 0 soll (wenn GO anliegt), DATA an das zaehler-Register geschrieben
werden. Das Ergebnis ist aber im Anhang gezeigt. Anstatt 0xFFFF liegt an
zaehler 0x3FFF an. Kann sich das jemand erklären?

von Schrotty (Gast)


Lesenswert?

Was ich noch erstaunlicher finde, ist die Tatsache, dass die einzelnen 
Bits deines Zählers zu scheinbar völlig willkürlichen Zeitpunkten ihren 
Zustand wechseln. Und das auch noch komplett asynchron zu den ganzen 
"Steuersignalen"

Wie hast denn das hinbekommen?

Führst du hier vielleicht gerade eine Back-Anotation-Simulation durch?

von Frank H. (gowi)


Lesenswert?

Das finde ich schon weniger verwunderlich. Die Simulation berücksichtigt 
ja die konkrete Synthese und Platzierung auf dem Ziel-FPGA. Und durch 
unterschiedliche Signal- und Gatterlaufzeiten kann es schon zu einigen 
Nanosekunden Unterschied beim Flankenwechsel kommen. Wichtig ist nur, 
dass alle Wechsel bis zur nächsten positiven Taktflanke erfolgt sind.

von Schrotty (Gast)


Lesenswert?

>Die Simulation berücksichtigt ja die konkrete Synthese und Platzierung auf >dem 
Ziel-FPGA.

Aber nicht die funktionale Simulation, sondern erst die 
Backanotation-Simulation.
Oder wird in Quartus nicht funktional simuliert?

Zu deinem Problem:
Ich kenne mich mit Verilog nicht wirklich aus, aber diese Zeile kommt 
mir seltsam vor:

always @(posedge RESET or posedge CLOCK) begin

Wenn tatsächlich synthetisiert wird, dann wird dieser Code vermutlich 
ein schlechtes Ergebnis bringen.
Es wird ein Register mit der einen ODER der anderen Flanke geschaltet.
Das führt auf jeden Fall zu einem asynchronen Design, wenn die Synthese 
es überhaupt akzeptiert hat.

In einem synchronen Design schalten ALLE Register mit dem gleichen Takt 
und bitte NUR mit diesem Takt.

Probier´s mal so:

always @ (posedge CLOCK) begin

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


Lesenswert?

Was ist das Gegenteil von inaktzeptabel? Klar: akzeptabel.
Was ist das Gegenteil von intolerant?    Klar: tolerant.
Was ist das Gegenteil von intuitiv?   Logisch: ... ;-)

Ich finde Verilog mit seinen Sensitivlisten so sehr tuitiv, denn mit der 
Zeile:
>>> always @(posedge RESET or posedge CLOCK) begin
wird ein asynchroner high-aktiver Reset und ein auf die steigende Flanke 
sensitiver Takt beschrieben. Nur ist hier irgendwie die fallende Flanke 
oder gar der Pegel des Reset laut Beschreibung gar nicht weiter 
interessant.
Siehe dazu auch http://de.wikipedia.org/wiki/Verilog
Ich kann mir jetzt gerade gar kein Bauteil vorstellen, das mit einer 
steigenden Flanke zurückgesetzt wird, der Pegel dieses Reset-Signals 
danach aber uninteressant ist  :-o
Dass der Reset aber durchaus pegelsensitiv implementiert werden wird, 
ist implizites Wissen, das ich zum Verstehen einer Verilog-Beschreibung 
unbedingt brauche.

Zum Thema:
Mich würde mal das Laufzeitverhalten des Signals state brennend 
interessieren. Und natürlich wäre eine Verhaltenssimulation statt 
einer Post-Route-Simulation als erster Schritt auch nicht ohne.

von Morin (Gast)


Lesenswert?

> Ich kann mir jetzt gerade gar kein Bauteil vorstellen, das mit einer
> steigenden Flanke zurückgesetzt wird, der Pegel dieses Reset-Signals
> danach aber uninteressant ist  :-o

Ich schon: Nach einer steigenden Flanke ist der Pegel immer "high". Da 
der Pegel eh immer derselbe ist, ist er auch nicht mehr interessant. Das 
wird ja mit der Clock genauso gemacht.

Ob die Tools das genauso sehen steht natürlich auf einem anderen 
Blatt...

Spielt aber hier keine Rolle: Da auf zwei verschiedene Signale 
gleichzeitig gewartet wird, muss danach überprüft werden, welches denn 
nun eine Flanke hatte.

von SuperWilly (Gast)


Lesenswert?

Hi,

ein paar Anmerkungen:

1. Die wires sind unnötig.
2. Sind "GO", "clk_en", "DATA" taktsynchron ?
1
module test(CLOCK, RESET, GO, clk_en, DATA, zaehler);
2
3
input CLOCK, RESET, GO, clk_en;
4
input [15:0] DATA;
5
output[15:0] zaehler;
6
7
reg [15:0] zaehler;
8
reg [3:0] state;
9
10
always @(posedge RESET or posedge CLOCK) begin
11
      if (RESET) begin
12
        zaehler <= 16'b0;
13
        state <= 0;
14
      end else
15
      if (clk_en) begin
16
        if (state == 0 & GO) begin
17
          zaehler <= DATA;
18
          state <= 1;
19
        end
20
      end
21
end
22
endmodule

Gruß,
SuperWilly

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


Lesenswert?

Morin schrieb:
> Ich schon: Nach einer steigenden Flanke ist der Pegel immer "high". Da
> der Pegel eh immer derselbe ist, ist er auch nicht mehr interessant. Das
> wird ja mit der Clock genauso gemacht.
Ok. Klar, jetzt :-/
Aber trotzdem tuitiv...
Warum werden dann bei Verilog nicht wie bei VHDL üblich nur die Signale 
in die Sensitivliste aufgenommen und die Flankenabhängigkeit im 
Quelltext aufgeführt? Ich könnte doch auch so schreiben:
1
always @(RESET or CLOCK) begin
2
  if (RESET) begin      *** pegelsensitiv
3
    :
4
  end else
5
    if (CLOCK) begin    *** steigende Flanke
6
       :
7
    end
8
  end
9
end

von SuperWilly (Gast)


Lesenswert?

@ Schrotty
--Es wird ein Register mit der einen ODER der anderen Flanke geschaltet.

Falsch!

1
always @(posedge RESET or posedge CLOCK)
2
begin
3
    if (RESET) begin
4
      
5
    end else
6
    if (clk_en) begin
7
       
8
    end
9
end
10
endmodule


ist in VHDL mit einem getakteten Prozess mit asynchronem Reset 
gleichzusetzen:

1
process(RESET, CLOCK)
2
begin
3
    if RESET = '1' then
4
5
6
    elsif rising_edge(CLOCK) then
7
8
        if clk_en = '1' then
9
10
        end if;
11
12
    end if;
13
end process;

Gruß,
SuperWilly

von Igor (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
Selbst ohne Verbesserungen klappt dieser Code bei mir vollkommen 
korrekt.
Quartus 4.1, Device - EP1C3T100C6

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


Lesenswert?

Igor schrieb:
> Quartus 4.1, Device - EP1C3T100C6
Du hast deutlich kürzere Verzögerungszeiten (5ns statt 10 ns).
Im Bild  Frank Hans (gowi) sind es 10ns. Aber der Reset geht nur 5ns vor 
der steigenden Flanke vom Clock weg. Evtl. ist das zu knapp...

Was passiert, wenn du den Zeitpunkt, an dem der Reset inaktiv wird, in 
deiner Post-Route-Simulation auf 57 oder 58 ns setzt?

von Frank H. (gowi)


Lesenswert?

Das ist (fast) das Problem!
Wird der Reset eher inaktiv, ändert das nichts am Verhalten. Wenn ich 
aber clk_en und GO eher auf HIGH setze, dann erhalte ich das erwartete 
Simulationsergebnis.

Also war das Problem, dass der Wechsel der Steuersignale auf den 
HIGH-Pegel die Setup-Time der entsprechende Flipflops verletzt hat?
In meinem Gesamtdesign sollte das dann nicht vorkommen, weil die 
Steuersignale taktsynchron erzeugt werden.

Aber was ist, wenn die Steuersignale extern erzeugt werden? Dann kann im 
worst-case doch durchaus das Simulations-Szenario eintreten? Müssten 
dann diese Signale erst "einsynchronisiert" werden?

von Igor (Gast)


Angehängte Dateien:

Lesenswert?

Lothar Miller schrieb:
> Was passiert, wenn du den Zeitpunkt, an dem der Reset inaktiv wird, in
deiner Post-Route-Simulation auf 57 oder 58 ns setzt?

Es ist nichts passiert.

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


Lesenswert?

Frank Hans schrieb:
> Also war das Problem, dass der Wechsel der Steuersignale auf den
> HIGH-Pegel die Setup-Time der entsprechende Flipflops verletzt hat?
Asynchrone Resets sind allgemein schlecht, weil sie durch 
unterschiedliche Laufzeiten unterschiedlich schnell an den FFs ankommen 
und insbesondere auch inaktiv werden. Ich habe da mal einen einfachen 
Aufbau dazu gemacht, der in der Praxis genau das von dir beschriebene 
Verhalten aufweist:
http://www.lothar-miller.de/s9y/archives/70-Asynchroner-Reset.html

Igor schrieb:
> Es ist nichts passiert.
Dann hängt es an den Laufzeiten der asynchronen Steuersignale...
Da hilft nur: Einsynchronisieren.

von Schrotty (Gast)


Lesenswert?

@SuperWilly:
Danke für den Hinweis.. wie gesagt, ich hab keine Ahnung von Verilog, 
aber mit ist das eben sofort in´s Auge gestochen.. aber mir war da nicht 
klar, dass es sich um eine sensitivity-List wie bei einem process 
handelt.
Bin halt doch ein VHDL-Kind :-)
Aber so lernt man nie aus...

@Lothar Miller:
tuitiv scheint hier wirklich das passende Wort zu sein.. sollen sich die 
Amis damit rumschlagen, ich bleib beim VHDL :-)

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Lothar Miller schrieb:
> Morin schrieb:
>> Ich schon: Nach einer steigenden Flanke ist der Pegel immer "high". Da
>> der Pegel eh immer derselbe ist, ist er auch nicht mehr interessant. Das
>> wird ja mit der Clock genauso gemacht.
> Ok. Klar, jetzt :-/

Klar ist der Pegel interessant. Der wird jedesmal abgefragt, wenn 
während des Reset eine Taktflanke auftritt. Daher geht auch das hier 
nicht:
1
always @(RESET or posedge CLOCK)
2
begin
3
    if (RESET)
4
    ...
5
    else if (CLOCK)
6
    ...
7
end

Wenn RESET deaktiviert wird, während CLOCK==1, dann wird der else-if 
Zweig ausgeführt.

> Aber trotzdem tuitiv...

Das kommt auf den Standpunkt an.

> Warum werden dann bei Verilog nicht wie bei VHDL üblich nur die Signale
> in die Sensitivliste aufgenommen und die Flankenabhängigkeit im
> Quelltext aufgeführt?

Genauso könnte man die Frage stellen, warum VHDL es nicht genauso wie 
Verilog macht. Diese Argumentation ist zwecklos.

Gruß
Marcus

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.