Przedstawiam opis PWMa o wirtualnym taktowaniu rzędu 500 GHz, którego sobie nazwałem FRPWM (Fractional Resolution PWM: PWM o Ułamkowej Rozdzielczości).
Zrobiłem go już ze 3 lata temu, i najwyższa pora opublikować.
Czasami potrzeba PWMa, albo innego generatora impulsów, o dużej rozdzielczości.
Ile tej rozdzielczości zwykle mamy?
Na najszybszych procesorach dostępnych dla amatorów, jest to ze 100...200MHz (nawet jak rdzeń chodzi szybciej, to peryferia zwykle mają ograniczenia).
Czyli mamy z 10...5vns rozdzielczości.
Jak zrobimy PWMa 8-bitowego przy pomocy licznika taktowanego częstotliwością 100MHz, to uzyskamy PWMa około 390 kHz, z 256 poziomami.
Chcemy mieć więcej poziomów, to spadnie nam częstotliwość PWMa.
Np. 16-bitowy (65536 poziomów) będzie miał już tylko 1.5 kHz.
Nie da się z tak taktowanego PWMa wyciągnąć jednocześnie dużej rozdzielczości i dużej częstotliwości. Nie da się tym szybko wysterować żadnego powszechnie stosowanego drivera mocy (w przetwornicy, w generatorze DDS, w sterowniku szybkich silników BLDC, itp.). Bo wszędzie tam potrzeba dość dużego próbkowania, ponad 10kHz. A rozdzielczość powinna być wysoka, na pewno co najmniej ze 12...16 bitów.
Żeby uzyskać PWMa 16-bitowego, o częstotliwości 100kHz, potrzeba by żeby miał taktowanie równe 100 kHz * 65536 = 6.5536 GHz. Czyli jego rozdzielczość byłaby równa 1 / 6.5536 GHz = 150 ps.
Takie coś da się uzyskać tylko na niektórych mało popularnych procesorach.
Gotowego układu scalonego z PWMem o większej rozdzielczości nie da się kupić w ogóle. Trzeba "zrobić" samemu.
Mi się udało uzyskać dokładność rzędu 10 ps, a rozdzielczość schodzącą nawet do 2 ps.
No i tu będzie opis jak to zrobiłem.
Na początek działanie zwykłego PWMa a liczniku:
Jest sobie jakiś tam główny zegar, powiedzmy 100MHz (niebieski). Czyli ma okres 10ns.
PWM jest tutaj generowany na narastających zboczach zegara, i tym sposobem uzyskujemy przebieg PWMa (czerwony).
Następny krok PWMa to będzie to co narysowałem na zielono. Będzie to jeden cykl zegara dalej, czyli 10ns dalej. Czyli rozdzielczość PWMa będzie równa okresowi PWMa, i będzie równa te same 10ns.
My chcemy o wiele większą rozdzielczość, rzędu dziesiątek ps.
To by się dało uzyskać dopiero dla zegara taktującego rzędu wielu GHz.
To nieosiągalne dla większości uC czy FPGAa, a już na pewno nieosiągalne dla amatora elektroniki.
No to jak to zrobić w wykonaniu DIY?
-> Nie zwiększać taktowania, tylko wcinać się w pomiędzy cykle zegara.
Tutaj to co chcemy uzyskać:
Chcemy uzyskać przebieg niebieski.
Czyli chcemy mieć możliwość zakończyć impuls PWMa również gdzieś w środku trwania jednego okresu zegara taktującego.
Zrobienie tego jest całkiem proste i oczywiste.
Można użyć kilku zegarów taktujących poprzesuwanych w fazie.
Albo można użyć linii Delay w torze sygnału PWMa.
I w jakiejś postaci jest już stosowane w niektórych procesorach. Np. niektóre procesory TI mają wbudowane bloki generacji PWMa o zwiększonej rozdzielczości:
https://www.ti.com/lit/ug/sprufl3c/sprufl3c.pdf
Uzyskują tam rozdzielczości 180...55 ps, zależnie od procesora.
(W FPGA można też użyć 3 opcji: użyć bloków DDR, co pozwoli zwiększyć rozdzielczość od 2 do 10 razy. Ale tego nie będę opisywał.)
No ale co jak potrzeba jeszcze mniej?
10 i mniej ps?
To już trzeba iść w DIY.
Okazuje się że można to dość łatwo zrobić na FPGA (pomijając to, że samo wejście w FPGA nie jest łatwe).
Wiele FPGA ma wbudowane delay-e na pinach IO.
Np. wszystkie silniejsze układy od Xilinxa (Kintex i Virtex, nie ma ich w Artix).
Używane są do ustawiania czasu propagacji przy komunikacji z szybkimi pamięciami jak DDR.
Ale można je użyć też do nietypowych zastosowań, jak np. takie:
https://www.xilinx.com/support/documentation/application_notes/xapp872.pdf
Tu mieli delaye o kroku 80 ps.
Ale w nowszych układach delay są nawet rzędu 10 ps.
Te same delaye użyłem do robienia FRPWMa.
Opis FRPWMa na bloku delay:
PWM jest zrobiony jako implementacja w FPGA. Jest to na tyle proste że nie będę tego opisywał.
Na wyjściu jest jednak dodany blok Delay:
Do PWMa przychodzi dość niskie taktowanie. W tym wypadku 250MHz (okres 4ns).
Oraz słowo sterujące (informacja jakie ma być wypełnienie).
PWM generuje z tego pierwszy, niskorozdzielczy przebieg PWMa, oraz dodatkowo generuje przebiegi synchronizujące dla bloku Delay. No bo chyba oczywiste jest, że Delay musi być sterowany, a nie ustawiony na jedną stałą wartość.
Załóżmy że niskorozdzoielczy PWM ma 16 kroków, a Delay ma 64 kroki po 100 ps.
Przykładowe przebiegi wyglądają tak:
PWM = 8.0 / 16 (równo 8 na 16 kroków)
Tuż przed początkiem impulsu PWMa ustawiamy DELAY na wartość 0 ps.
Tuż po rozpoczęciu się impulsu PWMa ustawiamy DELAY na potrzebną wartość. Tutaj 0 ps.
Czyli DELAY zawsze ma wartość 0 ps, i nie wpływa na przesunięcie sygnału PWM.
Niskorozdzielczy sygnał PWM (czerwony, o długości 8) przechodzi wprost w sygnał wysokorozdzielczy (niebieski).
Drugi przykład.
PWM = 8.15 / 16
1 Krok PWMa ma 4 ns, więc skoro chcemy uzyskać PWMa 8.15, to impuls ma mieć:
8.15 * 4 ns = 32.6 ns
8 możemy ustawić wprost, i nam to da 32 ns.
Brakuje wartości 0.15, która ma wynieść 0.15 * 4 ns = 0.6 ns = 600 ps.
DELAY ma kroki co 100 ps, więc po prostu potrzebujemy ustawić mu wartość "6".
Będzie to wyglądało tak:
Tu chyba nawet nie ma co opisywać.
Działanie jest proste i oczywiste.
Używając dodatkowego DELAYa, można ustawiać moment zakończenia impulsu PWMa z rozdzielczością tego DELAYa.
Jak mamy DELAYa o krokach 100 ps, to uzyskamy rozdzielczość 100 ps.
Niskorozdzielczy PWM miał krok 4 ns = 4000 ps, więc mamy 40-krotny wzrost rozdzielczości.
Dodam jeszcze że z DELAYa w tym przypadku możemy użyć tylko 40 wartości spośród wszystkich 64 dostępnych (od 0 do 39 = od 0 ps do 3900 ns). Kolejny krok da nam już 4000 ps, a więc tyle ile ma kolejny krok niskorozdzielczego PWMa. No ale to chyba oczywiste.
Podsumowując, używając DELAYa o kroku 100 ps, uzyskaliśmy PWMa który zachowuje się tak jakby był taktowany wirtualnym zegarem o częstotliwości 10 GHz (bo taki właśnie zegar ma okres 100 ps).
Pomiary działania FRPWMa:
Pasuje też sprawdzić czy to w ogóle działa.
Łatwo sobie wymyślić abstrakcyjne rozwiązanie, które potem nie będzie działać bo szumy będą większe niż to co niby mieliśmy uzyskać.
Trzeba więc potwierdzić że to będzie działać tak jak powinno.
Najpierw test DC. Dokładamy sobie tor wyjściowy w postaci zewnętrznej bramki logicznej, oraz filtr RC. Będzie to taki prosty przetwornik DAC. Całość zasilamy z niskoszumnego zasilania, i używamy tego zasilania jako napięcie referencyjne przetwornika ADC:
W tym wypadku użyłem PWMa o ilości kroków 512, a więc jeden duży krok to było 3.3V / 512 = 6.4453125 mV.
Jednocześnie była to dokładnie wartość 32768 odczytana z przetwornika, bo przetwornik był 24-bitowy.
1 / 512 skali przetwornika 24-bitowego, to 15 bitów, czyli właśnie wartość 32768.
Tu fragment wyników, dla samego PWMa niskorozdzielczego:
Wartości na osi Y to surowe wartości z ADC.
Jak widać stałość napięcia każdego z kroków jest bardzo duża.
Jeszcze w powiększeniu:
Dopiero tutaj widać że kroki mają jakieś małe szumy.
No ale są całkiem małe. Bez problemu takie duże kroki da się podzielić na mniejsze, i ciągle krok będzie mniejszy od szumów.
Tutaj przykład dla wprowadzenia podziału kroku na 10 (używane są ustawienia DELAY równe 0.0 ns, 0.4 ns, 0.8 ns, 1.2 ns, ..., 3,6 ns):
Ciągle kroki większe od szumów.
No i finalny pomiar. Podział na 40, czyli pełna rozdzielczość 100 ps:
Pomiary DC to jednak za mało. Bo mamy tu ostry filtr RC, który filtruje wysokie częstotliwości. ADC miał próbkowanie zaledwie kilka próbek na sekundę.
A pasowałoby żeby taki FRPWM miał też małe szumy wysokoczęstotliwościowe.
Żeby to sprawdzić trzeba zrobić test dla AC.
W tym celu zamiast ADC 24-bitowego, podłączamy analizator audio.
W moim przypadku był to nie tyle analizator audio, co po prostu analizator dźwięków (bo działa i w zakresie ultradźwięków).
Oprócz tego podnosimy częstotliwość graniczną filtru RC, żeby obejmowała co najmniej kilka kHz.
Tutaj pomiary. Czarne to widmo (niebieskie uśrednione widmo). Czerwone to przebieg czasowy.
Zwarte wejście analizatora:
Widmo z niemodulowanym FRPWMa (stała wartość 255):
PWM przełączany pomiędzy próbkami 255 i 256 (czyli tylko PWM niskorozdzielczy) (przebieg czasowy wyświetlony w powiększeniu 256 razy):
PWM przełączając tylko najmłodszy bit (zmiana z 255.000 do 255.006 = zmiana o 22 ps):
No i jak widać, w sygnale PWM nie ma specjalnych szumów czy spurów. Pojawia się tylko to co poda się na wejście modujące FRPWMa (harmoniczne w widmie to efekt tego że przebieg był prostokątny).
Tą prostą metodą z DELAYem, na tym FPGA więcej się nie osiągnie. Więc przeszedłem na inny FPGA, gdzie kroki miały około 20 ps. I udało się uzyskać podobne efekty, czyli dojść do pełnej rozdzielczości DELAYa (tam 20 ps), ciągle mając kroki znacznie większe od poziomu szumów. Zarówno dla DC jak i dla AC.
20 ps, to jakby wirtualne taktowanie 50 GHz.
Całkiem dobry wynik.
Taki FRPWM dawał się już używać w wielu zastosowaniach.
Ma pewne ograniczenia. Np. nie może pracować ze zbyt niskim albo ze zbyt wysokim wypełnieniem. A wszystko przez to że potrzebny jest jakiś czas przed i po początku impulsu PWMa, na zmianę ustawień bloku DELAY.
W wielu zastosowaniach nie ma to jednak znaczenia.
Np. w falownikach do silników, PWM zwykle pracuje na wypełnieniu spoczynkowym 50%. I dopiero podczas pracy jest modulowany w dół i w górę, ale nigdy do wartości 0 i 100%. Drivery MOSFETów też nie są w stanie pracować z wypełnieniem 0 i 100% (jeżeli zasilają się z układu bootstrap), więc to że FRPWM też ma takie ograniczenie nie będzie w niczym przeszkadzało.
Jeżeli użyjemy PWMa jako przetwornik DAC w DDSie, to będzie tak samo. Spoczynkowe wypełnienie 50% i modulacja w dół i w górę.
Inne ograniczenie to niemożliwość zrobienia PWMa o dowolnie wysokiej częstotliwości. Wysokie próbkowanie liczone w gigahercach jest tylko wirtualne.
W rzeczywistości to "taktowanie "pozwala tylko zwiększać rozdzielczość, ale nie pozwala zwiększać częstotliwości.
W praktyce jednak też nie jest to ograniczeniem. Można zrobić PWMa o niskorozdzielczej rozdzielczości rzędu 4 bitów, i uzyskać PWMa o częstotliwości około 15 MHz. I to przy rozdzielczości 9...10 bitów. Tym sposobem da się np. wygenerować obraz TV w dobre jakości (wraz z modulacją PAL czy NTSC).
Zamiast dodatkowego DACa na zewnątrz FPGA, dajemy tylko obwód RC do pinu IO, i tyle. I mamy analogowe wyjście TV (oczywiście to zastępuje tylko przetwornik DAC, ale ciągle musimy mieć cały cyfrowy blok generacji sygnału TV).
Akurat sygnału TV nie generowałem, ale sprawdzałem jakość pracy tego FRPWMa jako DAC przy wysokich częstotliwościach, i stąd wiem że sprawdziłby się w tym zastosowaniu.
W sumie to zrobiłem spoooooro różnych pomiarów. Wpływ jakości napięcia zasilania, wpływ zmian temperatury, wpływ starzenia się układu (uruchamiałem to w ciągu 3 lat), wpływ ustawionej wartości DELAY, wpływ routingu wewnątrz FPGA, itp. I dopiero przeanalizowanie tych pomiarów, i użycie tej wiedzy do poprawnego zaprojektowania FRPWMa wewnątrz FPGA, pozwoliło na uzyskanie tak dobrych parametrów (a w sumie to jeszcze lepszych parametrów, ale o tym w kolejnym punkcie).
No to gdzie te 500 GHz?
Póki co w najlepszym układzie FPGA jaki testowałem są DELAYe około 20 ps, co daje wirtualne taktowanie PWMa 50 GHz.
W najszybszym układzie Xilinxa było by z 10 ps, co by dało ze 100 GHz (o ile by to zadziałało bez dużych szumów). Tego jednak nie testowałem.
Analizując parametry tego cuda, doszedłem jednak do wniosku że da się ustabilizować jego działanie i sprytnie przekuć niedokładności na dodatkową rozdzielczość. No ale jak to zrobiłem, to już opiszę w kolejnej części. Ta cześć wyszła już wystarczająco długa.
