Forum: FPGA, VHDL & Co. Quadrature Decoder kann nicht synthetisiert werden


von Patrick B. (p51d)


Lesenswert?

Hallo

Ich bin nun endlich einmal dazu gekommen, ein wenig mit meinem FPGA 
Board zu spielen. Nun möchte ich eine einfache Schaltung, die einen 
Rotary switch einliest und die Leds durchschaltet.

Nur leider habe ich einen Fehler beim synthetisieren (Simulation hat 
geklappt).
1
entity QuadratureDecoder is
2
    Port ( A : in  STD_LOGIC;
3
           B : in  STD_LOGIC;
4
           Sector : out  STD_LOGIC_VECTOR (7 downto 0));
5
end QuadratureDecoder;
6
7
architecture Behavioral of QuadratureDecoder is
8
9
signal count : std_logic_vector(2 downto 0) := "000";
10
11
begin
12
13
  process(A, B)
14
  begin
15
    if rising_edge(A) then
16
      if B = '0' then
17
        count <= std_logic_vector(unsigned(count) + 1);
18
      else
19
        count <= std_logic_vector(unsigned(count) - 1);
20
      end if;
21
    elsif falling_edge(A) then
22
      if B = '0' then
23
        count <= std_logic_vector(unsigned(count) - 1);
24
      else
25
        count <= std_logic_vector(unsigned(count) + 1);
26
      end if;
27
    elsif rising_edge(B) then
28
      if A = '0' then
29
        count <= std_logic_vector(unsigned(count) - 1);
30
      else
31
        count <= std_logic_vector(unsigned(count) + 1);
32
      end if;
33
    elsif falling_edge(B) then
34
      if A = '0' then
35
        count <= std_logic_vector(unsigned(count) + 1);
36
      else
37
        count <= std_logic_vector(unsigned(count) - 1);
38
      end if;
39
    end if;
40
  end process;
41
42
  with count select
43
    Sector <=   "00000001" when "000",
44
            "00000010" when "001",
45
            "00000100" when "010",
46
            "00001000" when "011",
47
            "00010000" when "100",
48
            "00100000" when "101",
49
            "01000000" when "110",
50
            "10000000" when "111",
51
            "XXXXXXXX" when others;
52
53
end Behavioral;
1
line 44: Signal count cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.

Kann mir jemand weiterhelfen?

Nebenbei: Wie wird normalerweise ein flankengetriggertes Modul aufgebaut 
(mehrere Eingänge und unterschiedliche Flankten), oder soll dies über 
Pegel gelöst werden und einzig einen Clock verwenden?

Besten Dank,
Patrick

von Pongo unterwegs (Gast)


Lesenswert?

Mach schnell die vielen konkurrierenden rising und falling Konstrukte 
weg, bevor Lothar das sieht und Dich zerfetzt!

von Patrick B. (p51d)


Lesenswert?

Wie denn sonst (ist wie gesagt mein erstes VHDL Programm)? Jede 
Bedingung in einen eigenen Prozess?

: Bearbeitet durch User
von Pongo unterwegs (Gast)


Lesenswert?

nein, liest erstmal was rising edge macht.

das brauchst du EINMAL, ein Prozess innen drin die typischen Abfragen 
nach Pegeln und nicht nach Flanken - siehe die einschlägigen 
Beispielprojekte

von Patrick B. (p51d)


Lesenswert?

Ok, werds auf einen Master-Clk umschreiben.

von Christian R. (supachris)


Lesenswert?

Ohje. Musst noch viel lernen. Aber lass dich nicht entmutigen, jeder 
fängt mal an.
Schau doch mal hier: 
http://www.mikrocontroller.net/articles/Drehgeber#Beispielcode_in_VHDL 
diese Lösung klappt bestens, selbst in gestörten Industrie-Umgebungen.

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


Lesenswert?

Patrick B. schrieb:
> (ist wie gesagt mein erstes VHDL Programm)
Warum heißt VHDL VHDL und nicht VHPL?

Zum Thema: was du beschreibst, sind "Dual-Clock-Flipflops" und so etwas 
gibt es nicht...

Pongo unterwegs schrieb:
> und Dich zerfetzt!
Tja, Pech, zu spät...

Als kleiner Denkanstoss mit Wiedererkennungswert:

http://www.lothar-miller.de/s9y/archives/53-Drehgeber,-Encoder,-Quadraturdecoder.html

von Bitflüsterer (Gast)


Lesenswert?

Ich weiss nicht. Wie soll ich es sagen, ohne das Lothar Miller mir die 
Ohren abreisst - aber sagen will ich es doch:

Es ist richtig, dass die erhältlichen FPGAs keine Dual-Edge-Flip-Flops 
als Einheiten enthalten. Aber so etwas lässt sich in VHDL durchaus 
synthetisierbar beschreiben in dem man es mit zwei Flip-Flops - äh - 
sozusagen emuliert.

Mit den Suchbegriffen "Dual Edge FF VHLD" erhält man z.B. folgende 
interessante Links:

http://www.ralf-hildebrandt.de/publication/pdf_dff/pde_dff.pdf

und

http://asicdigitaldesign.wordpress.com/2007/07/31/the-double-edge-flip-flop/

(nebst weiteren)

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


Lesenswert?

Bitflüsterer schrieb:
> Dual-Edge-Flip-Flops
Naja, Dual-Edge ist nun nicht Dual-Clock. Ein FF mit 2 Takteingängen 
also.
Oder, wenn man sich den VHDL Code ganz oben ansieht, sogar 
Dual-Edge-Dual-Clock-FFs...

von Bitflüsterer (Gast)


Lesenswert?

Lothar Miller schrieb:
> Bitflüsterer schrieb:
>> Dual-Edge-Flip-Flops
> Naja, Dual-Edge ist nun nicht Dual-Clock. Ein FF mit 2 /Takteingängen/
> also.
> Oder, wenn man sich den VHDL Code ganz oben ansieht, sogar
> Dual-Edge-Dual-Clock-FFs...

Richtig. Meine armen Ohren ...

von Bitflüsterer (Gast)


Lesenswert?

... obowhl ... das sind dann eben zwei Dual-Edge-FFs. Habe noch 'ne 
Nase. :-)

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


Lesenswert?

Bitflüsterer schrieb:
> Habe noch 'ne Nase. :-)
Wenn unbedingt sein muss... ;-)

> das sind dann eben zwei Dual-Edge-FFs
Und wie verschaltest du die count FFs hier:
1
    if rising_edge(A) then
2
        count <= ...
3
    elsif falling_edge(A) then
4
        count <= ...
5
    elsif rising_edge(B) then
6
        count <= ...
7
    elsif falling_edge(B) then
8
        count <= ...

: Bearbeitet durch Moderator
von Punkt Setzer (Gast)


Lesenswert?

Bitflüsterer behauptetet:

>Es ist richtig, dass die erhältlichen FPGAs keine Dual-Edge-Flip-Flops
>als Einheiten enthalten.

Nein, das ist nicht richtig, zum Ansteuern von DDR-SDRAM gibbet es 
sowas, bspw im Spartan-6:

http://www.xilinx.com/support/documentation/sw_manuals/xilinx13_1/spartan6_scm.pdf 
S.428

MfG,

von Patrick B. (p51d)


Lesenswert?

Lothar Miller schrieb:
> Patrick B. schrieb:
>> (ist wie gesagt mein erstes VHDL Programm)
> Warum heißt VHDL VHDL und nicht VHPL?

Wie nennt man den das? Skript, File, Hardware...?

Nur so aus Neugierde: Wie werden bei einem MCU solche Peripherieteile 
realisiert? Wenn man es auf Flankengetriggert einstellt, wird das nur 
pseudomässig umgesetzt oder werden da wirkich die Flanken ausgewertet. 
Letzeres würde dann ja zu einer Asynchronität führen.

Habe mein Teil gestern noch auf ein ähnliches System (alles nür über 
einzelne Rising_edge und Falling_edge Funktionen) umgeschrieben, wie 
diese (habe ich vom Lothars Seite):
1
process (A,B) begin     
2
  if rising_edge(A) then        
3
  if (B='1') then p<=p+1; 
4
  else p<=p-1; end if;     
5
  end if;     
6
  if falling_edge(A) then        
7
    if (B='0') then p<=p+1; 
8
    else p<=p-1; end if;     
9
  end if;     
10
  if rising_edge(B) then        
11
    if (A='0') then p<=p+1; 
12
    else p<=p-1; end if;     
13
  end if;     
14
  if falling_edge(B) then        
