Forum: FPGA, VHDL & Co. Feedback für Drehgeber Design


von A. M. (am85)


Angehängte Dateien:

Lesenswert?

Hi,

ich muss für die Uni einen Inkrementaldrehgeber entwickeln. Die 
Simulation sieht nicht all zu schlecht aus, ich bin mir aber nicht 
sicher, ob ich evtl. etwas übersehe. Deswegen würde ich mich freuen, 
wenn ich von euch ein bisschen Feedback zum Design und vielleicht auch 
zum Stil des Code bekommen könnte, da ich häufig das Gefühl habe 
Software und nicht Hardware zu entwickeln. Ich würde mich über jedne 
konstruktiven Kommentar freuen.

Die Zielhardware ist ein Spartan 3 mit einem Takt von 100 kHz 
(Laborsystem). Die kürzeste Periode des Motorensignals ist ca. 2 ms. Die 
RPM sollen auf einer 7-Seg. Anzeige ausgegeben werden, die mit 100 Hz 
gemultiplext wird, um Flackern zu verhindern.

Vielen Danke schon einmal für eure Antworten.

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


Lesenswert?

> for i in 0 to 11 loop
Wenn du sowieso 1 komplette Sekunde Zeit hast, um einen neue Anzeige zu 
berechnen, warum machst du das dann die Binär->BCD Wandlung komplett 
parallel?
http://www.lothar-miller.de/s9y/archives/67-Vektor-nach-BCD-kombinatorisch.html
Du könntest das Ganze auch als Schieberegister abbilden. Die 11 Takte, 
die dann gebraucht werden, hast du locker Zeit...
http://www.lothar-miller.de/s9y/archives/34-Vektor-nach-BCD.html

> use IEEE.STD_LOGIC_1164.ALL;
> use IEEE.STD_LOGIC_UNSIGNED.ALL;
> use ieee.numeric_std.ALL;
Ach nein, nicht schon wieder. In welchem Buch steht das so?
Siehe den Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete"

> signal ANZEIGE     : bit_vector(1 downto 0)      := (others => '0');
> signal UMDREHUNGEN : std_logic_vector(11 downto 0)  := (others => '0');
> signal IMP4        : bit;
Arbeite statt mit BIT nur mit STD_LOGIC und dessen Vektor. So ist das 
üblich.

>     if SECCOUNTER = "10011100001110" then
>      SECCOUNTER  <=   "00000000000000"  after 5 ns;
Für Zähler bieten sich Integer an, weil man da Vergleichswerte 
natürlichsprachig hinschreiben kann. Kein Mensch weiß, ob 10011100001110 
jetzt tatsächlich passt.

>   SECCOUNTER  <=   "00000000000000"  after 5 ns;
Lass dieses after 5ns weg. Es ist unnötig und hat rein gar nichts mit 
der Hardware zu tun, die ist nämlich viel schneller! Und es verfälscht 
deine Simulation, weil es "Pseudotakte" erzeugen kann, wo keine sind... 
:-o

Ich bin mir nicht ganz sicher, ob deine
FSM: process(PHI, ZUSTAND)
in der Hardware fehlerfrei funktionieren wird. Denn du hast da eine 
recht aufwendige FSM und verwendest PHI als asynchrones Signal. Hier 
würde ich (trotz Gray-Codierung) nocht einsynchronisieren:
http://www.lothar-miller.de/s9y/categories/35-Einsynchronisieren
http://www.lothar-miller.de/s9y/categories/34-Getakteter-Prozess
Oder die Komplexität drastisch reduzieren:
http://www.lothar-miller.de/s9y/categories/46-Encoder


Ich würde auch das zuverlässige Funktionieren dieses Schaltwerks in 
Frage stellen:
1
OUTPUT_MUX: process(COUNT,RESET,ANZEIGE)
2
begin
3
  if RESET = '0' then
4
    :
5
  elsif ANZEIGE = "00" then
6
    :
7
    if COUNT = "1111101000" then         -- !!!! kombinatorisches Weiterschalten !!!!
8
      :
9
    end if;
