mikrocontroller.net

Forum: FPGA, VHDL & Co. Zaehler so langsam?


Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Abend,

ich hab ein 10Bit Zähler mit Übertrag. Ich komme mit diesem Design
gerade mal auf 129MHz maximum Frequenz. Ich hab vermutet das der 96Bit
: 8 Bit Mux das Problem ist. Aus diesem Grund hab ich den Mux in ein
extra Modul gepackt und synthesiert. Der Mux laueft mit einer maximal
Frequenz von 420MHz.

Könnte jemand sich mal den Code anschaun und Optimierungsvorschläge
äussern?

10Bit Zahler + 4Bit Carry + reload
ibrary IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity adressdecoder is
port (     CLK       : in    std_logic; 
          ADRESSE   : out    std_logic_vector(10 downto 0);
          RAMSEL     : out    std_logic_vector(3 downto 0);
          FULL      : out    std_logic; 
          rst        : in    std_logic; 
          EN        : in    std_logic 
      );
end adressdecoder;

architecture Behavioral of adressdecoder is

signal adress_cnt: std_logic_vector (10 downto 0);       -- Adresszaehler
signal ram_cnt: std_logic_vector (3 downto 0);           -- Ramzaehler    

begin

process(CLK,adress_cnt, ram_cnt) 
begin
ADRESSE <= adress_cnt;  
RAMSEL <= ram_cnt;  
if rising_edge(CLK) then                                -- rising edge 
    if rst = '1' then                                    -- sync. rst
      adress_cnt <= "00000000000";                        -- init the counters
      ram_cnt <= "0000";                                -- clear carry
      FULL <= '0';                                      -- clear full flag
    else                                                -- no rst 
      if EN = '1' then                                  -- enable
        case adress_cnt is                              -- check adress_cnt
          when "11111111111" =>                          -- overflow  
            adress_cnt <= "00000000000";                -- rst adress_cnt
              if ram_cnt = "1011" then                  -- when oveflow
                ram_cnt <= "0000";                      -- rst ram_cnt
                FULL <= '1';                            -- set full flag  
              else                                       -- no overflow increase ram_cnt
                ram_cnt <= ram_cnt + 1;                 -- increase carry  
                FULL <= '0';                            -- clear full flag    
            end if;
          when others =>                                
            adress_cnt <= adress_cnt + 1;                -- no overflow increase
adress_cnt
        end case;
      end if;
    end if;
  end if;
end process;
end Behavioral;

96Bit to 8Bit Mux
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity data_decoder is
port (    clk        : in    std_logic;
          RAMSEL    : in    std_logic_vector(3 downto 0);
          RAMENABLE  : out     std_logic_vector(11 downto 0);
          rst        : in    std_logic;
          DIN        : in    std_logic_vector(95 downto 0);
          DOUT      : out   std_logic_vector(7 downto 0)
      );
end data_decoder;

architecture RTL of data_decoder is
signal ramenable_int : std_logic_vector(11 downto 0);
begin
RAMENABLE <= ramenable_int;
process(clk,DIN,RAMSEL)
begin
  if rising_edge(CLK) then                                -- rising edge 
    if rst = '1' then                                    -- sync. rst
      ramenable_int <= "000000000000";                      -- select ram 0
    else                  
      case RAMSEL is
        when "0000" => ramenable_int <= "000000000000";  DOUT <= DIN(7
downto 0);
        when "0001" => ramenable_int <= "000000000001";  DOUT <= DIN(15
downto 8);
        when "0010" => ramenable_int <= "000000000010";  DOUT <= DIN(23
downto 16);
        when "0011" => ramenable_int <= "000000000100";  DOUT <= DIN(31
downto 24);
        when "0100" => ramenable_int <= "000000001000"; DOUT <= DIN(39
downto 32);
        when "0101" => ramenable_int <= "000000010000"; DOUT <= DIN(47
downto 40);
        when "0110" => ramenable_int <= "000000100000"; DOUT <= DIN(55
downto 48);
        when "0111" => ramenable_int <= "000001000000"; DOUT <= DIN(63
downto 56);
        when "1000" => ramenable_int <= "000010000000"; DOUT <= DIN(71
downto 64);
        when "1001" => ramenable_int <= "000100000000"; DOUT <= DIN(79
downto 72);
        when "1010" => ramenable_int <= "001000000000"; DOUT <= DIN(87
downto 80);
        when "1011" => ramenable_int <= "010000000000"; DOUT <= DIN(95
downto 88);
        when others => ramenable_int <= "000000000000"; DOUT <= DIN(7
downto 0);
      end case;
    end if;
  end if;