15
    if (A='1') then p<=p+1; 
16
    else p<=p-1; end if;     
17
  end if;  
18
end process;
Gleicher Fehler wie mit if-elsif Konstrukt.

Sehe gerade überhaupt nicht, was so nicht laufen soll.

Besten Dank, Gruss

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


Lesenswert?

Patrick B. schrieb:
> Lothar Miller schrieb:
>> Patrick B. schrieb:
>>> (ist wie gesagt mein erstes VHDL Programm)
>> Warum heißt VHDL VHDL und nicht VHPL?
> Wie nennt man den das? Skript, File, Hardware...?
Hardware DESCRIPTION Language
Hardware BESCHREIBUNG ssprache
Ich habe also kein VHDL Programm, sondern eine VHDL Beschreibung. Ich 
habe auch nicht einen Prozessor mit VHDL programmiert (fällt dir was 
auf: womit werden Prozressoren i.A. programmiert?), sondern ich habe mit 
VHDL einen Prozessor beschrieben.

> Sehe gerade überhaupt nicht, was so nicht laufen soll.
Hast du mit aller Gewalt meinen Link und alle Posts ignoriert?
Es gibt nirgends auf der Welt solche Bautsteine, die du da beschreibst!

> Habe mein Teil gestern noch auf ein ähnliches System (alles nür über
> einzelne Rising_edge und Falling_edge Funktionen) umgeschrieben, wie
> diese (habe ich vom Lothars Seite):
Und was steht dort dann auch?
1
Leider taugt dieser Quadraturdecoder wegen der Flankenauswertungen 
2
nur für die Simulation. Denn in einem programmierbaren Baustein gibt 
3
es kein Flipflop, das zwei Takteingänge hat, die sowohl auf die 
4
steigende wie auch die fallende Flanke reagieren könnten.
Taugt nur für die Simulation bedeutet, dass du das zwar simulieren 
kannst, aber nicht auf irgendeine Hadware bekommst. Merke: bestenfalls 
5% von VHDL können tatsächlich auf Hardware abgebildet werden. Aber 100% 
können simuliert werden...

> Nur so aus Neugierde: Wie werden bei einem MCU solche Peripherieteile 
realisiert?
So, wie es auf meiner HP ein paar Zeilen weiter unten gemacht ist: mit 1 
einzigen Mastertakt. Der muss nur ausreichend schnell sein. Und auf 
diesen Takt werden die Eingangssignale einsynchonisiert...
Es wird niemals auf ein Eingangssignal, das evtl. auch noch prellen 
oder überschwingen kann, ein rising_edge() oder ein falling_edge() 
abgefragt. Eine Flankenerkennung macht man wieder mit dem "Mastertakt": 
erst einsynchonisieren und dann eine Flankenauswertung:
http://www.lothar-miller.de/s9y/categories/35-Einsynchronisieren
http://www.lothar-miller.de/s9y/categories/18-Flankenerkennung
Sieh dir diese beiden Links genau an. Damit kannst du 90% aller 
Anfängerfehler umgehen...

: Bearbeitet durch Moderator
von Bitflüsterer (Gast)


Lesenswert?

Lothar Miller schrieb:
> Bitflüsterer schrieb:
>> Habe noch 'ne Nase. :-)
> Wenn unbedingt sein muss... ;-)
>
>> das sind dann eben zwei Dual-Edge-FFs
> Und wie verschaltest du die count FFs hier:
>
1
>     if rising_edge(A) then
2
>         count <= ...
3
>     elsif falling_edge(A) then
4
>         count <= ...
5
>     elsif rising_edge(B) then
6
>         count <= ...
7
>     elsif falling_edge(B) then
8
>         count <= ...
9
>

Ich habe leider kein ISE hier und kann das nicht ausprobieren. Aber 
meine Idee dazu wäre, jeweils einen Abwärts- und einen Aufwärtszähler zu 
benutzen, deren Differenz am Ende gebildet wird. Auch würde am Ende 
keine Sequenz von ifs in der gezeigten Form dastehen. Eher zwei 
Prozesse.

Lothar, ich weiß, solche theoretischen Einwände sind schwer 
ernstzunehmen. Wenn Du sagen willst, das es überhaupt nicht geht, auch 
nicht emuliert und mit Gebeten zum Spaghettimonster, nehme ich das mal 
unter Vorbehalt so an.

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


