Jeszcze raz VHDL - problem ze zwi?z?ym zapisem

Problem jest w zasadzie rozwinięciem poprzedniego wątkaDo rzeczy, układ ma obliczać coś takiego: C=|R(0)+...+R(15)-R(16)-....-R(31)|, gdzie C,R(i)-liczby 11 bitowe bez znaku. R(i) są to kolejne sekcje rejestru posuwnego, w którym na pierwszą sekcję jest podawana 11 bitowa liczba "A" (bez znaku). Układ działa poprawnie zarówno na symulatorze jak i na żywym organiźmie. Wszystkie operacje +/- zrobiłem krok po kroku. A co gdybym miał pierdyljon sekcji rejestru posuwnego? Jak to zwięźlej zapisać? Kod wygląda tak:

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; library UNISIM; use UNISIM.VComponents.all;

entity amod is

Port ( A : in STD_LOGIC_VECTOR (10 downto 0); CLK : in STD_LOGIC; C : out STD_LOGIC_VECTOR (10 downto 0)); end amod;

architecture Behavioral of amod is type Shift_Register_Type is array (31 downto 0) of std_logic_vector(10 downto 0); signal Cs:std_logic_vector(14 downto 0):="000000000000000"; signal Rejestr:Shift_Register_Type; begin

process(CLK) begin if rising_edge(CLK) then Rejestr<=Rejestr(30 downto 0)&A; Cs<=std_logic_vector(to_unsigned(abs(to_integer(signed('0'&Rejestr(0)))+ to_integer(signed('0'&Rejestr(1)))+ to_integer(signed('0'&Rejestr(2)))+ to_integer(signed('0'&Rejestr(3)))+ to_integer(signed('0'&Rejestr(4)))+ to_integer(signed('0'&Rejestr(5)))+ to_integer(signed('0'&Rejestr(6)))+ to_integer(signed('0'&Rejestr(7)))+ to_integer(signed('0'&Rejestr(8)))+ to_integer(signed('0'&Rejestr(9)))+ to_integer(signed('0'&Rejestr(10)))+ to_integer(signed('0'&Rejestr(11)))+ to_integer(signed('0'&Rejestr(12)))+ to_integer(signed('0'&Rejestr(13)))+ to_integer(signed('0'&Rejestr(14)))+ to_integer(signed('0'&Rejestr(15)))- to_integer(signed('0'&Rejestr(16)))- to_integer(signed('0'&Rejestr(17)))- to_integer(signed('0'&Rejestr(18)))- to_integer(signed('0'&Rejestr(19)))- to_integer(signed('0'&Rejestr(20)))- to_integer(signed('0'&Rejestr(21)))- to_integer(signed('0'&Rejestr(22)))- to_integer(signed('0'&Rejestr(23)))- to_integer(signed('0'&Rejestr(24)))- to_integer(signed('0'&Rejestr(25)))- to_integer(signed('0'&Rejestr(26)))- to_integer(signed('0'&Rejestr(27)))- to_integer(signed('0'&Rejestr(28)))- to_integer(signed('0'&Rejestr(29)))- to_integer(signed('0'&Rejestr(30)))- to_integer(signed('0'&Rejestr(31)))),15)); end if; end process; C<=Cs(14 downto 4); end Behavioral;

Reply to
stchebel
Loading thread data ...

<ciach>

Można użyć funkcji, która wygeneruje taką sumę dla zadanej liczby sygnałów, w funkcji trzeba by wykorzystać for ... loop. Można też bezpośrednio w procesie użyć for ... loop.

Reply to
Jakub Rakus

No więc właśnie tak kombinowałem. Pseudokod:

for i in 0 to 15 loop Cs<=Cs+R(i)-R(i+16) end loop;

