Hi
Für die Uni sollte ich eine Ampelsteuerung entwickeln. Diese läuft zwar
auch ganz wunderbar auf der Zielhardware, nur leider nicht im Simulator.
Das Design sollte nur mit einem Taktsignal ganz normal durchlaufen. In
Hardware ist das kein Problem und man kann schön dabei zusehen, wie die
Zustände nach der gewünschten Zeit wechseln. Im Simulator passiert
leider rein gar nichts. Das Taktsignal wackelt immer schön hin und her,
aber an den Zuständen ändert sich nichts. Jetzt weiß ich nicht, ob meine
Testbench vielleicht fehlerhaft ist oder ob ich an einer anderen Stelle
etwas übersehen habe. Ich habe sowohl die Taktperiode als auch den
Zählerstand für den Taktteiler variiert, aber getan hat sich am Ausgang
nichts. Ich würde mich sehr über jede Hilfe freuen.
Schöne Grüße
Unabhängig von der Simulator-Frage: Wer hat dir denn erzählt, es gäbe
außerhalb einer Testbench ein "after x ns" Statement??? Mach die mal
alle ganz schnell raus, der Sythesizer müsste dir doch massenhaft
Fehler/Warnungen um die Ohren werfen dafür. Sowas kann man
ausschließlich in der Simulation machen, in der Hardware gibts sowas
nicht.
Zum Simulator: Hast du denn auch ausreichend lange simulieren lassen?
Das mit den "after x ns" ist ein Überbleibsel alter Digitaltechnik
Zeiten. Das Synthesetool (ISE 12.x bzw. 13.1) geht da offensichtlich
einfach drüber. Es gibt weder Warnings noch Fehler wegen dieser
Anweisungen.
Den Simulator habe ich bis zu 10 Sekunden simulieren lassen. Real waren
es also einige Minuten. Bis auf die in der Testbench angegebenen
Stimulisignale ändert sich rein gar nichts.
André M. schrieb:> auch ganz wunderbar auf der Zielhardware, nur leider nicht im Simulator
Ohne mir jetzt Deine Quellen angeguckt zu haben: Das klingt nach
unvollständigen Sensitivitätslisten.
Duke
Wenn die Sensitivlisten falsch sind, dann ist die Simulation falsch. so
einfach ist das. Hier ist zuviel drin:
ANFORDERUNG_HAUPTS: process(CLK, HS1_S, HS2_S, FN_S)
ANFORDERUNG_NEBENS: process(CLK, NS1_S, NS2_S, FH_S)
COUNTER: process(CLK, ENCLK, COUNTER_EN)
Hier würde jeweils der CLK ausreichen, aber das ist noch nicht so
schlimm, damit wird "nur" unnötig viel gerechnet.
Aber hier ist zu wenig drin:
SN: process(ZUSTAND, ANFORDERUNG_NS, ANFORDERUNG_HS, BLINK_S)
Es fehlt COUNT, und das ist natürlich böse, denn genau wenn sich COUNT
ändert, sollte der Prozess neu berechnet werden... :-(
André M. schrieb:> Das Synthesetool (ISE 12.x bzw. 13.1) geht da offensichtlich> einfach drüber. Es gibt weder Warnings noch Fehler wegen dieser> Anweisungen.
Das steht im XST User Guide. Ein after ist auf einem FPGA nicht
synthetisierbar. Bisher von keinem Synthesizer...
André M. schrieb:> Den Simulator habe ich bis zu 10 Sekunden simulieren lassen.> Real waren es also einige Minuten.
Wie kommst du darauf?
Das hier macht aus den 50MHz erst mal 2 Hz. Also vergehen zwischen jedem
Enable 0,5 Sekunden.
1
-- Taktteiler von 50 MHz auf 2 Hz
2
PRESCALER:process(CLK)
3
begin
4
ifCLK='1'andCLK'eventthen
5
ifCNT=25000000then
Wirklich schneller geht die Simulation, wenn du das Enable wesentlich
öfter generierst. So z.B. simuliert das blitzschnell:
1
ifCNT=25then
Warum legst du deinen Reset gleich einen halben Tag lang an? 20ms sind
eine Eeeeeeeeeeeeewigkeit...
Mach das doch so, wenn du schon meinst, einen Reset zu brauchen:
1
-- Stimulus process
2
stim_proc:process
3
begin
4
-- hold reset state for 100 ns.
5
RESET<='1';
6
waitfor100ns;
7
RESET<='0';
8
wait;
9
endprocess;
Du brauchst aber eigentlich keinen Reset, weil du jedem Signal einen
Initialisierungswert zuweisen kannst, also auch deinem ZUSTAND. Ohne
Zuweisung wird hier übrigens immer der erste Wert der Definition
verwendet. In deinem Fall also INIT.
Das passiert dann auch mit deinem Signal COUNT:
signal COUNT : std_logic_vector(4 downto 0);
Weil du dem nie was zuweist, ist der Wert von COUNT anfänglich "UUUUU".
Und dann eins draufaddiert ergibt "XXXXX". Und damit bekommst du niemals
ein sinnvolles Simulationsergebnis.
Beim CNT hast du übrigens aus Versehen Glück gehabt, denn dessen
Init-Wert (der linke Wert des Typs) ist durch den eingeschränkten
Bereich
signal CNT : integer range 0 to 25000000
glücklicherweise 0.
Kurz und gut:
Du solltest also in deiner Simulation alle Signale initialisieren. Am
besten so, dann brauchst du keinen Reset.
Da ist mir dann noch aufgefallen, dass dein Vorteiler falsch läuft. Der
erzeugt nicht aus 50MHz die gewünschten 2Hz, sondern 1,99999992Hz. Und
zwar, weil von 0..24999999 schon 25000000 Zählschritte nötig sind. Du
zählst aber von 0...25000000 = 25000001 Zählschritte.
Und nein. Das "kann man doch vernachlässigen" gilt hier nicht!
Denn diesen Fehler wirst du auch machen, wenn du mal nur bis 16 zählen
willst... :-/
Hi
Danke erstmal für eure Antworten.
Lothar Miller schrieb:> Wenn die Sensitivlisten falsch sind, dann ist die Simulation falsch. so> einfach ist das. Hier ist zuviel drin:> ANFORDERUNG_HAUPTS: process(CLK, HS1_S, HS2_S, FN_S)> ANFORDERUNG_NEBENS: process(CLK, NS1_S, NS2_S, FH_S)> COUNTER: process(CLK, ENCLK, COUNTER_EN)> Hier würde jeweils der CLK ausreichen, aber das ist noch nicht so> schlimm, damit wird "nur" unnötig viel gerechnet.
Ich habe gelernt, dass neben dem Takt auch alle Signale in die
Sensitivityliste sollen, die in if, etc. abgefragt werden.
Lothar Miller schrieb:> André M. schrieb:>> Das Synthesetool (ISE 12.x bzw. 13.1) geht da offensichtlich>> einfach drüber. Es gibt weder Warnings noch Fehler wegen dieser>> Anweisungen.> Das steht im XST User Guide. Ein after ist auf einem FPGA nicht> synthetisierbar. Bisher von keinem Synthesizer...
Die "after x ns" sollen auch nur in der Simulation Sinn machen. Sie
sollen einfach nur Gatterlaufzeiten im Simulator nachbilden.
Lothar Miller schrieb:> André M. schrieb:>> Den Simulator habe ich bis zu 10 Sekunden simulieren lassen.>> Real waren es also einige Minuten.> Wie kommst du darauf?> Das hier macht aus den 50MHz erst mal 2 Hz. Also vergehen zwischen jedem> Enable 0,5 Sekunden.
Wie gesagt, ich habe die Werte auch schon variiert, passiert ist
trotzdem nichts.
Lothar Miller schrieb:> Warum legst du deinen Reset gleich einen halben Tag lang an? 20ms sind> eine Eeeeeeeeeeeeewigkeit...> Mach das doch so, wenn du schon meinst, einen Reset zu brauchen:
Die Testbench und der Ampelcode sind "nur" die aktuellen Fassungen
gewesen, die ich hochgeladen habe. Die Zeiten habe ich ebenfalls
variiert.
Lothar Miller schrieb:> Da ist mir dann noch aufgefallen, dass dein Vorteiler falsch läuft. Der> erzeugt nicht aus 50MHz die gewünschten 2Hz, sondern 1,99999992Hz. Und> zwar, weil von 0..24999999 schon 25000000 Zählschritte nötig sind. Du> zählst aber von 0...25000000 = 25000001 Zählschritte.>> Und nein. Das "kann man doch vernachlässigen" gilt hier nicht!> Denn diesen Fehler wirst du auch machen, wenn du mal nur bis 16 zählen> willst... :-/
Keine Sorge, das wollte ich auch gar nicht vernachlässigen ;-) Ganz im
Gegenteil, ich bin froh, dass du mich darauf nochmal hingewiesen hast.
Mein Code ist an der Stelle natürlich fehlerhaft.
André M. schrieb:> Ich habe gelernt, dass neben dem Takt auch alle Signale in die> Sensitivityliste sollen, die in if, etc. abgefragt werden.
Das ist falsch gelernt. In die Sensitivliste müssen alle Signale, die
eine Neuberechnung des Prozesses erfordern, auf die der Prozess also
empfindlich (=sensitive) zu sein hat.
In der Praxis ist das in einem reinen getakteten Prozess nur der Takt.
Nur eine Änderung des Taktsignals hat Auswirkungen auf das Ergebnis des
Prozesses.
Evtl. kommt dann noch ein asynchroner Reset dazu. Alles was weiters
dabei steht, ist verdächtig...
> Die Testbench und der Ampelcode sind "nur" die aktuellen Fassungen> gewesen, die ich hochgeladen habe. Die Zeiten habe ich ebenfalls> variiert.
Ich habe mal eine Simulation mit den Zeiten aus deinen anfangs
geposteten Files laufen lassen und da meine beiden angesprochenen
Änderungen aus dem Beitrag "Re: [isim] Probleme mit Testbench"
eingebaut:
> 1. die unvollständige Sensitivliste
SN: process(ZUSTAND, ANFORDERUNG_NS, ANFORDERUNG_HS, BLINK_S, COUNT)
> 2. der nicht initialisierte Zähler
signal COUNT : std_logic_vector(4 downto 0) := "00000";
Und nach ein paar Stunden Simulationsdauer kommt das heraus, was du
erwartest...
Sinnvollerweise kannst du den Vorteiler-Wert als Generic machen und
durch den Simulator dann auf einen sinnvoll simulierbar kleinen Wert
setzen lassen (falls ISim das kann, ansonsten gleich den Generic in der
TB fest vorgeben). Somit musst du am Code nix zwischen Simulation und
Hardware ändern.