Lesenswert?

Bitflüsterer schrieb:
> Aber meine Idee dazu wäre, jeweils einen Abwärts- und einen
> Aufwärtszähler zu benutzen, deren Differenz am Ende gebildet wird.
Das ergäbe einen recht glitchigen "Zählerstand", der zu nichts und 
niemandem synchron ist. Mir wäre nicht wohl dabei...

> Lothar, ich weiß, solche theoretischen Einwände sind schwer
> ernstzunehmen. Wenn Du sagen willst, das es überhaupt nicht geht, auch
> nicht emuliert und mit Gebeten zum Spaghettimonster, nehme ich das mal
> unter Vorbehalt so an.
Du wirst sicher auch in einem FPGA etwas hinbekommen, das irgendwie so 
oder so ähnlich etwas macht. Aber "funktioneren" würde ich das nicht 
nennen. Und die Not ist doch nicht groß, weil es ja Verfahren gibt, die 
100% zuverlässig arbeiten.

von berndl (Gast)


Lesenswert?

Bitflüsterer schrieb:
> Lothar Miller schrieb:
>> Bitflüsterer schrieb:
>>> Habe noch 'ne Nase. :-)
>> Wenn unbedingt sein muss... ;-)
>>
>>> das sind dann eben zwei Dual-Edge-FFs
>> Und wie verschaltest du die count FFs hier:
>>>     if rising_edge(A) then
>>         count <= ...
>>     elsif falling_edge(A) then
>>         count <= ...
>>     elsif rising_edge(B) then
>>         count <= ...
>>     elsif falling_edge(B) then
>>         count <= ...
>>
> Ich habe leider kein ISE hier und kann das nicht ausprobieren. Aber
> meine Idee dazu wäre, jeweils einen Abwärts- und einen Aufwärtszähler zu
> benutzen, deren Differenz am Ende gebildet wird. Auch würde am Ende
> keine Sequenz von ifs in der gezeigten Form dastehen. Eher zwei
> Prozesse.
>
> Lothar, ich weiß, solche theoretischen Einwände sind schwer
> ernstzunehmen. Wenn Du sagen willst, das es überhaupt nicht geht, auch
> nicht emuliert und mit Gebeten zum Spaghettimonster, nehme ich das mal
> unter Vorbehalt so an.

aehm, wenn ich mal einfach so davon ausgehe, dass der Drehgeber mit 
seinen Flanken weit langsamer als der FPGA-Takt ist: Was ist denn so 
schwer daran, eine gescheite Flankenerkennung mit dem FPGA-Takt zu bauen 
und dieses +1 oder -1 dann entsprechend auszuwerten?
Damit waerst du innerhalb des FPGA voll synchron.

Bei deinem Vorschlag wuerdest du mit einem externen Pseudotakt Register 
setzen/veraendern. Diese Register musst du aber erstmal aufwendig in 
deine FPGA-Taktdomaene einsynchronisieren. Merkst was? Aus einem 
Pseudotakt machst du auf einmal eine Synchronisierung von z.B. 16 
Registerbits (count).

Welche der beiden Moeglichkeiten ist denn da einfacher? Vermutlich doch 
die, die nur mit einer Leitung am Eingang zu tun hat, oder? Oder willst 
du ernsthaft behaupten, du musst das Flankensignal auf die Nanosekunde 
genau abtasten?

von Patrick B. (p51d)


Lesenswert?

Mhm, habe mich einmal an das Muster von Lothar gehalten...
1
entity Decoder is
2
    Port ( A : in  STD_LOGIC;
3
           B : in  STD_LOGIC;
4
           Clk : in  STD_LOGIC;
5
           Sector : out  STD_LOGIC_VECTOR (7 downto 0));
6
end Decoder;
7
8
architecture Behavioral of Decoder is
9
10
-- Zustandstypen und die Zustandsvariable
11
type states is (Z00, Z01, Z11, Z10);
12
signal state : states := Z00;
13
14
-- Zählervariable
15
signal count : std_logic_vector(2 downto 0) := "000";
16
17
-- Variablen zum Eintakten
18
signal DecoderInputUnstable : std_logic_vector(1 downto 0);
19
signal DecoderInputStable : std_logic_vector(1 downto 0);
20
21
begin
22
  -- Einsynchronisieren der asynchronen Eingangssignale
23
  process begin
24
    DecoderInputUnstable <= (B, A);                      -- Zusammenfassen der Signale
25
    DecoderInputStable <= DecoderInputUnstable;              -- 2. Stufe
26
  end process;
27
28
29
  -- Decoder
30
  process(Clk)
31
  variable Up, Down : std_logic := '0';                    -- Lokale Variable
32
  begin
33
    if rising_edge(Clk) then
34
      Up := '0';
35
      Down := '0';
36
    
37
      -- Zustäde
38
      case state is
39
        when Z00 => if DecoderInputStable = "01" then
40
                  state <= Z01;
41
                  Up := '1';
42
                elsif DecoderInputStable = "10" then
43
                  state <= Z10;
44
                  Down := '1';
45
                end if;
46
        when Z01 => if DecoderInputStable = "11" then
47
                  state <= Z11;
48
                  Up := '1';
49
                elsif DecoderInputStable = "00" then
50
                  state <= Z00;
51
                  Down := '1';
52
                end if;
53
        when Z11 => if DecoderInputStable = "10" then
54
                  state <= Z10;
55
                  Up := '1';
56
                elsif DecoderInputStable = "01" then
57
                  state <= Z01;
58
                  Down := '1';
59
                end if;
60
        when Z10 => if DecoderInputStable = "00" then
61
                  state <= Z00;
62
                  Up := '1';
63
                elsif DecoderInputStable = "11" then
64
                  state <= Z11;
65
                  Down := '1';
66
                end if;
67
      end case;
68
      
69
      -- Zählen
70
      if Up = '1' then
71
        count <= std_logic_vector(unsigned(count) + 1);
72
      end if;      
73
      if Down = '1' then
74
        count <= std_logic_vector(unsigned(count) - 1);
75
      end if;
76
    end if;
77
  end process;
78
79
  -- Variable ausgeben
80
  with count select
81
    Sector <=   "00000001" when "000",
82
            "00000010" when "001",
83
            "00000100" when "010",
84
            "00001000" when "011",
85
            "00010000" when "100",
86
            "00100000" when "101",
87
            "01000000" when "110",
88
            "10000000" when "111",
89
            "XXXXXXXX" when others;

Beim simulieren habe ich aber keine Signale mehr. Sobald ich den Prozess 
mit dem clk und den Teil mit dem Einsynchronisieren auskommentiere, dann 
sehe ich zumindest wieder Pegel.

Mhm, das ganze ist irgendwie eine eigene Welt. Habe mitlerweile viel 
Erfahrung mit MCUs (8Bit, DSP, 16Bit, 32Bit, ARM), aber hier habe ich 
das Gefühl, als hätte ich nicht den Hauch einer Ahnung.

@Lothar
Sorry, hab wohl nicht alles gelesen. Aber ist eine interessante Seite, 
die ich gerne mal durchlese.

MFG

von Fpgakuechle K. (Gast)


Lesenswert?

Patrick B. schrieb:
> Mhm, das ganze ist irgendwie eine eigene Welt. Habe mitlerweile viel
> Erfahrung mit MCUs (8Bit, DSP, 16Bit, 32Bit, ARM), aber hier habe ich
> das Gefühl, als hätte ich nicht den Hauch einer Ahnung.

Ja MCU in C-Programmieren ist keine Grundlage für FPGA-Entwicklung.
Was du brauchst ist ein Grundverständniss in digitaler 
Schaltungstechnik.

MfG,

von Duke Scarring (Gast)


Lesenswert?

Patrick B. schrieb:
> eim simulieren habe ich aber keine Signale mehr.
Häng doch mal den Code und die Testbench hier ran. Dann kann man es 
selber simulieren und nachvollziehen.

Duke

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


Lesenswert?

Patrick B. schrieb:
> -- Einsynchronisieren der asynchronen Eingangssignale
>   process begin
>     DecoderInputUnstable <= (B, A);
>     DecoderInputStable <= DecoderInputUnstable;
>   end process;
Da wird nichts einsynchronisiert, weil kein Takt (=Flipflop) beteiligt 
ist. Eigentlich muss der Simulator hier rummeckern, weil nichts in der 
Sensitivliste  steht und auch kein wait im Prozess vorkommt.

: Bearbeitet durch Moderator
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.