I wyszedł z tego akumulator :((

Reply to
stchebel

Bo to nie można tego zrobić na sygnałach tylko na variable wewnątrz procesu. I wtedy nie <= tylko :=.

Reply to
Jakub Rakus

OK, dzięki! Teraz działa.

Reply to
stchebel

Użytkownik napisał w wiadomości grup

Czy ja dobrze rozumiem ze mamy rejestr przesuwny o 32 slowach 11 bitowych, co takt zegara slowa wprowadzamy nowa wartosc, reszte przesuwamy, i wyliczamy sume pierwszych 16 slow minus suma drugich 16 slow ?

Pomijajac trudnosci jak to zwiezle w VHDL zapisac ... pomysleliscie jak to powinno byc zrealizowane ? Czy zdajecie sie na optymalizator ? :-)

Bo sumator 32 liczb jest dosc kosztowny, ciekawe - kompilatorowi pamieci zabraknie przy optymalizacji funkcji, czy zrealizuje kaskadowo. A im wiecej slow w tym rejestrze, tym ciezsze zadanie.

To sie w krzemie realizuje inaczej ...

J.

Reply to
J.F.

W dniu wtorek, 26 maja 2015 10:36:42 UTC+2 użytkownik J.F. napisał:

Dobrze rozumiesz.

Robię to na spartanie6 (XCS6LX45) i nie ma żadnego problemu z implementacją.

Jak?

Reply to
stchebel

Użytkownik napisał w wiadomości grup dyskusyjnych: snipped-for-privacy@googlegroups.com... W dniu wtorek, 26 maja 2015 10:36:42 UTC+2 użytkownik J.F. napisał:

A jest jakas szansa zobaczyc jak to kompilator zrobil ? Ewentualnie - ile makrocell mu to zajelo, jakie opoznienia wyszly ?

Pomysl pierwszy - rysunek by sie przydal, ale moze sie uda slowami:

32 rejestry w szeregu, tylko ze na wejsciu kazdego (z wyjatkiem pierwszego) z nich umieszczasz sumator A i wyjscia poprzednego rejestru.

Tym sposobem drugi rejestr widzi R1= A+A(-1), [A(-n) - A opoznione o n cykli) R2 = A+R1 = A+ A(-1) + A(-2) [bo w miedzyczasie sie o cykl opoznilo] itd. Gdzies w polowie musisz wstawic roznice A-R(15)

Pomysl drugi - jesli jest zwykla suma, to ona co cykl zmienia sie tylko o nowy wyraz, ktory wchodzi do sumy, i ostatni, ktory wypada. Czyli wystarczy jeden akumulator S, w ktorym co cykl liczymy S = S +A - A(-31) Oczywiscie na poczatku trzeba wyzerowac i S i wszystkie rejestry R, aby byla zgodnosc :-).

Ty masz roznice dwoch sum, to sie wyrazenie nieznacznie skomplikuje.

J.

Reply to
J.F.

W dniu środa, 27 maja 2015 10:40:37 UTC+2 użytkownik J.F. napisał:

Można to zobaczyć na edytorze wyroutowanego układu, ale analizę tego pozostawiam raczej mnichom z Shaolin, albo tym co mają czasu w nadmiarze. Makrocele to masz w CPLD. Ja robię na FPGA raczej dosyć małym, ale i tak ilość zasobów logicznych jest taka, że ten konkretny problem zajmuje kompletnie nieistotny procent. W ogóle o tym nawet nie myślę. Opóźnienia jak najbardziej możesz monitorować, ewentualnie narzucić swoje constraintsy. Ja tego nawet nie robię, zostawiam to kompilatorowi "as is", układ działa poprawnie na 20MHz.

Rozumiem, że coś w tym stylu:

formatting link

Jasne, można i tak i owak, niemniej jednak nie dostrzegam żadnych zalet w stosunku do przyjętego rozwiązania.

Pzdr.

Reply to
stchebel

Użytkownik napisał w wiadomości grup dyskusyjnych: snipped-for-privacy@googlegroups.com... W dniu środa, 27 maja 2015 10:40:37 UTC+2 użytkownik J.F. napisał:

Dokladnie.

Funkcja logiczna wydaje znacznie prosztsza. Ale moze nie doceniam kompilatora.

Jesli masz wszystko przygotowane ... moze bys zrobil drugi projekt w alternatywnej wersji, tylko jak to ocenic - % zajetosci zasobow, wyliczona maksymalna czestotliwosc pracy, czas pracy kompilatora ? To ostatnie najmniej istotne :-)

J.

Reply to
J.F.

W dniu środa, 27 maja 2015 12:09:27 UTC+2 użytkownik J.F. napisał:

