Dlaczego nie skorzystać z IP menedżera zegara Xilinx?
Arturs Vancans
Odpowiedzi:
19
Zasadniczo istnieją dwa sposoby na zrobienie tego. Pierwszym jest użycie natywnego rdzenia syntezatora zegara Xilinx. Jedną z zalet tego jest to, że narzędzia Xlinx rozpoznają zegar jako taki i kierują go wymaganymi ścieżkami. Narzędzia poradzą sobie również z wszelkimi ograniczeniami czasowymi (tak naprawdę nie ma zastosowania w tym przypadku, ponieważ jest to zegar 2 Hz)
Drugim sposobem jest użycie licznika do zliczenia liczby szybszych impulsów zegara, aż minie połowa wolniejszego okresu zegara. Na przykład w twoim przypadku liczba szybkich impulsów zegarowych, które składają się na jeden okres taktowania wolnego cyklu zegarowego, wynosi 50000000/2 = 25000000. Ponieważ chcemy pół okresu zegarowego, to 25000000/2 = 12500000 dla każdego półcyklu . (czas trwania każdego maksimum lub minimum).
Oto jak to wygląda w VHDL:
library IEEE;use IEEE.STD_LOGIC_1164.all;-- Uncomment the following library declaration if using-- arithmetic functions with Signed or Unsigned valuesuse IEEE.NUMERIC_STD.all;entity scale_clock isport(
clk_50Mhz :instd_logic;
rst :instd_logic;
clk_2Hz :outstd_logic);end scale_clock;architecture Behavioral of scale_clock issignal prescaler :unsigned(23downto0);signal clk_2Hz_i :std_logic;begin
gen_clk :process(clk_50Mhz, rst)begin-- process gen_clkif rst ='1'then
clk_2Hz_i <='0';
prescaler <=(others=>'0');elsif rising_edge(clk_50Mhz)then-- rising clock edgeif prescaler =X"BEBC20"then-- 12 500 000 in hex
prescaler <=(others=>'0');
clk_2Hz_i <=not clk_2Hz_i;else
prescaler <= prescaler +"1";endif;endif;endprocess gen_clk;
clk_2Hz <= clk_2Hz_i;end Behavioral;
Ważne uwagi:
Wygenerowany zegar ma wartość zero podczas resetowania. Jest to odpowiednie dla niektórych aplikacji, a nie dla innych, zależy tylko od tego, do czego potrzebujesz zegara.
Wygenerowany zegar będzie kierowany jako normalny sygnał przez narzędzia do syntezy Xilinx.
2 Hz jest bardzo wolne. Symulacja na sekundę zajmie trochę czasu. Jest to niewielka ilość kodu, więc symulacja powinna być stosunkowo szybka nawet przez 1 sekundę, ale jeśli zaczniesz dodawać kod, czas potrzebny do symulacji cyklu zegara 2 Hz może być znacznie dłuższy.
EDYCJA: clk_2Hz_i służy do buforowania sygnału wyjściowego. VHDL nie lubi używać sygnału po prawej stronie przypisania, gdy jest to również wyjście.
Nieźle, ale możesz dodać / porównać bez znaku z liczbą całkowitą, więc: if prescaler = 50_000_000/4 then ...i prescaler <= prescaler + 1;byłoby trochę prostsze.
@ evading, potrzebny jest bufor na wyjściu. VHDL nie podoba się fakt, że clk_2Hzjest to wynik, ale jego wartość jest odczytywana w tym wierszu clk_2Hz <= not clk_2Hz;. Edytowałem poprawkę.
stanri
+1 Świetny przykład. Ale tutaj pokazuje moja ignorancja (nowość w VHDL). Jaka jest różnica między prescaler <= (others => '0');i prescaler <= '0';?
cbmeeks
NVM! Zupełnie tęskniłem za tym, co othersbyło używane podczas czytania mojej książki VHDL. To tylko skrót do zadeklarowania wszystkich „innych” bitów do wspólnej wartości zamiast używania czegoś takiego jak „000000000000000000 ....” itd.
cbmeeks
9
Użyj zegarowego preskalera.
Twoja wartość preskalera będzie wynosić (prędkość_zegara / pożądana_godzina) / 2, więc (50 MHz (50 000 000) / 2 Hz (2)) / 2 = 12 500 000, co w przypadku binarnej wartości to 101111101011110000100000.
Wygląda na to, że generujesz dwa zegary, jeden o częstotliwości 0,5 Hz i jeden o częstotliwości 1 Hz? (skoro twój okres zegarowy to twój prescaler * 2?). Również „+” spowoduje błąd, ponieważ dodajesz slvs, a ja nie jestem pewien, czy w każdym razie użyję w ten sposób właściwości przepełnienia dodatku. dlaczego nie pójść newClock : std_logic := '0', policzyć do prescaler / 2 i przypisać newClk <= not newClk?
stanri
Dzięki, moja logika była trochę niepoprawna. Zaktualizowałem swój początkowy post przy pomocy przetestowanego kodu i kilku waszych sugestii :)
MLM
Ugh - wszystkie te zera i zera oraz komentarz do powiedzenia, co to naprawdę jest! Dlaczego nie skorzystać z kompilatora, aby zrobić to za Ciebie? I dlaczego by nie użyć liczb całkowitych?
Martin Thompson,
Mogę się mylić, ale myślę, że używanie wartości domyślnych przy definiowaniu sygnałów w architekturze jak w „: = (inni => '0')” nie jest możliwe do syntezy.
Arturs Vancans
Jest syntezowalny, ale w zasadzie działa tylko na FPGA opartych na SRAM, jak większość z Xilinx, Altera lub Lattice.
Yann Vernier
8
Zazwyczaj nie chcesz taktować tak wolno, po prostu utwórz zezwolenie z właściwą szybkością i użyj tego w logice:
Odpowiedzi:
Zasadniczo istnieją dwa sposoby na zrobienie tego. Pierwszym jest użycie natywnego rdzenia syntezatora zegara Xilinx. Jedną z zalet tego jest to, że narzędzia Xlinx rozpoznają zegar jako taki i kierują go wymaganymi ścieżkami. Narzędzia poradzą sobie również z wszelkimi ograniczeniami czasowymi (tak naprawdę nie ma zastosowania w tym przypadku, ponieważ jest to zegar 2 Hz)
Drugim sposobem jest użycie licznika do zliczenia liczby szybszych impulsów zegara, aż minie połowa wolniejszego okresu zegara. Na przykład w twoim przypadku liczba szybkich impulsów zegarowych, które składają się na jeden okres taktowania wolnego cyklu zegarowego, wynosi 50000000/2 = 25000000. Ponieważ chcemy pół okresu zegarowego, to 25000000/2 = 12500000 dla każdego półcyklu . (czas trwania każdego maksimum lub minimum).
Oto jak to wygląda w VHDL:
Ważne uwagi:
EDYCJA: clk_2Hz_i służy do buforowania sygnału wyjściowego. VHDL nie lubi używać sygnału po prawej stronie przypisania, gdy jest to również wyjście.
źródło
if prescaler = 50_000_000/4 then ...
iprescaler <= prescaler + 1;
byłoby trochę prostsze.clk_2Hz
jest to wynik, ale jego wartość jest odczytywana w tym wierszuclk_2Hz <= not clk_2Hz;
. Edytowałem poprawkę.prescaler <= (others => '0');
iprescaler <= '0';
?others
było używane podczas czytania mojej książki VHDL. To tylko skrót do zadeklarowania wszystkich „innych” bitów do wspólnej wartości zamiast używania czegoś takiego jak „000000000000000000 ....” itd.Użyj zegarowego preskalera.
Twoja wartość preskalera będzie wynosić (prędkość_zegara / pożądana_godzina) / 2, więc (50 MHz (50 000 000) / 2 Hz (2)) / 2 = 12 500 000, co w przypadku binarnej wartości to 101111101011110000100000.
Mówiąc prościej: (50 000 000) / 2) / 2 = 12 500 000 konwersji na binarne -> 101111101011110000100000
Oto kod tego, co należy zrobić: Użyj newClock do wszystkiego, czego potrzebujesz 2 Hz dla ...
źródło
newClock : std_logic := '0'
, policzyć do prescaler / 2 i przypisaćnewClk <= not newClk
?Zazwyczaj nie chcesz taktować tak wolno, po prostu utwórz zezwolenie z właściwą szybkością i użyj tego w logice:
możesz utworzyć włączenie w ten sposób:
utwórz kilka stałych na podstawie częstotliwości zegara i żądanej częstotliwości włączania i gotowe, korzystając z samokontrującego się kodu.
źródło
Raczej sugerowałbym użycie IP cyfrowego menedżera zegara Xilinx primitice .
Ma interfejs ustawień graficznych, w którym można określić żądaną częstotliwość. Wygeneruje komponent o pożądanej mocy wyjściowej jako częstotliwości.
Można go znaleźć w Kreatorze IP;
A potem będziesz mógł określić, jakiej częstotliwości chcesz:
źródło
Współczynnik = częstotliwość sygnału wejściowego / częstotliwość wyjściowa preskalera.
CE = Włącz zegar. Powinien to być impuls o szerokości jednego zegara (clk) lub wysoki, jeśli nie jest używany.
Q = Sygnał wyjściowy impulsu o szerokości jednego zegara z żądaną częstotliwością.
źródło