Forum: FPGA, VHDL & Co. [XC95 CPLD] Zähler mit einigen Zusatzfunktionen realisieren


von Ingo S. (logikneuling)


Lesenswert?

Hallo!

Ich habe bisher alle Counteraufgaben entweder direkt mittels 
Mikrocontrollern (in AVR-C) oder mit Hilfe von Logik-ICs realisiert. Da 
im aktuellen Fall (Zählfrequenz > 50 MHz, 16-Bit Zählerbreite) jedoch 
das Auslesen aufgrund von Glitches und Signallaufzeiten der kaskadierten 
ICs zunehmend problematischer wurde, wollte ich folgenden Zähler gerne 
mittels Xilinx XC9572XC CPLD realisieren.

- 16-Bit Auflösung/Breite, nur Aufwärtszählen nötig
- Impulse (Pulse-Eingang) treten unvorhersehbar und zufälllig, aber mit 
einer maximalen Frequenz < 90 MHz auf
- Zählerüberlauf ist nicht relevant (Zählzeiten sind kurz genug, als 
dass diese auftreten könnten)

Außerdem:
- Zähler soll über externes Signal (Gate-Eingang) "scharfgestellt" 
werden können und möglichst zeitnah nach dem ersten tatsächlich 
gezählten Impuls dies an einem Ausgang anzeigen (Active-Ausgang)
- Zählerstand soll parallel auslesbar sein, soll/braucht jeweils nur 
nach Aufforderung (Clk-Takt) aktualisiert werden
- Zähler soll nach Ende des Zählvorgangs zurückgesetzt werden (momentan 
einfach immer, wenn Gate-Eingang low ist)

Dies hier sind mein erstes CPLD-Projekt und meine ersten Schritte in 
VHDL, herausgekommen ist bisher folgendes:

1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
entity Counter16 is
7
  port( Clk,Pulse,Gate:    in   std_logic;
8
        Active:         out   std_logic;
9
        Data:           out   std_logic_vector(15 downto 0)
10
      );
11
end Counter16;
12
13
Architecture behaviour of Counter16 is
14
  signal Q: std_logic_vector(15 downto 0);
15
  
16
begin
17
18
process(Gate, Pulse)
19
begin
20
  if (Gate = '0') then 
21
    Q <= (others => '0');
22
   Active <= '0';
23
  elsif (rising_edge( Pulse)) then
24
   Active <= '1';
25
    Q <= Q +1;
26
  end if;
27
end process;
28
29
process( Clk)
30
begin
31
  if rising_edge( Clk) then
32
    Data <= Q;
33
  end if;
34
end process;
35
36
end behaviour;


Das Ganze funktioniert erstaunlicherweise schon einmal relativ gut, bis 
auf ein kleines Detail: In mehr oder weniger regelmäßigen Abständen 
erhalte ich nach einem Aktualisieren des Zählerstands an den Ausgangen 
mittels Clk-Takt einen Wert der 64/128/256 zu hoch ist, der 
darauffolgende Wert stimmt wieder.

Meine Vermutung ist, dies tritt immer dann auf, wenn zeitgleich ein 
Pulse-Takt den Zähler hochsetzt und ein Clk-Takt die Ausgabe 
aktualisiert. Vielleicht sind aber auch die Laufzeiten der FF im CPLD im 
Allgemeinen daran Schuld, oder ein Problem, dass ich noch gar nicht 
erkannt habe.

Ich wäre dankbar über jede Art von Tipp oder Anregung, wie ich diesen 
Zähler optimieren kann. Eventuell kann das eine oder andere auch besser 
völlig anders gelöst werden, als ich es bisher versucht habe.

Vielen Dank und viele Grüße
Ingo

von Schlumpf (Gast)


Lesenswert?

Du bist mit deiner Vermutung schon auf der richtigen Spur.

Du hast zum einen das Zählregister Q beschrieben, welches mit "pulse" 
getaktet wird und zum anderen ein Ausgangsregister, welches mit "Clk" 
getaktet wird.
Da "Pulse" und "Clk" aber keinen starren phasenbezug zueinander haben, 
kann es vorkommen, dass in dem Moment die Daten von Q aktualisiert 
werden, während du die Daten in "Data" übernimmst.

Lösungsmöglichkeiten:
Entweder lässt du das "Data"-Register ganz weg
Oder du taktest das Ausgangsregister "Data" auch mit "Pulse"
Oder du synchronisierst "Pulse" mit dem Takt "Clk" ein und taktest das 
Zählregister mit "clk" und enablest den Zähler immer nur dann, wenn eine 
steigende Flanke auf "Pulse" kam...

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


Lesenswert?

Ingo S. schrieb:
> Vielleicht sind aber auch die Laufzeiten der FF im CPLD im
> Allgemeinen daran Schuld,
Ja, richtig, das ist die Ursache...
> oder ein Problem, dass ich noch gar nicht erkannt habe.
Du musst asynchrone Signale einsynchronisieren. Das, was du da gerade 
beobachtest, findest du (in etwa) hier beschrieben:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html
Denn dein Pulssähler ist ein Zustandsautomat, und dein asynchroner 
Übernahme"takt" hat unterschiedlich lange Laufzeiten zu den 
Übernahme-Flipflops...

von Ingo S. (logikneuling)


Lesenswert?

Vielen Dank für die schnellen Antworten!

Ich versuche einmal der Reihe nach darauf einzugehen, bevor ich anfange, 
wild herumzuprobieren und die nächsten, ähnlichen Anfängerfehler 
einbaue...

Schlumpf schrieb:
>Entweder lässt du das "Data"-Register ganz weg
Kurz zur Erklärung, warum ich das Data-Register eingeführt habe: Ich 
lese dieses Register an den Ausgangspins mit einem 8-Bit Atmega2560 und 
16MHz Systemtakt aus. Ein 16-Bit Register auszulesen dauert also selbst 
im Idealfall zwei Taktzyklen, sprich 133ns. Bei einer Impulsfrequenz <= 
90 MHz kann sich der Zählerstand bereits mehrmals geändert haben, also 
wollte ich gerne eine "Standbildaufnahme" des momentanen Zählerstandes, 
den ich in Ruhe mit dem Atmega auslesen kann.


>Oder du taktest das Ausgangsregister "Data" auch mit "Pulse"
Wenn ich das richtig sehe, hätte ich damit das oben beschriebene Problem 
nicht gelöst, weil sich dann "Data" innerhalb von 133ns mehrmals ändern 
könnte, oder?

>Oder du synchronisierst "Pulse" mit dem Takt "Clk" ein und taktest das
>Zählregister mit "clk" und enablest den Zähler immer nur dann, wenn eine 
>steigende Flanke auf "Pulse" kam...
Dafür brauche ich einen Clk-Takt, der deutlich schneller ist, als mein 
Pulse-Takt es in der Praxis werden kann, oder? Es sieht mir langsam 
danach aus, als wäre mein Vorhaben unmöglich, dabei klingt es nach einer 
so simplen Aufgabe...

Lothar Miller schrieb:
>Denn dein Pulssähler ist ein Zustandsautomat, und dein asynchroner
>Übernahme"takt" hat unterschiedlich lange Laufzeiten zu den
>Übernahme-Flipflops...
Die ersten 8 Bit des Registers werden frühestens 62,5ns (16 MHz 
Systemtakt des uC) nach Erzeugen des "Clk"-Taktes ausgelesen, sind die 
Laufzeiten der CPLD-FlipFlops insgesamt noch langsamer? Hier könnte ich 
ja tatsächlich noch einfach eine Wartezeit einbauen.

Ist es eventuell möglich, dieses Problem mit einem zusätzlichen 
Zwischenschritt zu lösen? Ich dachte spontan an:
-Pulse lässt Zähler hochzählen
-Clk fordert Zählerstand an
-Im Fall eines angeforderten Zählerstandes wird Data mit dem nächsten 
Pulse einmalig aktualisiert
-Per Ausgabe-Pin wird die erfolgreiche Aktualisierung angezeigt
-Anschließend kann Data ausgelesen werden
-und "Anforderung" und "erfolreiche Aktualisierung" werden 
zurückgesetzt?

Das Hauptproblem lässt sich vermutlich so zusammenfassen: 
Verzhältnismäßig schnelle Zählimpulse sollen in einem sehr präzisen, 
aber im Vergleich zu den Zählimpulsen langsamen Zeitraster ausgelesen 
werden. So dass man beispielsweise mit 1kHz Clk-Frequenz irgendwann 
innerhalb des 1ms-Fensters die Gelegenheit hat, den genauen Zählerstand 
zur Zeit der 1kHz Clk-Flanke abzufragen.

Vielleicht ist das ganze auch ganz einfach, und ich habe nur noch nicht 
ganz durchblickt, wie genau ich ein entsprechendes "Einsynchronisieren" 
bewerkstelligen kann?

Das hinter der gegebenen URL erwähnte Problem des Asynchronen Resets in 
meinem Code habe ich übrigens bemerkt, ist aber glaube ich zum Glück in 
diesem Fall nicht besonders schlimm. Ich kann in meinem Fall sicher 
sein, dass sowohl zum Zeitpunkt, wenn Gate HIGH gesetzt wird, als auch 
beim LOW Zeitpunkt, keine Pulse-Takte auftauchen. Deshalb überhaupt erst 
ein "Active"-Signal, um den tatsächlichen Beginn eines hereinhagelnden 
Impulshaufens zu erfassen.

Vielen Dank für eure Mühen,
Ingo!

von Schlumpf (Gast)


Lesenswert?

Wenn du systembedingt davon ausgehen musst, dass sich dein Zählerwert 
ändert, während du ausliest, dann hilft es dir auch nichts, einfach den 
Zählerwert in ein langsameres Register zwischenzuspeichern.. denn auch 
dieses kann sich ja genau in dem Moment ändern, in dem du ausliest.
Du müsstest also eine Art Steuersignal einführen, mit dem du während des 
Auselesevorgangs das Leseregister "einfrierst".
Das könnte z.B. das RD-Signal des Busses sein..

Ingo S. schrieb:
> Es sieht mir langsam
> danach aus, als wäre mein Vorhaben unmöglich,

Nein, das ist es nicht.. man muss nur ein paar Sachen beachten, dann 
geht das..

Idealerweise arbeiten alle Register mit einem identischen Takt.
Diesen Takt wählst du so schnell, dass du damit das Eingangssignal 
abtasten kannst.
Die Abtastung erfolgt durch mindestens 2 hintereinandergeschaltete 
Register. Anhand des Zustandes der Register kannst du erkennen, ob das 
"Pulse"-Signal gerade eine steigende Flanke durchläuft.
Wenn das der Fall ist, dann enablest du den Counter für einen internen 
Systemtakt lang.
Das "Daten" Register übernimmt mit jedem Systemtakt den Wert vom 
Counter. Tut dies aber nicht, wenn das externe Signal die Aktualisierung 
"verbietet", während du das Register liest.
Achtung: Dieses Steuersignal muss auch synchronisiert werden!

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


Lesenswert?

Ingo S. schrieb:
> -Im Fall eines angeforderten Zählerstandes wird Data mit dem nächsten
> Pulse einmalig aktualisiert
Das ist der richtige Schritt...

> So dass man beispielsweise mit 1kHz Clk-Frequenz irgendwann
> innerhalb des 1ms-Fensters die Gelegenheit hat, den genauen Zählerstand
> zur Zeit der 1kHz Clk-Flanke abzufragen.
Du musst unbedingt die Namensgebung überarbeiten. Ein Takt ist idR. 
etwas (relativ) dauerhaft anliegendes Schnelles. Dein Puls ist 
eigentlich der Zähltakt.
Dein Takt ist nur ein Latch-Signal, das anzeigt, dass der aktuelle 
Zählerstand irgendwohin übernommen werden soll.

> Das hinter der gegebenen URL erwähnte Problem des Asynchronen Resets in
> meinem Code habe ich übrigens bemerkt, ist aber glaube ich zum Glück in
> diesem Fall nicht besonders schlimm.
Die Absicht war nicht, den Reset anzuprangern, sondern zu zeigen, dass 
du zwei asynchrone Signale hast, die aufeinander synchronisiert werden 
müssen...