10
  elsif ANZEIGE = "01" then
Was passiert, wenn hier der Zähler beim Umschalten einfach mal kurz 
glitcht (und das wird er IMMER tun) und z.B. für 300ps dieses Bitmuster 
zu sehen ist?

> da ich häufig das Gefühl habe Software und nicht Hardware zu entwickeln.
Na, wenigstens weisst du schon mal, dass es da einen Unterschied gibt... 
;-)
Sieh dir immmer wieder mal die RTL-Schematics an, dann bekommst du ein 
Gefühl dafür, was günstig und was umständlich beschrieben ist.

von A. M. (am85)


Lesenswert?

Vielen Dank für deine umfangreiche Antwort :-)

Lothar Miller schrieb:
>> for i in 0 to 11 loop
> Wenn du sowieso 1 komplette Sekunde Zeit hast, um einen neue Anzeige zu
> berechnen, warum machst du das dann die Binär->BCD Wandlung komplett
> parallel?
> http://www.lothar-miller.de/s9y/archives/67-Vektor...
> Du könntest das Ganze auch als Schieberegister abbilden. Die 11 Takte,
> die dann gebraucht werden, hast du locker Zeit...
> http://www.lothar-miller.de/s9y/archives/34-Vektor...

Ich habe mir deinen Code natürlich schon angesehen, ganz nebenbei sind 
deine Seiten sehr interessant und hilfreich. Als Einsteiger wirkte mir 
die Lösung aber doch etwas stark optimiert, so dass ich nicht mehr jede 
Aktion nachvollziehen konnte. Die genommene Lösung, deren 
Ursprungsquelle in der bin2bcd.vhd Datei angegeben ist, sah für mich 
gleich viel verständlicher aus.

Lothar Miller schrieb:
>> use IEEE.STD_LOGIC_1164.ALL;
>> use IEEE.STD_LOGIC_UNSIGNED.ALL;
>> use ieee.numeric_std.ALL;
> Ach nein, nicht schon wieder. In welchem Buch steht das so?
> Siehe den Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete"

U.a. in "VHDL Synthese" bzw. in "Lehrbuch Digitaltechnik" bei einem 
Beispiel für einen 4-Bit Zähler steht:

use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

In meinem Fall ist ersteres jetzt aber eine Auflage von 2001 und ich 
weiß nicht, in wie weit sich da was getan hat in den Neuauflagen.

Lothar Miller schrieb:
>> signal ANZEIGE     : bit_vector(1 downto 0)      := (others => '0');
>> signal UMDREHUNGEN : std_logic_vector(11 downto 0)  := (others => '0');
>> signal IMP4        : bit;
> Arbeite statt mit BIT nur mit STD_LOGIC und dessen Vektor. So ist das
> üblich.

Meine Profs., u.a. der Herr Reichardt, raten sowohl in den Büchern als 
auch in der Vorlesung dazu so lange "bit" zu nehmen, bis man wirklich 
Eigenschaften von std_logic braucht, z.B. bei Tree-State Geschichten 
oder für Zähler.

Lothar Miller schrieb:
>>     if SECCOUNTER = "10011100001110" then
>>      SECCOUNTER  <=   "00000000000000"  after 5 ns;
> Für Zähler bieten sich Integer an, weil man da Vergleichswerte
> natürlichsprachig hinschreiben kann. Kein Mensch weiß, ob 10011100001110
> jetzt tatsächlich passt.

Das stimmt natürlich und hier möchte ich aus dem Zählerstand auch nicht 
noch etwas anderes ablesen bzw. eine andere Auswertung machen. Ich werde 
es hier mit Integer machen.

Lothar Miller schrieb:
>>   SECCOUNTER  <=   "00000000000000"  after 5 ns;
> Lass dieses after 5ns weg. Es ist unnötig und hat rein gar nichts mit
> der Hardware zu tun, die ist nämlich viel schneller! Und es verfälscht
> deine Simulation, weil es "Pseudotakte" erzeugen kann, wo keine sind...
> :-o

