Forum: FPGA, VHDL & Co. VHDL Frequenz der Clock durch Code ändern


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Maximilian L. (mex_1991)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich will den Takt der FPGA Clock von 50Mhz auf einen Sekundentakt 
runterbrechen (--> Frequenz runter auf 0,5Hz?)
Leider passiert beim Ausführen immer folgendes:
Die Led leuchtet etwa  1 Sekunde auf und dann nicht mehr.
Oder sind die LOW Phasen etwa soooo lang?

Ich hoffe auf eure Unterstützung,

Max

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
2 lesenswert
nicht lesenswert
Warum nimmst du nicht einfach einen Integer zum Zählen? Dann kannst du 
natürlichsprachliche, lesbare Zahlen da hinschreiben...

Schau dich mal um, wer ausser dir "wait until rising_edge()" und "if 
rising_edge()" hintereinander im selben Prozess verwendet. Niemand? 
Richtig! Wie machen es Andere? Was steht denn im Handbuch des 
Synthesizers, wie so ein getakteter Prozess auszusehen hat?

BTW: wenn ich mir deinen getakteten Prozess so anschaue, wirst du bald 
Erfahrung mit dem Thema "Latency" machen. Du kannst dich schon mal dazu 
ein wenig einlesen... ;-)

: Bearbeitet durch Moderator
von Maximilian L. (mex_1991)


Bewertung
0 lesenswert
nicht lesenswert
Danke für deine Antwort.
Das mit den Integern ist eine gute Idee, ich machs mal so.

von Christoph db1uq K. (christoph_kessler)


Bewertung
1 lesenswert
nicht lesenswert
2hoch27 ist 134217728, und 101111101011110000100000000 sind 100 
Millionen soweit ok.
Die LED soll vermutlich 50% der Zeit leuchten. Das "enable" ist aber nur 
eine Taktperiode (1/50 MHz) lang high.
Soll "newClock <= enable; led(0) <= newClock;" die LED togglen? Ich 
hätte das irgendwie mit led <= /led wenn enable=high gemacht.
Und wieso hat led 4 bit und nur das LSB wird genutzt?

von Maximilian L. (mex_1991)


Bewertung
0 lesenswert
nicht lesenswert
Die Led hat 4 bit, da es ein Board mit 4 Leds ist (ich verwende aber nur 
die eine).

"newClock <= enable; led(0) <= newClock;" - das soll das Signal (0 oder 
1) von der neu "erstellten" Clock an die Led weitergeben.

"led <= /led" Was bedeutet hier "/" , das sehe ich zum ersten mal?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Lothar M. schrieb:
> Schau dich mal um, wer ausser dir "wait until rising_edge()" und "if
> rising_edge()" hintereinander im selben Prozess verwendet.

Neugierig: was passiert dabei, wird da effektiv auf zwei Flanken 
gewartet?

@Max: irgendwie hast du dich mit counter vs. counter_vector wohl arg 
verheddert. Mal wird das eine, mal das andere betrachtet, das kann nicht 
Sinn der Sache sein. Habe nicht viel Ahnung von VHDL :), aber für einen 
Zweck solltest du wohl auch nur ein Signal haben. Ggf. kannst du ja über 
Typumwandlungen immer noch das eine aus dem anderen ableiten (wenn du 
aber Lothars Rat mit den Integern befolgst, ist da gar nicht nötig).

von Maximilian L. (mex_1991)


Bewertung
0 lesenswert
nicht lesenswert
Danke für die vielen Antworten.

Ich habe nun Integer verwendet, weiß aber da noch nicht wie ich eine
If Abfrage mit machen kann.

So jedenfalls geht es nicht:  if (counter = "100000000") then ...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Angehängte Dateien:

Bewertung
1 lesenswert
nicht lesenswert
ps: Habe vorhin gerade meinen ersten eigenen Taktteiler gezimmert, um 
vom PLL-Takt innerhalb des FPGAs andere ableiten zu können.

Wenn du dir davon eine Instanz mit einem divisor von 50_000_000 zimmerst 
und an clk_o dein LED-Signal hängst, solltest du eine mit 1 Hz blinkende 
LED haben.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
2 lesenswert
nicht lesenswert
Maximilian L. schrieb:
> So jedenfalls geht es nicht:  if (counter = "100000000") then ...

Ganz ohne eine Sprachreferenz oder mal nachlesen wird das wohl nichts 
werden. :}

Ich bin da auch totaler Anfänger, aber ein bisschen quer lesen muss man 
halt schon mal.

von Maximilian L. (mex_1991)


Bewertung
0 lesenswert
nicht lesenswert
Jörg W. ich habe noch eine Frage:

Wofür steht die Abkürzung rstn? Ist das Reset?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
2 lesenswert
nicht lesenswert
"reset negative", also low-aktiv.

Händisch würde man über das Signal einen Strich drüber schreiben. Geht 
in einer Programmiersprache aber schlecht, und auch sowas wie ¬ ist in 
VHDL halt nicht in einem Bezeichner zugelassen.

In meinem Falle läuft "reset" extern auf einen Schalter, der low-aktiv 
ist.

von Maximilian L. (mex_1991)


Bewertung
1 lesenswert
nicht lesenswert
Super, danke!

