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
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 ?
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
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
Achso und im Xilinx CPLD Report kannst du ganz oben zwischen 2 Blättern wechseln, im zweiten(recchten) steht der timing Report.
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.
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
Hans-Georg Lehnard schrieb: > Wahrscheinlich kommen diese "get" Signale asynchron vom AVR ... Denke ich auch. Versuchs mal mit einer Impulsverkürzung.
@ 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.
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.
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
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.
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
> 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
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
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
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
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
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).
@ 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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.