Symbolische Signallaufzeiten sind haufenweise in den genannten Büchern 
zu finden und ich habe diesen Stil auch in der Uni (mit diesen Büchern) 
gelernt. Deine Argumentation finde ich aber sehr schlüssig und lasse sie 
jetzt lieber weg.

Lothar Miller schrieb:
> Ich bin mir nicht ganz sicher, ob deine
> FSM: process(PHI, ZUSTAND)
> in der Hardware fehlerfrei funktionieren wird. Denn du hast da eine
> recht aufwendige FSM und verwendest PHI als asynchrones Signal. Hier
> würde ich (trotz Gray-Codierung) nocht einsynchronisieren:
> http://www.lothar-miller.de/s9y/categories/35-Eins...
> http://www.lothar-miller.de/s9y/categories/34-Geta...
> Oder die Komplexität drastisch reduzieren:
> http://www.lothar-miller.de/s9y/categories/46-Encoder

Hier hast du natürlich auch Recht, dass die asynchronen Eingangssignale 
besser einsynchronisiert werden sollten. Da ich das Gefühl habe, vor 
lauter Bäumen den Wald nicht mehr zu sehen, habe ich diesen Punkt in 
meinem Design leider unterschlagen. Da rüste ich jetzt noch nach.

Lothar Miller schrieb:
> Ich würde auch das zuverlässige Funktionieren dieses Schaltwerks in
> Frage stellen:
1
OUTPUT_MUX: process(COUNT,RESET,ANZEIGE)
2
 begin
3
   if RESET = '0' then
4
     :
5
   elsif ANZEIGE = "00" then
6
     :
7
     if COUNT = "1111101000" then         -- !!!! kombinatorisches Weiterschalten !!!!
8
       :
9
     end if;
10
   elsif ANZEIGE = "01" then
> Was passiert, wenn hier der Zähler beim Umschalten einfach mal kurz
> glitcht (und das wird er IMMER tun) und z.B. für 300ps dieses Bitmuster
> zu sehen ist?

Wie kann ich dieses Problem am besten umgehen? Mir fällt da, auf Grund 
meiner mangelnden Erfahrung, auf Anhieb keine bessere Lösung ein.

Lothar Miller schrieb:
>> da ich häufig das Gefühl habe Software und nicht Hardware zu entwickeln.
> Na, wenigstens weisst du schon mal, dass es da einen Unterschied gibt...
> ;-)
> Sieh dir immmer wieder mal die RTL-Schematics an, dann bekommst du ein
> Gefühl dafür, was günstig und was umständlich beschrieben ist.

Ja, der Unterschied ist mir hoffentlich hinlänglich bekannt ;-) Nur in 
der Umsetzung hapert es dann doch etwas arg und wenn man unter Zeitdruck 
etwas zum laufen bekommen muss, dann sieht es meist nicht schön aus, so 
lange es irgendwie funktioniert...aber dieses irgendwie ist mir auch 
nicht recht.

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


Lesenswert?

André M. schrieb:
> Lothar Miller schrieb:
>>> use IEEE.STD_LOGIC_1164.ALL;
>>> use IEEE.STD_LOGIC_UNSIGNED.ALL;
>>> use ieee.numeric_std.ALL;
>> Ach nein, nicht schon wieder....
> U.a. in "VHDL Synthese" bzw. in "Lehrbuch Digitaltechnik" bei einem
> Beispiel für einen 4-Bit Zähler steht:
> use IEEE.STD_LOGIC_1164.ALL;
> use IEEE.STD_LOGIC_UNSIGNED.ALL;
Da fehlt aber explizit die NUMRIC_STD, und darum gings mir. Entweder die 
alten Synopsys-Libs
> use IEEE.STD_LOGIC_1164.ALL;
> use IEEE.STD_LOGIC_UNSIGNED.ALL;
Oder die
>>> use ieee.numeric_std.ALL;
Aber nicht beide nach dem Motto viel hilft viel...
Denn sowohl in STD_LOGIC_UNSIGNED wie auch in NUMERIC_STD sind eienige 
Datentypen und Konvertierungen doppelt und daher u.U auch 
doppeldeutig...


> Meine Profs., u.a. der Herr Reichardt, raten sowohl in den Büchern als
> auch in der Vorlesung dazu so lange "bit" zu nehmen, bis man wirklich
> Eigenschaften von std_logic braucht, z.B. bei Tree-State Geschichten
> oder für Zähler.
Das hat (vermutlich) mit den (wegen der Auflösungstabelle) längeren 
Simulationszeiten für den Typ std_logic zu tun. Aber zwischenzeitlich 
optimieren die Compiler so gut, dass man da kaum eine Auswirkung mehr 
spürt.
Und in der Praxis wird der Typ Bit eigentlich nicht verwendet. Man 
müsste mal eine Umfrage machen, wer wieviele Jahre VHDL verwendet und 
welche Basisdatentypen (für die Synthese) im täglichen Leben einsetzt. 
Ich sehe keinen Vorteil darin, einen weiteren Datentyp mit seinen 
Eigenheiten kennenzulernen und zu beherrschen, nur weil irgendein 
Argument, das mir nicht bekannt ist, dafür spricht. Meine 
Basisdatentypen sind Integer, Signed, Unsigned und Std_logic. Das reicht 
für 90% der Anwendungen.
> Meine Profs., u.a. der Herr Reichardt, raten sowohl in den Büchern als
> auch in der Vorlesung dazu
Frag doch mal nach, WARUM der Datentyp Bit hier empfohlen wird...

André M. schrieb:
> Da ich das Gefühl habe, vor lauter Bäumen den Wald nicht mehr zu sehen,
> habe ich diesen Punkt in meinem Design leider unterschlagen.
Teile und Herrsche:
Mach eine Encoderauswertung, simuliere die und wenn die dann läuft mach 
einen Haken dran: FERTIG.
Dann machst du ein Modul Zähler. Du simulierst das und machst bei Erfolg 
einen Haken dran: FERTIG.
Das selbe mit dem BIN-BCD Wandler, dann mit dem Anzeigen-MUX.
Und wenn alles funktioniert klemmst du das einfach zusammen.

So ähnlich, wie ich das dort mit der DDFS und der PWM gemacht habe:
Beitrag "Re: PWM Signal erzeugen"

> Was passiert, wenn hier der Zähler beim Umschalten einfach mal kurz
> glitcht (und das wird er IMMER tun) und z.B. für 300ps dieses Bitmuster
> zu sehen ist?
> Wie kann ich dieses Problem am besten umgehen? Mir fällt da, auf Grund
> meiner mangelnden Erfahrung, auf Anhieb keine bessere Lösung ein.
Eigentlich ganz einfach: du machst einen Takt in den Prozess.
Damit hat der Vergleicher immmer einen ganzen Taktzyklus Zeit, sich zu 
stabilisieren. Sowas nennt sich dann synchrones Design. Und nur das 
funktioniert auf FPGAs zuverlässig.

> Symbolische Signallaufzeiten sind haufenweise in den genannten Büchern
> zu finden und ich habe diesen Stil auch in der Uni (mit diesen Büchern)
> gelernt. Deine Argumentation finde ich aber sehr schlüssig und lasse sie
> jetzt lieber weg.
Der VHDL-Text wird dadurch zudem auch leserlicher... ;-)

Hier mal ein einfacher Zähler, der im Simulator schön im 5ns Takt 
hochzählt, in der Realität aber eine kombinatorische Schleife darstellt:
1
signal cnt : integer := 0;
2
:
3
// process (cnt) begin   -- als Prozess oder auch einfach Nebenläufig/Concurrent
4
     cnt <= cnt+1 after 5 ns;
5
// end process;
6
:
Wenn du hier das ganze ohne diese Pseudo-Verzögerung schreibst:
1
signal cnt : integer := 0;
2
:
3
// process (cnt) begin   -- als Prozess oder auch einfach Nebenläufig/Concurrent
4
     cnt <= cnt+1;
5
// end process;
6
:
Dann klopft dir der Simulator sofort auf die Finger!!!

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.