Skocz do zawartości

[FPGA] Bardziej rozbudowane obliczenia. Jak to zaprojektować


Halon

Pomocna odpowiedź

Witam.

Na uczelni kontynuujemy projekt robota na FPGA. Mam encję która na wejściu otrzymuje sygnał zegarowy, fazę ruchu oraz położenie serwa. Położenie może być zmieniane niezależnie w zależności od tego która z grupy podobnych encji ma działać (np ruchy przód/tył lub "rozglądanie się"). Wymyśliłem coś takiego:

oblicz na podstawie fazy jakie powinno być wychylenie serwa (robione to jest za pomocą działania w kilku if'ach)

porównanie faktycznego położenia serwa z wyliczonym - jeżeli różne ustawiamy wartość poprawki (kolejna grupa if'ów)

ustawienie kroku - step lub -step w zależności od kierunku ruchu

zsumowanie kroku i poprawki

na razie mam to zaimplementowane w jednym procesie (wyzwalanym zboczem zegara) na sygnałach. Nie ma to prawa działać i teraz zastanawiam się:

czy zamiana na zmienne ma jakiś sens? zsyntezują się? będą działać?

czy lepsze jest rozbicie tego na kilka procesów? Czym je wtedy synchronizować? Najlepiej jeżeli wszystkie obliczenia zamieściłyby się w jednym takcie zegara.

Link do komentarza
Share on other sites

Możesz pokazać kod ? Powiedziałoby mi to nieco więcej. Co do rozwiązania synchronizacji dla kilku procesów to dajesz wspólny zegar i dodatkowo odpowiednie sterowanie za pomocą sygnałów. Pokaż kod, coś poradzimy.

Wpadł mi do głowy pomysł, że można by to robić iteracyjnie, na podstawie sygnału faza i położenie serwa. Coś a'la CORDIC. Ale jednak pokaż ten kod 😉

Link do komentarza
Share on other sites

Od czasu napisani poprzedniego postu kod przeszedł drobne modyfikacje. Rozdzieliłem opisywane operacje do trzech procesów.

porownajpozycje: process (computeDifferences)
begin
	if (computeDifferences'event and computeDifferences = '1') then
		if (inputState >= zeroBorder and inputState < firstBorder ) then
			computedPosition <= (inputState - zeroBorder) * basic ;
			tmpChange <= basic;
		elsif (inputState >= firstBorder and inputState < secondBorder) then
			computedPosition <= firstBorder * basic;
			tmpChange <= basic*2;
		elsif (inputState >= secondBorder and inputState < thirdBorder ) then
			computedPosition <= (firstBorder - inputState + secondBorder) * basic;
			tmpChange <= -basic*2;
		elsif (inputState >= thirdBorder and inputState < fourthBorder ) then
			computedPosition <=  0 ;
			tmpChange <= -basic;
		end if;
	end if;
end process;

ustalWartosci: process (computeValues)
begin 
	if (computeValues'event and computeValues = '1') then
		if (computedPosition /= inputPos) then
			if (computedPosition > inputPos ) then 
				syncChange <= basic;
			else
				syncChange <= - basic;
			end if;
		else
			syncChange <= 0;
		end if;
		if (action.direction = l) then
			actChange <= - tmpChange;
		else
			actChange <= tmpChange;
		end if;

	end if;
end process;

zsumujWartosci: process (computeResult)
begin
	if (computeResult'event and computeResult = '1') then
		change <= actChange + syncChange;
	end if;
end process;

Steruję tym przez generyczną maszynę stanów z jednym sygnałem aktywnym. Położenie serwa może być zmieniane na zewnątrz, stąd potrzeba obliczania pozycji i porównywania z fazą ruchu.

Dzisiaj doszedłem do wniosku, że dla bardziej skomplikowanego ruchu serwa obliczanie położenia takie jak jest, może nie być zbyt optymalne (w sumie może nie tyle optymalne co ładnie wyglądające. Lepsze chyba by było obliczanie pozycji sumując pozycje przechodząc po każdej grupie, a nie ustawiając (inaczej zamienić <= lub := na +<= lub +:=). Wtedy ładniej by to wyglądało na zmiennych.

Pytanie drugie:

Ostatnio w książce "VHDL for Designers" Stefana Sjoholma doczytałem że można instancjonować entity podając konkretną architekturę do której się odwołujemy. Kawałek dalej jest napisane, o ile dobrze zrozumiałem (książka po angielsku), że architektury muszą spełniać te same funkcje. Bardziej logiczne mi się wydaje, że jest to tylko zalecenie dla programistów by nie zmniejszać czytelności kodu.

IndividualControl.txt

Link do komentarza
Share on other sites

Przepraszam za zwłokę, ale ostatnio mam dużo pracy.

Ostatnio w książce "VHDL for Designers" Stefana Sjoholma doczytałem że można instancjonować entity podając konkretną architekturę do której się odwołujemy. Kawałek dalej jest napisane, o ile dobrze zrozumiałem (książka po angielsku), że architektury muszą spełniać te same funkcje. Bardziej logiczne mi się wydaje, że jest to tylko zalecenie dla programistów by nie zmniejszać czytelności kodu.

Owszem, da się to zrobić, definiuje się kilka architektur i podczas wykorzystywania danego komponentu podaje się odpowiedni parametr, co skutkuje syntezą odpowiedniej architektury. Nie pamiętam, niestety, jak dokładnie się to robiło. Aha, i te architektury muszę mieć tylko te same wejścia-wyjścia, mogą robić różne rzeczy, inaczej nie miałoby to sensu.

Co do Twojego kodu, źle masz opisane procesy synchroniczne. Powinny mieć one jakiś wspólny, asynchroniczny sygnał resetu, co ustawi rejestry w jakiś ustalony stan początkowy. Widzę, że za bardzo traktujesz VHDL jak język programowania, coś takiego. Dość skomplikowane warunki i zagnieżdżone if-y, hmmm, jakoś to pójdzie, ale zużyje w cholerę logiki, popróbuj z case. Co do obliczeń to możesz je wykonywać na std_logic_vector, byle załączyć na początku pliku źródłowego:

library IEEE;
use IEEE.STD_LOGIC_1164.all; 
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;

Jaki FPGA wykorzystujesz ?

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Widzę, że za bardzo traktujesz VHDL jak język programowania

To niestety jest prawda. Jakoś ciężko mi się przestawić na opisywanie sprzętu.

Do obliczeń wykorzystuje integery, bo łatwiej mi było przypisywać konkretne wartości liczbowe. Używając std_logic_vector i podane biblioteki mogę ustawić wartości grupy Border np na 135? (jak znajdę chwile czasu to sam sprawdzę)

Co do sygnału reset nie widziałem potrzeby wykorzystywania go. Na wejściu podaje aktualne wychylenie serwa i fazę ruchu (do nich podpięty jest reset po naciśnięciu klawisza). Jeżeli je zresetuje to po kilku taktach zegara (przejście przez obliczenia) cała architektura mi się zresetuje.

Na razie używam płytki UP2 z modułem FLEX10KA-70. Jak do tej pory mieściło się wszystko(20% użycia). Na uczelni mamy jeszcze klika DE2(-70) z układami Cyclone i chyba jednego Stratixa. Wszystko od Altery. Układów innych firm nie spotkałem.

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.