von Duke Scarring (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> In meinem Falle läuft "reset" extern auf einen Schalter, der low-aktiv
> ist.
Und der vermutlich prellt. Ist der Reset wenigstens einsynchronisiert?
Wenn nein, sind das die Begriffe um hier im FPGA-Forum die Beiträge mit 
dem richtigen Lesefutter zu finden :-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Duke Scarring schrieb:
> Ist der Reset wenigstens einsynchronisiert?

Nö.

Allerdings hätte man den ganzen Reset-Zirkus wohl für den Taktteiler 
auch komplett weglassen können. War mehr wegen "stand da schon immer so 
drin :)".

von Christoph Z. (christophz)


Bewertung
1 lesenswert
nicht lesenswert
Maximilian L. schrieb:
> "led <= /led" Was bedeutet hier "/" , das sehe ich zum ersten mal?

In VHDL eher "led <= not led;"

Maximilian L. schrieb:
> So jedenfalls geht es nicht:  if (counter = "100000000") then ...

"if (counter = 16#100000000#) then" sollte gehen aber wie Lothar schon 
geschrieben hat, der Vorteil von integer ist vor allem, dass man hier 
einfach Dezimalzahlen hinschreiben kann:

"if (counter = 256) then"

von Maximilian L. (mex_1991)


Bewertung
0 lesenswert
nicht lesenswert
Alles klar, danke.
Es funktioniert auch nach paar Änderungen super :-)

von Christoph db1uq K. (christoph_kessler)


Bewertung
0 lesenswert
nicht lesenswert
Hab grade nachgeschaut, das habe ich 2008 in Verilog formuliert, ein 
Taktteiler um mehrere DC/DC-Wandler zu synchronisieren. Die 
Ausgangsschwingung ist ein symmetrisches Rechteck:
//--(6+1)-Bit-Teiler 25,6 MHz / 80 = 320,000 kHz "sync640k[5:0]/sync320khz"--
  always @(posedge clock)
  begin
    if  (sync640k[5:0] == 0)         // von Null
      begin
      sync640k[5:0]  <=  6'b100111;  // auf 39 rückstellen
      sync320khz    <=  ~sync320khz; // symm. Ausgang invertieren
      end
    else  
      sync640k[5:0] <= sync640k[5:0] - 6'b000001; //zählen
  end  
Also da wird die Negation mit Tilde formuliert. In WinCUPL und ABEL ist 
es das Ausrufezeichen. Hier im Forum endet eine Formatierung tatsächlich 
mit slash.

von Maximilian L. (mex_1991)


Bewertung
0 lesenswert
nicht lesenswert
Danke dass du extra nochmal nachgeschaut hast.
Ich merk mir am besten einfach:

not signalname

wenn ich etwas in VHDL invertieren muss

von Christoph db1uq K. (christoph_kessler)


Bewertung
0 lesenswert
nicht lesenswert
Was mir an meinem Zähler noch auffällt, ich lasse den rückwärts zählen. 
Das kommt eher aus der Mikrocontrollertechnik, eine Abfrage auf Null 
kostet einen Vergleichsbefehl weniger. Das Zero-Flag wird sowieso 
gesetzt, wenn man auf Null dekrementiert. Für programmierbare Logik ist 
es ziemlich egal.

Und ich habe die Zahlen auch binär geschrieben. Die Angewohnheit stammt 
vielleicht noch aus der TTL-Logikzeit.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Habe vorhin gerade meinen ersten eigenen Taktteiler gezimmert
Aber Obacht: so werden keine Takte erzeugt, die innerhalb des Designs 
als Takt weiterverwendet werden. Denn der Skew, der durch die Verwendung 
von "normalen" Flipflops in Logikblöcken entsteht, kann von der 
Toolchain nicht ermittelt werden. Sie kann einen derart abgeleiteten 
internen Takt also nicht auf die Einhaltung von Setup- und Hold-Zeiten 
prüfen.

Takte für die Interne Verwendung werden über die Clock-Manager erzeugt. 
Und sonst wird intern mit Clock-Enables gearbeitet.

Das ideale und einfach zu wartende Design hat intern genau 1 Takt und 
der Rest wird mit Clock-Enables abgehandelt.

Wenn auf solche Art ein Signal namens "Takt" für ein externes Gerät 
(SPI, I2C, usw) erzeugt wird, dann passt das. Denn so ein "Takt" nach 
draußen muss sowieso wie ein Datensignal behandelt und qualifiziert 
werden.

Christoph db1uq K. schrieb:
> Was mir an meinem Zähler noch auffällt, ich lasse den rückwärts zählen.
> Das kommt eher aus der Mikrocontrollertechnik, eine Abfrage auf Null
> kostet einen Vergleichsbefehl weniger. Das Zero-Flag wird sowieso
> gesetzt, wenn man auf Null dekrementiert. Für programmierbare Logik ist
> es ziemlich egal.
Da ist es eher ungeschickt, den Zähler rückwärts laufen zu lassen. Denn
1. bei einem Rückwärtszähler müssen alle Stellen auf 0 abgefragt werden, 
wogegen bei einem anderen Zählerstand ggfs optimiert werden kann (bei 
einem Rückwärtszähler mit 16 Schritten müssen 4 Bit auf 0 verglichen 
werden, bei einem Vorwärtszähler mit 16 Schritten nur 1, nämlich der 
Überlauf ins 5. Bit). Und
2. kann zum Zurücksetzen des Zählers dann der Reset-Eingang des 
Flipflops verwendet werden, wogegen zum Setzen eines Wertes ggfs. 
zusätzliche Logik aufgebaut wird.
Ausprobieren, wie sich der verwendete Synthesizer bei der verwendeten 
FPGA Architektur verhält, macht hier schlau...   ;-)

