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


von Dirk (Gast)


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
1
ibrary IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
---- Uncomment the following library declaration if instantiating
7
---- any Xilinx primitives in this code.
8
--library UNISIM;
9
--use UNISIM.VComponents.all;
10
11
entity adressdecoder is
12
port (     CLK       : in    std_logic; 
13
          ADRESSE   : out    std_logic_vector(10 downto 0);
14
          RAMSEL     : out    std_logic_vector(3 downto 0);
15
          FULL      : out    std_logic; 
16
          rst        : in    std_logic; 
17
          EN        : in    std_logic 
18
      );
19
end adressdecoder;
20
21
architecture Behavioral of adressdecoder is
22
23
signal adress_cnt: std_logic_vector (10 downto 0);       -- Adresszaehler
24
signal ram_cnt: std_logic_vector (3 downto 0);           -- Ramzaehler    
25
26
begin
27
28
process(CLK,adress_cnt, ram_cnt) 
29
begin
30
ADRESSE <= adress_cnt;  
31
RAMSEL <= ram_cnt;  
32
if rising_edge(CLK) then                                -- rising edge 
33
    if rst = '1' then                                    -- sync. rst
34
      adress_cnt <= "00000000000";                        -- init the counters
35
      ram_cnt <= "0000";                                -- clear carry
36
      FULL <= '0';                                      -- clear full flag
37
    else                                                -- no rst 
38
      if EN = '1' then                                  -- enable
39
        case adress_cnt is                              -- check adress_cnt
40
          when "11111111111" =>                          -- overflow  
41
            adress_cnt <= "00000000000";                -- rst adress_cnt
42
              if ram_cnt = "1011" then                  -- when oveflow
43
                ram_cnt <= "0000";                      -- rst ram_cnt
44
                FULL <= '1';                            -- set full flag  
45
              else                                       -- no overflow increase ram_cnt
46
                ram_cnt <= ram_cnt + 1;                 -- increase carry  
47
                FULL <= '0';                            -- clear full flag    
48
            end if;
49
          when others =>                                
50
            adress_cnt <= adress_cnt + 1;                -- no overflow increase
51
adress_cnt
52
        end case;
53
      end if;
54
    end if;
55
  end if;
56
end process;
57
end Behavioral;

96Bit to 8Bit Mux
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
---- Uncomment the following library declaration if instantiating
7
---- any Xilinx primitives in this code.
8
--library UNISIM;
9
--use UNISIM.VComponents.all;
10
11
entity data_decoder is
12
port (    clk        : in    std_logic;
13
          RAMSEL    : in    std_logic_vector(3 downto 0);
14
          RAMENABLE  : out     std_logic_vector(11 downto 0);
15
          rst        : in    std_logic;
16
          DIN        : in    std_logic_vector(95 downto 0);
17
          DOUT      : out   std_logic_vector(7 downto 0)
18
      );
19
end data_decoder;
20
21
architecture RTL of data_decoder is
22
signal ramenable_int : std_logic_vector(11 downto 0);
23
begin
24
RAMENABLE <= ramenable_int;
25
process(clk,DIN,RAMSEL)
26
begin
27
  if rising_edge(CLK) then                                -- rising edge 
28
    if rst = '1' then                                    -- sync. rst
29
      ramenable_int <= "000000000000";                      -- select ram 0
30
    else                  
31
      case RAMSEL is
32
        when "0000" => ramenable_int <= "000000000000";  DOUT <= DIN(7
33
downto 0);
34
        when "0001" => ramenable_int <= "000000000001";  DOUT <= DIN(15
35
downto 8);
36
        when "0010" => ramenable_int <= "000000000010";  DOUT <= DIN(23
37
downto 16);
38
        when "0011" => ramenable_int <= "000000000100";  DOUT <= DIN(31
39
downto 24);
40
        when "0100" => ramenable_int <= "000000001000"; DOUT <= DIN(39
41
downto 32);
42
        when "0101" => ramenable_int <= "000000010000"; DOUT <= DIN(47
43
downto 40);
44
        when "0110" => ramenable_int <= "000000100000"; DOUT <= DIN(55
45
downto 48);
46
        when "0111" => ramenable_int <= "000001000000"; DOUT <= DIN(63
47
downto 56);
48
        when "1000" => ramenable_int <= "000010000000"; DOUT <= DIN(71
49
downto 64);
50
        when "1001" => ramenable_int <= "000100000000"; DOUT <= DIN(79
51
downto 72);
52
        when "1010" => ramenable_int <= "001000000000"; DOUT <= DIN(87
53
downto 80);
54
        when "1011" => ramenable_int <= "010000000000"; DOUT <= DIN(95
55
downto 88);
56
        when others => ramenable_int <= "000000000000"; DOUT <= DIN(7
57
downto 0);
58
      end case;
59
    end if;
60
  end if;
61
end process;
62
end RTL;



Dirk

von Dirk (Gast)


Lesenswert?

Zieldevice : XC3S400 Speegrade -4

von Dirk (Gast)


Lesenswert?

Hallo,

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

Gruß,

Dirk

von schlumpf (Gast)


Lesenswert?

was meckert denn dein Synthesetool als kritischen Pfad an?

von Dirk (Gast)


Lesenswert?

Hi,

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

Gruß,
Dirk

von schlumpf (Gast)


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

von Daniel R. (daniel_r)


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

von schlumpf (Gast)


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 ;-)

von schlumpf (Gast)


Lesenswert?

sorry, ich meinte natürlich Daniel

von Axel (Gast)


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

von Dirk (Gast)


Lesenswert?

Hi,

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


gruß,
Dirk

von Dirk (Gast)


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

von Daniel R. (daniel_r)


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).

von Axel (Gast)


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

von schlumpf (Gast)


Lesenswert?

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

von Axel (Gast)


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.

von schlumpf (Gast)


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.

von T.M. (Gast)


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
=============================

von Axel (Gast)


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

von Dirk (Gast)


Lesenswert?

Hi,

ein kleiner Zaehler kann schon sehr kompliziert werden :) .

Ich bedanke mich nochmal recht herzlich.

Gruß,
Dirk

von Dirk (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

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

Gruß,
Dirk

von Jörn (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Dirk,

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

Gruß Jörn

von Dirk (Gast)


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
1
if ram_cnt = "1011" then -- when oveflow
2
 ram_cnt <= "0000"; -- rst ram_cnt
3
 FULL <= '1'; -- set full flag
4
else -- no overflow
5
 ram_cnt <= ram_cnt + 1; -- increase carry
6
 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

von Dirk (Gast)


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

von Axel (Gast)


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

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.