Jako jedeny moduł w FPGA, Twoja wersja zajmuje minimalnie mniej zasobów czysto logicznych (LUT's), ale tyle samo Flip-Flopów, co jest akurat oczywiste (rejestr posuwny). Natomiast w całości mojego projektu zastosowanie modułu w/g Twojego pomysłu - na odwrót. Dzieje się tak zapewne dlatego, że mapowanie w przypadku wykorzystania większej liczby zasobów zaczyna być bardziej "agresywne". Algorytmów nie znamy, więc są to czyste spekulacje z mojej strony. Prędkość praktycznie ta sama, można to popychać ~140MHz.

Reply to
stchebel

Użytkownik napisał w wiadomości grup W dniu środa, 27 maja 2015 12:09:27 UTC+2 użytkownik J.F. napisał:

No, to ciekaw jestem jak to kompilator zrealizowal.

Dodawanie 32 liczb 11-bit- wydaje mi sie, ze to bardzo wredna funkcja. Oczywiscie mozna zrealizowac zwyklymi sumatorami dwoch liczb, nawet tyle samo ich trzeba, ale czas propagacji powinien wzrosnac. Jak zrobil "liniowo" a nie "drzewem binarnym", to nawet sporo wzrosnac ...

Chyba, ze nawet nie zblizyles sie do granicy szybkosci ...

J.

Reply to
J.F.

W dniu środa, 27 maja 2015 17:40:54 UTC+2 użytkownik J.F. napisał:

W FPGA jest trochę inaczej i nie należy, wręcz NIE WOLNO myśleć w kategoriach bramek logicznych i połączeń między nimi i wydawałoby się wynikających z tego czasów propagacji. Tutaj masz generatory funkcji, które w obrębie pojedyńczego CLB są niczym innym jak pamięcią statyczną i realizują dowolną funkcję logiczną n-zmiennych (n-zależne od typu FPGA). Jest to właściwie LUT(look up table), w którym wartości zmiennych wejściowych stanowią adres do gotowego wyniku. Oczywiście taka kobyła jak sumator 32 liczb 11-bitowych nie wlezie w pojedyńczy LUT, więc czasy propagacji są pomiędzy poszczególnymi CLB, ale jest to mocno zniwelowane..

Na próbę pocisnąłem to na 80MHz, co akurat w moim projekcie nie ma sensu. Też działa!!

Reply to
stchebel

W dniu środa, 27 maja 2015 17:40:54 UTC+2 użytkownik J.F. napisał:

A jednak Twój pomysł jest lepszy!! Postanowiłem rozszerzyć zagadnienie do 64 liczb. No i od tego momentu zaczęły się chece. Zasoby i czas propagacji poszły ostro w górę, podczas gdy w/g Twojej porady nadal wszystko jest cacy.

Reply to
stchebel

Użytkownik napisał w wiadomości grup W dniu środa, 27 maja 2015 17:40:54 UTC+2 użytkownik J.F. napisał:

Ciesze sie, ze choc raz teoria zgadza sie z praktyka :-)

Ale nadal jestem ciekaw jak on to zrobil z 32 liczbami, ze tak dobrze bylo :-)

J.

Reply to
J.F.

W dniu piątek, 29 maja 2015 13:39:46 UTC+2 użytkownik J.F. napisał:

Jeżeli teoria nie zgadza się z praktyką, to tym gorzej dla praktyki :))) Eeee tam.., jeżeli w cyfrówie wymiśli się coś BANALNIE prostego, to nie ma bata we wsi, coby to nie działało.. Podałeś też pomysł z wykorzystaniem akumulatora.. Toż to pierwsze o czym pomyślałem, ale doszedłem do wniosku, że to lipa.. No bo po n+1 mlasknięciach zegara akumulator się "przekręci". Resetowanie co n-mlasknięć jest też beż sensu, bo tracę dane R(n downto 0)!!

Ale..., Twój pomysł z akumulatorem + mój pomysł z rejestrem posuwnym ma sens.

Robimy taki akumulator : Acc:=Acc+A(n)-A(0). A(n) - aktualna próbka z ADC, A(0) - n-mlasknięć starsza próbka z FIFO. Owym FIFO może być właśnie rejestr posuwny. Innymi słowy A(i) leci równolegle na akumulator i rejestr posuwny. Wyjście z rejestru (na końcu), to A(0). Minimalne zużycie zasobów FPGA dla dowolnego 'n', powinno śmigać na ciężkich MHz. Jutro sprawdzę na 'żywym organiźmie'. Dzięki za pomysły, sensownie się z Tobą gada !!

Reply to
stchebel

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.