Maximilian L. schrieb:
> So jedenfalls geht es nicht:  if (counter = "100000000") then ...
Ja klar. Weil in VHDL mit " eine Zeichenkette beginnt. Eine Zahl ist 
aber keine Zeichenkette. Es ist aber auf diesem urschleimigen Level echt 
einfach: Google findet tausende Beispiele für solche simplen Sachen. Und 
jetzt schaust du dir einfach mal ein paar an und versuchst sie zu 
verstehen. Und wenn du sie verstanden hast(**), dann verwendest du eines 
davon.

Maximilian L. schrieb:
> Es funktioniert auch nach paar Änderungen super :-)
Ja, und so richtig schön wäre es, wenn du das Ergebnis dann auch noch 
zeigst. Denn so könntest du dann mal Anderen helfen.


(**) das kann schon mal einen oder zwei Tage dauern. Aber Tage voll 
ausgiebiger Beschäftigung mit dem Thema, nicht solche "auf die Seite 
legen und YT gucken und hoffen dass es nebenher klick macht"-Tage.

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Lothar M. schrieb:
> Takte für die Interne Verwendung werden über die Clock-Manager erzeugt.
> Und sonst wird intern mit Clock-Enables gearbeitet.

Hast du mal ein Beispiel, wie man mit clock enable bspw. einen Takt von 
¼ des Mastertakts erzeugt?

> das kann schon mal einen oder zwei Tage dauern

Hihi, ja, so langsam wird es hier.

Danke auch an alle für die diversen Hilfen!

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Lothar M. schrieb:
>> Takte für die Interne Verwendung werden über die Clock-Manager erzeugt.
>> Und sonst wird intern mit Clock-Enables gearbeitet.
> Hast du mal ein Beispiel, wie man mit clock enable bspw. einen Takt von
> ¼ des Mastertakts erzeugt?
Ist hier das Ziel, diesen erzeugten "Takt" intern verwenden? Oder soll 
da nur ein Rechtecksignal nach aussen an einen anderen Baustein gegeben 
werden?

> Hast du mal ein Beispiel, wie man mit clock enable bspw. einen Takt von
> ¼ des Mastertakts erzeugt?
Erst mal vorneweg: an einen Takt, der im FPGA auf die Takteingänge von 
Flipflops darf, werden ziemliche ansprüche gestellt. Er muss mit 
dedizierten Taktmanagern hergestellt und Taktbuffern im FPGA auf 
Clocknetze verteilt werden. Das ist ziemlicher Aufwand, deshalb wird im 
einfachsten zu handhabenden Fall mit 1 Mastertakt im ganzen Design 
gearbeitet.
Der Rest wird mit Clock-Enalbes abgehandelt, die jeweils 1 
Mastertakt-Zyklus lang gesetzt sind. Und deshalb wird damit auch kein 
"Takt" im altbekannten Sinne erzeugt, sondern z.B. jeden 4. Mastertakt 
eine Aktion ausgeführt.

Mal basierend auf dem Code des Lauflichts dort 
http://www.lothar-miller.de/s9y/archives/61-Lauflicht.html käme sowas 
heraus:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity Clockdivider is
    Generic ( fclk     : integer := 10000000);
    Port ( clk : in  STD_LOGIC;
           clken : out  STD_LOGIC);
end Clockdivider;

architecture Behavioral of Clockdivider is
signal clkdiv : integer range 0 to 3 := 0;
begin
   process begin
      wait until rising_edge(clk);
      if (clkdiv < 3) then
         clkdiv <= clkdiv+1;
         clken  <= '0';
      else
         clkdiv <= 0;
         clken  <= '1';
      end if;
   end process;
end Behavioral;

Die meisten Clock-Enables sind aber eher "versteckt", wie auch hier im 
RS232 Interface:
http://www.lothar-miller.de/s9y/categories/42-RS232
   process begin
      wait until rising_edge(CLK);
   :
   :
         if(txcnt<(Quarz_Taktfrequenz/Baudrate)-1) then  -- Vorteiler
            txcnt <= txcnt+1;
         else  -- nächstes Bit ausgeben                  -- "versteckter" Clock-Enable
            if (txbitcnt<10) then
   :
Denn ich hätte diesen Prescaler natürlich auch ausserhalb machen können 
und dann beim Compare-Match ein Enable-Flag setzen können.

Clock-Enables sind also einfach Zähler, die bei einem Ablauf jedesmal 
einmalig ein Flag setzen und dieses dann auch "selber" beim nächsten 
Takt wieder zurücksetzen.
Weil bei einem FPGA dann ja jeder, der dieses Flag "brauchen" könnte, 
parallel angeschlossen ist, und deshalb unmittelbar darauf reagieren 
wird, muss man nicht wie bei Software warten, bis auch der Letzte noch 
mitbekommen hat, dass er ein Flag zu bearbeiten hat.

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Lothar M. schrieb:
> Der Rest wird mit Clock-Enalbes abgehandelt, die jeweils 1
> Mastertakt-Zyklus lang gesetzt sind. Und deshalb wird damit auch kein
> "Takt" im altbekannten Sinne erzeugt, sondern z.B. jeden 4. Mastertakt
> eine Aktion ausgeführt.

Ja, genau sowas interessiert mich.

Muss ich mir heute Abend mal näher ansehen.

Die PLL in meinem iCE40 fängt in der Ausgabefrequenz erst bei 16 MHz an; 
ich habe sie auf 40 MHz konfiguriert (genauer 39,75), brauche aber für 
meine Videosignal-Generierung dann 10 MHz. Das wird also genau auf sowas 
rauslaufen, das Dingens mit 40 MHz zu speisen und nur bei jedem 4. 
Taktimpuls tatsächlich etwas zu tun.

von Duke Scarring (Gast)


Angehängte Dateien:

Bewertung
1 lesenswert
nicht lesenswert
Christoph db1uq K. schrieb:
> Was mir an meinem Zähler noch auffällt, ich lasse den rückwärts zählen.
Das mache ich i.d.R. auch so. Irgendwo hab ich mal aufgeschnappt: die 
Abfrage auf '0' könne über die Carry-Chain erfolgen.

Ich habs gard eben mal mit Lattice Diamond (und LSE) ausprobiert.
In die eine Richtung (up):
################### Begin Area Report (up)######################
Number of register bits => 25 of 1604 (1 % )
CCU2D => 13
FD1S3AX => 1
FD1S3IX => 24
GSR => 1
IB => 1
LUT4 => 9
OB => 1

Timing Report Summary
--------------
--------------------------------------------------------------------------------
Constraint                              |   Constraint|       Actual|Levels
--------------------------------------------------------------------------------
                                        |             |             |
create_clock -period 5.000000 -name     |             |             |
clk0 [get_nets clk_c]                   |  200.000 MHz|   74.493 MHz|    10 *
                                        |             |             |
--------------------------------------------------------------------------------

Und in die andere Richtung (down):
################### Begin Area Report (down)######################
Number of register bits => 25 of 1604 (1 % )
CCU2D => 13
FD1S3AX => 1
FD1S3IX => 10
FD1S3JX => 14
GSR => 1
IB => 1
LUT4 => 10
OB => 1

Timing Report Summary
--------------
--------------------------------------------------------------------------------
Constraint                              |   Constraint|       Actual|Levels
--------------------------------------------------------------------------------
                                        |             |             |
create_clock -period 5.000000 -name     |             |             |
clk0 [get_nets clk_c]                   |  200.000 MHz|  138.045 MHz|     5 *
                                        |             |             |
--------------------------------------------------------------------------------

von Christoph Z. (christophz)


Bewertung
0 lesenswert
nicht lesenswert
Duke Scarring schrieb:
> Das mache ich i.d.R. auch so. Irgendwo hab ich mal aufgeschnappt: die
> Abfrage auf '0' könne über die Carry-Chain erfolgen.
>
> Ich habs gard eben mal mit Lattice Diamond (und LSE) ausprobiert.

Vielen dank dafür. Der Unterschied ist jetzt viel höher als ich 
angenommen hätte. Ist natürlich FPGA Typ abhängig aber genau so Detail 
wissen ist nicht einfach zu bekommen.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Duke Scarring schrieb:
> Ich habs gard eben mal mit Lattice Diamond (und LSE) ausprobiert.
Interessant, das muss ich offenbar auch mal wieder näher anschauen... 
;-)

Ich finde es ziemlich gruselig, dass dieser Vergleicher angeblich 10 
Logiklevel braucht. Und das bei annähernd gleichem Logikverbrauch.

Könntest du das in Bezug auf den 
Beitrag "Re: Vergleichsoperator "<" benötigt weniger Logikelemente als "!=" ?" nochmal mit einem 
"ungleich" ausprobieren?
Hier für den "up" Counter:
        if count != count_max then
            count   <= count + 1;
        else
            count   <= 0;
            toggle  <= not toggle;
        end if;

Und das hier beim "down":
        if count != 0 then
            count   <= count - 1;
        else
            count   <= count_max;
            toggle  <= not toggle;
        end if;

: Bearbeitet durch Moderator
von Duke Scarring (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Lothar M. schrieb:
> nochmal mit einem "ungleich" ausprobieren?
Kein Problem:
################### Begin Area Report (up_ungleich)######################
Number of register bits => 25 of 1604 (1 % )
CCU2D => 13
FD1S3AX => 1
FD1S3IX => 24
GSR => 1
IB => 1
LUT4 => 9
OB => 1

Timing Report Summary
--------------
--------------------------------------------------------------------------------
Constraint                              |   Constraint|       Actual|Levels
--------------------------------------------------------------------------------
                                        |             |             |
create_clock -period 5.000000 -name     |             |             |
clk0 [get_nets clk_c]                   |  200.000 MHz|  134.989 MHz|     5 *
                                        |             |             |
--------------------------------------------------------------------------------

Und hier wieder abwärts:
################### Begin Area Report (down_ungleich)######################
Number of register bits => 25 of 1604 (1 % )
CCU2D => 13
FD1S3AX => 1
FD1S3IX => 10
FD1S3JX => 14
GSR => 1
IB => 1
LUT4 => 10
OB => 1

Timing Report Summary
--------------
--------------------------------------------------------------------------------
Constraint                              |   Constraint|       Actual|Levels
--------------------------------------------------------------------------------
                                        |             |             |
create_clock -period 5.000000 -name     |             |             |
clk0 [get_nets clk_c]                   |  200.000 MHz|  138.045 MHz|     5 *
                                        |             |             |
--------------------------------------------------------------------------------

Ich finde die 'ungleich'-Varianten sind nicht so schön lesbar.

Duke

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Duke Scarring schrieb:
> Ich finde die 'ungleich'-Varianten sind nicht so schön lesbar.
Eigenartig ist hier, dass die "kleiner"-Varianten teilweise deutlich 
schlechter implementiert werden...

> Ich finde die 'ungleich'-Varianten sind nicht so schön lesbar.
Ich hätte da noch was für einen Test... ;-)
Hoch:
        if count = count_max then
            count   <= 0;
            toggle  <= not toggle;
        else
            count   <= count + 1;
        end if;
