FPGA: policzyć czy odliczać?


11

Uczę się korzystać z FPGA (planszy Papilio, która ma xilinx spartan3e, używając vhdl).

Muszę podzielić przychodzący puls przez (zakodowany na stałe) numer.

Widzę 3 opcje - z grubsza jako pseudokod (na przykładzie 10 zliczeń):

  1. Zainicjuj na 0, przy wzroście zbocza narastającego o 1, w porównaniu do 10; jeśli są równe, zresetować do 0 i wyzwolić impuls wyjściowy
  2. Zainicjuj do 10, przy spadku narastającego zbocza wejściowego o 1, w porównaniu do 0; jeśli są równe, zresetuj do 10 i uruchom impuls wyjściowy
  3. Zainicjuj na 9, ale upewnij się, że jest co najmniej 1 wiodący bit „0”, który jest moim bitem wyjściowym. Przy narastającym zboczu narastającym zmniejsz o 1. Po zboczu narastającym bitu wyjściowego zresetuj.

Cykl pracy jest nieistotny.

Czy jeden z nich jest lepszy od innych? Czy istnieje jeszcze lepsza metoda, o której nie myślałem?

Czy istnieje „standardowy” sposób, który da kompilatorowi najlepszą szansę na optymalizację?


3
To tylko trzy opcje :-) ... Ale tak na serio, to naprawdę nie ma aż tak wielkiego znaczenia w FPGA. Poszczególne elementy logiczne są na tyle ogólne, że zajmują tyle samo zasobów i dają taką samą wydajność niezależnie od sposobu, w jaki to robisz. Decyzja sprowadza się do tego, czy przydatne jest, aby gdzie indziej w projekcie liczby były liczone w górę, czy w dół, czy w inny sposób.
Dave Tweed,

2
Czwarta opcja: 10-bitowy okrągły rejestr przesuwny załadowany „1000000000” i przesunięty na zboczu narastającym. Użyj jednego bitu rejestru przesuwnego jako zezwolenia na to, co robisz.
Lincoln

1
Na marginesie - narzędzie GUI kompilatora / instalatora, po zakończeniu pracy, powinno mieć opcję pokazującą rzeczywisty obwód, który utworzył na różnych poziomach abstrakcji, aż do bramek, abyś mógł zobaczyć, jak to narzędzie dopasowało twój obwód i następnie możesz wprowadzić odpowiednie zmiany w źródle.
Anonimowy

Odpowiedzi:


12

Optymalizacja do tego poziomu złamie ci serce. Wynik może się zmienić ze względu na zastosowaną technologię FPGA, inne czynniki w FPGA, ale również z powodu czynników niezależnych od ciebie, w tym losowej liczby instalatora.

Mimo to uważam, że wariant 3 będzie najlepszy. Opcje 1 i 2 mają bramkę porównawczą / OR przechodzącą między licznikami, aby mogła zasygnalizować, że liczba docelowa została osiągnięta. Opcja 2 może być nieco szybsza niż 1, ponieważ wszystko może być proste LUB połączone razem bez żadnych falowników, ale ponownie napotykasz małe różnice technologiczne, w których może być szybsze do AND lub XOR.

Opcja 3 pomija porównanie z niskim kosztem jednego dodatkowego bitu w kasie. To powinno być tego warte, chyba że masz poważne ograniczenia w klapkach.

Ciekawym faktem na temat liczników jest to, że mają one tendencję do grupowania w rozmiarach specyficznych dla urządzenia w bloku logicznym, a zobaczysz zmianę taktowania bardziej niż oczekiwano, jeśli ten dodatkowy bit wypchnie cię z tej grupy.


+1, zakazując taktowania zegara, które przesuwają ograniczenia technologii, należy pozwolić raportowi taktowania pokierować ich optymalizacjami. Ściganie setek pikosekund na Spartan 3e lub dowolnej innej FPGA bez przyczyny to generalnie strata czasu.
jalalipop

4

Jedna inna opcja byłoby zainicjować licznik do 6 (= 2 4 - 10), liczy się, a następnie zresetować kiedy uaktywnia wyjście carry (tj FFS są wszystkie te).

Zaletą tego jest to, że nie wymaga dodatkowego FF, a wiele FGPA ma dedykowaną logikę pomocniczą, aby przyspieszyć ten rodzaj operacji przenoszenia w obwodzie licznika lub sumatora.


3

Zależy. Na przykład: opóźnienie propagacji przerzutu dla 0 → 1 i 1 → 0 może być różne, a zatem opóźnienia przejścia licznika dla 000 → 001 i 001 → 000 mogą być nieco inne. Może być wyższa lub niższa, w zależności od technologii cmos stosowanej w FPGA. Musisz więc zsyntetyzować i dowiedzieć się, który z nich ma lepszą wydajność synchronizacji.


3

Z perspektywy autora kompilatora: jeśli go użyjesz integer, wewnętrzna reprezentacja jest niezdefiniowana, a kompilator może wybrać najbardziej efektywną implementację.

Jeśli wymusisz określoną reprezentację wewnętrzną, optymalizator będzie nadal próbował ją ulepszyć, ale zacznie od nieco gorszego punktu widzenia.

Niektóre układy FPGA mają funkcje „wstępnego ładowania”, w których rejestry mogą być inicjowane do dowolnych wartości, w takim przypadku inicjowanie N.-1, odliczanie i użycie najwyższego bitu przenoszenia jako wyjścia i resetu (w następnym cyklu) jest bardziej wydajne niż implementacja zarówno sumatora, jak i komparatora. Bez wstępnego ładowania sumator może być lepszy.

O ile nie znasz wewnętrznej struktury, zasoby przydzielone na inną logikę (wiele układów FPGA ma dedykowaną zmiennoprzecinkową logikę wielokrotnego dodawania, której możesz również użyć do implementacji licznika, jeśli masz resztki jednostek) i masz całkowitą pewność, że nie zmienisz w innym modelu odpowiedź brzmi „nie myśl o tym”.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.