www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Probleme bei der Umstellung von Verilog nach VHDL


Autor: Michael Fischer (mifi)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

da ich glaubte VHDL etwas mehr verstanden zu habe, hatte ich mir gedacht
das ich mal einen Verilog Code versuche in VHDL umzusetzen. Gleichzeitig
wollte ich dort die benutzen Latches in ein synchrones Design umstellen,
weil jeder erzählt das Latches "böse" sind.

Leider bekomme ich folgende Fehlermeldung von ISE WebPack 11.3:

>Cpld:892 - Cannot place signal im_reg_l<6>. Consider reducing the collapsing 
>input limit or the product term limit to prevent the fitter from creating high 
>input and/or high product term functions.

Benutzt wird ein XC95144XL-10-TQ144

Das CPLD ist aus dem OpenSource Projekt Ethernut, Infos zum CPLD gibt
es hier: http://www.ethernut.de/en/hardware/enut3/memory.html

Ich dachte, sind ja nur einige Register, das kann ja nicht so schwer
sein. Im Moment habe ich Probleme mit den Interrupt Registern. Für
die Erkennung einer Flanke habe ich den Source von Lothar Miller
genommen. (Danke für die Hilfe bei meinen ersten Gehversuchen mit VHDL).

Hier soll ein Interrupt (Flanke low => high, oder high => low) erkannt 
werden, und die Info im Latch Register gespeichert. Mit dem Clear 
Register kann dann diese Information wieder gelöscht werden. Später wird 
das Latch Register mit dem Mask Register verundet und hierdurch der 
Interrupt ausgelöst. Dies ist auch ein etwas längeres Konstrukt, ab 
Zeile 430:

   P9 <= '0' when ( ((sl_reg_l(0) = '1') and (im_reg_l(0) ='1')) or
         usw.
         usw....

Geht das noch einfacher?

OK, genug geschrieben, anbei nun der neue VHDL Source und die
originalen Verilog Quellen.

Da man besonders gut aus Fehlern lernen kann, bin ich mal gespannt
auf Eure Anregungen wie man das Problem lösen, bzw. besser machen kann.

Viele Grüße,

Michael

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohne direkt das eigentliche Problem aufzugreifen:
>    -- Shift register for the edge detection
>   signal ccts_sr      : std_logic_vector(3 downto 0);
>   :
>   :
Du hast in einem CPLD wesentlich weniger FFs...
Auf jeden Fall reichen garantiert auch 3. Dann ist jede Metastabilität 
weg.
Ich würde die Flankenerkennung nur 2 FFs lang machen. Das sollte auch 
gehen.

In einem FPGA habe ich mit der Länge der Schieberegisterkette kein 
Problem, die wird in diesem Fall sowieso in eine LUT abgebildet. Auf 
einem CPLD sind FFs extrem wertvoll.

Insgesamt zähle ich in dem Design schon fast 130 Speicherglieder, und 
das bei nur 144 Makrozellen/FFs. Das muss knapp werden... :-/

Autor: Michael Fischer (mifi)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Lothar,

>Ich würde die Flankenerkennung nur 2 FFs lang machen
Das habe ich jetzt umgesetzt und konnte etwas weiter arbeiten.
Nun bin ich am MMC Teile, d.h. es wird hier versucht eine
SPI Schnittstelle nachzubilden. Und schon platzt das CPLD
wieder aus allen Nähten:

>Cpld:886 - Function block FB8 was too congested to route successfully.
>This occurs due to excessive (>= 50) product term input fanins to this
>function block. Consider moving output signals in this function block to
>less congested function blocks, buffering output signals that must remain
>in this function block, or selecting a larger package.

Von den FFs sieht es noch gut aus:

Macrocells Used: 129/144
Pterms Used:     460/720
Registers Used:   95/144
Pins Used:        83/117
Function Block
Inputs Used:     309/432

Der Source ist wieder im Anhang, hast Du noch eine Idee wie man
den MMC Teil platzsparender umsetzen könnte? So gut sieht das auch
noch nicht aus weil hier kein Clock Pin benutzt wird, sondern der
Clock wird selber erzeugt. Ich weis nicht ob ich hier noch Platz
für eine StateMachine habe.

Viele Grüße,

Michael

Autor: Der Besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>weil jeder erzählt das Latches "böse" sind.

Latches an sich sind ganz feine Bauteile, die, richtig verwendet, einem 
viele spezielle Schaltungsrealisierungen ermöglichen.

Das Problem ist meist, das in einem geplanten vollsynchronen Design 
Latches auf Schwächen in diesem Hinweisen. Meist bedingt durch nicht 
vollständig beschriebene kombinatorische Logik. Daher kommt wohl die 
Latchparanoia.

Aber wenn man wirklich ein Latch verwenden will ist wirklich nix 
schlimmes dran. Man muß nur wissen was man tut.

Der Besucher

Autor: SuperWilly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was passiert eigentlich, wenn du das Original-Verilog-Design mit ISE 
WebPack 11.3 synthetisierst ? Passt das Design denn dann in den von dir 
genannten Baustein ?


SuperWilly

Autor: Michael Fischer (mifi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo "SuperWilly",

das Original-Verilog-Design kann mit ISE 11.3 übersetzt werden.
Aber es sieht so aus als wenn hier ein Signal weg optimiert wird
was eigentlich auch gebraucht wird.

Gruß,

Michael

Autor: Michael Fischer (mifi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich habe jetzt noch mal einen Tip bekommen, und dadurch konnte
dann das Problem behoben werden. Folgender Source:

   ccts_falling_test : process (CPLD_CLK, reset0_irq, sl_reg_l, ccts_sr, 
CCTS)
   begin
      -- Check for reset
      if (reset0_irq(0) = '0') then
         sl_reg_l(0) <= '0';
         ccts_sr     <= "11";
      else
         -- edge detection
         sl_reg_l(0) <= not ccts_sr(0) and ccts_sr(1);

         -- read the input into the shift register
         if CPLD_CLK = '1' and CPLD_CLK'event then
            -- but only if no edge was detected before
            if (sl_reg_l(0) = '0') then
               ccts_sr <= ccts_sr(0) & CCTS;
            end if;
         end if;
      end if;
   end process ccts_falling_test;

wurde geändert in:

   ccts_falling_test : process (CPLD_CLK, reset0_irq)
   begin
      -- Check for reset
      if (reset0_irq(0) = '0') then
         sl_reg_l(0) <= '0';
         ccts_sr     <= "11";
      elsif CPLD_CLK = '1' and CPLD_CLK'event then

         -- read the input into the shift register
         -- but only if no edge was detected before
         if (sl_reg_l(0) = '0') then
            -- edge detection
            sl_reg_l(0) <= not ccts_sr(0) and ccts_sr(1);
            ccts_sr <= ccts_sr(0) & CCTS;
         end if;
      end if;
   end process ccts_falling_test;

Warum das jetzt kleiner geworden ist kann ich nicht sagen.
Als nächstes geht es nun an die Simulation...

Viele Grüße,

Michael

Autor: SuperWilly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wäre es nicht noch einfacher, die Flankenerkennung ohne if-Abfrage zu 
beschreiben ?




ccts_falling_test : process (CPLD_CLK, reset0_irq)
   begin
      -- Check for reset
      if (reset0_irq(0) = '0') then
         sl_reg_l(0) <= '0';
         ccts_sr     <= "11";
      elsif rising_edge(CPLD_CLK) then

         -- edge detection
         sl_reg_l(0) <= not ccts_sr(0) and ccts_sr(1);

         -- read the input into the shift register
         -- but only if no edge was detected before
         if (sl_reg_l(0) = '0') then            
            ccts_sr <= ccts_sr(0) & CCTS;
         end if;
      end if;
   end process ccts_falling_test;


Gruß,
SuperWilly

Autor: Michael Fischer (mifi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo SuperWilly,

ich habe jetzt ein Latch benutzt:

   ccts_falling_test : process (CCTS, reset0_irq)
   begin
      -- Check for reset
      if (reset0_irq(0) = '0') then
         sl_reg_l(0) <= '0';
      elsif CCTS = '0' and CCTS'event then
         -- but only if no edge was detected before
         if (sl_reg_l(0) = '0') then
            sl_reg_l(0) <= '1';
         end if;
      end if;
   end process ccts_falling_test;

Gruß,

Michael

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist kein Latch  ;-)
sl_reg_l ist ein lokales FF, das synchron zurückgesetzt wird.

So ähnlich wie mein Impulsmerker:
http://www.lothar-miller.de/s9y/archives/19-Kurzer...

BTW:
Das solltest du dir nochmal genauer überlegen:
         -- but only if no edge was detected before
         if (sl_reg_l(0) = '0') then
            sl_reg_l(0) <= '1';
         end if;
Meiner Meinung nach kannst du das funktionsgleich ersetzen durch:
           -- but only if no edge was detected before
           sl_reg_l(0) <= '1';

Am Rande:
Du hast es jetzt mit 2 Taktdomänen zu tun. Wundere dich nicht, wenn sich 
das Design ab und zu (ich meine damit Stunden oder Tage) eigenartig 
verhält. Z.B. synchronisierst du sl_reg_l(0) nicht auf CPLD_CLK ein...

Autor: Michael Fischer (mifi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Lothar,

>Am Rande:
>Du hast es jetzt mit 2 Taktdomänen zu tun. Wundere dich nicht, wenn sich
>das Design ab und zu (ich meine damit Stunden oder Tage) eigenartig
>verhält. Z.B. synchronisierst du sl_reg_l(0) nicht auf CPLD_CLK ein...
Danke für den Hinweis, gr%#&...
Ich hatte es erst mit dem CPLD_CLK und den zwei FF, danach war aber kein
Platz mehr für das MMC Interface (Nachbildung SPI) vorhanden.

Außerdem gab es ein Problem bei der ersten Lösung das wenn man ein
Signal auf steigende und fallende Flanke hin überwachen möchte.

Wenn die Ruhelage High war, wurde mir gleich eine steigende Flanke
gemeldet, war die Ruhelage Low, eine fallende Flanke.

Das IF-Statement kann raus, denn wenn sl_reg_l schon 1 ist, ist es nicht
schlimm wenn es weiterhin auf 1 gesetzt wird.

Dann werde ich mir noch mal den Spikedetector anschauen. FFs habe ich
noch genug über. Das Problem waren irgendwelche internen Verbindungen.

Viele Grüße,

Michael

Autor: Michael Fischer (mifi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Lothar,

was hältst Du nun von folgender Version?

   -- Merker-FF
   process (reset0_irq, CCTS)
   begin
      if (reset0_irq(0) = '0') then
         merkin <= '0';
      elsif CCTS = '0' and CCTS'event then
         merkin <= '1';
      end if;
   end process;

   -- Asynchrones Merker-FF eintakten
   process (reset0_irq, CPLD_CLK)
   begin
      if (reset0_irq(0) = '0') then
         sr0 <= '0';
         sr1 <= '0';
      elsif CPLD_CLK= '1' and CPLD_CLK'event then
         sr0 <= merkin;
         sr1 <= sr0;
      end if;
   end process;

   sl_reg_l(0) <= sr1;

Gruß,

Michael

Autor: Michael Fischer (mifi)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

mir fehlt gerade eine Macrocell:

ERROR:Cpld:837 - Insufficient number of macrocells. The design needs at 
least
   145 but only 144 left after allocating other resources.
Device 95144XL144TQ was disqualified.
ERROR:Cpld:868 - Cannot fit the design into any of the specified devices 
with
   the selected implementation options.

Ich habe schon mit den Werten für Imput Limit und Pterm Limit gespielt,
und das beste Ergebnis bekomme ich bei folgende Werten:

Input Limit 21
Pterm Limit 20

Hat noch jemand eine Idee wo ich im Source was sparen kann?

Viele Grüße,

Michael

Autor: Michael Fischer (mifi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

habe nun noch einige Macrocells gefunden. Das Schieberegister
im MMC Teil für die Ausgabe wurde nun durch einen Multiplexer
ersetzt. Ich hoffe mal das es ein Multiplexer ist :o) Die
Post-Fit Simulation geht immer noch.

               case mmc_creg is
                  when "0000" =>
                     mmc_doreg <= mmc_mosi_reg(7);

                  when "0001" =>
                     mmc_doreg <= mmc_mosi_reg(6);

                  when "0010" =>
                     mmc_doreg <= mmc_mosi_reg(5);

                  when "0011" =>
                     mmc_doreg <= mmc_mosi_reg(4);

                  when "0100" =>
                     mmc_doreg <= mmc_mosi_reg(3);

                  when "0101" =>
                     mmc_doreg <= mmc_mosi_reg(2);

                  when "0110" =>
                     mmc_doreg <= mmc_mosi_reg(1);

                  when others =>
                     mmc_doreg <= mmc_mosi_reg(0);

               end case;


Gruß,

Michael

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Das Schieberegister im MMC Teil für die Ausgabe wurde nun durch einen
> Multiplexer ersetzt.
Das ist eine gute Lösung für CPLDs. Die haben mit ihren Makrozellen 
mächtige Kombinatorik, sind also ideal für Multiplexer.

Autor: Michael Fischer (mifi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen Lothar,

Du hattest etwas weiter oben folgendes geschrieben:

>Am Rande:
>Du hast es jetzt mit 2 Taktdomänen zu tun.

Wie erkennt dies eigentlich ein Anfänger, gibt es hier irgendwelche
Tips? Wo ist denn dort der Unterschied zu einem einfachen CPU
Interface? Beim CPU Interface benutzt man doch auch die steigende
Flanke von nWE um die Daten zu übernehmen. Wenn ich von einem CPU
Interface mit folgenden Signalen ausgehe, A, D, nWE, nCS:

if (nWE = '1') and (nWE 'event) then
  if (A = X) and (nCS = '0') then
     daten <= D;
  end if;
end if;

Hier schiebt man die Daten "daten" doch auch nicht über eine
zweite FF-Stufe. Der einzige Unterschied den ich hier sehe ist das
nWE auf einen Clock Eingang liegen sollte.

Und nun zurück zu meiner ersten Flankenerkennung für das Signal X und
den Ausgang Q. Nehmen wir an es soll eine steigende Flanke erkannt
werden:

if (nRESET = '0') then
   Q <= '0';
elsif (X = '1') and (X 'event) then
   Q <= '1';
end if;

Wo mache ich den Denkfehler?

Viele Grüße,

Michael

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wie erkennt dies eigentlich ein Anfänger...
Genauso wie es auch ein Profi erkennt ;-)
Unterschiedliche Takte im Design sind ein Indiz.
Externe Signale sind generell verdächtig.
Diese externen Signale können zu sich selber durchaus synchron sein 
(Speicherinterface mit nWE, SPI mit SCLK...), zum CPLD/FPGA-Takt sind 
sie idR. asynchron.

> Wenn ich von einem CPU Interface mit folgenden Signalen ausgehe...
Dann ist die erste Aufgabe, die Daten zu übernehmen. Das kann durchaus 
mit einem lokalen Takt (nWE) geschehen. Aber für die Weiterverarbeitung 
muß dann das Validierungssignal nWE einsynchronisiert werden, damit 
sichergestellt ist, dass die Daten bei der Verwendung stabil und gültig 
sind.

Es muß also nicht jedes Signal einsynchronisiert werden, sondern "nur" 
das signal, das die Gültigkeit der Daten anzeigt. Beim SPI z.B. sind die 
unkritischsten Signale MOSI und MISO. Augenmerk muß auf SCLK und auch SS 
gelegt werden.

> Und nun zurück zu meiner ersten Flankenerkennung ...
Das ist hier so beschrieben, die Flanke wird erkannt und gespeichert.
Das Problem liegt nicht in diesem Stück Code, sondern im Übergang zur 
weiteren Verarbeitung. Die erkannte Flanke wird zu beliebiger Zeit in 
Q gespeichert. Wenn jetzt irgendwas dieses Q verwendet und dabei einen 
anderen Takt hat, dann hast du wieder Probleme, die tsu und th der 
nachfolgenden FF einzuhalten.

Autor: Michael Fischer (mifi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Lothar,

ich versuche das noch mal von einer anderen Sichtweise zu betrachten und 
mit einem C-Beispiel zu vergleichen. Nehmen wir eine 8-Bit CPU die auf 
ein 32 Bit Wert lesend zugreift der im Interrupt verändert werden kann.

Hier kann es passieren das der Lesezugriff der CPU durch den Interrupt 
unterbrochen wird (die CPU benötigt 4 Zugriffe und kann den Wert nicht 
auf einmal lesen), dieser den Wert verändert, und die CPU dann nur noch 
Unsinn ausliest.

Am einfachsten kann man nun das Problem lösen indem man beim Zugriff auf 
die Variable außerhalb des Interrupts die Interrupts selber sperrt und 
nach dem Zugriff wieder freigibt. Somit ist sichergestellt das die 
Variable nicht verändert werden kann wenn man außerhalb des Interrupts 
lesend darauf zugreift.

Zurück zur Hardware. Hier kann man ja nicht die Interrupts sperren, also 
muß man sicherstellen das sich der Wert nicht ändert, oder stabil 
anliegt, wenn man einen Zugriff macht. Dies kann nur dadurch erreicht 
werden das man das Signal durch  zwei FF schiebt.

sr0 <= In
sr1 <= sr0

Und dann die "Variable" sr1 benutzt. Hier ändert sich sr1 nicht wenn 
schon eine Änderung an In auftritt.

Gruß,

Michael

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Problem unsynchronisierter Eingänge bei Hardware ist eher folgendes:
Wenn ein Eingang mehrfach in einer Statemachine zum Weiterschalten von 
zuständen verwendet wird, dann kann es ohne Einsynchronisierung zu 
fehlerhaftem Verhalten dieser SM kommen, weil aufgrund 
unterschiedlicher Laufzeiten zu den FFs ein unterschiedlicher Pegel 
des Eingangs erkannt wird. Es wird dann z.B. nicht der Folgezustand 
angesprungen, sondern ein x-beliebiger.

Allein das Eintakten auf ein Speicherregister ist relativ ungefährlich. 
Metastabile Zustände treten signifikant erst bei Frequenzen um 300MHz 
auf (ich lasse hier gerade einen Versuch laufen). Die heutigen FFs in 
FPGAs (und vermutlich auch CPLDs) sind so schnell, dass bei 
"handelsüblichen" Frequenzen Metastabilität keine Rolle spielt.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.