Forum: FPGA, VHDL & Co. VGA Versuch - Problem beim Simulieren


von Samuel J. (capstrovor)


Angehängte Dateien:

Lesenswert?

Hallo

ich probiere seit lange wieder mal was mit meinem DE0.
Das letzte mal habe ich den VGA-Controller nicht hinbekommen und wollte 
es jetzt weiterversuchen.
Ich habe beim letzten Mal den Fehler gemacht, alles in eine Datei bzw. 
in eine Entity zu schreiben.
Jetzt habe ich als erstes die signals-Entity geschrieben, welche das 
vsync und das hsync signal ausgibt.
Ich habe das ganze simuliert, allerdings zählt der Zähler überhaupt 
nicht so wie er soll und dadurch natürlich auch nicht v- und hsync.
Hier der Code der signal-Entity:
1
library IEEE;
2
use ieee.std_logic_1164.all;
3
4
entity signals is
5
port
6
(
7
  clk: in std_logic;
8
  vsync: out std_logic;
9
  hsync: out std_logic;
10
  drawEN: out std_logic
11
);
12
end entity;
13
14
architecture behav of signals is
15
type count is range 0 to 800;
16
signal hcount: count:=0;
17
signal vcount: count:=0;
18
begin
19
  process(clk) begin
20
    if(rising_edge(clk)) then
21
      hcount <= hcount + 1;
22
      if(hcount > 799) then
23
        hcount <= 0;
24
        vcount <= vcount + 1;
25
      end if;
26
      if(vcount > 520) then
27
        vcount <= 0;
28
      end if;
29
      
30
      if(hcount >= 0 AND hcount < 96) then
31
        hsync <= '0';
32
      else
33
        hsync <= '1';
34
      end if;
35
      
36
      if(vcount >= 0 AND vcount < 2) then
37
        vsync <= '0';
38
      else
39
        vsync <= '1';
40
      end if;
41
      
42
      if(hcount > 143 AND hcount < 783 AND vcount > 31 AND vcount < 510) then
43
        drawEN <= '1';
44
      else
45
        drawEN <= '0';
46
      end if;
47
    end if;
48
  end process;
49
end behav;

Und hier noch die Top-Level entity:
1
library IEEE;
2
use ieee.std_logic_1164.all;
3
4
entity vgaTop is
5
port
6
(
7
  clk50: in std_logic;
8
  hsync: out std_logic;
9
  vsync: out std_logic;
10
  r: out std_logic_vector(3 downto 0);
11
  g: out std_logic_vector(3 downto 0);
12
  b: out std_logic_vector(3 downto 0)
13
);
14
end entity;
15
16
architecture behav of vgaTop is
17
  Component signals
18
    Port(
19
      clk: in std_logic;
20
      vsync: out std_logic;
21
      hsync: out std_logic;
22
      drawEN: out std_logic);
23
  end Component;
24
  
25
  signal drawEN: std_logic;
26
begin
27
  signals1: signals Port Map(clk50, vsync, hsync, drawEN);
28
end behav;

im Anhang noch das Bild der Simulation.

lg

von Achim S. (Gast)


Lesenswert?

in der Verhaltenssimulation sollte der Code funktionieren, ich sehe ihm 
keinen Fehler an.

Allerdings zeigt dein Simulationsergebnis keine Verhaltenssimulation 
sondern eine Timingsimulation, oder? Sonst würden die Signale ja bei der 
Taktflanke umschalten, und nicht kreuz und quer verteilt.

Was für eine Taktfrequenz hast du denn in der Simu vorgegeben? Und hast 
du per constraints geprüft, dass dein Design diese Frequenz schafft?

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


Lesenswert?

Probiers mal mit einem Integer-Subtype zum Zählen statt des 
selbstdefinierten count-Typs...

von Fpgakuechle K. (Gast)


Lesenswert?

Statt
type count is range 0 to 800;

besser:
subtype count is integer range 0 to 800;

von Achim S. (Gast)


Angehängte Dateien:

Lesenswert?

integer-subtype zum Zählen wäre sinnvoll. Aber der Isim läuft auch mit 
dem Orginalcode des TO und zeigt (in der Verhaltenssimu) genau das 
Verhalten, das man erwartet

von Fpgakuechle K. (Gast)


Lesenswert?

Ja der Simulator verhält sich irgendwie besoffen, das schaut mir auch 
nicht nach Timing-simu aus.

MfG,

von Achim S. (Gast)


Lesenswert?

wenn CLK50 in der Simu mit ein paar GHz läuft, dann könnte es schon eine 
Timing-Simu sein ;-)

Die Zeitskala sieht man den Ausschnitt ja nicht an.

von Fpgakuechle K. (Gast)


Lesenswert?

Achim S. schrieb:
> wenn CLK50 in der Simu mit ein paar GHz läuft, dann könnte es schon eine
> Timing-Simu sein ;-)
>
> Die Zeitskala sieht man den Ausschnitt ja nicht an.

