Forum: FPGA, VHDL & Co. VHDL-Code Funktioniert in Modelsim und auf FPGA nicht


von Tobi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche den Code combine.vhd zum laufen zu bewegen. Unter ModelSim 
funktioniert er wie er soll (siehe Anhang). Leider funktioniert er auf 
den FPGA nicht (der Counter zählt nicht). Über Testpins habe ich 
sichergestellt, dass die Eingangssignale gleich den in der Simulation 
sind. Die Frequenz von clk1 und clk2 betragen jeweils 40kHz und sind um 
180° phasenverschoben. Das high von clk1 und clk2 liegen über 20ns an.
Könnt ihr mir weiterhelfen? Wo ist der Fehler?

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


Lesenswert?

Tobi schrieb:
> Wo ist der Fehler?
In deiner Takterzeugung. So wird das niemals gehen.

Hier werden Setup- und Hold-Zeiten verletzt, das wird niemals 
zuverlässig auf richtiger Hardware laufen:
1
  clk <= clk1 or clk2; -- Hoppala! Ein Kombinatorischer Takt. 
2
                       -- So macht man das aber nicht. 
3
                       -- Da hat dir die Toolchain sicher was gesagt...
4
 
5
  process(clk...)      -- Siehe Kommentar unten...
6
    begin
7
      if clk = '1' and clk'event then
8
        ...
9
        -- mal angenommen, eine steigende Flanke von clk1 wäre der Grund, 
10
        -- dass wir hierher kommen
11
        if enable1 = '1' and clk1 = '1' then 
12
              -- dann ist clk1 hier nicht sicher schon '1',  weil in der 
13
              -- Realität Laufzeiten im FPGA sind, und zudem noch eine 
14
              -- logische Verknüpfung mit enable zu durchlaufen wäre.
15
              -- Auf jeden Fall erwarte ich hier in der Realität einen Takt Latency.
16
        elsif enable2 = '1' and clk2 = '1' then
17
          ...
18
        else


BTW:
>  process(clk,clk1,enable1,h1,clk2,enable2,h2)
Da ist viel zu viel in der Liste. clk allein würde reichen...

: Bearbeitet durch Moderator
von Schlumpf (Gast)


Lesenswert?

Ziemlich wilde Sache, die du da machst.
Nur beim kurz drüber schauen sehe ich:
kombinatorische Takte --> gefährlich
Takt selbst nochmal kombinatorisch verknüpft --> sehr gefährlich

Also alles in allem ist das echt ein ganz gruseliger Code und alles 
andere als synchron.
Daran wird es auch irgendwo liegen, dass dein FPGA nicht das macht, was 
du gerne hättest.

Du baust an einer Stelle ein Register für writedata wo du den Eingang 
des Registers mit dem Takt verknüpfst.. das geht mit großer 
wahrscheinlichkeit schief. Und wenn man genauer drüberschaut, wird man 
noch viele andere "Schweinereien" dieser Art in deinem Code finden.

Woran es jetzt konkret liegt, sehe ich auf die Schnelle auch nicht.
Aber was ich sehe ist, dass der ganze Code so ziemlich gegen alle Regeln 
verstößt, die man bei synchronen Designs einhalten sollte :-(

von Tobi (Gast)


Lesenswert?

Vielen Dank :)
habe jetzt den Code geändert und er Funktioniert jetzt:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
library altera_mf;
6
use altera_mf.altera_mf_components.all;
7
8
entity combine is
9
  port
10
  (
11
    clk:            in  std_logic;
12
    new_data1:        in  std_logic;
13
    enable1:          in  std_logic;
14
    h1:            in  std_logic_vector (15 downto 0);
15
    new_data2:        in  std_logic;
16
    enable2:          in  std_logic;
17
    h2:            in  std_logic_vector (15 downto 0);
18
    adress:          out std_logic_vector (9 downto 0);
19
    chipselect:        out std_logic;
20
    clken:          out std_logic;
21
    write:          out std_logic;
22
    writedata:        out std_logic_vector (31 downto 0);
23
    byteenable:        out std_logic_vector (3 downto 0);
24
    hig_val_pos:      out std_logic_vector (15 downto 0);
25
    a:              out std_logic;
26
    b:              out std_logic
27
  );
28
end combine;
29
30
architecture a01 of combine is
31
  begin
32
  process(clk)
33
    variable counter: unsigned(9 downto 0) := "0000000000";
34
    begin
35
      if clk = '1' and clk'event then
36
        if (enable1 = '1') and (new_data1 = '1') then
37
          byteenable <= "1111";
38
          write <= '1';
39
          chipselect <= '1';
40
          clken <= '1';
41
          writedata <= std_logic_vector(resize(signed(h1),32));
42
          if counter = "1111111111" then
43
            counter := "0000000000";
44
          else
45
            counter := counter + 1;
46
          end if;  
47
        elsif (enable2 = '1') and (new_data1 = '1') then
48
          byteenable <= "1111";
49
          write <= '1';
50
          chipselect <= '1';
51
          clken <= '1';
52
          writedata <= std_logic_vector(resize(signed(h2),32));
53
          if counter = "1111111111" then
54
            counter := "0000000000";
55
          else
56
            counter := counter + 1;
57
          end if;
58
        elsif (enable2 = '0') and (enable2 = '0') then
59
          counter := "0000000000";
60
          byteenable <= "0000";
61
          write <= '0';
62
          chipselect <= '0';
63
        end if;
64
        adress <= std_logic_vector(counter);
65
        hig_val_pos <= std_logic_vector(resize(counter,16));
66
        a <= counter(0);
67
        b <= counter(1);
68
      end if;
69
    end process;
70
71
end a01;

von Schlumpf (Gast)


Lesenswert?

Das sieht doch zumindest auf den ersten Blick schon viel besser aus ;-)

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


Lesenswert?

Auch mein Gedanke, wobei mich die Variable counter noch ein wenig 
stört... ;-)

von Schlumpf (Gast)


Lesenswert?

Ja, Variablen sind mir auch ein Dorn im Auge..
Außerdem würde ich den Counter noch komplett aus den ganzen IF´s 
rausnehmen und nur im letzten IF den Counter-Wert überbügeln

und clken ist eh immer "1"..

Aber alles in allem ein Quantensprung zu dem ursprünglichen Code ;-)

von Schlumpf (Gast)


Lesenswert?

.. btw..
Wenn ein Signal "clken" heißt, dann ahne ich schon das nächste Problem 
^^

von Tobi (Gast)


Lesenswert?

Clken ist verbunden mit einen Speicher der zwischen den fpga und 
Mikrocontroller sitzt. Clken habe ich vergessen auf 0 zu setzen.  Der 
Speicher ist eine Art fifo Speicher. Aus der variablen counter kann ich 
auch ein Signal machen.

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


Lesenswert?

Tobi schrieb:
> Aus der variablen counter kann ich auch ein Signal machen.
Tu das und lies auch mal den Beitrag "Variable vs Signal"

von T.U.Darmstadt (Gast)


Lesenswert?

Stellen sich zwei Fragen:

Wozu wird denn hier überhaupt eine Variable verwendet, wo doch garnichts 
variabel ist? Die Variable dient in dem einen Syntheselauf, der während 
der Umsetzung dieses Codestücks in eine Netzliste getätigt wird, nur 
dazu einmal einen Wert zu speichern. Dafür braucht es keine Variable, 
sondern man nimmt ein Signal, das man ohnehin verwenden will. Variablen 
benötigt man doch nur, wenn die Formulierung einer Funktion zu komplex 
ist, um sie in einer Zeile zu schreiben oder wenn in einem Syntheselauf 
im jeweiligen Codestück mehrfach gelooped wird und die dort verwendete 
Variable mehrere Werte annimmt, aus denen dann am Ende ein Wert für ein 
Signal abgeleitet wird. Sonst sind Variablen unnötig. Sie existieren nur 
zur Compilationszeit. So haben wir das einst gelernt.

Und die zweite Frage:
Woher haben die heutigen Hardwarebeschreiber nur die Manie, Variablen 
einzuführen? Zuviel C gemacht? Kann es eigentlich nicht sein. Ich hatte 
auch schon 10 Jahre C auf dem Buckel bevor der erste Verilogbefehl vor 
meinem geistigen Auge auftauchte. VHDL kam dann nochmals später.

von Daniel R. (dan066)


Lesenswert?

Thomas Ulrich schrieb:
> Woher haben die heutigen Hardwarebeschreiber nur die Manie, Variablen
> einzuführen?
Welche Alternative hat man denn wenn man Berechnungen anstellen will die 
aus mehreren Befehlen bestehen? Das einzige was mir einfällt wäre einen 
Automaten zu bauen der in jedem Zustand eine weitere Teilberechnung 
durchführt. Wenn die Zwischenergebnisse nicht außerhalb gebraucht werden 
ist das eine schöne Art viele Takte für etwas zu verschwenden, das von 
der Signallaufzeit her auch in einen gepasst hätte;)

von Christian R. (supachris)


Lesenswert?

Daniel R. schrieb:
> Welche Alternative hat man denn wenn man Berechnungen anstellen will die
> aus mehreren Befehlen bestehen?

Dafür kann man ja auch Variablen nehmen. Aber auch in deinen Beispielen 
aus dem anderen Thread sind die Variablem komplett sinnbefreit und 
machen im Zweifelsfall nur Verwirrung. Wo immer es geht, Signale. So 
einfach ist das. Ein Anfänger braucht sowieso keine Variablen, 
mindestens ein Jahr lang nicht.

von T.U.Darmstadt (Gast)


Lesenswert?

Daniel R. schrieb:
> Welche Alternative hat man denn wenn man Berechnungen anstellen will die
> aus mehreren Befehlen bestehen?
Man schreibt sie ausserhalb des getakteten Prozesses als Kombinatorik 
hin.

> Wenn die Zwischenergebnisse nicht außerhalb gebraucht werden
> ist das eine schöne Art viele Takte für etwas zu verschwenden, das von
> der Signallaufzeit her auch in einen gepasst hätte
Davon ausgehend, dass es wirklich so klein ist, dass es in einen Takt 
passt, wird es mit der oben genannten Methode genau so funktionieren. 
Genaus so. Durch das Weglassen des Taktes gibt man sie zum Wegoptimieren 
in beide Richtungen frei, d.h. sie wird mit der davor liegenden oder 
danach kommenden Logik verbacken, sofern da an den FFs mal was gewändert 
wird oder es über Hierachiegrenzen geht.

Im anderen Fall benutzt man register balancing, um Kombinatorik so 
verschieben zu lassen, dass sie mit andere Kombinatorik zusammenkommt.
Variablen bringen da sicher keinen Vorteil, sondern hindern das eher.

Christian R. schrieb:
> Ein Anfänger braucht sowieso keine Variablen,
> mindestens ein Jahr lang nicht.
Lieber 2 Jahre, wie bei den jungen Autofahrern. Ich bin ohnehin ein 
Befürworter eines VHDL-Zertifikats, eine Art Führerschein :-)

von Tobi (Gast)


Lesenswert?

Mal angenommen man will die Berechnungen x=a+b+c und y=a+b+d 
durchführen. Wäre es da nicht sinnvoller eine variable zu verwenden 
(z=a+b und x=c+z und y=d+z)  als die Berechnungen auszuschreiben(x=a+b+c 
und y=a+b+d). Durch die variable bleibt die Laufzeit gleich jedoch wird 
die Zahl der Le verringert.

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


Lesenswert?

Tobi schrieb:
> Durch die variable bleibt die Laufzeit gleich jedoch wird die Zahl der
> Le verringert.
Nur auf den ersten Blick. Aber natürlich kann die Toolchain (in diesem 
Fall schon der Synthesizer) diese simplen (und auch wesentlich 
komplexere Beziehungen) erkennen und optimieren. Aber wie gesagt: das 
kann man in 5 Minuten selber mal kurz ausprobieren...

Wobei man ntürlich auch in den ersten zwei Jahren mal eine Variable 
verwenden darf. Nur muss man sich zuvor mindestens solche einfachen 
Überlegungen gemacht haben. Aber man sollte keine Variablen nehmen, weil 
es gerade hipp ist oder einfacher scheint, und ein Professor oder ein 
Gaisler diese Methoden präferieren. Wobei man beim Professor natürlich 
schnell aufs Glatteis kommt, wenn man den

> Mal angenommen man will die Berechnungen x=a+b+c und y=a+b+d durchführen.
Hier mal ein paar Versuche und das Ergebnis des Synthesizers:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity MehrstufigeAddierer is
6
    Port ( a : in   unsigned (7 downto 0);
7
           b : in   unsigned (7 downto 0);
8
           c : in   unsigned (7 downto 0);
9
           d : in   unsigned (7 downto 0);
10
           x : out  unsigned (7 downto 0);
11
           y : out  unsigned (7 downto 0)
12
           );
13
end MehrstufigeAddierer;
14
15
architecture Behavioral of MehrstufigeAddierer is
16
begin
17
   process (a,b,c,d) 
18
     variable z : unsigned (7 downto 0);
19
   begin
20
     z := a+b;
21
     x <= c+z;
22
     y <= d+z;
23
   end process;
24
end Behavioral;
25
--> Macro Statistics  8-bit adder  : 3
26
27
28
architecture Behavioral of MehrstufigeAddierer is
29
   signal z : unsigned (7 downto 0);
30
begin
31
   z <= a+b;
32
   x <= c+z;
33
   y <= d+z;
34
end Behavioral;
35
--> Macro Statistics  8-bit adder  : 3
36
37
38
architecture Behavioral of MehrstufigeAddierer is
39
begin
40
   process (a,b,c,d) 
41
   begin
42
     x <= a+b+c;
43
     y <= a+b+d;
44
   end process;
45
end Behavioral;
46
--> Macro Statistics  8-bit adder  : 3
47
48
49
architecture Behavioral of MehrstufigeAddierer is
50
begin
51
     x <= a+b+c;
52
     y <= a+b+d;
53
end Behavioral;
54
--> Macro Statistics  8-bit adder  : 3
Fazit: schon der Synthesizer erkennt das Optimierungspotential und macht 
den Zwischenschritt über a+b.

von Schlumpf (Gast)


Lesenswert?

Wenn man bei VHDL in Hardware denkt, braucht man niemals Variablen.
ALLES lässt sich über Signale lösen.
Echte Hardware kennt nur Signale und keine Variablen. Und da man mit 
synthetisierbarem HDL echte Hardware beschreibt, sind Variablen unnötig.

Vielleicht reduzieren sie an der einen oder anderen Stelle den 
Codierungsaufwand ein wenig, aber NÖTIG sind sie zumindest aus meiner 
Erfahrung nie!

von meckerziege (Gast)


Lesenswert?

Nötig nicht, aber es ist angenehm sie zu verwenden. Das mache ich hin 
und wieder mal, um Verknüpfungen zu vereinfachen die sich über mehrere 
Zeilen erstrecken. Dann wirds übersichtlicher.
Genauso wie Variablen kann man auch for und while in VHDL verwenden, 
wenn man versteht was es jeweils macht!
Man muss ich nur klar darüber sein, dass Variablen und Schleifen nie im 
FPGA ausgeführt werden, sondern eben schon zuvor beim Übersetzen 
bearbeitet werden. Sobald Signal und Variable als zwei völlig 
unterschiedliche Dinge aufgefasst wurden, kann man sie nahezu gefahrlos 
beide verwenden.

@lkmiller: Da stimme ich durchaus zu, man kanns auch übertreiben. 
Soviele Variablen wie Gaisler würde ich nie einsetzen.

von Schlumpf (Gast)


Lesenswert?

meckerziege schrieb:
> Nötig nicht, aber es ist angenehm sie zu verwenden.

Hab ich ja auch geschrieben. Sie können den Codieraufwand reduzieren 
(oder eben den Code übersichtlicher gestalten).
Wobei ein kleiner Code nicht zwingend ein übersichtlicher Code sein 
muss. Wenn man immer aufpassen muss, ob man es gerade mit einem Signal 
oder einer Variablen zu tun hat, kann das auch zu Fehlern führen. 
Außerdem denke ich, dass es gerade für Anfänger und wenig Erfahrene 
einfacher ist, die Hardware im Hinterkopf zu behalten, wenn man sich auf 
Signale beschränkt.

Aber das ist natürlich Geschmackssache und bleibt jedem selbst 
überlassen, wie er sich wohlfühlt.

Ich wollte nur sagen, dass es IMMER eine Lösung ohne Variablen gibt. Ob 
das immer die eleganteste ist, sei mal dahingestellt ;-)


meckerziege schrieb:
> Man muss ich nur klar darüber sein, dass Variablen und Schleifen nie im
> FPGA ausgeführt werden, sondern eben schon zuvor beim Übersetzen
> bearbeitet werden.

Und das ist vielen leider nicht klar ;-)

Ich stimmt dir voll zu: Wenn man weiss, was man tut, kann man beides 
verwenden.

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


Lesenswert?

Schlumpf schrieb:
> Ich wollte nur sagen, dass es IMMER eine Lösung ohne Variablen gibt.
Das wäre schön, aber tatsächlich ist es leider nur so, dass es nicht 
IMMER eine Lösung gibt. Auch ohne Variablen... :-(

Aber wenn es eine Lösung mit Variablen gibt, dann kann man das Problem 
auch ohne Variablen lösen.

von berndl (Gast)


Lesenswert?

Lothar Miller schrieb:
> Aber wenn es eine Lösung mit Variablen gibt, dann kann man das Problem
> auch ohne Variablen lösen.

hmm, XST user guide, dual-ported (B)RAM. Da ist eine (sogar) shared 
variable notwendig. Ich hab' allerdings noch nie ausprobiert, ob das 
auch ohne variable geht. Und ja, das ist halt auch was sehr 
spezielles...

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


Lesenswert?

berndl schrieb:
> Ich hab' allerdings noch nie ausprobiert, ob das auch ohne variable
> geht.
Es geht, wenn du das RAM manuell als Komponente instantiierst. Das würde 
ich bei so einem Bauteil mit vielen weiteren Parametern auch zwingend 
empfehlen.

von Schlumpf (Gast)


Lesenswert?

Lothar Miller schrieb:
> Das wäre schön, aber tatsächlich ist es leider nur so, dass es nicht
> IMMER eine Lösung gibt. Auch ohne Variablen... :-(

Wie konnte ich mich nur so unpräzise audrücken :-)
Wobei mein Chef da manchmal anderer Meinung ist...

> Aber wenn es eine Lösung mit Variablen gibt, dann kann man das Problem
> auch ohne Variablen lösen.

So war´s natürlich auch gemeint..

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.