Zaehler so langsam?

Gast #389893
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
Gast #389898
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
Gast #389902
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
Gast #389904
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
Gast #389906
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
Gast #389908
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.
Gast #389909
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.
Gast #389910
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
=============================
Gast #389911
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
Gast #389915
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
Gast #389917
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren