Forum: FPGA, VHDL & Co. maximale Xilinx CPLD clock Frequenz


von Reinhard J. (rvj)


Angehängte Dateien:

Lesenswert?

Hallo Forum,

seit einigen Wochen arbeite ich mich in VHDL ein. Ich nutze dafür den 
Xilinx ISE Project Navigator 13.4 und programmiere einen XC9572XL CPLD. 
Der CPLD zählt Encoder und gibt den 24 Bit breiten Zählerstand nach 
Aufforderung Byte-weise aus. Dieser wird von einem AVR weiterverarbeitet 
und auf einer Siebensegmentanzeige ausgegeben.

Für die positive Zählrichtung funktioniert das fast tadellos. Zähle ich 
in die negative Richtung und gelange zu negativen Zahlen treten an ganz 
unterschiedlichen Stellen Fehler auf. In der positiven Richtung zeigen 
sich  diese Fehler sehr sehr viel seltener. Ich habe mein C-Programm auf 
dem AVR unter die Lupe genommen und meines Erachtens alle Fehler 
eliminiert.

Als letzten Schritt tauschte ich den 48MHZ Quarzoszilator am CPLD gegen 
einen 20MHz Quarzoszilator aus. Dadurch traten die Fehler deutlich 
seltener auf.

Meine Frage lautet nun: Wo kann ich in der Xilinx Design Suite die 
maximal mögliche Frequenz der clock ablesen?

Mein derzeitiger Aufbau befindet sich auf einem Steckbrett (siehe 
Bilder). Kann es sein, dass ich mir durch die lanhen Kabel Ärger 
einhandele? Wird der Aufbau auf gefädeltem Lochraster stabiler?

Vielen Dank für die Hilfe
Reinhard

von Hans-Georg L. (h-g-l)


Lesenswert?

Unter Design Summary findest du alle Reports.

Aber das Cpld ist sicher schneller als dein AVR und kann deshalb bei den 
langen Leitungen Spikes erzeugen wenn die Stützkondensatoren fehlen.

Deshalb löte mal Stützkondensatoren auf deinem Adapter ein.

Hast du eine Testbench und was sagt der Simulator ?

von Reinhard J. (rvj)


Angehängte Dateien:

Lesenswert?

Danke Hans-Georg!

Das CPLD ist in der Tat viel schneller als der AVR. Deshalb reagiert es 
auf einen Puls, bei dem ein Zählerschnappschnuss angelegt und das erste 
Byte für den AVR an 8 Pins ausgegeben wird. Die beiden restlichen Bytes 
hole ich dann später pulsgesteuert ab.

Eine Testbench für den Simulator habe ich auch. ich habe meinen VHDL 
Code dort vor dem Stecken überprüft. Sieht gut aus. Ich habe mal einen 
Teil der Simulation abfotografiert. Ein Puls get0 erzeugt den 
Schnappschuss und legt das least significant Byte der 24 Bit Zahl nach 
count. Nach dem nächsten Puls namens get1 geht das mittlere Byte auf 
count und nach dem Puls get2 das most significant Byte nach count. Der 
Zähler läuft währendessen immer weiter, so dass auf count nur der 
Schnappschuss zu einem bestimmten Zeitpunkt ausgegeben wird.

Die Design Summary Reports hab ich schon gelesen. Leider habe ich nichts 
zur maximalen Taktung gefunden. Kannst Du bitte meinen Blick auf die 
entscheidende Passage richten?

Was meinst Du mit Stützkondensatoren? Etwa Abblockkondensatoren zwischen 
3,3V und GND oder was anderes?

Auf dem Adapter sind tatsächlich an jeder Ecke drei Lötösen. Deren 
Verwendung erschließt sich mir nicht. Das war übrigens meine erste SMD 
Lötung.

Viele Grüße
Reinhard

von dden (Gast)


Lesenswert?

