Układy FPGA można scharakteryzować na podstawie ich budowy, wydzielając cztery główne elementy:
- sposób realizacji logiki,
- dostępne bloki pamięci,
- sprzętowe bloki DSP,
- tzw. Hardware IP realizujące specyficzne funkcje (transcivery, kontrolery pamięci, interfejsy PCIe, Ethernet PHY, itd.).
Zaprezentujemy w jaki sposób różni producenci odnoszą się do tych czterech punktów. Zamieszczone fragmenty dokumentacji pokażą, w jaki sposób realizowane są te podstawowe bloki.
Na podstawie pokazanych przykładów Czytelnik zrozumie jak można porównywać układy FPGA.
Zaprezentujemy sześciu różnych producentów, wśród których można wyznaczyć dwóch wiodących – Intel i Xlinix, dwóch ścigających czołówkę – Lattice i Microchip oraz dwóch nowych - Anlogic i Gowin. Na zakończenie zaprezentujemy listę dostępnych zestawów startowych, które pozwolą na szybkie rozpoczęcie pracy z opisanymi układami.
Intel (kiedyś Altera)
Układy FPGA firmy Intel (dawniej Altera) są podzielone na pięć grup różniących się między sobą budową wewnętrzną. Ich porównanie znajduje się w tabeli 1.
MAX 10
Podstawowym elementem układów MAX 10 jest Logic Element (LE). Budowa tego bloku została pokazana na rysunku 1, składa się z 4-wejściowej tablicy LUT i pojedynczego rejestru [1]. Szesnaście LE tworzy pojedynczy blok LAB (Logic Array Blocks).
Przerzutniki z bloku LAB mogą służyć jako niewielkie pamięci RAM. Jednak gdy potrzebna jest większa ilość pamięci, to używane są specjalne bloki M9K o pojemności 9 kb. W układzie znajdują się, także bloki DSP pozwalające na zrealizowanie pojedynczego mnożenia dwóch liczb stałoprzecinkowych o długości 18×18 bitów. Można go też skonfigurować jako dwa niezależne bloki mnożenia liczb 9×9 bitów. Jego uproszczony schemat został pokazany na rysunku 2.
Układy tej rodziny, są także wyposażone w nieulotną pamięć Flash, która może być użyta do przechowywania zarówno konfiguracji układu jak i danych użytkownika. Niektóre modele układów mają także kontroler pamięci DDR3, przetwornik analogowo-cyfrowy oraz interfejs LVDS.
Cyclone
Cyclone IV
Podstawowe elementy składowe takie jak LE, pamięć czy bloki DSP są podobne jak dla rodziny MAX 10. W wersjach oznaczonych jako GX dodatkowo dostępne są transceivery o prędkości 3 Gbps oraz wsparcie dla PCIe [2].
Cyclone V
Podstawowym elementem logiki jest blok nazwany Adaptive Logic Module (ALM) [3]. Jego uproszczony schemat został pokazany na rysunku 3. Składa się on z dwóch 6-wejściowych tablic LUT, dwóch jednobitowych bloków dodawania oraz czterech przerzutników. Jego dokładną budowę wewnętrzną i dostępne konfiguracje można znaleźć w [4].
Pamięć RAM jest dostępna w blokach po 10 kb oznaczanych jako M10K. Blok DSP pozwala na wykonanie jednego mnożenia liczb stałoprzecinkowych o długości 27×27 bitów, dwóch mnożeń 18×19, albo trzech 9×9. Na wyjściu znajduje się akumulator o długości 64 bitów. Dzięki dodatkowym blokom dodawania/odejmowania za pomocą dwóch modułów można zrealizować mnożenie dwóch liczb zespolonych. Jego uproszczony schemat został pokazany na rysunku 4.
Układy z rodziny Cyclone V dostępne są w różnych wersjach oznaczonych kombinacją liter [5]:
- E – wersja podstawowa,
- X – wyposażony w transceiver 3,125 Gbps,
- T – wyposażony w transceiver 6,144 Gbps,
- S – wyposażony w rdzeń ARM Cortex-A9.
Cyclone 10 LP
Układy podobne do Cyclone IV, wyposażone w elementy LE, bloki pamięci M9K oraz moduły DSP.
Cyclone 10 GX
Architektura bloków ALM jest podobna do tej z Cyclone V. Pamięć RAM jest dostępna w blokach po 20 kb – M20K. Bloki DSP wspierają zarówno arytmetykę stało jak i zmiennoprzecinkową. Pojedynczy blok może zrealizować jedno mnożenie 27×27 bitów, albo dwa mnożenia 18×19 bitów. Poza mnożeniem dodane jest, także wsparcie dla dodawania, akumulacji oraz zaokrągleń. Pojedynczy blok może wykonać dodawanie i mnożenie na liczbie zmiennoprzecinkowej pojedynczej precyzji. Uproszczony schemat pracy w tym trybie pokazuje rysunek 5.
Główną różnicę, w stosunku do wcześniejszych wersji układów są transceivery o prędkości 12,5 Gbps oraz wsparcie dla PCIe oraz Ethernet 10 Gbps [6].
Arria
Arria V
Blok ALM oraz DSP są takie same jak w układzie Cyclone V [7]. Pamięć RAM, w zależności od wersji, występuje w rozmiarach po 10 kb albo 20 kb. Różne wersję są opisane kodem literowym. Pierwsza litera wersji oznacza:
- G – bez rdzenia ARM,
- S – z rdzeniem ARM Cortex-A9.
Natomiast druga litera:
- X – zawiera transceiver 6,5 Gbps,
- T – zawiera transceiver 10,31 Gbps,
- Z – zawiera transceiver 12,5 Gbps.
Arria 10
Budowa bloku ALM jest analogiczna jak we wcześniejszych wersjach [8]. Pamięć RAM jest dostępna w blokach po 20 kb. Blok DSP posiada podobne funkcję jak w Cyclone10 GX. Dostępne są trzy wersje układów oznaczone literami:
- GX – zawiera transcivery 17,4 Gbps
- GT – zawiera transcivery 25,78 Gbps
- SX – z dwurdzeniowym procesorem ARM Cortex-A9.
Stratix
Stratix V
Budowa wewnętrzna jest podobna do układów z rodziny Arria V. Główną różnica jest większa liczba zasobów oraz dostępność innych peryferiów, takich jak szybsze transceivery [9].
Stratix 10
Budowa bloku ALM jest analogiczna jak we wcześniejszych układach. Nowością są dodatkowe rejestry – hyper-registers, w strukturze połączeniowej między blokami pozwalające na uzyskanie wyższej częstotliwości taktowania [10]. Dostępne są różne wersje:
- GX – zawiera transcivery 28,3 Gbps,
- SX – zawiera transcivery 28,3 Gbps, czterordzeniowy ARM Cortex-A53 (także w niektórych układach T i M),
- TX – zawiera transcivery 56 Gbps,
- MX – zawiera zintegrowaną pamięć DRAM,
- DX – zawiera PCIe gen4 oraz wsparcie dla magistrali UPI,
- NX – zawiera blok akceleracji sztucznej inteligencji (AI tensor block).
Agilex
Zmianie uległa budowa bloku ALM. Jego nowa wersja została pokazana na rysunku 6 [11].
Blok DSP wspiera mnożenie liczb stało i zmiennoprzecinkowych. Pozostałe wyposażenie to między innymi wsparcie dla Ethernet 400 Gb, kontroler pamięci DDR5 oraz interfejs PCIe gen4.
Xilinx (wkrótce AMD)
Kolejnym dużym producentem układów FPGA jest firma Xilinx. Została ona wykupiona przez firmę AMD, proces przejmowania powinien zakończyć się w 2021 roku [12]. Dostępne układy można podzielić na kategorię 6, kategorię 7 oraz UltraScale.
Spartan 6
Podstawową komórką tego układu jest Configurable Logic Block (CLB) [13]. Jak widzimy na rysunku 7 składa się on z dwóch bloków Slice [14], jednak tylko Slice(0) jest podłączony do linii szybkiego przeniesienia (oznaczonej CIN/COUT).
W układzie występują trzy typy bloków: SLICEX, SLICEL, SLICEM.
- Blok SLICEX – zawiera 4 tablice LUT, które mogą pracować jako 6-wejściowa funkcja logiczna, lub 5-wejściowa funkcja logiczna z dwubitowym wyjściem. Do każdej tablicy dołączone są dwa przerzutniki. Ten typ stanowi 50% wszystkich Sliceów występujących w układzie. Jego fragment został pokazany na rysunku 8.
- Blok SLICEL – zawiera dodatkowo dołączone szybkie przeniesienie. Stanowią one 25% układu.
- Blok SLICEM – zawiera wszystkie funkcje bloku SLICEL, a dodatkowo może być skonfigurowany jako 64-bitowa pamięć RAM albo 32-bitowy rejestr przesuwny.
Wielkość układu w dokumentacji jest charakteryzowana za pomocą wartości logic cells, która jest liczbą dostępnych tablic LUT pomnożonych przez 1,6 (aby porównywać z 4-wejściowymi tablicami ze starszych wersji). Blokowa pamięć RAM dostępna jest w formie 2-portowych modułów o pojemności 18 kb. Układy Spartan 6 są także wyposażone w blok DSP48A1 [15]. Jego wewnętrzną budowę prezentuje rysunek 9. Pozwala on na mnożenie dwóch liczb stałoprzecinkowych o długości 18 bitów. Na wyjściu znajduje się 48-bitowy akumulator.
Pozostałe peryferia obejmują między innymi kontrolery pamięci DDR, DDR2, DDR3, LPDDR. Układy oznaczone jako LXT są ponadto wyposażone w transceiver o prędkości 3,2 Gbps oraz wsparcie dla PCie 1.1.
Jest to ostatnia rodzina układów firmy Xilinx, która bazuje na środowisku programistycznym ISE Design Suite. Pozostałe korzystają z nowszego środowiska Vivado.
FPGA serii 7
Podobnie jak w układach Spartan 6 logika dzieli się na CLB składające się z dwóch bloków Slice. Główną różnicą jest wycofanie najmniejszych SLICEX. Dodano także więcej zasobów połączeniowych pomiędzy CLB, co zostało pokazane na rysunku 10.
Tak jak w przypadku układów Sartan 6 podawana ilość logic cells odpowiada liczbie tablic LUT pomnożonej przez 1,6 [17]. Blokowa pamięć RAM jest dostępna jako moduły o pojemności 36 kb z wbudowaną logiką pozwalające na używanie ich jako kolejek FIFO.
W układach serii 7 zastosowany jest nowszy blok DSP oznaczony jako DSP48E1. Pozwala on na mnożenie liczby 18-bitowej przez liczbę 25-bitową. Za mnożarką znajduje się 48-bitowy akumulator, a przed nią dodatkowy blok pozwalający wykonać dodawanie (rysunek 11).
Układy z tej rodziny są także wyposażone w kontrolery pamięci DDR3, przetworniki analogowo-cyfrowe, transceivery czy wsparcie dla protokołów komunikacyjnych.
Podzielone są na cztery rodziny. W kolejności od układów najsłabszych do najmocniejszych są to:
- Spartan-7,
- Artix-7,
- Kintex-7,
- Virtex-7.
Różnią się między sobą głównie liczbą dostępnych zasobów oraz dostępnością szybkich interfejsów. Porównanie parametrów znajduje się w tabeli 2.
Dostępna jest także seria układów Zynq-7000 SoC, w których strukturze zintegrowany są: procesor ARM Cortex-A9 (jeden albo dwa rdzenie) oraz logika programowalna Artix-7 lub Kintex-7. Komunikują się one za pomocą interfejsu AMBA [19].
UltraScale/UltraScale+
W układach UltraScale podobnie jak dla rodziny 7 logika jest podzielona na bloki CLB [20]. Tym razem każdy z nich składa się z tylko jednego bloku Slice zawierającego 8 tablic LUT.
Oznacza to, że zasoby przypadające na blog CLB są porównywalne, jak dla ukłądów poprzednich rodzin, ale liczba slice-ów będzie o połowę mniejsza [21]. Pamięć RAM także jest dostępna w blokach po 36 kb, jednak możliwości ich konfiguracji są bardziej rozbudowane. Został wprowadzony także nowy typ nazwany UltraRAM. Jest to pamięć dwuportowa, ale taktowana tylko jednym zegarem. Rozmiar pojedynczego bloku wynosi 288 kb [22]. Niektóre układy z rodziny Virtex UltraScale+ mają wbudowaną pamięć HBM DRAM (High Bandwidth Memory DRAM) o rozmiarze od 4 do 16 GB. Wprowadzony został także nowy typ bloku DSP – DSP48E2 (rysunek 12).
Jego głównym elementem jest mnożarka 27×18 bitów [23].
Układy z tej serii występują w sześciu odmianach:
- Kintex UltraScale FPGA,
- Kintex UltraScale+ FPGA,
- Virtex UltraScale FPGA,
- Virtex UltraScale+ FPGA,
- Zynq UltraScale+ MPSoC,
- Zynq UltraScale+ RFSoC.
Różnią się one liczbą dostępnych zasobów oraz występowaniem wyspecjalizowanych peryferiów. Znajdziemy tu między innymi wsparcie dla PCIe generacji 3 i 4, Ethernet 100 Gb/s, czy przetworniki ADC i DAC pracujące na częstotliwościach radiowych. Rodzina Zynq zawiera zintegrowane rdzenie ARM Cortex-A53 oraz Cortex-R5F. Niektóre z nich są także wyposażone w kartę graficzną z rodziny Mali. Porównanie parametrów zostało pokazane w tabeli 3.
Lattice
iCE40
W układach tego typu podstawową jednostką logiki jest Programmable Logic Blocks (PLB). Jego budowa została pokazana na rysunku 13.
Składa się on z ośmiu bloków Logic Cells (LC) oraz logiki przeniesienia. Poszczególne LC składają się z 4-wejściowej tablicy LUT oraz przerzutnika [24]. Blokowa pamięć RAM dostępna jest w dwóch typach bloków: Embedded Block RAM (EBR) o rozmiarze 4 kb i Single Port RAM (SPRAM) o rozmiarze 256 kb [25]. Dostępny jest też blok DSP nazwany sysDSP. Składa się on z mnożarki 16×16 bitów (mogącej pracować jako dwie niezależne mnożarki 8×8) i 32 bitowego akumulatora [26]. Jego budowa została pokazana na rysunku 14.
ECP2
Logika programowalna w tych układach podzielona jest na bloki Programmable Function Units (PFU). Jak widać na rysunku 15, każdy z nich dzieli się na 4 Slice-y.
Każdy z nich zawiera po dwie 4-wejściowe LUT, jednak tylko trzy pierwsze wyposażone są w przerzutniki (po 2 sztuki) i logikę przeniesienia. Pamięć występuje w blokach EBR o rozmiarze 18 kb. Pojedynczy blok DSP (sysDSP) wspiera mnożenia do 36×36 bitów. Może być także skonfigurowany do wykonania czterech mnożeń 9×9 albo dwóch 16×16. Dla rozmiarów 8 i 16 może zostać skonfigurowany akumulator pozwalający wykonywać operacje MAC. Prace w tym trybie prezentuje rysunek 16.
Układy tej rodziny mogą być wyposażone w blok wspierający obsługę zewnętrznej pamięci DDR. Układy serii M mają także moduł SERDES zapewniający prędkość transmisji do 3,125 Gbps. Może służyć do obsługi interfejsu PCIe [27].
XP2
Dostępne bloki logiki PFU oraz DSP (sysDSP) są podobne do tych dostępnych w układach ECP2. Także bloki pamięci EBR są analogiczne, jednak tym razem każdemu z nich odpowiada blok nieulotnej pamięci Flash (FlashBAK). Układy tej rodziny posiadają wbudowaną nieulotną pamięć Flash mogącą przechowywać konfigurację [28].
ECP3
Budowa bloków PFU oraz EBR jest analogiczna jak w układach z rodziny ESP2. Zmianie uległa architektura bloków DSP (rysunek 17). W tej rodzinie nosi on nazwę sysDSP Slice.
Pojedynczy blok może wspierać pojedyncze mnożenie 18×36, dwa mnożenia 18×18 albo cztery 9×9. Połączenie dwóch modułów pozwala na realizację mnożenia 36×36. Operacja MAC może być realizowana z mnożeniem 18×36 i długością akumulatora równą 54 bitów [29].
ECP5/ECP5-5G
W układach tej rodziny zmianie uległa budowa bloku PFU i wygląda jak na rysunku 18. Tym razem wszystkie 4 Slice są wyposażone w przerzutniki oraz logikę przeniesienia. Budowa bloków pamięci EBR jest analogiczna w układach rodziny ECP3. Także podstawowe funkcjonalności bloku sysDSP Slice są podobne. Jednak zostały rozszerzone możliwości konfiguracji.
Z pozostałych peryferiów znajdziemy blok wspierający obsługę pamięci (LP)DDR 2 i 3, XGMII oraz PCIe. Dostępne są także transcivery o prędkości 3,2 Gbps, a w wersji 5 G–5 Gbps [30].
Certus-NX
Architektura bloku PFU jest podobna do tej z układów ECP5. W dokumentacji można znaleźć liczbę logic cells, która jest oznaczana jako liczba tablic LUT (4-wejściowych) mnożona razy współczynnik efektywności równy 1,2. Pamięć RAM dostępna jest w dwóch typach bloków: znanym nam już EBR oraz nowym Large RAM (LRAM) o rozmiarze 0,5 Mbita. Zmianie uległa architektura bloku DSP, jest to Certus-NX sysDSP Slice. Pozwala on na wykonanie mnożenia o maksymalnej długości 36×36 bitów (rysunek 19).
Natomiast przy porównaniu układów zamiast liczby bloków DSP podana jest liczba mnożarek 18×18. Jako że jeden blok DSP można skonfigurować jako cztery takie mnożarki, to aby poznać liczbę bloków, podaną wartość należy podzielić przez 4. Niektóre układy z tej rodziny posiadają też sprzętowe wsparcie dla PCIe generacji 1 i 2 oraz dla obsługi pamięci DDR3 [31].
Microchip
IGLOO
Podstawowa komórka logiki nosi nazwę VersaTile a jej schemat został pokazany na rysunku 20.
Zaznaczone przełączniki (switch) są konfigurowane przez zaprogramowany bitstream. Pojedyncza komórka może pełnić jedną z trzech ról:
- 3-wejściowa funkcja logiczna,
- zatrzask Latch,
- Przerzutnik D
Bloki pamięci SRAM mają rozmiar po 4608 bitów. Użytkownik ma też dostęp do bloków FlashROM o rozmiarze 1024 bitów. Układy tych rodzin nie są wyposażone w bloki DSP, ale niektóre zawierają rdzeń ARM Cortex-M1 [32].
IGLOO 2
Podstawowym elementem układów tej rodziny jest logic element składający się z 4-wejściowej tablicy LUT oraz przerzutnika typu D [33]. Jego budowa została pokazana na rysunku 21.
Pamięć RAM dostępna jest w dwóch wariantach: LSRAM o pojemności 18 kb i µSRAM o pojemności 1 kb. Układy te są wyposażone w bloki DSP o nazwie Math Block, które pozwalają na mnożenie dwóch liczb 18-bitowych a za mnożeniem znajduje się moduł dodawania. Ich budowa została pokazana na rysunku 22, pozwalają między innymi na implementację operacji MAC.
Układy tej rodziny mają także wbudowane transcivery pozwalające na obsługę interfejsów XGMII (dla Ethernetu 10 Gbps) interfejsy PCIe drugiej generacji, a także interfejsy dla pamięci DDR3.
PolarFire
Najmniejszą częścią logiki jest Logic Element (LE) składający się z 4-wejściowej tablicy LUT i przerzutnika. Dwanaście LE składa się na jeden Logic Cluster (LC). Dostępne są cztery typy bloków pamięci:
- LSRAM (large SRAM) o pojemności 20 kb,
- µSRAM o pojemności 768 bitów,
- µPROM, nieulotna pamięć PROM, programowana przez bitstream, służy do inicjalizacji bloków LSRAM i µSRAM,
- sNVM – blok bezpiecznej pamięci nieulotnej, podobnie jak µPROM może być użyty do inicjalizacji pamięci RAM.
Blok DSP (Math Block) pozwala na wykonanie mnożenia 18×19 bitów. Jego schemat został pokazany na rysunku 23.
Przed i za mnożeniem dostępne są operacje dodawania [34]. Układy tej serii mają wbudowane interfejsy dla pamięci DDR4, linie LVDS o prędkości do 1,6 Gbps oraz transceivery mogące pracować z prędkością 12,7 Gbps. Dostępny jest także blok Phy dla Ethernetu 10 Gbps oraz kontroler PCIe. Wersja PolarFire SoC dodatkowo jest wyposażona w 64-bitowy procesor RISC-V.
Anlogic
Jest to dalekowschodni producent układów FPGA. W ofercie ma dwie rodziny układów oznaczone jako ELF i EAGLE. Niestety większość dostępnej dokumentacji jest w języku chińskim.
Płytki prototypowe są dostępne w Polsce. Parametry układów znajdują się w tabeli 6.
Podstawową jednostką logiki jest blok PFB składający się z czterech Slice-ów: dwóch LSLICE i dwóch MSLICE. Ciekawostką jest zastosowanie dwóch różnych typów tablic LUT. LSLICE składa się z dwóch przerzutników i dwóch 5-wejściowych tablic LUT, natomiast MSLICE z dwóch 4-wejściowych LUT i dwóch przerzutników. Budowa bloku została pokazana na rysunku 24.
Pamięć RAM dostępna jest w postaci bloków o rozmiarze 9 kb, 32 kb, 128 kb i 256 kb. Układ zawiera dość prosty blok DSP składający się z mnożarki 18×18 bitów (rysunek 25).
Niektóre z układów są także wyposażone w kontroler pamięci DDR2, przetwornik ADC oraz wejścia/wyjścia LVDS.
Gowin
Jest to drugi dalekowschodni producent ujęty w zestawieniu. Dostępna jest dokumentacja oraz strona internetowa w języku angielskim, a płytki prototypowe są dostępne w polskich sklepach.
Budowę logiki zaprezentujemy na przykładzie układów GW2A. Logika w układach tego producenta dzieli się na bloki nazwane Configurable Logic Unit (CFU), których budowę pokazuje rysunek 26.
Składa się on z: Configurable Logic Unit (CLU) i Configurable Routing Unit (CRU) (czyli zasobów połączeniowych). CLU dzieli się na cztery configurable logic slices (CLS). Każdy CLS zawiera dwie czterowejściowe tablice LUT i dwa przerzutniki.
Pamięć RAM jest podzielona na moduły Block SRAM (B-SRAM). Jeden blok zawiera 18,432 bitów. Może być skonfigurowany jako pamięć jedno albo dwu-portowa. Pojedynczy blok DSP składa się z dwóch bloków Macro. Budowę pojedynczego modułu pokazano na rysunku 27.
Każdy blok Macro składa się z dwóch dodawań, dwóch mnożarek 18×18 i 3-wejściowego ALU z 54-bitowym akumulatorem [37].
Dostępne są dwie główne serie układów:
- Arora
- GW2A
- R – zawiera SDRAM,
- NR – zawiera SDRAM i Flash,
- GW2A
- LittleBee (GW1N) – zawierające pamięć nieulotną
- Z – bardzo niski pobór mocy,
- S–C zawiera rdzeń Cortex-M3,
- E – dodatkowe funkcje bezpieczeństwa (Root of Trust),
- R – zawiera SDRAM,
- RF – zawiera Bluetooth 5.0.
Porównanie parametrów znajduje się w tabeli 7.
Podsumowanie
Zaprezentowane porównanie oczywiście nie wyczerpuje tematyki układów FPGA, ale mam nadzieje, że pozwoli zrozumieć sposób opisu parametrów używany przez różnych producentów.
Rafał Kozik
rafkozik@gmail.com
Bibliografia:
[1] http://intel.ly/35tdr41
[2] https://intel.ly/3q6tpcd
[3] http://intel.ly/2LmGUpo
[4] http://intel.ly/39fyUPe
[5] http://intel.ly/2K4ln4o
[6] https://intel.ly/3i1v1kP
[7] http://intel.ly/3boTE9E
[8] https://intel.ly/39mpjWy
[9] http://intel.ly/2XrKAZx
[10] http://intel.ly/2MLcKwp
[11] http://intel.ly/3sdlSdu
[12] https://bit.ly/2LmdVCj
[13] https://bit.ly/38txD7J
[14] https://bit.ly/35ojUgv
[15] https://bit.ly/3sbOq7j
[16] https://bit.ly/39fz3SM
[17] https://bit.ly/38t0xVM
[18] https://bit.ly/3hXSCD1
[19] https://bit.ly/38xjMgE
[20] https://bit.ly/3q4h3Bs
[21] https://bit.ly/2K0AXOm
[22] https://bit.ly/35v2grM
[23] https://bit.ly/3nrSA7z
[24] https://bit.ly/3q6fu5V
[25] https://bit.ly/3ow1XV7
[26] https://bit.ly/3bqZzv1
[27] https://bit.ly/3bo6aGr
[28] https://bit.ly/3scjuE4
[29] https://bit.ly/3hXTCXA
[30] https://bit.ly/35sQXjB
[31] https://bit.ly/2K7dETe
[32] https://bit.ly/3bp0axl
[33] https://bit.ly/2LBUuoK
[34] https://bit.ly/3bpPGO9
[35] https://bit.ly/35pMU7C
[36] https://bit.ly/3i1VBKo
[37] https://bit.ly/2MRmXYo