end process;
end RTL;



Dirk

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zieldevice : XC3S400 Speegrade -4

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

natuerlich ist es kein 10Bit Zaehler, sondern ein 11Bit Zaehler. Hat
niemand eine Idee wieso mein Zaehler so langsam ist?

Gruß,

Dirk

Autor: schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was meckert denn dein Synthesetool als kritischen Pfad an?

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

@Schlumpf kann ich leider erst heute abend prüfen. Sitze hier bei
meinem Broetchengeber :/ .

Gruß,
Dirk

Autor: schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, dann würd ich bis heut abend warten. ;-)
Eventuell könnte es was bringe, wenn der Reset asynchron ausgfeführt
wird, denn dann wird eine Kombinatorik für den Reset der FF generiert,
die separat zur Kombinatorik des eigentlichen Zählers ist.
Beim synchronen Reset, wird, so denk ich mal, die Kombinatorik des
Zählers einfach etwas komplexer, da eben auch genau dieser Fall in der
Wolek mit abgedekt werden muss.
Könnte also was bringen, aber nagel mich da bitte nicht fest

Autor: Daniel R. (daniel_r)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meistens ist ein synchroner Reset schneller(meine Erfahrung).
Lass mal die Case-Anweisung weg. Das geht auch mit if - else.
Vielleicht bringt das was.

Daniel

Autor: schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bin gespannt wegen dem Reset... rein vom theoretischen Verständnis hätt
ich es gerade andersrum gesehen als du, Dirk. Aber weiss man, was das
synthesetool macht ;-)

Autor: schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sorry, ich meinte natürlich Daniel

Autor: Axel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nimm den "adress_cnt <= "00000000000";" da raus und lass das den
Zähler mit erledigen. Macht der ja sowieso und ist hier doppelt.

Der kritische Pfad dürfte auf dem Zaehler liegen, also alles raus, was
den evtl. langsamer macht.

Also so:

if EN = '1' then -- enable
  adress_cnt <= adress_cnt + 1; -- check adress_cnt
  if adress_cnt = "11111111111" then -- overflow
        if ram_cnt = "1011" then -- when oveflow
            ram_cnt <= "0000"; -- rst ram_cnt
            FULL <= '1'; -- set full flag
        else -- no overflow
            ram_cnt <= ram_cnt + 1; -- increase carry
            FULL <= '0'; -- clear full flag
        end if;
   end if;
end if;

und Reset asynchron.

Oder so ähnlich.

Gruss
Axel

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

danke Axel werde ich mal testen. Mir scheint es auch so als wenn der
Reloadwert das problem ist.


gruß,
Dirk

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich wollte ein Bericht abgeben. Der Zaehler von Axel ist mit synchron
Reset 134MHz (meiner ist fast genauso schnell) und mit asynchronen
Reset ist der Zaehler maximal 184MHz.

Jetzt ist die Frage: Sollte man asycnhron Reset und sychron Reset in
dem ganzen Design mischen oder sich fuer eins entscheiden?

Ich würde ich nun fuer ein kompletten asynchronen Reset entscheiden.

Gruß,
Dirk

Autor: Daniel R. (daniel_r)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Echt? OK, mag sein...

Mr. Chapman von Xilinx persönlich rät dringenst zu einem synchronen
Reset. Er hat den PicoBlaze entwickelt(nur so am Rande).