Hallo,
so wie es aussieht hast du NULL Kondensatoren am Chip?
Wenns nicht anderst geht dann würde ich erstmal an JEDEN Versorgungspin 
direkt am Chip einen 100nf löten.Ohne irgenwas geht so was nicht korekt.
Vielleicht postest du noch deinen vhdl code?

Mfg

von dden (Gast)


Lesenswert?

Achso und im Xilinx CPLD Report kannst du ganz oben zwischen 2 Blättern 
wechseln, im zweiten(recchten) steht der timing Report.

von Grendel (Gast)


Lesenswert?

Das bei DEM Antennenwald da Fehler passieren wundert nicht ;-)


dden schrieb:
> Wenns nicht anderst geht dann würde ich erstmal an JEDEN Versorgungspin
> direkt am Chip einen 100nf löten.

Und zusätzlich auf der CPLD Platine noch einen 10 - 100µF Elko für die 
ganze Versorgung (muss nicht direkt an den Chip, kann ein paar cm weit 
weg).

Die Pins der 100nf Kondensatoren so KURZ wie möglich halten! Nicht so 
wie auf dem Breadboard da so lange Beinchen lassen sowas muss so Nahe an 
den Chip ran wie möglich... beim 100µF Elko hingegen ists egal.

von Duke Scarring (Gast)


Lesenswert?

Reinhard J. schrieb:
> Der CPLD zählt Encoder und gibt den 24 Bit breiten Zählerstand nach
> Aufforderung Byte-weise aus.
Wie sieht das Protokoll aus?
Wie werden die Steuersignale im CPLD verabeitet?
Wieviele Taktquellen sind verbaut?
Falls mehrere Taktquellen im Spiel sind: Sind die Übergänge an den 
Clockdomains richtig designt?

Duke

von Hans-Georg L. (h-g-l)


Lesenswert?

Wahrscheinlich kommen diese "get" Signale asynchron vom AVR ...

von Frank (Gast)


Lesenswert?

Hans-Georg Lehnard schrieb:
> Wahrscheinlich kommen diese "get" Signale asynchron vom AVR ...

Denke ich auch. Versuchs mal mit einer Impulsverkürzung.

von Falk B. (falk)


Lesenswert?

@ Reinhard J. (rvj)

>sich  diese Fehler sehr sehr viel seltener. Ich habe mein C-Programm auf
>dem AVR unter die Lupe genommen und meines Erachtens alle Fehler
>eliminiert.

;-)

>Als letzten Schritt tauschte ich den 48MHZ Quarzoszilator am CPLD gegen
>einen 20MHz Quarzoszilator aus. Dadurch traten die Fehler deutlich
>seltener auf.

>Meine Frage lautet nun: Wo kann ich in der Xilinx Design Suite die
>maximal mögliche Frequenz der clock ablesen?

In den TIming Reports. Gibt man sinnvollerweise ein Constraint für den 
Takt an, hat man es direkt schwarz auf Weiß.

>Mein derzeitiger Aufbau befindet sich auf einem Steckbrett (siehe
>Bilder). Kann es sein, dass ich mir durch die lanhen Kabel Ärger
>einhandele?

Ja. Denn die CPLDs sind SAUSCHNELL, wenn der Takt nicht WIRKLICH sauber 
ist, kann es sein, dass du dir hin und wieder doppelte Taktflanken 
reinziehst, wo nur eine ist. Siehe Wellenwiderstand.

Das Thema asynchrone Taktdomänen (CPLD/AVR) wurde ja schon angesprochen.

> Wird der Aufbau auf gefädeltem Lochraster stabiler?

Kann sein, muss man aber auch solide machen.

von Falk B. (falk)


Lesenswert?


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


Lesenswert?

Hans-Georg Lehnard schrieb:
> Wahrscheinlich kommen diese "get" Signale asynchron vom AVR ...
Und gehen asynchron in den Zähler...

Reinhard J. schrieb:
> arbeite ich mich in VHDL ein. Ich nutze dafür den Xilinx ISE Project
> Navigator 13.4 und programmiere einen XC9572XL CPLD. Der CPLD zählt
> Encoder und gibt den 24 Bit breiten Zählerstand nach Aufforderung
> Byte-weise aus
Lass doch mal deine VHDL-Beschreibung sehen.

von Hans-Georg L. (h-g-l)


Lesenswert?

Lothar Miller schrieb:
> Hans-Georg Lehnard schrieb:
>> Wahrscheinlich kommen diese "get" Signale asynchron vom AVR ...
> Und gehen asynchron in den Zähler...
>

Und in der Testbench/Simulation ist alles wunderbar synchron ;)

In der Simulation (Cursor) sieht es aus wie wenn die Daten an der 
Anstiegsflanke vom AVR übernommen werden sollen. Das macht der AVR aber 
erst (synchron) bei seinem nächsten Takt und da können die Datenausgänge 
des CPLD schon wieder etwas ganz anderes zeigen.

Ohne ein echtes Handshake wird das zur Glücksache.

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

Nur mal so als Richtwert:

Mit nem kleineren Coolruner (64er) sind synchrone Zähler bis über 450 
MHz drin, selber ausprobiert.

Mit nem XC95er sollten allemal meht als 130 MHz drin sein.

Also dran denken: So ein CPLD ist ein ausgesprochenes 
Hochfrequenz-Bauteil und will deshalb auch so behandelt sein. Also ne 
HF-gerechte Leiterplatte machen und erst dann weitermurksen.

W.S.

von Reinhard J. (rvj)



Lesenswert?

Hallo Forum,

vielen herzlichen Dank für die vielen Antworten.

Ich habe den Eintrag gefunden und den Bildschirm für andere Leser 
abfotografiert (siehe Bilder). Danke dden!

Meinen Code stelle ich als Anhang ein. Ich dachte er sei ein wenig lang 
und hatte ihn deshalb erst mal weggelassen. Insbesondere der AVR C-Code 
muss noch aufgeräumt werden. Er sollte aber in der jetzigen Form lesbar 
sein. Der Nullwert wurde auf 8388607 gelegt, da ich zunächst Fehler bei 
der Bildung des Zweierkomplements vermutete. Das ist aber nicht der 
Fall.

Ich vergaß zu sagen, dass ich einen Pegelwandlung von 3,3 V nach 5V 
versucht habe. Einmal mit zwei SN74HCT125N Bausteinen und nachdem dies 
nicht klappte mit zwei HD74LS06P. Die erste Variante wird im Beitrag 
Pegelwandlung vorgeschlagen. Beide habe nicht funktioniert und so gebe 
ich die Signale des CPLD direkt auf den AVR Atmmega32, welcher mit 5V 
läuft.

Tatsache ist, dass mein C-Programm immer einen Wert abholt und 
darstellt. Eine einzelne Fehlübertragung dürfte sich auf die nächsten 
Transfers nicht auswirken, da der Zähler ja im CPLD verwaltet wird.

Das Fehlerbild ist aber wie folgt: Stellt sich ein Fehler ein, so wird 
mit der falschen Zahl weitergezählt. Folglich liegt die Zahl schon 
falsch am CPLD an.

Ich werde nun meine Schaltung auf Lochraster auflöten. Die 
Spannungsversorgung löte ich auf festen Bahnen und die Signale werde ich 
fädeln. Dies ist mein erster Fädelversuch und ich bin gespannt wie es 
klappt. Die Kondensatoren bringe ich wie empfohlen an.

Über den Fortgang werde ich berichten.

Nochmals Danke an alle Leser und insbesondere an alle Kommentatoren. Ich 
versuche Eure Tipps umzusetzen.

Viele Grüße
Reinhard

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


Lesenswert?