> wie genau ich ein entsprechendes "Einsynchronisieren"
> bewerkstelligen kann?
Wie "zufällig" kommt der Zähltakt? Denn der Zähler läuft in seiner 
eigenen Taktdomäne und nur diese Taktdomäne kennt einen "ungefährlichen" 
Zeitpunkt zur Datan übernahme in das Schattenregister...

von Ingo S. (logikneuling)


Lesenswert?

Lothar Miller schrieb:
>Das ist der richtige Schritt...
Ich bin dabei, es zu versuchen. Aber es scheint schwieriger, als 
angenommen. Bisher ist nichts dabei herausgekommen, dass synthetisiert 
werden konnte. Fehler wegen Multi-Source, wegen schreibendem/lesenden 
Zugriff zugleich, Fehler in der Sensitivitätsliste, ...

>Du musst unbedingt die Namensgebung überarbeiten. [...]
>Dein Takt ist nur ein Latch-Signal, das anzeigt, dass der
>aktuelle Zählerstand irgendwohin übernommen werden soll.

Du hast völlig Recht, die Namen sind eher Relikt aus meinen ersten 
VHDL-Tutorials. Latch beschreibt besser, was Clk hier tut!

>Die Absicht war nicht, den Reset anzuprangern, sondern zu zeigen, dass
>du zwei asynchrone Signale hast, die aufeinander synchronisiert werden
>müssen..
Genau das habe ich natürlich auch gesehen und so verstanden. 
Informationen in Hülle und Fülle, ich bin schon dabei, mich hier schlau 
zu lesen. Wollte hier lediglich einer Asynchroner-Reset-Diskussion 
vorausgreifen, dessen Problematik bin ich mir bewusst.

>Wie "zufällig" kommt der Zähltakt? Denn der Zähler läuft in seiner
>eigenen Taktdomäne und nur diese Taktdomäne kennt einen "ungefährlichen"
>Zeitpunkt zur Datan übernahme in das Schattenregister...
Eventuell kommt er sogar nie, es ist gar nicht garantiert, dass 
innerhalb der Gate-Zeit Impulse auftreten. Eventuell aber auch welche 
mit bis zu 90 MHz. Eine Art Geiger-Müller-Zählrohr beschreibt den 
Anwendungszweck ganz gut.