Runter:
        if count = 0 then
            count   <= count_max;
            toggle  <= not toggle;
        else
            count   <= count - 1;
        end if;
Nur zum Test, weil das jetzt wirklich grauenhaft zu lesen ist. Zumindest 
dürfte die gedankliche Invertierung ja keinerlei Unterschiede im 
Ergebnis machen...

: Bearbeitet durch Moderator
von Duke Scarring (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Lothar M. schrieb:
> Zumindest
> dürfte die gedankliche Invertierung ja keinerlei Unterschiede im
> Ergebnis machen...
:)
Schaun wir mal:
################### Begin Area Report (up_gleich)######################
Number of register bits => 25 of 1604 (1 % )
CCU2D => 13
FD1S3AX => 1
FD1S3IX => 24
GSR => 1
IB => 1
LUT4 => 9
OB => 1

Timing Report Summary
--------------
--------------------------------------------------------------------------------
Constraint                              |   Constraint|       Actual|Levels
--------------------------------------------------------------------------------
                                        |             |             |
create_clock -period 5.000000 -name     |             |             |
clk0 [get_nets clk_c]                   |  200.000 MHz|  134.989 MHz|     5 *
                                        |             |             |
--------------------------------------------------------------------------------

Und nach aufwärts kommt abwärts:
################### Begin Area Report (down_gleich)######################
Number of register bits => 25 of 1604 (1 % )
CCU2D => 13
FD1S3AX => 1
FD1S3IX => 10
FD1S3JX => 14
GSR => 1
IB => 1
LUT4 => 10
OB => 1

Timing Report Summary
--------------
--------------------------------------------------------------------------------
Constraint                              |   Constraint|       Actual|Levels
--------------------------------------------------------------------------------
                                        |             |             |
create_clock -period 5.000000 -name     |             |             |
clk0 [get_nets clk_c]                   |  200.000 MHz|  138.045 MHz|     5 *
                                        |             |             |
--------------------------------------------------------------------------------

Das scheint der Synthesizer hinzubekommen. Jetzt kann sich das ja mal 
jemand mit Synplify, Quartus, Vivado und evtl. ISE anschauen.

Anzumerken wäre noch: das sind die Ergebnisse nach der Synthese. Durch 
Map und Place&Route können da nochmal ganz andere Timing-Werte 
rauskommen (in beide Richtungen).

von Weltbester FPGA-Pongo (Gast)


Bewertung
-2 lesenswert
nicht lesenswert
Jörg W. schrieb:
> "reset negative", also low-aktiv.

logisch invertiert, nicht "low aktiv".

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Lothar M. schrieb:
>> Schau dich mal um, wer ausser dir "wait until rising_edge()" und "if
>> rising_edge()" hintereinander im selben Prozess verwendet.
> Neugierig: was passiert dabei, wird da effektiv auf zwei Flanken
> gewartet?
Das war noch offen... ;-)
Hier die Antwort: weil sich während der Berechnung des Prozesses clk und 
clk'last nicht ändern, ist die if-Abfrage einfach völlig unnötig und 
kann schlicht ignoriert werden:
process
begin
  wait until rising_edge(clk);  -- warten, bis clk='1' und clk'last='0'
  :
  :                             -- clk und clk'last ändern sich nicht...
  :
  if (rising_edge(clk)) then    -- damit ist auch diese Abfrage immer wahr
     :
  end if;
:
end process;

: Bearbeitet durch Moderator
von Robert P. (fpgazumspass) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Duke Scarring schrieb:
> Jetzt kann sich das ja mal jemand mit Synplify, Quartus, Vivado
> und evtl. ISE anschauen.

Bedingungen: neues Projekt, default settings.
Buildzeit = Synthese + Routing + Bitstream + Timing Analyse

Quartus 18.1 für 5CEBA2F17C8 (kleinster und langsamster Cyclone 5)
Design         | LUTs | FFs | FMax(MHz) | Buildzeit
---------------|------|-----|-----------|----------
up             |  34  |  36 |  231.59   | 0:39
down           |  46  |  35 |  245.88   | 0:40
up_gleich      |  31  |  28 |  228.62   | 0:38
down_gleich    |  45  |  33 |  241.20   | 0:39
up_ungleich    |  31  |  28 |  228.62   | 0:39
down_ungleich  |  45  |  33 |  241.20   | 0:39

Down ist also auch schneller als Up, braucht aber mehr Ressourcen.

Vivado 2019.2 für xc7a12tcpg238-1 (kleinster und langsamster Artix 7)
Design         | LUTs | FFs | FMax(MHz) | Buildzeit
---------------|------|-----|-----------|----------
up             |    9 | 25  |   247.16  | 1:07
down           |   30 | 25  |   324.57  | 1:09
up_gleich      |   10 | 25  |   294.44  | 1:07
down_gleich    |   33 | 25  |   290.53  | 1:07
up_ungleich    |    7 | 25  |   318.87  | 1:07
down_ungleich  |   30 | 25  |   324.57  | 1:08

Vivado verhält sich komplett anders. Für Up werden hier wohl 
"Optimierungen" eingesetzt, so dass man viel weniger LUTs braucht. Dafür 
ist der erreichbare Takt manchmal aber auch viel niedriger.

Im Schematic zeigt sich der Einsatz von etwas mehr CARRY4 Elementen bei 
Up_ungleich, während down_ungleich sehr viele LUT1 verwendet.

: Bearbeitet durch User
von Christoph Z. (christophz)


Bewertung
0 lesenswert
nicht lesenswert
Hui, das ist ja mal wieder spannend hier. Da will ich doch auch 
mithelfen :-)

Hier die Resultate für Synplify für ProASIC3L. Neues Projekt, default 
Settings, keine Constraints, kein Pinning.
Microsemi Libero SoC 11.8 (Synplify Pro L2016.09M-2) für A3P1000L-1FG144 (kleinster und langsamster ProASIC3L)

Design         | Core Cells | FMax(MHz)
---------------|------------|----------
up             |  91        | 76.7
down           |  117       | 135.5
up_gleich      |  115       | 140.2
down_gleich    |  117       | 140.3
up_ungleich    |  115       | 140.2
down_ungleich  |  117       | 140.3

von Christoph Z. (christophz)


Bewertung
0 lesenswert
nicht lesenswert
Und weil es so schön ist gleich noch mal eine andere Architektur. Diese 
besitzt sog. Carrychains in der FPGA Fabric um Zähler, Addierer etc. zu 
beschleunigen.
NanoXplore NXmap 2.9.7 für NG-MEDIUM
        
Design         | 4-LUT | DFF | Carry | FMax(MHz)
---------------|-------|-----|-------|----------
up             |  2    | 25  | 49    | 157.629
down           |  6    | 35  | 49    | 152.975
up_gleich      |  9    | 25  | 24    | 188.395
down_gleich    |  23   | 34  | 24    | 157.903
up_ungleich    |  12   | 25  | 24    |  71.551
down_ungleich  |  27   | 33  | 24    | 125.439

Interessanterweise ist der langsamste Fall völlig unerwartet der 
up_ungleich. Interessant ist, dass die Registerzahl springt zwischen den 
verschiedenen Beschreibungen. Der schnellste Fall ist gleichzeitig auch 
der kompakteste.

Jetzt wo wir es hier vergleichen bin ich sehr neugierig geworden auf 
Zahlen mit Yosys und GHDL-synth...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Dann beteilige ich mich auch mal am Wettbewerb. :-)

Lattice Radiant, iCE40UP5K, LSE, defaults
        LUT4    PFU Registers   IO Buffers      Carry Cells
up      9(9)    25(25)          2(2)            13(13)
down    9(9)    25(25)          2(2)            13(13)
up_ne   9(9)    25(25)          2(2)            13(13)
down_ne 9(9)    25(25)          2(2)            13(13)

Das ist das Resultat, was ich als compilerverwöhnter Mensch intuitiv 
erwartet hätte. ;-) Egal, wie man es formuliert, die Software stellt 
fest, dass das Ergebnis sich dadurch nicht ändert, und generiert das 
gleiche draus.

Wie ich aus der LSE da die von euch geposteten Timing-Werte rausbekomme, 
finde ich aber auf die Schnelle nicht.

Vielleicht schiebe ich das heute Abend auch nochmal durch die 
Synplify-Pro-Synthese.

: Bearbeitet durch Moderator
von Markus F. (mfro)


Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Das ist das Resultat, was ich als compilerverwöhnter Mensch intuitiv
> erwartet hätte. ;-) Egal, wie man es formuliert, die Software stellt
> fest, dass das Ergebnis sich dadurch nicht ändert, und generiert das
> gleiche draus.

Jede Synthesesoftware hat gefühlt >100 Schalter deren Änderung einen 
anderen (zumindest für mich manchmal ganz unerwarteten und/oder gar 
erstaunlichen) Effekt hat. Eigentlich müssten da m.E. nicht eine Hand 
voll, sondern ein paar Hundert Zeilen stehen...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Markus F. schrieb:
> Jede Synthesesoftware hat gefühlt >100 Schalter deren Änderung einen
> anderen (zumindest für mich manchmal ganz unerwarteten und/oder gar
> erstaunlichen) Effekt hat.

Ja, dass die Optimierung das eine gegen das andere abwägen muss, ist 
völlig klar. Bei den Compilern sind wir da mittlerweile halt so weit, 
dass es schon (fast) genügt, -O0, -O1, -Os, -O2 und -O3 zu haben :), bei 
der Synthese gibt's da vielleicht mehr Feinheiten.

Aber dass das gleiche Problem, egal, wie man es formuliert, zu gleichem 
Resultat führt, ist bei Compilern mittlerweile nahezu die Norm. Insofern 
haben mich die teils großen Unterschiede, die nicht von den 
Optimierungsstrategien, sondern nur von der Gestaltung des Codes 
abhängen, bei den Synthetisanten weiter oben schon etwas verwundert.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Insofern haben mich die teils großen Unterschiede, die nicht von den
> Optimierungsstrategien, sondern nur von der Gestaltung des Codes
> abhängen, bei den Synthetisanten weiter oben schon etwas verwundert.
Wenn du sowas wie dort unten bei "Gimmick" gesehen hast, wundert dich da 
nichts mehr:
http://www.lothar-miller.de/s9y/archives/52-Kompakte-Flankenerkennung.html

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Gut, aber inzwischen sind auch 10 weitere Jahre ins Land gegangen …

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:

> Vielleicht schiebe ich das heute Abend auch nochmal durch die
> Synplify-Pro-Synthese.

Hier das Resultat:
        LUT4    PFU Registers   IO Buffers      Carry Cells
up      17(17)  25(25)          2(2)            12(12)
down    18(18)  25(25)          2(2)            13(13)
up_ne   17(17)  25(25)          2(2)            12(12)
down_ne 18(18)  25(25)          2(2)            13(13)

Also kleinere Unterschiede als bei manch anderer Synthese hier, aber 
interessanterweise deutlich mehr LUTs als LSE. Gut, Lattice kann 
natürlich die Synthese für ihre Devices gut zurecht schneidern.

Dafür bekomme ich bei Synopsis zumindest etwas, was den oben angegebenen 
Timingwerten ähnelt:
Clock Name (clock_name)  Req Freq (req_freq)  Est Freq (est_freq)   Slack (slack)
down_ne|clk              200.0 MHz            NA                    NA
System                   200.0 MHz            115.8 MHz             -3.639

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
OK, wenn ich die timing constraints explizit für "clk" festlege, dann 
bekomme ich auch bei LSE dafür Daten.
up    From clk |             Target |           5.000 ns |        200.000 MHz
               | Actual (all paths) |          19.734 ns |         50.674 MHz

down  From clk |             Target |           5.000 ns |        200.000 MHz
               | Actual (all paths) |          24.838 ns |         40.261 MHz

up_ne From clk |             Target |           5.000 ns |        200.000 MHz
               | Actual (all paths) |          19.734 ns |         50.674 MHz

down_nw From clk |           Target |           5.000 ns |        200.000 MHz
               | Actual (all paths) |          24.838 ns |         40.261 MHz

von Robert P. (fpgazumspass) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Der Unterschied ist ja enorm im Takt.

Ich gehe davon aus die untere Tabelle ist Synthese + Routing durch LSE?

Dann wäre natürlich interessant ob der estimated clock tatsächlich 
erreicht wird, also Synthese von Synplify und Routing von LSE.
Die Ressourcen können sich nach dem Placement/Routing ja auch nochmal 
ändern.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Robert P. schrieb:
> Der Unterschied ist ja enorm im Takt.

Wundert mich auch, und ich gehe bisschen davon aus, dass das irgendwo 
Äpfel und Birnen sind, die da verglichen werden.

Das iCE40 ist ein low-power device, und ich habe auch schon woanders 
gelesen, dass das wohl so um die 40 MHz an Taktfrequenz erreicht, 
insofern sind die LSE-Zahlen sicherlich nicht unrealistisch.

Meiner Erinnerung nach war das erstmal der Wert nur nach der Synthese, 
ohne Routing. Muss mich da aber auch noch bisschen tiefer einlesen. Ich 
könnte ja auch mal versuchen, das tatsächlich noch zu pinnen und auf dem 
realen FPGA zu testen.

von Christoph Z. (christophz)


Bewertung
0 lesenswert
nicht lesenswert
Robert P. schrieb:
> Die Ressourcen können sich nach dem Placement/Routing ja auch nochmal
> ändern.

Du meinst sicherlich Timing bzw. max. Taktfrequenz. Die Ressourcen 
ändern sich nach dem mappen nicht mehr.

Jörg W. schrieb:
> Wundert mich auch, und ich gehe bisschen davon aus, dass das irgendwo
> Äpfel und Birnen sind, die da verglichen werden.

Nein, wir vergleichen hier wie ein Synthesetool auf verschiedene 
schreibweisen des selben Zählers reagiert und ob up/down schneller ist. 
Theoretisch könnte da jedesmal so ein Ergebnis rauskommen wie bei 
Radiant/LSE: Alle up varianten sind X schnell, alle down Varianten sind 
Y schnell.



Das ein Artix-7 schneller ist als ein ice40 müssen wir hier nicht 
untersuchen, das ist schon bekannt :-)

Markus F. schrieb:
> Jede Synthesesoftware hat gefühlt >100 Schalter deren Änderung einen
> anderen (zumindest für mich manchmal ganz unerwarteten und/oder gar
> erstaunlichen) Effekt hat. Eigentlich müssten da m.E. nicht eine Hand
> voll, sondern ein paar Hundert Zeilen stehen...