> use IEEE.std_logic_arith.all; -- import add/sub of std_logic_vector
Oh, das fängt schon gut an...
Such hier im Forum mal nach "std_logic_arith obsolete". Fazit: man 
rechnet nicht mit uneingeschränkten Vektoren! Nimm für deinen Zähler 
signed oder unsign
ed Vektoren. Oder noch besser: nimm einen Integer.

: Bearbeitet durch Moderator
von D. V. (mazze69)


Lesenswert?


von Reinhard J. (rvj)


Lesenswert?

Hallo Lothar,

habe nach "std_logic_arith obsolete" geschaut und muss zugeben, dass ich 
mit den libraries noc nicht durchblicke. Ich denke das werde ich lernen 
müssen.

Mein Zähler heißt t_cnt.

Zum Zeitpunkt des Schnappschusses gebe ich das niederwertigste Byte am 
Ausgang COUNT aus. Die beiden höherwertigen Bytes merke ich mir in 
t_cnt2. Sie werden später mit den Signalen GET1 und GET2 abgeholt.

Kurz mit t_cnt2 wird nicht gerechnet. Der Zähler heißt t_cnt und der ist 
ein signed.
1
  --  Counter                                  "011111111111111111111111"      123456789012345678901234
2
   signal t_cnt   : signed(23 downto 0); -- := "000000000000000000000000";          -- internal counter signal
3
   signal t_cnt2   : std_logic_vector(15 downto 0); -- := "0000000000000000";          -- internal counter signal to store t_cnt for bytewise transmission

Ich denke Dein Hinweis zielt auf die library. Ich lese die Links nochmal 
durch und frage ggf.. Bitte bedenke ich bin begeisterter VHDL Anfänger.

Vielen Dank!
Reinhard

von Marius S. (lupin) Benutzerseite


Lesenswert?

Kann mir vorstellen, dass der Zählerstand sich während oder nach der 
ersten Übertragung ändert.
Wenn GET0 am cpld anliegt dann wird der aktuelle Zählerstand für die 
unteren Bits durch gereicht anstatt gelatcht und dann übertragen zu 
werden.
Das Problem verschlimmert sich durch deine Wartezeiten im AVR. Warum 
sind die da drin?

Warum überhaupt 24 Bit? Da kann man ja ewig drehen :-)

Praktischer wäre eine SPI Übertragung denke ich.

Oben im Kommentar hat dir ISE doch schon hin geschrieben welche Library 
du für signed/unsigned nutzen sollst. Integer würde ich in diesen Fall 
nicht nehmen.

Die Zuweisung der Vektoren beim Auslesen wäre schöner, wenn du sie als 
Vektoren zuweist (also über downto).

Im C Code würde ich uint8_t für das Byte-Array nehmen. Macht aber keinen 
Unterschied :-)

Mehr fällt mir nicht auf...

: Bearbeitet durch User
von Reinhard J. (rvj)


Lesenswert?

Hallo Marius,

Du hast meinen Code aber fix gelesen. Danke.

Ich denke Du meinst diese Stelle:
1
    if (rising_edge(clk)) then
2
      if GET0 = '1' then
3
        -- COUNT(23 downto 0) <= std_logic_vector(t_cnt(23 downto 0));
4
        t_cnt2(15)   <= t_cnt(23);
5
        t_cnt2(14)   <= t_cnt(22);
6
        t_cnt2(13)   <= t_cnt(21);
7
        t_cnt2(12)   <= t_cnt(20);
8
        t_cnt2(11)   <= t_cnt(19);
9
        t_cnt2(10)   <= t_cnt(18);
10
        t_cnt2(9)   <=  t_cnt(17);
11
        t_cnt2(8)   <=  t_cnt(16);
12
        t_cnt2(7)   <=  t_cnt(15);
13
        t_cnt2(6)   <=  t_cnt(14);
14
        t_cnt2(5)   <=  t_cnt(13);
15
        t_cnt2(4)   <=  t_cnt(12);
16
        t_cnt2(3)   <=  t_cnt(11);