Autor: Axel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm, 5 Mhz schneller. Naja, hätte mehr erwartet :-(

Asynchroner Reset ist unschön. Du musst dann sehr darauf achten, dass
das Freigeben des RESET Synchron läuft und alle FF den tatsächlich
released bekommen, bevor der erste Takt kommt.

Ich weiss jetzt nicht genau, wie das beim FPGA ist, aber so eine
Leitung, die quer über den Baustein an alle FF geht und max. eine
Periode Zeit hat, ist natürlich ein bischen kritisch.

Gruss
Axel

Autor: schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Axel:
Wieso 5 MHz? 184-134 = 50 !
Und das finde ich schon ganz beachtlich! sind immer hin ca 37%
schneller!

Autor: Axel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schlumpf:

Im nachhinein ist das schon nachvollziehbar. In der ursprünglichen
Lösung gab es zwei Quellen für den synchronen Reset des Zähler, RST und
"adr_cnt = "11111111111".

Ich hatte den adr_cnt = "111111111" wegoptimiert, was nur ein bischen
gebracht hat, weil der Zähler immer noch einen synchronen Reset
brauchte. Erst das Wegoptimieren des synchronen Resets bringt wirklich
den Speed, weil jetzt ein reiner Zähler übrigbleibt und die Verzögerung
durch das "Clr" im Datenpfad wegfällt.

Gruss
Axel
PS: Was ich da zum asynchronen/synchronen Reste geschrieben hatte, ist
natürlich Quatsch. Aber ich würde mich dann doch für eins entscheiden.

Autor: schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Axel:

Muss ja auch so sein.
letztendlich werden die Eingänge der FFs des Zählers kombinatiorisch
aus den Ausgängen und den Eingängen in das System gebildet und mit
jedem Takt übernommen.
Beim synchronen Reset wird das Reset-Signal in diese Kombinatorik
reingewurschtelt udn somit wird die Logik größer.
Beim asynchronen Reset geht die Reset-Leitung an dieser Logik vorbei
auf den dedicated Reset-Anschluss des FF.
Also ich verwende IMMER asynchrose Resets und hatte noch nie schlechte
Erfahrungen gemacht.

Autor: T.M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, wenn man asynchrone Resets verwendet, dann brauch man sich auch
keine Gedanken um das "einclocken" von asynchronen Eingangssignalen
machen. Es kann aber dann doch zu nicht vorraussagbaren Zuständen
kommen, meinetwegen der Reset tritt gleichzeitig zur Taktflanke auf.
Oder die Setup- und Holdzeiten reichen nicht aus... Deshalb macht man
ja eigentlich alles synchron. Naja, jeder wie er will.


T.M.


=============================
http://editthis.info/freefpga
=============================

Autor: Axel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch ein "asynchroner" Reset muss natürlich synchron weggenommen
werden,
damit so ein Fall nicht auftaucht.

Ich beziehe die Aussage "asynchron" eher darauf, dass man den am
asynchronen "CLR" Eingang des FF anklemmt, was dann die Datenpfade
nicht verlangsamt.

Gruss
Axel

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ein kleiner Zaehler kann schon sehr kompliziert werden :) .

Ich bedanke mich nochmal recht herzlich.

Gruß,
Dirk

Autor: Dirk (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

hier die letzte Version. Laut ISE8.2i soll der Zähler mit einer maximal
Frequenz von 183.722MHz laufen.

Gruß,
Dirk

Autor: Jörn (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Dirk,

probier mal die angehängt Version. Vielleicht bringen die Änderungen
noch ein bisschen was.

Gruß Jörn

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

Danke Joern ich hab es nun durch eine komplette Abaenderung meines
Designs hinbekommen.

Es lag nicht am sychronen / asychronen Reset, sondern an der 'else'
Verzweigung
if ram_cnt = "1011" then -- when oveflow
 ram_cnt <= "0000"; -- rst ram_cnt
 FULL <= '1'; -- set full flag
else -- no overflow
 ram_cnt <= ram_cnt + 1; -- increase carry
 FULL <= '0'; -- clear full flag

Die Elseanweisung kostet 70 MHz und wenn der Zaehler auf ein
Überlaufwert verglichen wird und reloaded kostet das nochmal 30MHz.

Ich hab es nun alles ein bischen besser gelöst. Statt zwei Counter hab
ich nur noch ein 12 Bit Counter mit Überlaufflag. Das letzte Bit wird
zur Bank Selection der Block Rams genutzt, also Bit12 = '1' ober Bank
mit 8 Block Rams sind aktiv und mit '0' ist die untere Bank aktiv.

So komme auf eine maximale Geschwindigkeit von 207MHz.

Gruß,

Dirk

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PS: Falls jemand den Wunsch aeussert uploade ich die Top RTL mit Block
RAMs,  Adresszaehler mit Überlauf und  Ram Bank Selector (einfacer
Inverter) und 192Bit to 8 Bit demultiplexer.

Gruß,
Dirk

Autor: Axel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
DAS haut mich jetzt vom Hocker.

Anscheinend hat die Synthese sich da vollkommen einen Wolf
synthetisiert.

Denn eigentlich ist die "Else" Verzweigung vollkommen unabhängig vom
11 Bit Zähler.

Kann aber sein, dass die Synthese das nicht mitbekommt und das
irgendwie versucht zu verwurschteln.

Gruss
Axel

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.