Schlumpf schrieb:
>Idealerweise arbeiten alle Register mit einem identischen Takt.
>Diesen Takt wählst du so schnell, dass du damit das Eingangssignal
>abtasten kannst.
Dazu wäre eine Taktquelle nötig, die etwa dem dreifachen des maximalen 
Eingangssignals entspricht, oder? Das ist ja kaum aufzutreiben :( 
Vielleicht sollte ich doch einen Logik-IC wie den ACT161 oder Ähnlich 
davor setzen, um die Frequenz schon mal auf 1/16 zu teilen, und mit 
einem mäßig schnellen Clock-Signal den ACT161-Überlauf abtasten.

Mittlerweile liegt auch der Kompaktkurs VHDL auf dem Tisch, vielleicht 
schaffe ich ja mit Hilfe von diesem Forum, Web-Tutorials und 
Papierlektüre, dem Problem doch noch Herr zu werden.

Viele Grüße
Ingo

von Schlumpf (Gast)


Lesenswert?

Ingo S. schrieb:
> Dazu wäre eine Taktquelle nötig, die etwa dem dreifachen des maximalen
> Eingangssignals entspricht, oder? Das ist ja kaum aufzutreiben :(

Wollte grad PLL schreiben, aber du hast ja nen CPLD und keinen FPGA.. 
--> Blöde Sache :-(

Wenn du keinen schnellen Systemtakt bereitstellen kannst, dann wird die 
Sache wirklich sehr knifflig.

Ein einfaches Data-Latch (oder Register) hilft nicht weiter, da der 
Zeitpunkt der Übernahme unbekannt ist und daher die Möglichkeit besteht, 
dass du genau zu dem Zeitpunkt übernimmst, wenn sich gerade der Zähler 
ändert. Aufgrund der unterschiedlichen Laufzeiten der einzelnen Bits vom 
Zähler zum Latch und der eventuell auftretenden Setup-Zeit-Verletzungen 
kann dann "irgendwas" im Latch stehen.

Eventuell kannst du drüber nachdenken, ob du dieses Register mit dem 
Zähltakt selbst taktest. Dann steht halt im Register nicht der aktuelle 
Wert des Zählers, sondern der vorangegangene Wert.
Aber Zähler und Schattenregister wären dann zumindest in der gleichen 
Domain.

Dann bleibt aber noch das Problem, ein Aktualisieren des 
Schattenregisters zu unterbinden, während du ausliest.
Das könnte mit einem Steuersignal geschehen, welches ebenfalls mit dem 
Zähltakt synchronisiert wird.

Dann müsstest du dir allerdings das Timing des Zugriffs genau anschauen, 
ob sichergestellt ist, dass das Timing zwischen Steuersignal, Zähler und 
Schattenregister zusammenspielt..

Alles in Allem wird das ein ziemlicher Murks. Aber mir fällt grad auf 
die Schnelle auch nichts Schlaues ein

von Schlumpf (Gast)


Lesenswert?

Nachtrag:
Wenn die Zählimpulse zufällig auftreten, dann wird das von mir 
beschriebene Verfahren auch kaum umsetzbar sein..
Aber vielleicht lässt sich was machen, indem man auf beiden Flanken des 
Zählsignals arbeitet..

von bko (Gast)


Lesenswert?

Wenn eine Unsicherheit von +-1 ok ist, könne eventuell ein
gray-Code Counter helfen ..

Hab mal schnell den Code aus -
http://chipverification.blogspot.de/2008/07/gray-code-counter-implementation.html
-genommen und unten (nicht Syntaxfehlerfrei) eingefügt:
1
...
2
signal Q: std_logic_vector(15 downto 0); 
3
signal gray: std_logic_vector(15 downto 0);  -- Gray addon
4
5
gray[15] <= Q[15];
6
--   2..14 eintippen oder loop oder andere elegantere Beschreibung ...
7
gray[1] <= Q[2] EXOR Q[1];
8
gray[0] <= Q[1] EXOR Q[0];
9
10
11
process(Gate, Pulse)
12
begin
13
  if (Gate = '0') then 
14
    Q <= (others => '0');
15
   Active <= '0';
16
  elsif (rising_edge( Pulse)) then
17
   Active <= '1';
18
    Q <= Qgray;               -- Gray addon
19
  end if;
20
end process;
21
22
process( Clk)
23
begin
24
  if rising_edge( Clk) then
25
    Data <= Q;
26
  end if;
27
end process;
28
29
end behaviour;
Die Software muss halt den Inhalt von "Data" wieder nach binär wandeln
http://de.wikipedia.org/wiki/Gray_code#Generierung_als_Gray-Z.C3.A4hler

von W.S. (Gast)


Lesenswert?

Schlumpf schrieb:
> Wollte grad PLL schreiben, aber du hast ja nen CPLD und keinen FPGA..
> --> Blöde Sache :-(

Nö.

Im Gegensatz zu FPGA's haben CPLD's richtig große AND-Gates am Eingang 
der Macrozelle - anstelle der popligen LUT. Das prädestiniert sie 
geradezu für große schnelle Synchronzähler. Man muß es bloß richtig 
machen.

Mit Schematics ;-) würde ich als erste Stelle einen FDE (Flipflop mit 
Clock, Dateneingang und Enable, ist bei den '95ern intrinsic) nehmen, 
womit das Zähl-Enable des gesamten eigentlichen Zählers bereits erledigt 
ist.

Die nachfolgenden Stellen kriegen die UND-Verknüpfung aller vorherigen 
Stellen als Enable. Damit haben wir einen synchronen Zähler mit Enable, 
der in jedem Falle nur 1 Gatterlaufzeit braucht.

Zum Auslesen kommt an jeden FF-Ausgang des Zählers ein weiterer FDE. Die 
Enables dieser FDE's gehen allesamt an das Auslesesignal vom 
angeschlossenen uC und getaktet werden sie ebenfalls mit der 
Eingangsfrequenz. Damit ist sichergestellt, daß dieses Auffangregister 
synchron zum Zählerstand-1 läuft, solange es nicht ausgelesen wird. 
Während des Auslesens ändert es sich hingegen nicht (wegen Enable jetzt 
auf 'passiv').

So, nun schreibt das mal mit VHDL hin.

W.S.

von Schlumpf (Gast)


Lesenswert?

@ W.S.

Schlumpf schrieb:
> Eventuell kannst du drüber nachdenken, ob du dieses Register [anm.
> Data-Tegister] mit dem > Zähltakt selbst taktest. Dann steht halt im
> Register nicht der aktuelle Wert des Zählers, sondern der vorangegangene
> Wert.
> Aber Zähler und Schattenregister wären dann zumindest in der gleichen
> Domain.

Wo ist da jetzt der Unterschied?

von bko (Gast)


Lesenswert?

Hoppla falsch abgeschrieben, bin schon müde,
also nochmal richtig:
1
...
2
signal Q: std_logic_vector(15 downto 0); 
3
signal gray: std_logic_vector(15 downto 0);  -- Gray addon
4
5
gray[15] <= Q[15];
6
--   2..14 eintippen oder loop oder andere elegantere Beschreibung ...
7
gray[1] <= Q[2] EXOR Q[1];
8
gray[0] <= Q[1] EXOR Q[0];
9
10
11
process(Gate, Pulse)
12
begin
13
  if (Gate = '0') then 
14
    Q <= (others => '0');
15
   Active <= '0';
16
  elsif (rising_edge( Pulse)) then
17
   Active <= '1';
18
    Q <= Q+1;               
19
  end if;
20
end process;
21
22
process( Clk)
23
begin
24
  if rising_edge( Clk) then
25
    Data <= gray;  -- hier gehört er hin, da Gray Code nur fehler +-1 
26
                   -- möglich oder?
27
  end if;
28
end process;
29
30
end behaviour;

von Ingo S. (logikneuling)


Lesenswert?

Vielen Dank für alle eure Antworten. Ich bin mittlerweile etwas weiter 
gekommen und wollte dies auch mitteilen:

Um nicht weiterhin im Dunkeln zu forschen, habe ich die Zählerwerte, die 
bei Anlegen von 1-40 MHz Rechtecksignalen erfasst werden, genauer 
analyisiert und zwei unterschiedliche Arten festgestellt.

Den Bärenanteil schienen zufällig auftretende, relativ 
frequenzunabhängige Fehler auszumachen. Ich habe daraus geschlossen, 
dass dies eigentlich nichts mit Asynchronität und FF-Laufzeiten zu tun 
haben kann, sondern eventuell eher mit einem schlechten Aufbau (momentan 
noch Seeedstudio Breakoutboard auf Steckbrett). Tatsächlich war die 
Lösung, die Pins des Ausgaberegisters nicht alle direkt nebeneinander, 
sondern mit Abstand und mit Pull-Down-Rs auszustatten und möglichst 
kurze Leitungen zum AVR einzusetzen. Ich war so beschäftigt mit der 
CPLD-Thematik, dass ich an Leitungsreflexionen und Fehler durch 
miserable Breadboards gar nicht mehr gedacht habe...

Bei Frequenzen größer 5MHz sind zunehmend häufiger auch die die bereits 
beschriebenen "Spikes" zu sehen, die wohl aus dem asynchronen Auslesen 
herrühren. Hier sieht meine Lösung etwas anders aus: Ich habe die 
langasme Latch-Frequenz (das "Clk"-Signal) von 1kHz auf die mit dem AVR 
maximal realisierbare Geschwindigkeit erhöht, um möglichst kleine 
Differenzen zwischen vorigem und aktuellem Zählerstand zu erreichen 
(90MHz -> nicht mehr als 90 Impulse pro Mikrosekunde). Fehler von +128, 
+256, ... können also mittels Software anschließend relativ gut erkannt 
und korrigiert werden.

Ich habe außerdem die Einführung eines zweiten Counters (busy) für die 
Zeit während des Auslesens versucht:
1
[...]
2
  signal Q: std_logic_vector(15 downto 0);
3
  signal busy: std_logic_vector(3 downto 0);
4
[...]
5
process(Gate, Pulse)
6
begin
7
  if (Gate = '0') then 
8
    Q <= (others => '0');
9
    Active <= '0';
10
  elsif (rising_edge( Pulse)) then
11
    if(Clk = '1') then
12
     busy <= busy +1;  
13
   else
14
     Active <= '1';
15
      Q <= Q +busy +1;
16
     busy <= (others => '0');
17
   end if;
18
  end if;
19
end process;
20
[...]

Dieses zusätzliche "busy"-Register hat aber weder einen positiven noch 
einen negativen Effekt gehabt, außer dass damit der XC9572 nahezu 
vollständig belegt ist. Vielleicht ist auch ein Denkfehler meinerseits 
drin, dass es gar nicht helfen kann.

Alles in Allem treten nach Optimierung des Aufbaus und Erhöhung der 
Latch-Frequenz die beschriebenen Fehler vielleicht noch jedes 1000. bis 
5000. Mal auf. Mit diesem Fehler kann ich problemlos leben, das ganze 
läuft deutlich besser als mit dem vorigen Versuch, alles mit ACT161s zu 
realisieren.

Die Gray-Code Variante scheint mir sehr interessant, allerdings kann ich 
mit der nun gewählten AVR Latch-Frequenz den Gray-Code nicht mehr 
schnell genug umwandeln. Das ist aber eventuell auch nicht unbedingt an 
dieser Stelle nötig, ich werde den Gray-Counter im Hinterkopf behalten 
und eventuell eine Übertragung von Gray-Code und spätere Umwandlung 
ausprobieren. Vielen Dank auf jeden Fall für das Gray-Code VHDL Snippet.

Abschließend noch eine Frage: Die Schematics-Variante klingt sehr 
interessant, sind damit (bei entsprechendem Wissen) prinzipbedingt noch 
bessere Realisierungen möglich als durch Beschreibung mittels Sprachen 
wie VHDL?

Viele Grüße
Ingo

von W.S. (Gast)


Lesenswert?

Ingo S. schrieb:
> sind damit (bei entsprechendem Wissen) prinzipbedingt noch
> bessere Realisierungen möglich als durch Beschreibung mittels Sprachen
> wie VHDL?

Tja, dazu ein ganz dickes JEIN.

Die VHDL-Fraktion hier wird natürlich antworten, daß man ja bei 
hinreichend intimer Kenntnis von VHDL alles viel besser machen könnte, 
aber wenn ich deine letzten Beiträge lese, dann hab ich da leise 
Bedenken.

Immerhin gilt eines: Mit Schematics kann man prinzipiell sehr exakt 
arbeiten und dem Entwurfssystem sehr pingelig sagen, was man von ihm 
haben will - auch dann, wenn man nicht jeden Tag 8 Stunden VHDL übt.

Mit VHDL ist das ein bissel schwieriger. Ich kann mich noch an damalige 
Versuche meinerseits erinnern, wo die ISE mir für einen 16 Bit 
Ausgangstreiber mit Tristate partout 32 Macrozellen verbraten wollte (in 
VHDL). Das Ganze mit Schematics und außer den eigentlichen 
Ausgangstreibern hat es gar keine Macrozelle gekostet. Klar: ich hätte 
es ja gaaaaaanz anders formulieren können und dann, ja dann.. Also: Mit 
HW-Beschreibungssprachen kriegt man häufig genug nicht das, was man 
eigentlich haben wollte, entweder aus Mangel an Übung oder 
prinzipbedingt.

In dem Sinne frohes Basteln. Aber was du da mit ""Spikes" zu sehen, die 
wohl aus dem asynchronen Auslesen herrühren.." treibst, ist m.E. Pfusch, 
der aus schierer Unüberlegtheit des Entwurfes herrührt. Lies dir meinen 
ernst gemeinten Vorschlag weiter oben mal durch, ich meine, damit 
arbeitet man schlichtweg störungsfrei.

W.S.

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


Lesenswert?

W.S. schrieb:
> Ich kann mich noch an damalige Versuche meinerseits erinnern,
> wo die ISE mir für einen 16 Bit Ausgangstreiber mit Tristate partout
> 32 Macrozellen verbraten wollte (in VHDL).
Was hast du denn da falsch gemacht?

Ingo S. schrieb:
> Abschließend noch eine Frage: Die Schematics-Variante klingt sehr
> interessant, sind damit (bei entsprechendem Wissen) prinzipbedingt noch
> bessere Realisierungen möglich als durch Beschreibung mittels Sprachen
> wie VHDL?
Dir muss eines klar sein: du malst da auch nur ein paar Bildchen hin, 
die erst mal nichts mit der tatsächlichen Struktur des 
programmierbaren Bausteins zu tun haben. Auch die müssen übersetzt 
werden (und liegen ihrerseits im Hintergrund oft auch "nur" als HDL 
Beschreibung da). Denn wenn du in deinem Schaltplan ein UND-Gatter 
malst, dann wird trotzdem kein UND-Gatter eingebaut, sondern die 
Makrozelle so konfiguriert, dass sie sich wie ein UND verhält...

> sind damit (bei entsprechendem Wissen) prinzipbedingt noch
> bessere Realisierungen möglich als durch Beschreibung mittels Sprachen
> wie VHDL?
Nich mit sinnvollem Aufwand. Und die Darstellung wird auch unerträglich. 
Hier der Klassiker im Beitrag "kruder Fehler bei FPGA-Programmierung (ISE WEBpack-Schematic)"
(Es lohnt sich, diesen Beitrag ganz durchzulesen, bevor man mit 
Schematics anfängt)

von W.S. (Gast)


Lesenswert?

Lothar Miller schrieb:
> Was hast du denn da falsch gemacht?

Ähem.. na eben VHDL benutzt. Mal im Ernst, es ist fast 15 Jahre her und 
ich hab damals die Sache mit Schematics final erledigt, ohne mich noch 
länger mit der VHDL-Quelle zu befassen.

Lothar Miller schrieb:
> die erst mal nichts mit der tatsächlichen Struktur des
> programmierbaren Bausteins zu tun haben.

Erstens ist das zumeist falsch, weil ne ganze Menge der einfachen 
Gatter eben intrinsics sind, also die direkte Struktur des Bausteins 
darstellen. Konkret: sich durch die direkte Funktionalität einer 
Makrozelle machen lassen. Das ist was anderes, als wenn man eine 
Funktion in einer HDL beschreiben will, bei der dann die ISE (wir 
bleiben mal bei Xilinx) erst schauen muß, durch welche Kombinationen aus 
Makrozellen sich das gewünschte Verhalten realisiern läßt.

Zweitens ist der 'menschliche' Faktor nicht zu vegessen: Man will ja 
haben, was man meint und nicht das, was man hinzuschreiben in der Lage 
ist. Da steckt ne Menge Übung, Gewöhnung oder aber Schusselfehler, 
Mißverständnis usw. drin. Ist wie gesagt, bei einer HDL 
fehlerträchtiger, bei Schematics bei Weitem nicht so sehr. (nur der, der 
ein UND mit nem FF verwechselt, ist zu doof). In dem Sinne kann man 
Schematics mit Assemblerprogrammierung vergleichen, wo man dediziert 
selbst über die exakte Logik entscheiden kann - und eine HDL kann man 
dann mit dem Programmieren in höheren programmiersprachenvergleichen. 
Ich denk mal, dieser Vergleich hinkt gar nicht so sehr.

Abgesehen davon macht Schematics genau dann richtig Sinn, wenn man 
hierarchisch arbeitet, sich also Funktionsblöcke macht. Kleine Beispiele 
meinerseits: QVGA-LCD-Modul, DDS-Modul usw.
Ja, gilt elleweil, ich weiß.


W.S.

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


Lesenswert?

W.S. schrieb:
> Lothar Miller schrieb:
>> Was hast du denn da falsch gemacht?
> Ähem.. na eben VHDL benutzt. Mal im Ernst, es ist fast 15 Jahre her
Ich vermute mal, die VHDL-Synthesizer haben sich in den letzten 15 
Jahren deutlich weiter entwickelt als die Schaltplaneditoren...

> weil ne ganze Menge der einfachen Gatter eben intrinsics sind,
> also die direkte Struktur des Bausteins darstellen.
Keineswegs: eine Makrozelle oder eine LUT sind eben kein 7-fach UND 
oder ein 4zu1-Multiplexer. Auch diese einfachen "Basisfunktionen" sind 
nur nachgebildet...

> In dem Sinne kann man Schematics mit Assemblerprogrammierung
> vergleichen, wo man dediziert selbst über die exakte Logik
> entscheiden kann.
Und hinterher genauso die Optimierung zuschlägt und eine beliebig 
komplexe logische Funktion aus vielen einzelnen Gattern in 1 Makrozelle 
oder LUT packt. Denn ich wäre sehr enttäuscht, wenn ich in ein 36 
Makrozellen CPLD 36 einfache logische Funktionen mit je 2 Eingängen 
(UND, ODER, NAN, NOR, XOR...) und letzlich 1 gemeinsamen Ausgang packen 
würde, und dann wäre es voll...


Aber es ist wie es ist: wenn es (jemandem) reicht, mit 
herstellerspezifischen Schaltplänen zu arbeiten, weil er einen 
FPGA-Wechsel nicht in Betracht zieht (oder ziehen muss/darf/kann/will), 
dann kann er auch die jeweiligen Schaltplaneditoren aus der Toolchain 
verwenden.

von W.S. (Gast)


Lesenswert?

Lothar Miller schrieb:
> Ich vermute mal, die VHDL-Synthesizer haben sich in den letzten 15
> Jahren deutlich weiter entwickelt als die Schaltplaneditoren...

Jaaa, das glaub ich gern, wenn ich mir Schematics von Xilinx anschaue. 
Und die Brüder von Altera und Lattice sind noch viel schlimmer.

Lothar Miller schrieb:
> eine Makrozelle oder eine LUT sind eben kein 7-fach UND
> oder ein 4zu1-Multiplexer.

Du kennst aber (hoffentlich) den Unterschied zwischen Makrozellen und 
LUT's, ja?

Ich bin momentan zu faul, um nachzuschauen, aber bei den Coolrunnern ist 
es so, daß eine Makrozelle kein 7-fach UND hat, sondern 8 Stück (oder 
noch mehr) 36-fach UND's, deren Ausgängen dann auf ein 8(oder mehr)-fach 
ODER geht, woran sich ein D-FF mit diversen Eingängen (D, T, R, P, C, S, 
E usw) anschließt. (Daten, Takt, Enable, synchrones setzen und 
rücksetzen, dito asynchron) Das ist erheblich anders als eine LUT. Und 
weil so eine Makrozelle eben riesige UND-Gatter hat, ist der Aufbau 
großer synchroner Zähler bei CPLD's eben günstiger als bei FPGA's, weil 
schneller. Bei FPGA's muß man für sowas mehrere LUT's kaskadieren.

Und so ein D-FF in so einer Makrozelle ist für viele einfache 
schematics-Elemente eben intrinsic. Da wird nix "nachgebildet". Lies dir 
mal die entsprechenden Dokus durch. In dem Punkt ist Xilinx vorbildlich.

W.S.

von Guido (Gast)


Lesenswert?

Hinter den lustigen Bildchen steckt bei Xilinx wohldokumentierter
VHDL-Code. Das ist auch gut so, man kann daher sehr schnell z.B.
aus einem 8-Bit-Zähler einen mit 11 Bit ableiten. Dass aber die
Bildchen ein anderes Syntheseergebniss liefern sollen als
entsprechender VHDL-Code, ist eine sehr naive Vorstellung.


W.S. schrieb:
> Du kennst aber (hoffentlich) den Unterschied zwischen Makrozellen und
> LUT's, ja?

Mit Verlaub, gegenüber Lothar ist das schon eine Frechheit. :-(

von Schlumpf (Gast)


Lesenswert?

@ W.S.

Du bist also der Auffassung, dass die Synthese 1:1 das in den Chip 
packt, was du in Schematics zeichnest?
Da habe ich aber ganz große Zweifel, dass das so stimmt.

Zeichne doch mal zwei Inverter hintereinander und schau, ob du die 
nachher in deinem Chip wieder findest? Ich könnte wetten, dass du da 
sehr lange suchen wirst ;-)

In VHDL kann man mindestens genauso exakt beschreiben, wie die Schaltung 
im Chip aussehen soll. Vermutlich sogar noch exakter, da man nicht über 
eine art "Zwischencode" gehen muss, der aus den Schaltsymbolen gebildet 
wird, und auf den du keinen Einfluss hast.

Wenn das damals vor 15 Jahren bei dir gehörig in die Hose ging, dann 
sicher nur deswegen, weil du einen bösen Fehler in der VHDL-Beschreibung 
gemacht hast. Eventuell hast du ein Latch beschrieben, ohne es zu 
merken.

Natürlich gebe ich dir recht, dass es für jemanden, der keine Ahnung von 
VHDL hat, einfacher ist, einen Schaltplan zu zeichnen. Aber dass du, 
aufgrund einer Erfahrung vor 15 Jahren, bei der du in VHDL gescheitert 
bist, jetzt behauptest, dass man mit Schematics viel "näher" an der HW 
ist, halte ich für den falschen Schluss.

Garantiert hast du damals eine Schaltung im Kopf gehabt, aber warst 
nicht im Stande, diese korrekt in VHDL zu beschreiben. Und dann hat die 
Synthese eben das umgesetzt, was du beschrieben hast. Wie gesagt, 
vermutlich hast du, ohne es zu merken, ein Latch beschrieben.
Deine Schlussfolgerung damals war dann ganz offensichtlich: Die Synthese 
ist zu doof, meinen schönen HDL-Code umzusetzen, also zeichne ich 
Schematics. Das hat dann wunderbar geklappt und nun bist du seit 15 
Jahren der Auffassung, dass VHDL nicht geeignet ist, Hardware exakt zu 
beschreiben.

Vielleicht gibts du HDL nochmal eine Chance und fängst mit ganz kleinen 
"Elementen" an und du wirst sehr schnell feststellen, dass bei korrekter 
Beschreibung auch exakt das rauskommt, was du dir wünschst.

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


Lesenswert?

Guido schrieb:
> W.S. schrieb:
>> Du kennst aber den Unterschied zwischen Makrozellen und LUT's, ja?
> Mit Verlaub, gegenüber Lothar ist das schon eine Frechheit.
Danke für die Stellungnahme, aber ich steh da drüber... ;-)

W.S. schrieb:
> Ich bin momentan zu faul, um nachzuschauen, aber bei den Coolrunnern ist
> es so, daß eine Makrozelle kein 7-fach UND hat, sondern 8 Stück (oder
> noch mehr) 36-fach UND's, deren Ausgängen dann auf ein 8(oder mehr)-fach
> ODER geht
Also wird auch dort ein einfacher Schaltplan mit einem 7-fach UND und 
einem weiteren Gatter dahinter eben nicht genau so umgesetzt, sondern 
noch heftig optimiert. Denn wenn der Schaltplan genauso umgesetzt 
würde, dann könnte ich gerade mal 36 logische 2-Input 
Basisfunktionen realisieren, und dann wäre das CPLD "voll".

> Und weil so eine Makrozelle eben riesige UND-Gatter hat, ist der Aufbau
> großer synchroner Zähler bei CPLD's eben günstiger als bei FPGA's, weil
> schneller. Bei FPGA's muß man für sowas mehrere LUT's kaskadieren.
Nichtsdestrotz bekomme ich ohne weiteres in einem billigen S3 FPGA 
einen 32-Bit-Zähler hin, der mit 500MHz getaktet werden kann. Und das, 
weil die FPGA-Designer genau diese Problematik auch erkannt haben und 
für solche Zähler (und/oder allgemein Addierer) eine extra Carry-Chain 
eingbaut haben.

> Und so ein D-FF in so einer Makrozelle ist für viele einfache
> schematics-Elemente eben intrinsic. Da wird nix "nachgebildet".
Damit ist dann aber auch schon Ende.
Ein Addierer existiert nicht, ein Mux auch nicht, die ganzen 
2,3,4...16..-fach UND/ODER/NOR/NAND... existieren auch nicht, sondern 
werden erst zusammengefasst und dann optimiert. Und die Tabelle, die 
dabei herauskommt, hat mit dem ursprünglichen Schaltplan nur noch die 
Funktion gemeinsam. Du könntest nicht einfach "rückwärts" gehen und 
hättest deinen Schaltplan wieder. Und die Funktion kann ich mit VHDL 
auch ganz einfach und genau beschreiben.

von W.S. (Gast)


Lesenswert?

Lothar Miller schrieb:
> Also wird auch dort ein einfacher Schaltplan mit einem 7-fach UND und
> einem weiteren Gatter dahinter eben nicht genau so umgesetzt, sondern
> noch heftig optimiert.

Ja. Wenn man ein CPLD mit was extrem Simplem füllt, dann ist es auch mit 
diesem Simplem ruckzuck voll.

Aber deine Darstellung ist so nicht richtig. Wenn das "einem weiteren 
Gatter dahinter" eine logische Verknüpfung ist, dann ist das mit dem 
ODER am Ausgang des UND erledigt. Aber bleiben wir lieber auf dem 
Teppich.

Ergo wird dein Beispiel mit dem 7fach UND "und einem weiteren Gatter 
dahinter" überhaupt nicht optimiert, sondern genau so umgesetzt wie 
gemalt, denn das ist bereits intrinsic - bei CPLD's. Bei FPGA's sieht 
die Sache anders aus, da ist der Hardwareansatz ganz anders und das 
7fach UND braucht mehr als nur 1 LUT. Also zieh dir mal ne CPLD-Doku 
rein - ist ja nicht sooo.. umfänglich.

Aber so langsam fange ich an, mich zu ärgern. Eigentlich mehr über dich 
als über den Schlumpf, weil der ja auch nur Gast ist wie ich (aber das 
überleg ich mir nochmal..).

Im Prinzip könnte ich dem Schlumpf zustimmen, wenn er meine Worte nicht 
so bösartig vebogen hätte. Nicht alles in Schematics kann (und wird) 1:1 
umgesetzt - sowas hab ich auch nicht geschrieben. Aber näher an der HW 
ist man mit Schematics - es sei denne, man ist ein geübter VHDL-Guru und 
kennt genau 100% aller möglichen Fallstricke, über die man in VHDL zu 
stolpern pflegt. Das ist nämlich der Punkt, den ich schon in nem anderen 
Beitrag geschrieben hab: Wer nicht 3 Stunden täglich VHDL übt, sondern 
nen Sack anderer Probleme hat, wird mit dieser Programmiersprache nicht 
glücklich. Das ist auch ne Frage des Anspruches. Ich brauch Tools, die 
mir helfen, das zu realisieren, was ich an Ideen hab - und ich kann 
Tools nicht leiden, die sich durch Eigenartigkeiten und Störrischkeit 
hervortun - VHDL ist so ein Tool. Sowas benutze ich nicht freiwillig. 
Schließlich soll die Maschine dem Menschen dienen (und nützen) und nicht 
umgekehrt.

Aber das ist alles nur Herumtheoretisieren. OK, ist ja grad Wochenende 
und zu kühl für den Liegestuhl im Garten.

So.
Nun denkt mal an den TO und sein Anliegen. Die allermeisten Leute, die 
Geräte entwickeln und elektronische Schaltungen entwickeln, weil diese 
in den Geräten halt gebraucht werden, kommen mit Schematics prinzipiell 
(bis auf die Hakeligkeiten der Programme) sofort klar und fallen selbst 
bei 80% Kenntnis von VHDL immer noch auf die Nase. Daß der TO hier seine 
Probleme mit Datenverfälschungen hat, die auf asynchrones 
Hineingrabschen in einen Zähler zurückzuführen sind, zeigt uns 
allerdings, daß die wahren Probleme jenseits der Diskussion Schematics 
versus HDL liegen.

W.S.

von Schlumpf (Gast)


Lesenswert?

Nun, um´s von meiner Seite auch zuende zu bringen:
Stein des Anstoßes war ja eigentlich, dass du in deinem Post als Lösung 
"Schematics" angegeben hast und im Nachsatz, dass man das natürlich auch 
mit HDL lösen kann, aber dass es dann ungleich viel komplexer ist und 
eigentlich nur ein paar elitären Gurus möglich, die jeden Tag mindestens 
3h HDL klimpern..

Und diese Behauptung wollten weder Lothar noch ich so stehen lassen. Für 
meinen Teil war es so, bei Lothar nehme ich mal an, dass das auch sein 
Ansinnen war.

Ich gebe dir recht: VHDL ist mächtig und man kann sehr gewagte Dinge 
damit machen, wo man wirklich genau wissen muss, was die Synthese daraus 
bastelt.
ABER: Kein Mensch wird gezwungen, diese Konstrukte zu verwenden.

Wenn du Schematics eingibst, dann beschränkst du dich auch auf 
Basiselemente wie Gatter, MUXer, Register etc. Und genau das kann man in 
VHDL auch.
Die Regeln für diese Beschreibungen sind definitiv nicht nur 
irgendwelchen Freaks vorbehalten, sondern so einfach, dass sie von jedem 
innerhalb kurzer Zeit erlernbar sind.
Damit lässt sich dann schon alles realisieren.
VHDL bietet aber auch Konstrukte, denen man nicht direkt ansieht, was 
sie tun. z.B. Loops etc. Aber wie gesagt, man kann jedes Design auch 
komplett ohne diese Konstrukte abbilden.

Nun, aber am Ende bleibt es natürlich dem persönlichen Geschmack, den 
eigenen Fähigkeiten und der Bereitschaft, sich mit Neuem zu befassen, 
überlassen, wie man die Entry macht.

Und wie du geschrieben hast, hast du ja ordentlich andere Probleme zu 
lösen und möchtest dich daher nicht mit HDL rumärgern. Vielleicht wäre 
das ja genau der Anlass, sich mal mit der Materie zu befassen. Denn das, 
was in stundenlanger unübersichtlicher Arbeit und der damit verbundenen 
Fehlerträchtigkeit aufgrund falsch gezeichneter Schematics eingegeben 
wird, lässt sich in VHDL mit BASISWISSEN meistens in wenigen Minuten 
textuell eingeben.
Da wäre dann unter´m Strich mehr Zeit, sich um die eigentlichen Probleme 
zu kümmern. :-)

Fazit der Sache ist: Du stellst eine Behauptung über VHDL in den Raum, 
ohne dich wirklich mit VHDL auszukennen. Du hast einmal aus Unwissenheit 
ein Design in VHDL verkorkst und nun steht für dich fest, dass VHDL ein 
Ungetüm ist, von dem man jedem nur abraten kann, der nicht extrem tief 
in die Materie einsteigen will.
Und das ist nicht gut, wenn man von etwas nur rudimentär Ahung hat, es 
dann so hinzustellen, als sei es schlecht.
Lerne die VHDL-Basics und wenn du dann immer noch der Meinung bist, dass 
Schematics viel besser sei, oder VHDL so irrsinnig komplex, dann kannst 
du deine Behauptungen auch untermauern. Aber so sind sie einfach nur 
haltlos.


So, hier war´s definitiv nicht zu kalt für in die Sonne liegen und drum 
verschwinde ich auch gleich wieder an die frische Luft.

Btw: VHDL ist kein Tool, sondern eine Beschreibungssprache..

Euch allen einen schönen Sommerabend!

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.