17
        t_cnt2(2)   <=  t_cnt(10);
18
        t_cnt2(1)   <=  t_cnt(9);
19
        t_cnt2(0)   <=  t_cnt(8);
20
        --
21
        COUNT(7)   <=  t_cnt(7);
22
        COUNT(6)   <=  t_cnt(6);
23
        COUNT(5)   <=  t_cnt(5);
24
        COUNT(4)   <=  t_cnt(4);
25
        COUNT(3)   <=  t_cnt(3);
26
        COUNT(2)   <=  t_cnt(2);
27
        COUNT(1)   <=  t_cnt(1);
28
        COUNT(0)   <=  t_cnt(0);

Stimmt während dieser Zeit darf sich der Zähler nicht ändern.

Folglich muss die Zuweisung in einem erfolgen. Muss mir ansehen wie das 
syntaktisch geht. Ich fange mit dem Lernen von VHDL mit diesem Projekt 
an und muss alles nachschauen. Mit einer Aufgabe macht es einfach mehr 
Laune.

Den 24bit counter habe ich gewählt, da ich das an eine Motor-Encoder 
Einheit anschließen möchte. Wenn der Encoder irrwitzige Auflösung hat 
sind 24 Bit ganz ok.

Gruß Reinhard

von dden (Gast)


Lesenswert?

Hallo,
1
elsif (rising_edge(ce)) then           -- bei steigender Flanke von CLK
2
      if (up_down = '1') then 
3
--        t_cnt <= CONV_STD_LOGIC_VECTOR(UNSIGNED(t_cnt) + 1, 24);
4
        t_cnt <= t_cnt + 1;
5
      else 
6
        t_cnt <= t_cnt - 1;
7
      end if;
8
    end if;
sowas hier sollte man nicht konstruieren, daher kommen wahrscheinlich 
auch deine Probleme, immer mit einer stabilen clk  und einem 
Clock-Enable(in deinem Fall z.B. mit einer Flanken-Erkennung auf ce) 
arbeiten.Als Beispiel:
1
  elsif (rising_edge(clk)) then
2
    if ce='1' then
3
      if (up_down = '1') then 
4
        t_cnt <= t_cnt + 1;
5
      else 
6
        t_cnt <= t_cnt - 1;
7
      end if;
8
    end if;
9
  end if;

und deinen Count würde ich auch komplett Registern und über einen 
Multiplexer auslesen.
ein z.B. zusätzliches signal in_speichern Flankensynchronisieren und als 
sample(cnt>>cnt_tmp) nutzen
und dann direkt die Daten auslesen, dazu musst du aber auch deinen 
C-Code ändern.Dann kannst du sowas benutzen.
1
  with readvect select
2
    count <= t_cnt_tmp(7 downto 0) when "100" ,
3
    count <= t_cnt_tmp(15 downto 8) when "010" ,
4
    count <= t_cnt_tmp(23 downto 16) when "001" ,
5
    count <= (0 to 7 => 'Z') when others ,

Ach und nochwas benutze keine VHDL reservierten Wörter wie error schreib 
einfach error_flag oder oERROR.
Und du solltest dir auch die Warnungen im Report genau anschauen.Ein 
"Possible Asynch-Clk" hat da nichts zu suchen.

Mfg

von Marius S. (lupin) Benutzerseite


Lesenswert?

dden hat recht, wenn du jetzt noch einen Zähler hinzufügst und anstatt 8 
Bit immer nur das eine Bit ausgibst auf welches der Zähler gerade zeigt 
und den zähler mit jeder Übertragung aktualisierst dann hast du ein 
schieberegister, welches du mit SPI lesen kannst.

Musst nur den Zähler nach der Übertragung zurück setzen (mit CE-Signal).

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

@ Reinhard J. (rvj)

Das ist einiges nicht OK. Besser so, siehe Anhang.
Noch ein Tip. Schreibe sinnvolle Komentare, keine Lyrik.

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.