Hm, bei 5 GHz erwarte ich timing violations die in der Timing (aka 
Post-P&R)- Simulation mit 'X' angezeigt werden sollten. Davon ist auch 
nix zu sehen. Manchmal liegt es am falschen "Radix" im Waveform also 
signed/unsigned/Hex statt integer - aber danach schaut es auch nicht aus 
...

von Joschua C. (Gast)


Lesenswert?

Ist das Design so eigentlich synthetisierbar? Wenn die Zuweisung, die 
vcount oder hcount auf 0 springen lassen aktiv werden, sind die count <= 
count + 1 Zuweisungen doch noch aktiv, die den jeweiligen Zähler 
hochzählen lassen?

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


Lesenswert?

Im Prozess "gewinnt" die letzte Zuweisung an ein Signal...

von Joschua C. (Gast)


Lesenswert?

Wieder was gelernt, danke

von Samuel J. (capstrovor)


Lesenswert?

Hallo

Danke für die ganzen Antworten!
Also liegt es in dem Fall nicht an meinem Code, sondern am Simulator?
Ich habe es auch schon mit sehr niedrigen Frequenzen versucht (200kHz 
oder so) und da war das gleiche Problem...
Ich habe mit Quartus II simuliert...
Verwendet ihr immer die Simulatoren, die in den IDEs (also Quartus II, 
Xilinx, usw) oder externe Simulatoren? Wenn ja, welchen könntet ihr mir 
empfehlen (wäre cool, wenn es den auch für Mac OS X geben würde).

lg

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


Lesenswert?

Quartus verwendet doch eh ModelSim von Mentor...

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


Angehängte Dateien:

Lesenswert?

Samuel J. schrieb:
> Also liegt es in dem Fall nicht an meinem Code, sondern am Simulator?
WAS simulierst du?
Machst du eine Verhaltenssimulation oder eine Timingsimulation?

Mit dem Vivado-Simulator funktioniert der Code auf jeden Fall auch 
problemlos...

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


Angehängte Dateien:

Lesenswert?

Auch der Aldec Simulator kann es, aber erst nachdem ein paar Zeilen 
geändert wurden:
1
    :
2
    :
3
    if(rising_edge(clk)) then
4
      if(hcount < 800) then
5
        hcount <= hcount + 1;
6
      else
7
        hcount <= 0;
8
        vcount <= vcount + 1;
9
      end if;
Beim ORiginalcode mosert er vollkommen zu Recht:
1
# RUNTIME: Fatal Error: RUNTIME_0043 vgacontroller.vhd (29): Value 801 out of range (0 to 800).
2
# KERNEL: Time: 16010 ns,  Iteration: 0,  Instance: /tb_topVGA/tvga/signals1,  Process: line__20.
3
# KERNEL: Stopped at time 16010 ns + 0.
4
# Error: Fatal error occurred during simulation.
Denn hier wird der hcount vor dem Zurücksetzen auf 801 hochgezählt und 
verlässt so seinen Wertebereich...

: Bearbeitet durch Moderator
von Fpgakuechle K. (Gast)


Lesenswert?

Lothar M. schrieb:
> Auch der Aldec Simulator kann es, aber erst nachdem ein paar Zeilen
> geändert wurden:

> Beim ORiginalcode mosert er vollkommen zu Recht:

?? beim Orginalcode (Beitrag ganz oben) steht doch:
    if(hcount > 799) then
        hcount <= 0;

und das ist äquivalent zu

>       if(hcount < 800) then
        ...
>       else
>         hcount <= 0;

 Da kann es die Fehlermeldung:


> # RUNTIME: Fatal Error: RUNTIME_0043 vgacontroller.vhd (29): Value 801
> out of range (0 to 800).

eigentlich nicht geben.

? Welchen Orginalcode meinst du?

MfG,

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


Lesenswert?

Fpga K. schrieb:
> ? Welchen Orginalcode meinst du?
Den vom ersten Post...

> ?? beim Orginalcode (Beitrag ganz oben) steht doch:
>     if(hcount > 799) then
>         hcount <= 0;
Richtig. Aber bei 799 wird der Zähler noch auf 800 erhöht. Und im 
nächsten Takt wird er (vorübergehend!) auf 801 hochgezählt, um dann zwei 
Zeilen weiter drunter auf 0 zurückgesetzt zu werden.
Und jetzt kommt das Unbestimmte, das die unterschiedliche Reaktion 
begünstigt: ausserhalb des Prozesses hat der Zähler niemals mehr als 
800. Aber er hätte beim "Einzelschrittbetrieb" innerhalb des Prozesses 
kurz den Wert 801.

> und das ist äquivalent zu
Nein, genau das ist es nicht: im "Originalfall" wird unkonditioniert 
weitergezählt. In meiner "korrigierten" Version wird erst abgefragt und 
dann entweder gezählt oder zurückgesetzt.
Ich kann mit beiden Resultaten (Vivado und Aldec) leben, die 
Beschreibung ist an dieser aber so unsauber, dass ich eher Richtung 
Aldec tendiere...

