Hallo,
ich habe ein scheinbar einfaches Verilog-Modul in Quartus II
geschrieben:
1
moduletest(CLOCK,RESET,GO,clk_en,DATA,zaehler);
2
3
inputCLOCK,RESET,GO,clk_en;
4
input[15:0]DATA;
5
output[15:0]zaehler;
6
7
wireCLOCK,RESET,clk_en,GO;
8
wire[15:0]DATA;
9
reg[15:0]zaehler;
10
reg[3:0]state;
11
12
always@(posedgeRESETorposedgeCLOCK)begin
13
if(RESET)begin
14
zaehler<=16'b0;
15
state<=0;
16
endelse
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?
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?
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.
>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
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.
> 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.
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:
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?
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?
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.
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.
@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 :-)
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