www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Hardware mit VHDL "richtig" beschreiben.


Autor: Dimi (Gast)
Datum:

Guten Tag an alle!!!

Ich brauche paar tipps zum Thema VHDL.
Mein Design funktioniert zwar, aber ich hatte viele Timing-Probleme (die
ich
bereits schot gelöst habe).
Trotzdem mache ich mir immer noch gedanken um "richtigkeit" meines
VHDL-Codes.
So sieht's bei mir aus...
PORT_CS <= '1' when cpu_IORQ = '0' and cpu_WR = '0' and cpu_A(15 downto 8) = "01110011" else '0';

process (clk25,reset)
begin
   if reset = '0' then
      RAM_Page <= "00";
      ROM_Page <= '0';
   elsif rising_edge(clk25) then
      if P7ORT_CS = '1' then
         RAM_Page <= cpu_DO(1 downto 0);
         ROM_Page <= cpu_DO(3);
      end if;
   end if;
end process;


Jetzt weiss ich nicht ob es besser wäre die Bedingug direkt im "IF" zu
schreiben:



process (clk25,reset)
begin
   if reset = '0' then
      RAM_Page <= "00";
      ROM_Page <= '0';
   elsif rising_edge(clk25) then
      if cpu_IORQ = '0' and cpu_WR = '0' and cpu_A(15 downto 8) = "01110011" then
         RAM_Page <= cpu_DO(1 downto 0);
         ROM_Page <= cpu_DO(3);
      end if;
   end if;
end process;


Macht es überhaupt underschiede? Wenn ja, welche???
Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

>Macht es überhaupt underschiede?
Nein, schau dir einfach mal die RTL-Schematics an.
Die 2. Lösung ist einfach schöner lesbar, weil kompakter...



Ein Tipp:
Nimm den Reset mit in den synchronen Teil des Prozesses, auch wenn die
allgegenwärtigen Code-Beispiele anders aussehen.
process (clk25)
begin
   if rising_edge(clk25) then
      if reset = '0' then
         RAM_Page <= "00";
         ROM_Page <= '0';
      elsif cpu_IORQ = '0' and cpu_WR = '0' and cpu_A(15 downto 8) = "01110011" then
         RAM_Page <= cpu_DO(1 downto 0);
         ROM_Page <= cpu_DO(3);
      end if;
   end if;
end process;
1. Grund: Was würde in deinem Design passieren, wenn der Reset super
knapp vor der steigenden Flanke des Taktes inaktiv würde? Bekommen das
alle FFs gleich- und rechtzeitig mit? Läuft dann dein ganzes FPGA
zuverlässig an?
Nein: der Reset ist ein asynchrones Signal (das asynchrone Signal
schlechthin), der muss auch auf deinen Takt einsynchronisiert werden
(wie jedes andere asynchrone Signal). Und wenn der Reset dann schon
synchron ist, gehört er auch in den getakteten Teil.

2. Grund: Der ganze Rest des Designs ist synchron, nur für den
asynchronen Reset zwingst du das Synthesetool, asynchrone FFs zu
verwenden. Der Synthesizer verwendet dann sozusagen die "falschen" FFs.
Und mit diesen FFs kann der synchrone Teil der Schaltung (und das ist
der, der die Arbeit tut) nicht so schön optimiert werden.

3. Grund: wozu brauchst du einen Reset? Für den allgegenwärtigen
Reset-Taster? Ist der es Wert, wertvolle Resourcen zu vergeuden?

Dazu auch:
http://www.xilinx.com/support/documentation/white_...

Meine Aussagen gelten für Xilinx, inwiefern das für andere Architekturen
passt: bitte selber überprüfen.
Autor: Dimi (Gast)
Datum:

Vielen dank für die Info!!!!

Alles super erklärt!

Zu Punkt 3.
Ein Reset brauche ich schon, kann aber 90% davon wegschmeissen.
Ich werde heute noch alles ändern. :)
Es ist mir einfach SEHR interessant, wie sich die
Laufzeiten ändern!

p.S. ich dachte immer das "reset" eines FlipFlops keine
zusätzliche Resourcen verwendet, da die FlipFlops
SET- und RESET- eingänge haben und diese werden dafür verwendet.
Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