Ganz am Rande: die 0..800 sind der übliche Gartenzaunpfosten-Fehler. Das 
sind nämlich nicht wie gewünscht 800 Takte, sondern es sind 801 Takte...

: Bearbeitet durch Moderator
von Samuel J. (capstrovor)


Lesenswert?

Ich versteh nicht ganz wieso der counter auf 801 gesetzt wird.
Wenn ich schreibe:
1
if(hcount > 799) then
2
   hcount <= 0;
3
else
4
   hcount <= hcount + 1;
5
end if;

Dann sollter er ja eigentlich bei 800 nicht mehr den Befehl in der 
else-Bedingung ausführen, oder?

> Ganz am Rande: die 0..800 sind der übliche Gartenzaunpfosten-Fehler. Das
> sind nämlich nicht wie gewünscht 800 Takte, sondern es sind 801 Takte...
Ja das ist mir auch schon aufgefallen... hab ich schon ausgebessert :)

> WAS simulierst du?
> Machst du eine Verhaltenssimulation oder eine Timingsimulation?
Eine Verhaltenssimulation

lg

von Fpgakuechle K. (Gast)


Lesenswert?

Samuel J. schrieb:
> Ich versteh nicht ganz wieso der counter auf 801 gesetzt wird.
> Wenn ich schreibe:
>
1
> if(hcount > 799) then
2
>    hcount <= 0;
3
> else
4
>    hcount <= hcount + 1;
5
> end if;
6
>
>
> Dann sollter er ja eigentlich bei 800 nicht mehr den Befehl in der
> else-Bedingung ausführen, oder?

Ja, das wird er auch in diesen code-schnipsel nicht. Allerdings hat es 
im Orginal code-schnipsel kein else (wie ich erst jeztz bemerkte):


da steht:
      hcount <= hcount + 1;
      if(hcount > 799) then
        hcount <= 0;
        vcount <= vcount + 1;
      end if;

Steht das signal hcount bei process-eintritt auf 799 wird es erst bei 
process-ende auf den neuen Wert -800- gesetzt so dass der If-zweig nicht 
abgearbeitet (da bis zum processende auf 799) wird, aber beim nächsten 
process-eintritt auf 801 hochtickert.
Das ist halt ein Unterschied zwischen VHDL-signal und variable.

MfG,

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


Lesenswert?

Samuel J. schrieb:
>> WAS simulierst du?
>> Machst du eine Verhaltenssimulation oder eine Timingsimulation?
> Eine Verhaltenssimulation
Dann ist es im Prinzip schnurzegal, ob du mit 5GHz oder 5µHz taktest. 
Kurioses Ergebnis...

Fpga K. schrieb:
> aber beim nächsten process-eintritt auf 801 hochtickert. Das ist halt
> ein Unterschied zwischen VHDL-signal und variable.
Eigentlich nicht.
Denn der hcount ist ja ein Signal, das seinen neuen Wert erst am 
Ende des Prozesses übernehmen sollte. Die Zehl 801 ist da also nur 
vorübergehend vorhanden, man könnte es wie Vivado halten und 
vorausschauend sagen: das ist ein theoretischer Wert, der wird dem 
Signal nie zugewiesen, weil er vor dem Ende des Prozesses zurückgesetzt 
wird.

von Fpgakuechle K. (Gast)


Lesenswert?

Lothar M. schrieb:

> man könnte es wie Vivado halten und
> vorausschauend sagen: das ist ein theoretischer Wert, der wird dem
> Signal nie zugewiesen, weil er vor dem Ende des Prozesses zurückgesetzt
> wird.

Vielleicht liegt es auch daran, das bei vivado-isim defaultmäßig range 
checking deaktiv ist. War jedenfalls bei mir der Fall.

MfG,

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


Angehängte Dateien:

Lesenswert?

Fpga K. schrieb:
> Vielleicht liegt es auch daran, das bei vivado-isim defaultmäßig range
> checking deaktiv ist. War jedenfalls bei mir der Fall.
Ja helle Hölle, das ist tatsächlich so!
Und es wurde schon 2013 als kritischer Punkt angesehen:
https://forums.xilinx.com/t5/Simulation-and-Verification/Isim-natural-counter-exceeds-its-range/td-p/359383/page/3
Ein Simulation, die defaultmäßig nicht auf Einhaltung der Grenzen prüft 
ist den Aufwand nicht wert.

Also frohgemut den Schalter mal eingeschaltet undmanglaubteskaum: der 
läuft mit diesem Code hier
1
      hcount <= hcount + 1;
2
      if(hcount > 810) then
3
        hcount <= 0;
4
        vcount <= vcount + 1;
5
      end if;
trotzdem munter ohne Meldung über die 800 raus. Das muss ich mir bei 
Gelegenheit mal genauer ansehen. Und bis dahin nehme ich den 
Aldec-Simulator...

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.