Jaein, wichtig für diesen Vergleich hier ist, dass alle sechs Codes mit 
den selben Einstellungen verglichen werden.

Die vielen Schalter zur Optimierung sind sicher ein wichtiger Punkt aber 
meine Vermutung ist, dass diese ihren Job auch erst effizient machen 
können, wenn das Front-End (VHDL in nicht optimierte Logik übersetzen) 
seine Aufgabe gut macht und hier in allen Fällen den selben up bzw. down 
counter erkennt.

Die Ergebnisse zeigen, dass dies alles andere als eine triviale Aufgabe 
ist.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Christoph Z. schrieb:
>> Wundert mich auch, und ich gehe bisschen davon aus, dass das irgendwo
>> Äpfel und Birnen sind, die da verglichen werden.
>
> Nein, wir vergleichen hier wie ein Synthesetool auf verschiedene
> schreibweisen des selben Zählers reagiert und ob up/down schneller ist.

Ich meinte meine Timing-Werte von einerseits LSE und andererseits 
SynplifyPro. Ich vermute, dass das verschiedene Aussagen sind.

von Christoph Z. (christophz)


Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Ich meinte meine Timing-Werte von einerseits LSE und andererseits
> SynplifyPro. Ich vermute, dass das verschiedene Aussagen sind.

Schicke beides mal durch Place&Route und analysiere das Timing dann.

Eigentlich sollten diese beiden Werte die selbe Aussage sein. Deckt sich 
auch mit meiner (7 Jahre alten) Erfahrung mit LSE für den MachXO2. Da 
war Synplify auch mehr als doppelt so schnell.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Christoph Z. schrieb:
> Da war Synplify auch mehr als doppelt so schnell.

OK.

Wobei sie ja hier auch mit doppeltem Ressourcenverbrauch glänzen. ;-)
(17/18 LUTs statt nur 9)

von Robert P. (fpgazumspass) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Christoph Z. schrieb:
> Robert P. schrieb:
>> Die Ressourcen können sich nach dem Placement/Routing ja auch nochmal
>> ändern.
>
> Du meinst sicherlich Timing bzw. max. Taktfrequenz. Die Ressourcen
> ändern sich nach dem mappen nicht mehr.

Ich meinte die Ressourcen. Die unterscheiden sich zwischen "nach der 
Synthese" und "nach dem Mapping" durchaus.

Wenn die eine Übersicht von Synplify hier nach der Sythese ist, die von 
LSE aber nach dem komplettem Build, kann sich da durchaus noch etwas 
tun.

Bei nochmaligem lesen scheint es mir aber, das nur das Timing vom 
Synplify Report stammt, die Ressourcen aber vom "kompletten" Build.

von Christoph Z. (christophz)


Bewertung
0 lesenswert
nicht lesenswert
Robert P. schrieb:
> Ich meinte die Ressourcen. Die unterscheiden sich zwischen "nach der
> Synthese" und "nach dem Mapping" durchaus.
>
> Wenn die eine Übersicht von Synplify hier nach der Sythese ist, die von
> LSE aber nach dem komplettem Build, kann sich da durchaus noch etwas
> tun.

Nach der Synthese hast du aber noch gar keine Ressourceninformation. 
Also nicht die, die wir hier vergleichen. LUTs, Core-cells, Carry-* gibt 
es erst nach dem Mapping.

Synplify übernimmt die Schritte Synthese und Mapping. Place & Route sind 
dann Vendor Tools. Nach meiner Erfahrung sind die Frequenzschätzungen 
von Synplify knapp konservativ und nach dem P&R habe ich üblicherweise 
etwas bessere Werte.

von Robert P. (fpgazumspass) Benutzerseite


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Christoph Z. schrieb:
> Nach der Synthese hast du aber noch gar keine Ressourceninformation.
> Also nicht die, die wir hier vergleichen. LUTs, Core-cells, Carry-* gibt
> es erst nach dem Mapping.

Also mir zeigt sowohl Vivado als auch Quartus diese Information schon 
nach der Synthese an. Siehe Screenshots.
Zumindest mal für LUTs, FFs, DSP und Blockram, also alles Wichtige.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Robert P. schrieb:
> Also mir zeigt sowohl Vivado als auch Quartus diese Information schon
> nach der Synthese an.

Ich denke auch, dass die Zahlen, die ich da gepostet habe, jeweils die 
Reports der Synthese waren, aber ich schau mir das heute Abend nochmal 
an.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Jetzt habe ich mal noch ein Pinning ergänzt und den Flow komplett laufen 
lassen. Nicht ganz unerwartet rödelt das P&R dann eine Weile, merkt an 
dass das Timing "hard to meet" sei und bricht dann ab.
SynplifyPro

up      | Actual (all paths) |          14.291 ns |         69.974 MHz
down    | Actual (all paths) |          14.738 ns |         67.852 MHz
up_ne   | Actual (all paths) |          15.016 ns |         66.596 MHz
down_ne | Actual (all paths) |          14.738 ns |         67.852 MHz

LSE

up      | Actual (all paths) |          13.923 ns |         71.824 MHz
down    | Actual (all paths) |          13.725 ns |         72.860 MHz 
up_ne   | Actual (all paths) |          14.134 ns |         70.751 MHz
down_ne | Actual (all paths) |          13.725 ns |         72.860 MHz

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.