Dimi wrote:
> p.S. ich dachte immer das "reset" eines FlipFlops keine
> zusätzliche Resourcen verwendet
Richtig: es werden für den Reset keine zusätzlichen Ressourcen
verschwendet, die sind alle schon da.
Nur werden für den asynchronen Reset dann auch asynchrone FFs
eingesetzt. Und so ein FF kann nur entweder asynchron (FDCP, mit preset
und clear) oder synchron (FDRS, mit set und reset) konfiguriert werden.
Und bei einem synchronen Design kann der Synthesizer mit einem
synchronen FF wesentlich mehr anfangen.

> da die FlipFlops SET- und RESET- eingänge haben
Ja, es gibt wie gesagt grundlegend 2 verschiedene Möglichkeiten, die FFs
zu konfigurieren (mal von den DDR-FFs abgesehen).

Ein kleines Beispiel:
Asynchroner Reset
architecture Behavioral of Reset_1 is -- AsyncSync
signal do : std_logic;
begin
   process (clk)
   begin
      if (reset='1') then            -- async. Reset
         do <= '0';
      elsif rising_edge(clk) then
         if    (set='1') then        -- sync. Set
            do <= '1';
         elsif (load='1') then       -- laden
            do <= din;
         else
            do <= do;                -- speichern
         end if;
      end if;
   end process;
   dout <= do;
end Behavioral;

Und im Anhang die RTL-Schematic.
Schön aufwendig, nicht wahr?
:
:
:
Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

:
:
Und dann:
Synchroner Reset
architecture Behavioral of Reset_1 is -- Synchron
signal do : std_logic;
begin
   process (clk)
   begin
      if rising_edge(clk) then
         if   (reset='1') then       -- sync. Reset
            do <= '0';
         elsif (set='1')  then       -- sync. Set
            do <= '1';
         elsif (load='1') then       -- laden
            do <= din;
         else
            do <= do;                -- speichern
         end if;
      end if;
   end process;
   dout <= do;
end Behavioral;

Schön einfach, nicht wahr?
Welche der beiden Lösungen dürfte schneller sein?
Spätestens jetzt sollte der Groschen fallen... ;-)
Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Meine Lieblingsschreibweise wäre dann so:
architecture Behavioral of Reset_1 is -- Synchron
signal do : std_logic;
begin
   process begin
      wait until rising_edge(clk);
      if    (reset='1') then   do <= '0';  -- sync. Reset
      elsif (set='1')   then   do <= '1';  -- sync. Set
      elsif (load='1')  then   do <= din;  -- laden
--    else                     do <= do;   -- speichern: implizit
      end if;
   end process;
   dout <= do;
end Behavioral;

Schöner gehts nimmer...   ;-)
Autor: Dimi (Gast)
Datum:

VIELEN VIELEN DANK!!!

Die Ergebnisse kommen noch :)
Autor: Matthias F. (flint)
Datum:

@lkmiller: Könntest du, nachdem du das ganze schon parat hast, das ganze
noch umdrehen, also im Reset '1' zuweisen und im synchronen Set '0'.

Dann müsste sich das Ganze, wenigstens bei Xilinx, wieder ziemlich
ändern, weil das Reset an sich eine höhere Priorität hat als das Set und
das Synthesetool das wieder so hinbauen muss.

Würde mich interessieren, ob ich mit dieser Vermutung recht habe.
Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

>Würde mich interessieren, ob ich mit dieser Vermutung recht habe.
Hier geht die Geschichte unentschieden aus:
beide Lösungen brauchen gleich viel zusätzliche Logik.

Ansatz:
(Beispiel: synchron)
         wait until rising_edge(clk);
         if   (reset='1') then       -- sync. Reset 
            do <= '1';               --    auf '1'
         elsif (set='1')  then       -- sync. Set
            do <= '0';               --    auf '0'
         elsif (load='1') then       -- laden
            do <= din;
         else
            do <= do;                -- speichern
         end if;

Im Bild:
oben asynchrones FF
unten synchrones FF


Fazit:
man muss dem FPGA schon ein wenig "nach dem Maul" programmieren ;-)
Autor: Matthias F. (flint)
Datum:

Danke für die Mühe.

Theoretisch könnte man ja auch die Daten an Eingang und Ausgang
invertieren, dann könnte man auch das Set/Reset Assignment umdrehen und
das Synthesetool könnte wieder die Priorisierung der verschiedenen
Eingänge ausnutzen.

Wobei das wohl auch Hirnw*chserei ist, nachdem man für eine Invertierung
ja erst wieder über eine LUT gehen muss. Aber spannend ist das Thema
jedenfalls :) .

Lesetipp dazu ist übrigens das Xilinx WP275 "Get your priorities right".
Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

>nachdem man für eine Invertierung ja erst wieder über eine LUT gehen muss
Nein, das ist nicht nur theoretische Kunst. Natürlich wirst du nicht
jeden Pfad optimal hinbekommen. Aber wenn du den kritischen Logikpfad
u.U. durch das Herausnehmen einer Logikebene und Einfügen derselben in
den Set/Reset-Pfad schneller bekommst, dann hat das was.

Wichtig ist hier zuerst das Wissen oder wenigstens eine Ahnung, _was
überhaupt_ aus der Beschreibung gemacht werden wird. Wenn man nicht
alles falsch macht, hat man schon Vieles richtig gemacht.
Autor: Matthias F. (flint)
Datum:

Es kann jedenfalls nicht schaden, zu verstehen, wie die HW die man da
bearbeitet, funktioniert. In diesem speziellen Fall braucht man aber
auch für den ungünstigen Fall nur eine Logikebene (wenn ich es richtig
sehe), wenn man Daten davor und danach invertieren will aber zwei. Darum
hab ich das doppelte Invertieren mal nur in die Ecke Spielerei
geschoben.

Und wenn man gerade so an der Grenze ist mit dem Timing würden viele
wohl einfach einen schnelleren Speedgrade nehmen, ist vermutlich auch
wirtschaftlich die vernünftigere Entscheidung.

Aber ein wenig Spielerei muss ja auch sein :) .
Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

> In diesem speziellen Fall...
Richtig, hier wird sowieso nur 1 LUT nötig sein. Aber sobald in die Set-
und Reset-Abfragen etwas mehr reinkommt (Adressdecoder, States) könnten
unnötigerweise 2 Logikebenen synthetisiert werden. Und auf einmal ("Ich
habe doch fast nichts geändert") ist es zu langsam oder zu groß.

> verstehen, wie die HW die man da bearbeitet, funktioniert...
Das ist wie mit dem Wissen, wie die rote Ampel funktioniert:
Die Strasse darunter ist an sich immer gleich gut befahrbar. Aber mit
dem Wissen, dass die Ampel zur Strasse gehört, wirds dann auch
ungefährlich. Sonst geht das Überqueren mal gut und und mal nicht... ;-)
Autor: Rick Dangerus (Gast)
Datum:

@Lothar Miller:
Jetzt musst Du nur noch die C-like Klammern in den if-Abfragen
einsparen. Da wäre es perfekt :-)

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

Danke für die Blumen,
aber wenn ich tippe geht nach if( automatisch die Klammer auf.
Egal ob C oder VHDL, ich kann da gar nicht anders... ;-)
Autor: FPGA-Designer (Gast)
Datum:

Die Klammern machen schon Sinn, wenn man zwsichen C<->VHDL wechselt.

"Die 2. Lösung ist einfach schöner lesbar, weil kompakter..."

Ich nicht! Ich finde die erste mit dem explizieten chip select die
bessere.
Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

>Ich finde die erste mit dem explizieten chip select die bessere.
Wenn ich aus einem ganzen Adressraum mehrere Adressbereiche selektieren
will, dann erzeuge ich mir auch einzelne Chip-Selects für jeden Bereich.
Nur bestehen die dann nicht wie hier
PORT_CS <= '1' when cpu_IORQ = '0' and cpu_WR = '0' and cpu_A(15 downto 8) = "01110011" else '0';
aus einer ganzen Latte Kombinatorik, sondern eben nur aus den
Adressleitungen. So etwa:
PORT_CS <= '1' when (cpu_A(15 downto 8) = "01110011") else '0';
:
:
    elsif (cpu_IORQ='0' and cpu_WR='0' and PORT_CS) then
:
Und am eigentlichen Verwendungsort werden dann RD bzw WR dazu
kombiniert.
Autor: Hagen Re (hagen)
Datum:

und wo ist da der Unterschied ? Der Synthese juckt das nicht.

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




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 erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net