FlyingDutch Napisano Maj 3, 2018 Udostępnij Napisano Maj 3, 2018 Witam wszystkich, chciałem zobaczyć jak wygląda wydajność obliczeń (4 podstawowe działania) dla liczb zmiennopozycyjnych Double dla popularnych układów FPGA. Znalazłem na stronie opencores.org IP core: FPU Double VHDL. Oto link do strony: https://opencores.org/project/fpu_double W zał1. dołączam pobrany kod źródłowy (VHDL) dla tego IP core. Okazało się, że projekt zajmuje za dużo zasobów dla płytek "Elbert V2" oraz "Mimas V2",dlatego postanowiłem go zaimplementować za pomocą płytki FPGA "Digilent Cmod A7-35T ", opartej na FPGA Artix-7. Oto link do tej płytki: https://kamami.pl/zestawy-uruchomieniowe/562401-digilent-cmod-a7-35t-modul-uruchomieniowy-z-fpga-artix-7-410-328-35.html Użyty układ FPGA: XC7A35T-1CPG236C zawiera około 20800 LUT (w porównaniu do Elbert'a 1400 LUT). Projekt "FPU Double zajmuje sporo zasobów, jak widać na zrzucie ekranu poniżej: I tutaj napotkałem problem, oto główne entity projektu: ENTITY fpu_double IS PORT( clk, rst, enable : IN std_logic; rmode : IN std_logic_vector (1 DOWNTO 0); fpu_op : IN std_logic_vector (2 DOWNTO 0); opa, opb : IN std_logic_vector (63 DOWNTO 0); out_fp: OUT std_logic_vector (63 DOWNTO 0); ready, underflow, overflow, inexact : OUT std_logic; exception, invalid : OUT std_logic ); END fpu_double; Jak widać FPU ma dwie wejściowe magistrale o długości 64 bit każda i jedną wyjściową - także 64-bitową. Jest to problem, który napotykam już w którymś z kolei projekcie o kodzie dostępnym w sieci: długości magistral układu mają liczbę pinów I/O przekraczającą znacznie ilości pinów I/O danego zestawu FPGA (a często także samego układu scalonego FPGA użytego w danym zestawie). Płytka ""Digilent Cmod A7-35T" posiada łącznie 48 pinów I/O, więc postanowiłem nieco skrócić magistrale układu. Każdą z dwóch magistral wejściowych skróciłem do 16-tu bitów - liczby double w tym projekcie FPU mają długość 64 bity, więc jej wprowadzenie można zrobić w czterech porcjach po 16 bitów. Na każdą z magistral wejściowych podłączyłem demultiplekser (z 16 na 64 bit). Oprócz danych wejściowych potrzebny jest jeszcze adres 16-to bitowej części i sygnał "strobe", który zboczem narastającym przepisuje 16-bitową porcję danych na właściwe miejsce w 64 bitowym rejestrze wyjściowym. Oto kod entity Demux8To64: LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_misc.all; entity Demux8To64 is Port ( in16bit : in STD_LOGIC_VECTOR (15 downto 0); sel : in STD_LOGIC_VECTOR (1 downto 0); --Adress of 16-bit input (4 parts) out64bit : out STD_LOGIC_VECTOR (63 downto 0); strobe : in STD_LOGIC; -- Active rising edge resetL : in STD_LOGIC; -- Active LOW CLK : in STD_LOGIC -- clock ); end Demux8To64; architecture Behavioral of Demux8To64 is begin SEQ: process (CLK, resetL, strobe) begin if (resetL = '0') then out64bit <= (others => '0'); elsif (strobe' event and strobe = '1') then case sel is when "00" => out64bit(63 downto 48) <= in16bit; --Most significant 16-bit part when "01" => out64bit(47 downto 32) <= in16bit; when "10" => out64bit(31 downto 16) <= in16bit; when "11" => out64bit(15 downto 0) <= in16bit; when others => null; end case; else NULL; --Do nothing end if; end process; ------------------------------------- end Behavioral; Na wyjściu "FPUDouble" (wynik obliczeń liczba 64 bitowa) umieściłem multiplekser wyjściowy 64 bity na 16 bitów. Oto kod entity Mux64To16: library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity Mux64To16 is Port ( in64bit : in STD_LOGIC_VECTOR (63 downto 0); sel : in STD_LOGIC_VECTOR (1 downto 0); --Adress of 16-bit input (4 parts) out16bit : out STD_LOGIC_VECTOR (15 downto 0); strobe : in STD_LOGIC; -- Active rising edge resetL : in STD_LOGIC; -- Active LOW CLK : in STD_LOGIC -- clock ); end Mux64To16; architecture Behavioral of Mux64To16 is begin SEQ: process (CLK, resetL, strobe) begin if (resetL = '0') then out16bit <= (others => '0'); elsif (strobe' event and strobe = '1') then case sel is when "00" => out16bit <= in64bit(63 downto 48); --Most significant 16-bit part when "01" => out16bit <= in64bit(47 downto 32); when "10" => out16bit <= in64bit(31 downto 16); when "11" => out16bit <= in64bit(15 downto 0); when others => null; end case; else NULL; --Do nothing end if; end process; ------------------------------------- end Behavioral; Dodałem nowy plik źródłowy (VHDL) entity fpu_top, który teraz jest "top entity" projektu (oryginalnie było nim entity fpu_double. oto kod entity fpu_top: LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_misc.all; library work; use work.comppack.all; use work.fpupack.all; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx leaf cells in this code. --library UNISIM; --use UNISIM.VComponents.all; entity fpu_top is PORT( in16bitA : in STD_LOGIC_VECTOR (15 downto 0); selA : in STD_LOGIC_VECTOR (1 downto 0); --Adress of 8-bit input (4 parts) strobeA : in STD_LOGIC; -- Active rising edge resetLA : in STD_LOGIC; -- Active LOW ---- in16bitB : in STD_LOGIC_VECTOR (15 downto 0); selB : in STD_LOGIC_VECTOR (1 downto 0); --Adress of 8-bit input (4 parts) strobeB : in STD_LOGIC; -- Active rising edge resetLB : in STD_LOGIC; -- Active LOW ---- pclk, prst, penable : IN std_logic; prmode : IN std_logic_vector (1 DOWNTO 0); pfpu_op : IN std_logic_vector (2 DOWNTO 0); pout_fp: OUT std_logic_vector (15 DOWNTO 0); -- 16 bit out after Multiplexer pready, punderflow, poverflow, pinexact : OUT std_logic; pexception, pinvalid : OUT std_logic; -- selMux : in STD_LOGIC_VECTOR (1 downto 0); --Adress of 8-bit input (4 parts) strobeMux : in STD_LOGIC; -- Active rising edge resetLMux : in STD_LOGIC -- Active LOW ); end fpu_top; architecture Behavioral of fpu_top is component Demux8To64 is Port ( in16bit : in STD_LOGIC_VECTOR (15 downto 0); sel : in STD_LOGIC_VECTOR (1 downto 0); --Adress of 16-bit input (4 parts) out64bit : out STD_LOGIC_VECTOR (63 downto 0); strobe : in STD_LOGIC; -- Active rising edge resetL : in STD_LOGIC; -- Active LOW CLK : in STD_LOGIC -- clock ); end component; component fpu_double IS PORT( clk, rst, enable : IN std_logic; rmode : IN std_logic_vector (1 DOWNTO 0); fpu_op : IN std_logic_vector (2 DOWNTO 0); opa, opb : IN std_logic_vector (63 DOWNTO 0); out_fp: OUT std_logic_vector (63 DOWNTO 0); ready, underflow, overflow, inexact : OUT std_logic; exception, invalid : OUT std_logic ); end component; component Mux64To16 is Port ( in64bit : in STD_LOGIC_VECTOR (63 downto 0); sel : in STD_LOGIC_VECTOR (1 downto 0); --Adress of 16-bit input (4 parts) out16bit : out STD_LOGIC_VECTOR (15 downto 0); strobe : in STD_LOGIC; -- Active rising edge resetL : in STD_LOGIC; -- Active LOW CLK : in STD_LOGIC -- clock ); end component; signal outDemuxA : STD_LOGIC_VECTOR (63 downto 0); signal outDemuxB : STD_LOGIC_VECTOR (63 downto 0); signal fpuOut64bit : STD_LOGIC_VECTOR (63 downto 0); begin DmuxA : Demux8To64 port map (in16bitA, selA, outDemuxA, strobeA, resetLA, pclk); DmuxB : Demux8To64 port map (in16bitB, selB, outDemuxB, strobeB, resetLB, pclk); FPUD : fpu_double port map (pclk, prst, penable, prmode, pfpu_op, outDemuxA, outDemuxB, fpuOut64bit, pready, punderflow, poverflow, pinexact, pexception, pinvalid ); MuxOut: Mux64To16 port map ( fpuOut64bit, selMux, pout_fp, strobeMux, resetLMux, pclk ); end Behavioral; Tutaj oryginalny kod entity początek fpu_double: LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_misc.all; library work; use work.comppack.all; use work.fpupack.all; ENTITY fpu_double IS PORT( clk, rst, enable : IN std_logic; rmode : IN std_logic_vector (1 DOWNTO 0); fpu_op : IN std_logic_vector (2 DOWNTO 0); opa, opb : IN std_logic_vector (63 DOWNTO 0); out_fp: OUT std_logic_vector (63 DOWNTO 0); ready, underflow, overflow, inexact : OUT std_logic; exception, invalid : OUT std_logic ); END fpu_double; -- FPU Operations (fpu_op): --======================== -- 0 = add -- 1 = sub -- 2 = mul -- 3 = div --Rounding Modes (rmode): --======================= -- 0 = round_nearest_even -- 1 = round_to_zero -- 2 = round_up -- 3 = round_down architecture rtl of fpu_double is ... Niestety źle policzyłem i nadal zabrakło mi pinów I/O - patrz zrzut ekranu poniżej: Tzn. synteza przechodzi bez błędów a są błędy w fazie implementacji bo brakuje pinów I/O. To co mogę zrobić to np. zmienić jeszcze długość magistral IN/OUT do 8 bitów i wprowadzać/wyprowadzać liczby 64-bitowe w ośmiu porcjach po 8-bitów. Drugą opcją jest zastosowanie rejestrów przesuwnych gdzie dane są wprowadzane szeregowo do rejestru równoległego 64 bitowego i na wyjściu wyprowadzane szeregowo. I stąd moje bardziej ogólne pytanie: jakiego rozwiązania używać w przypadku "za długich" magistral w projekcie FPGA? 1) Czy używać wprowadzania/wyprowadzania danych szeregowo (z głównego entity projektu)? 2) Czy używać krótszych magistral np. 1-bajtowych i wprowadzać/wyprowadzać dane porcjami zależnymi od długości głównej magistrali? To o czym jeszcze pomyślałem to zrobić gotowe sprzętowe moduły na CPLD (lub mniejszych FPGA), skracające długości magistral (np. konfigurowalne za pomocą "DIPswitch) i podłączalne do zestawów FPGA (łącznie z własnym drukiem płytki). To co przychodzi mi na myśl w przypadku mojej płytki "Digilent Cmod A7-35T" to użycie 512 kB pamięci SRAM z 8-bitową szyną i czasem dostępu 8 ns Będę odczytywał dane do obliczeń z tej pamięći SRAM (8 bajtów) i zapisywał wynik także w postaci 8 bajtów w innej lokalizacji RAM. Podobny problem napotkałem przy realizacji Soft-CPU "Microblaze" Xilinx'a. Jakieś przemyślenia, czy podpowiedzi ? Będę wdzięczny za każdy komentarz 😃 W drugim załączniku zamieszczam projekt Vivado "FPUDouble" - synteza kończy się pomyślnie, implementacja nie (z powodu braku pinów I/O). Pozdrawiam fpu_double_latest.tar.gz FPUDouble02.zip Link do komentarza Share on other sites More sharing options...
Elvis Maj 3, 2018 Udostępnij Maj 3, 2018 FlyingDutch, wyprowadzanie 64-bitowej magistrali z FPGA oczywiście jest możliwe, ale to chyba trochę bez sensu. Nawet gdyby wystarczyło pinów, to co byś z tą magistralą zrobił? Podłączył 64 przełączniki i diody, żeby wprowadzać dane i odczytywać wyniki? Tak szeroka magistrala ma sens wewnątrz układu - a jak sam już odkryłeś na zewnątrz lepiej używać czegoś mniej wymagającego - magistrali 8-bitowej, czy nawet łącza szeregowego. Ja ostatnio doszedłem do podobnego punktu w moich "studiach" nad FPGA - czyli do zagadki skad brać dane i co z nimi robić. Dlatego kombinuję z procesorami w FPGA - wtedy nie muszę wystawiać i ręcznie dekodować pinów, magistralę można zrealizować wewnątrz układu, a za generowanie, odbieranie, czy przesyłanie danych może odpowiadać procesor. Link do komentarza Share on other sites More sharing options...
FlyingDutch Maj 3, 2018 Autor tematu Udostępnij Maj 3, 2018 FlyingDutch,Tak szeroka magistrala ma sens wewnątrz układu - a jak sam już odkryłeś na zewnątrz lepiej używać czegoś mniej wymagającego - magistrali 8-bitowej, czy nawet łącza szeregowego. Ja ostatnio doszedłem do podobnego punktu w moich "studiach" nad FPGA - czyli do zagadki skad brać dane i co z nimi robić. Dlatego kombinuję z procesorami w FPGA - wtedy nie muszę wystawiać i ręcznie dekodować pinów, magistralę można zrealizować wewnątrz układu, a za generowanie, odbieranie, czy przesyłanie danych może odpowiadać procesor. Cześć Elvis, widzę, że doszliśmy do podobnych wniosków 😉 Na pierwszy rzut spróbuję użyć pamięci SRAM na mojej płytce Cmod-A7 (interfejs pamięci SRAM jest za-mapowany na piny FPGA Artix-7). Poeksperymentuje z soft-CPU "Microblaze" i/lub NIOS (na płytce Maximator) i tym IP core "FPUDouble". Tak z ciekawości znasz może jakieś zestawienie dla ARM Cortex-M7 z STM32Nucleo-F7 ile taktów zegara zajmują 4 działania arytmetyczne z wykorzystaniem FPU tego procka? Pozdrawiam Link do komentarza Share on other sites More sharing options...
Elvis Maj 3, 2018 Udostępnij Maj 3, 2018 Jak będziesz miał jakieś rezultaty z soft-CPU to pisz 🙂 Ja próbuję się zabrać, ale jakoś ciągle mało czasu. Więc poza tutorialem - jak wgrać Nios-a do Maximatora na razie niewiele zrobiłem. A jak chodzi o Cortex-M7 to nie miałem jeszcze czasu się pobawić niestety. Zatrzymałem się na M4, albo raczej przeskoczyłem na A5 😉 Dla M4 informacja jest np. tutaj: http://infocenter.arm.com/help/topic/com.arm.doc.ddi0439b/BEHJADED.html O M7 widzę, że piszą jakie są instrukcje, ale już nie bardzo ile taktów zajmują: http://infocenter.arm.com/help/topic/com.arm.doc.dui0646a/CHDHHAJF.html Ale ogólnie strony ARM-a to chyba najlepszy kierunek poszukiwań. Inna opcja to zrobienie testów - to chyba nawet lepsze, bo można się więcej nauczyć. Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. 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
FlyingDutch Maj 4, 2018 Autor tematu Udostępnij Maj 4, 2018 Jak będziesz miał jakieś rezultaty z soft-CPU to pisz 🙂 Ja próbuję się zabrać, ale jakoś ciągle mało czasu. Więc poza tutorialem - jak wgrać Nios-a do Maximatora na razie niewiele zrobiłem. A jak chodzi o Cortex-M7 to nie miałem jeszcze czasu się pobawić niestety. Zatrzymałem się na M4, albo raczej przeskoczyłem na A5 😉 Dla M4 informacja jest np. tutaj: http://infocenter.arm.com/help/topic/com.arm.doc.ddi0439b/BEHJADED.html O M7 widzę, że piszą jakie są instrukcje, ale już nie bardzo ile taktów zajmują: http://infocenter.arm.com/help/topic/com.arm.doc.dui0646a/CHDHHAJF.html Ale ogólnie strony ARM-a to chyba najlepszy kierunek poszukiwań. Inna opcja to zrobienie testów - to chyba nawet lepsze, bo można się więcej nauczyć. Cześć Elvis, z podanych linków wynika, że FPU w ARM Cortex-M4 jest szybsze niż to z IP core. Np. czas dzielenia dla ArM'a M4 to 14 cykli zegara a dla FPU FPGA 71 cykli. w Microblaze FPU można dodać jako opcję, nie wiem jak to jest z NIOS. Jak będę miał jakieś wyniki to napiszę. Update: udało mi się w pełni zsyntetyzować "FPUDouble" (implementacja przeszła), ale pojawił się nowy problem: Vivado sygnalizuje przekroczenie mocy układu FPGA (wydzielana moc około 33 W, a dopuszczalna 20 W - temperatura układu FPGA przekracza 125 stopni). Patrz zrzut ekranu poniżej: Poprawiłem plik XDC (user constraints) - problem powodowały sygnały: strobeA i strobeB (nie były synchronizowane z głównym zegarem). Rozwiązaniem (brzydkim i chwilowym były klauzule: set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets strobeA] set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets strobeB] w pliku user constraints. Poprawię to niedługo (zsynchronizuję te sygnały z zegarem), ale to trochę później. Teraz wszystkie trzy magistrale z entity fpu_top mają po 8-bitów, dane są wprowadzane i wyprowadzane w ośmiu porcjach. Teraz implementacja zajmuje ułamek wata, patrz obrazek: W załączniku syntetyzujący się projekt Vivado (poprawiony). BTW: znalazłem fajny konwerter liczby Double do 64 bitowej postaci (IEEE754 Double): http://www.binaryconvert.com/convert_double.html Pozdrawiam FPUDouble02P.zip Link do komentarza Share on other sites More sharing options...
FlyingDutch Maj 5, 2018 Autor tematu Udostępnij Maj 5, 2018 Cześć, uruchomiłem implementację "FPU Double" w Vivado z zegarem 100 MHz (okres: 10 ns) i wygląda na to, że projekt może pracować bez problemu z taką częstotliwością (ograniczenia czasowe i wydzielana moc są w prawidłowym zakresie). Czasy poszczególnych operacji arytmetycznych są według autora następujące: Each operation takes the following amount of clock cycles to complete: 1. addition : 20 clock cycles - 200ns 2. subtraction: 21 clock cycles - 210 ns 3. multiplication: 24 clock cycles - 240 ns 4. division: 71 clock cycles - 710 ns --------------------------------------------------------------- Dla zegara 250 MHz implementacja kończy się błędem - nie spełnione ograniczenia czasowe. Dla zegara 142 MHz (okres: 7ns), też nie przechodzi z powodu ograniczeń czasowych. A jednak spróbowałem dla zegara 111 MHz (okres: 9ns) i dla tej częstotliwości układ jeszcze powinien działać OK 😃 Nie chce mi się już więcej próbować, bo każda faza syntezy i implementacji trwa u mnie długo. Wygląda jednak na to że na płytce FPGA CmodA7-35T (Artix-7) projekt jednostki zmiennoprzecinkowej może pracować z max. częstotliwością zegara niewiele większą niż 100 MHz. Następnym etapem prac nad tym projektem będzie ulepszenie design'u: zsynchronizowanie trzech sygnałów strobe z głównym zegarem projektu (dotychczas były asynchroniczne). Następnie wykonanie symulacji układu. Potem wykorzystanie pamięci SRAM z tej płytki FPGA do zapisu danych do obliczeń i wyników (liczby 64-bitowe Double). Na koniec uruchomienie projektu na zestawie FPGA i pomierzenie rzeczywistych czasów wykonania obliczeń. Wklejam, jeszcze link, który był pomocny - ustalenie max.częstotliwości pracy układu: http://billauer.co.il/blog/2017/01/vivado-minimal-period-timing/ Niestety w Vivado, jest to dużo gorsze niż w ISE, bo trzeba uruchamiać syntezę i implementację z różnymi ograniczeniami czasowymi i widzimy, czy implementacja przechodzi bez błędów lub nie. Pozdrawiam Link do komentarza Share on other sites More sharing options...
FlyingDutch Maj 6, 2018 Autor tematu Udostępnij Maj 6, 2018 Cześć, zsynchronizowałem dziś z głównym zegarem płytki FPGA trzy sygnały strobe używane w demultiplekserach i multiplekserze wyjściowym do przepisania porcji danych wejściowych/wyjściowych. Zrobiłem to za pomocą rejestru (można to też osiągnąć za pomocą zwyłkego przerzutnika typu D: zegar podajemy na wejście zegarowe przerzutnika, na wejście D sygnał synchronizowany, a z wyjścia prz. Q bierzemy sygnał zsynchronizowany z zegarem). Utworzyłem entity SyncToClock identyczne jak w bibliotece XESS: https://github.com/xesscorp/VHDL_Lib/blob/master/SyncToClk.vhd Oto ten dodany plik: library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity SyncToClock is generic ( NUM_SYNC_STAGES_G : natural := 2 ); port ( clk_i : in std_logic; -- Clock for the domain being entered. unsynced_i : in std_logic; -- Signal that is entering domain. synced_o : out std_logic -- Signal sync'ed to clock domain ); end entity; architecture arch of SyncToClock is -- This is the sync'ing shift register. The index indicates the number of clocked flip-flops the incoming signal -- has passed through, so sync_r(1) is one clk_i cycle stage, sync_r(2) is two cycles, etc. signal sync_r : std_logic_vector(NUM_SYNC_STAGES_G downto 1); begin process(clk_i) begin if rising_edge(clk_i) then -- Shift the unsync'ed signal into one end of the sync'ing register. sync_r <= sync_r(NUM_SYNC_STAGES_G-1 downto 1) & unsynced_i; end if; end process; -- Output the sync'ed signal from the other end of the shift register. synced_o <= sync_r(NUM_SYNC_STAGES_G); end architecture; Zmieniłem kod głównego projektu - dodałem trzy komponenty SyncToClock w celu synchronizacji sygnałów strobe. Tak teraz wygląda główne entity projektu: LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_misc.all; library work; use work.comppack.all; use work.fpupack.all; entity fpu_top is PORT( in8bitA : in STD_LOGIC_VECTOR (7 downto 0); selA : in STD_LOGIC_VECTOR (2 downto 0); --Adress of 8-bit input (4 parts) strobeA : in STD_LOGIC; -- Active rising edge resetLA : in STD_LOGIC; -- Active LOW ---- in8bitB : in STD_LOGIC_VECTOR (7 downto 0); selB : in STD_LOGIC_VECTOR (2 downto 0); --Adress of 8-bit input (4 parts) strobeB : in STD_LOGIC; -- Active rising edge resetLB : in STD_LOGIC; -- Active LOW ---- pclk, prst, penable : IN std_logic; prmode : IN std_logic_vector (1 DOWNTO 0); pfpu_op : IN std_logic_vector (2 DOWNTO 0); pout_fp: OUT std_logic_vector (7 DOWNTO 0); -- 8 bit out after Multiplexer pready, punderflow, poverflow, pinexact : OUT std_logic; pexception, pinvalid : OUT std_logic; -- selMux : in STD_LOGIC_VECTOR (2 downto 0); --Adress of 8-bit input (4 parts) strobeMux : in STD_LOGIC; -- Active rising edge resetLMux : in STD_LOGIC -- Active LOW ); end fpu_top; architecture Behavioral of fpu_top is component SyncToClock is generic ( NUM_SYNC_STAGES_G : natural := 2 ); port ( clk_i : in std_logic; -- Clock for the domain being entered. unsynced_i : in std_logic; -- Signal that is entering domain. synced_o : out std_logic -- Signal sync'ed to clock domain ); end component; component Demux8To64 is Port ( in8bit : in STD_LOGIC_VECTOR (7 downto 0); sel : in STD_LOGIC_VECTOR (2 downto 0); --Adress of 16-bit input (4 parts) out64bit : out STD_LOGIC_VECTOR (63 downto 0); strobe : in STD_LOGIC; -- Active rising edge resetL : in STD_LOGIC; -- Active LOW CLK : in STD_LOGIC -- clock ); end component; component fpu_double IS PORT( clk, rst, enable : IN std_logic; rmode : IN std_logic_vector (1 DOWNTO 0); fpu_op : IN std_logic_vector (2 DOWNTO 0); opa, opb : IN std_logic_vector (63 DOWNTO 0); out_fp: OUT std_logic_vector (63 DOWNTO 0); ready, underflow, overflow, inexact : OUT std_logic; exception, invalid : OUT std_logic ); end component; component Mux64To16 is Port ( in64bit : in STD_LOGIC_VECTOR (63 downto 0); sel : in STD_LOGIC_VECTOR (2 downto 0); --Adress of 16-bit input (4 parts) out8bit : out STD_LOGIC_VECTOR (7 downto 0); strobe : in STD_LOGIC; -- Active rising edge resetL : in STD_LOGIC; -- Active LOW CLK : in STD_LOGIC -- clock ); end component; signal outDemuxA : STD_LOGIC_VECTOR (63 downto 0); signal outDemuxB : STD_LOGIC_VECTOR (63 downto 0); signal fpuOut64bit : STD_LOGIC_VECTOR (63 downto 0); signal strobeASync : STD_LOGIC; signal strobeBSync : STD_LOGIC; signal strobeMuxSync : STD_LOGIC; begin SyncCLK1 : SyncToClock port map (pclk, strobeA, strobeASync); SyncCLK2 : SyncToClock port map (pclk, strobeB, strobeBSync); SyncCLK3 : SyncToClock port map (pclk, strobeMux, strobeMuxSync); DmuxA : Demux8To64 port map (in8bitA, selA, outDemuxA, strobeASync, resetLA, pclk); DmuxB : Demux8To64 port map (in8bitB, selB, outDemuxB, strobeBSync, resetLB, pclk); FPUD : fpu_double port map (pclk, prst, penable, prmode, pfpu_op, outDemuxA, outDemuxB, fpuOut64bit, pready, punderflow, poverflow, pinexact, pexception, pinvalid ); MuxOut: Mux64To16 port map ( fpuOut64bit, selMux, pout_fp, strobeMuxSync, resetLMux, pclk ); end Behavioral; Mogłem teraz wyrzucić klauzule do obejścia błędów implementacji (złe przekazywanie sygnału zegarowego pomiędzy komponentami) z pliku user constraints: set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets strobeA] set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets strobeB] i nie ma teraz w fazie implementacji żadnych błędów, czy ostrzeżeń. Cały projekt syntetyzuje się poprawnie. W zał. poprawiony projekt Vivado 2018.1. FPUDouble02C.zip Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »