Realizacja własnych modułów IP Cores w srodowisku EDK Zespół Rekonfigurowalnych Systemów Obliczeniowych AGH Kraków http://www.fpga.agh.edu.pl/ 3.10.2007 1
Wstęp Celem ćwiczenia jest zapoznanie się z możliwościami realizacji własnych modułów urządzeń peryferyjnych współpracujących z procesorem MicroBlaze za pośrednictwem magistrali OPB. Spełnienie pewnych formalnych założeń przy projektowaniu własnego urządzenia umożliwia jego późniejsze wykorzystanie jako modułu automatycznie rozpoznawanego i zintegrowanego ze środowiskiem EDK. W ćwiczeniu zaproponowano metodę projektowania własnego sprzętu w oparciu o interfejs IPIC skojarzony z elementem bibliotecznym IPIF dostarczonym przez firmę Xilinx. Wykorzystanie tego uniwersalnego elementu pośredniczącego w komunikacji modułu użytkownika z magistrala OPB przyśpiesza integrację własnych urządzeń ze środowiskiem EDK oraz chroni przed koniecznością zachowania dbałości o spełnienie wymagań czasowych modułów IPCores projektowanych dla EDK. Ponadto IPIC umożliwia migrację urządzeń peryferyjnych pomiędzy różnymi magistralami systemowymi dostępnymi w środowisku EDK oraz pomiędzy kolejnymi wersjami pakietu. Jako przykład w poniższym ćwiczeniu zaprezentowany będzie dodatkowy moduł RTC (ang. Run-Time clock). i sposób jego integracji ze środowiskiem EDK. Moduł zostanie uruchomiony w konfiguracji z procesorem Microblaze, modułem interfacu szeregowego opb_uart Light, pojedynczą magistralą OPB oraz dwoma magistralami LMB. Wymagania Przed przystąpieniem do ćwiczenia dobrze jest zapoznać się z User Core Templates Reference Guide. Aby możliwe było ukończenie ćwiczenia konieczna jest także podstawowa znajomość środowiska EDK. (wykonanie odpowiednich ćwiczeń i przykładów). Przygotowanie do ćwiczenia POLECENIE Utworzyć katalog o wybranej przez siebie nazwie realizowanego projektu (Projekt_Katalog) i rozpakować do niego zawartość pliku MBCores.zip (http://www.fpga.agh.edu.pl/russek/sprzetowa/mbcores.zip). Po rozpakowaniu powinniśmy otrzymać trzy pliki: RTC.vhd, RTC.vhi, system.c Dodatkowo, korzystając z umiejętności zdobytych podczas pierwszych ćwiczeń, należy w tym folderze wygenerować przykładowy projekt EDK (w dalszej części ćwiczenia będziemy go potrzebować). Opis części składowych ćwiczenia Sposób integracji urządzeń ze środowiskiem EDK zostanie zaprezentowany na przykładzie modułu zegara czas rzeczywistego RTC W celu realizacji ćwiczenia należy posłużyć się przygotowanymi w VHDL komponentem RTC. Znajduje się on w Projekt_Katalog\RCT.vhd. Moduł RTC Moduł RTC jest bardzo prostym układem zegara czasu rzeczywistego. Jego wyprowadzenia przedstawia rysunek poniżej. Funkcję sygnałów zestawiono w tabeli. 2
Nazwa sygnału Opis Wr Sygnał zapisu czasu do modułu RTC. Kiedy Wr= 1 wraz z narastającym zboczem zegara wpisywany jest czas wystawiony na liniach BCDHourIn, BCDMinIn, BCDSecIn BCDHourIn[7:0] Sygnał wejściowy. Godzina w kodzie BCD BCDMinIn[7:0] Sygnał wejściowy. Minuta w kodzie BCD BCDSecIn[7:0] Sygnał wejściowy. Sekunda w kodzie BCD BCDHourOut[7:0] Sygnał do odczytu. Godzina w kodzie BCD BCDMinOut[7:0] Sygnał do odczytu. Minuta w kodzie BCD BCDSecOut[7:0] Sygnał do odczytu. Sekunda w kodzie BCD Stop Sygnał zatrzymania zegara. Stop=1: zegar nie liczy Rst Reset Clk Zegar. POLECENIE Zapoznać się z zawartością pliku RTC.vhd Przygotowanie IPCore zegara czasu rzeczywistego Wykorzystanie w projekcie EDK własnego modułu wymaga umieszczenie jego opisu w katalogu pcores znajdującego się w każdym katalogu z projektem EDK. W katalogu pcores znajdują się elementy IPCore użytkownika i zawartość tego katalogu jest wczytywana do EDK podczas otwierania projektu. Każdy moduł użytkownika ma swój podkatalog o nazwie składającej się z nazwy modułu i numeru wersji EDK dla której był przygotowany (Np.:.\pcores\RTC_Core_v1_00_a ) W pierwszej fazie przygotowana własnego modułu IPCore współpracującego z magistrala OPB najwygodniejsze jest posłużenie się narzędziem do generowania szablonu nowo tworzonego IPCore. Narzędzie Create-Import Pheripherial ułatwia zastosowanie odpowiedniego nazewnictwa dla nowo tworzonego modułu (nazewnictwo musi uwzględniać numer wersji EDK), tworzy odpowiednia strukturę katalogów z plikami projektowymi nowego IPCore i wyręcza projektanta w wielokrotnym powielaniu typowych informacji wspólnych dla wielu IPCore. 3
POLECENIE: Uruchomić z menu Start->Xilinx Platform Studio 8.2i->Accessories-> Create and Import Peripheral Wizard. Wybrać kolejno: 4
5
Zaznaczyć: Bus2IP_Clk, Bus2IP_Reset, Bus2IP_Addr, Bus2IP_Data, Bus2IP_BE, Bus2IP_RdCE, Bus2IP_WrCE, Bus2IP_CS IP2Bus_Data, IP2Bus_Ack, IP2Bus_Retry, IP2Bus_Error IP2Bus_ToutSup. a następnie Finish. 6
W wyniku pracy narzędzia powstaje katalog rtccore_v1_00_a w katalogu pcores. Katalog zawiera podkatalogi: /data zawiera pliki MPD (opisujące sposób dołączania modułu IPCore do magistral w EDK) oraz PAO (zawiera informacje o tym jak kompilować moduł) /hdl zawiera opis modułu w języku opisu sprzętu: plik rtccore nadrzędny plik projektowy. Zawiera deklarację i konkretyzację elementów składowych IPCore a: USER_LOGIC oraz OPB_IPIF plik user_logic szablon pliku w którym znajdzie się opis pracy układu zbudowanego przez użytkownika. Plik jest wstępnie przygotowany tak aby dobrze pasował do interfacu OPB_IPIC. /devl zawiera miedzy innymi projekt ISE umożliwiający niezależną implementację IPCore Integracja elementu RTC z USER_LOGIC POLECENIE Do katalogu Projekt_Katalog\pcores\rtccore_v1_00_a\hdl\vhdl skopiować plik RTC.vhd (plik ten był zawarty w pliku MBCores.zip ściągniętym ze strony). Otworzyć wygenerwany przez Create-Import periperal projekt ISE znajdujący się w katalogu Projekt_Katalog\pcores\RTC_core\devl\projnav. Projekt ten znakomicie ułatwi wprowadzanie modyfikacji w utworzonym automatycznie szablonie. 7
POLECENIE Do projektu ISE dodać plik Projekt_Katalog\pcores\rtccore\hdl\vhdl\RTC.vhd. (W okienku sources klikamy prawym przyciskiem myszy i wybieramy Add Source). POLECENIE: Zmodyfikować architekturę USER_LOGIC w user_logic.vhd dodając w odpowiednie miejsca fragmenty zamieszczonego kodu (Poniższy kod źródłowy znajduje się w pliku RTC.vhi dostępnym w pliku MBCores.zip) component RTC is port ( Rst : in std_logic; --asynchronious Clk: in std_logic; --50MHz BCDHourIn: in std_logic_vector (7 downto 0); BCDMinIn: in std_logic_vector (7 downto 0); BCDSecIn: in std_logic_vector (7 downto 0); BCDHourOut: out std_logic_vector (7 downto 0); BCDMinOut: out std_logic_vector (7 downto 0); BCDSecOut : out std_logic_vector (7 downto 0); Wr: in std_logic; Stop: in std_logic); end component RTC; signal Wr: std_logic; ------------------------------------------------------------------------------- -- Begin architecture ------------------------------------------------------------------------------- process( Bus2IP_WrCE, Bus2IP_CS) begin if( Bus2IP_WrCE(0)='1' AND Bus2IP_CS(0)='1') then Wr<='1'; else Wr<='0'; end if; end process; RTC_0: RTC port map (Rst=>Bus2IP_Reset, Clk => Bus2IP_Clk, BCDHourIn=>Bus2IP_Data(8 to 15), BCDMinIn=>Bus2IP_Data(16 to 23), BCDSecIn=>Bus2IP_Data(24 to 31), BCDHourOut=>IP2Bus_Data(8 to 15), BCDMinOut=>IP2Bus_Data(16 to 23), BCDSecOut=>IP2Bus_Data(24 to 31), Wr=>Wr, Stop=>Stop); IP2Bus_Ack IP2Bus_Error IP2Bus_Retry IP2Bus_ToutSup <= Bus2IP_WrCE(0) or Bus2IP_RdCE(0); <= '0'; <= '0'; <= '0'; W ten sposób deklarujemy komponent RTC (konstrukcja component) łączymy sygnały IPIC z sygnałami modułu zegarowego RTC (konstrukcja port map) oraz zapewniamy sygnał strobu zapisu Wr (konstrukcja process). Dokonać próbnej syntezy projektu po zmianach. Usunąć ewentualne błędy. 8
Sygnał zewnętrzny STOP Ponieważ narzędzie Create-Import periperal nie zapewnia możliwości dodania do elementu IPIC sygnałów zewnętrznych nie będących częścią interfacu IPIC musimy takie sygnały dodać ręcznie w kodzie źródłowym elementu rtccore. Moduł zegara zawiera sygnał STOP zatrzymujący zliczanie czasu który powinien być dostępny na zewnątrz systemu/układu FPGA. POLECENIE: Wykorzystując edytor kodu vhdl wbudowany w project Navigator, kolejno dodać port stop w: rtccore entity (w pliku rtccore.vhd) entity rtccore is generic ( -- ADD USER GENERICS BELOW THIS LINE --------------- --USER generics added here -- ADD USER GENERICS ABOVE THIS LINE --------------- -- DO NOT EDIT BELOW THIS LINE --------------------- -- Bus protocol parameters, do not add to or delete C_BASEADDR : std_logic_vector := X"00000000"; C_HIGHADDR : std_logic_vector := X"0000FFFF"; C_OPB_AWIDTH : integer := 32; C_OPB_DWIDTH : integer := 32; C_FAMILY : string := "virtex2p" -- DO NOT EDIT ABOVE THIS LINE --------------------- ); port ( -- ADD USER PORTS BELOW THIS LINE ------------------ stop : in std_logic; -- ADD USER PORTS ABOVE THIS LINE ------------------ user_logic port map (w pliku rtccore.vhd) USER_LOGIC_I : entity rtccore_v1_00_a.user_logic port map ( -- MAP USER PORTS BELOW THIS LINE ------------------ --USER ports mapped here -- MAP USER PORTS ABOVE THIS LINE ------------------ Bus2IP_Clk Bus2IP_Reset Bus2IP_Addr Bus2IP_Data Bus2IP_BE Bus2IP_CS Bus2IP_RdCE Bus2IP_WrCE IP2Bus_Data IP2Bus_Ack IP2Bus_Retry IP2Bus_Error IP2Bus_ToutSup stop => stop ); => ibus2ip_clk, => ibus2ip_reset, => ibus2ip_addr, => ubus2ip_data, => ubus2ip_be, => ubus2ip_cs, => ubus2ip_rdce, => ubus2ip_wrce, => uip2bus_data, => iip2bus_ack, => iip2bus_retry, => iip2bus_error, => iip2bus_toutsup, entity user_logic (w pliku user_logic.vhd) entity user_logic is generic 9
( -- ADD USER GENERICS BELOW THIS LINE --------------- --USER generics added here -- ADD USER GENERICS ABOVE THIS LINE --------------- -- DO NOT EDIT BELOW THIS LINE --------------------- -- Bus protocol parameters, do not add to or delete C_AWIDTH : integer := 32; C_DWIDTH : integer := 32; C_NUM_CS : integer := 1; C_NUM_CE : integer := 1 -- DO NOT EDIT ABOVE THIS LINE --------------------- ); port ( -- ADD USER PORTS BELOW THIS LINE ------------------ stop : in std_logic; -- ADD USER PORTS ABOVE THIS LINE ------------------ Chodzi o to, aby dodany port Stop przewędrował przez całą hierarchię projektu od elementu rtccore do elementu RTC. Dokonać próbnej syntezy projektu po zmianach. Usunąć ewentualne błędy Rysunek poniżej przedstawia sposób w jaki komponent USER_LOGIC ma być podłączony do elementu bibliotecznego OPB_IPIF. Zmiany w pliku MPD Na końcu pliku rtccore_v2_1_0.mpd ( Projekt_Katalog\pcores\rtccore_v1_00_a\data ) dodać deklarację portu użytkownika STOP: # --USER-- change to user core ports PORT stop = "", DIR = IN 10
Struktura katalogu z IPCore Opis modułu rtccore składa się z następujących plików: Projekt_Katalog\pcores\rtccore_v1_00_a\hdl\vhdl\RTC.vhd opis modułu RTC Projekt_Katalog\pcores\rtccore_v1_00_a\hdl\vhdl\rtccore.vhd opis modułu rtccore Projekt_Katalog\pcores\rtccore_v1_00_a\hdl\vhdl\user_logic.vhd opis modułu USER_LOGIC Projekt_Katalog\pcores\rtccore_v1_00_a\data\rtccore_v2_1_0.mpd opis zewnętrznej struktury rtccore dla potrzeb narzędzia EDK. Projekt_Katalog\pcores\rtccore_v1_00_a\data\rtccore_v2_1_0.pao lista bibliotek i elementów składowych modułu rtccore koniecznych do jego kompilacji. O ile opis pracy modułu znajduje się oczywiście w plikach VHDL to, aby możliwa była integracja z pakietem EDK konieczne są dodatkowe opisy elementu zawarte w plikach MPD (Microprocessor Peripherial Description) i PAO (Peripherial Analyze Order). Zmiany w pliku PAO Plik PAO zawiera listę elementów składowych modułu wraz z nazwami bibliotek w których się znajdują. Ponieważ przy tworzeniu logiki użytkownika korzystamy z dodatkowego modułu RTC element ten należy dopisać do biblioteki kompilatora POLECENIE: Do listy elementów w pliku PAO (Projekt_Katalog\pcores\rtccore_v1_00_a\data\rtccore_v2_1_0.pao ) dopisać elementy biblioteki rtccore: lib rtccore_v1_00_a RTC Projekt EDK Dalsza część ćwiczenia kontynuujemy w środowisku EDK. POLECENIE: Otwieramy Start->Xilinx Platform Studio 8.2i->Xilinx Platform Studio Otwieramy projektu Projekt_Katalog\system.xmp. W otwartym projekcie przystępujemy do uzupełnienia systemu z procesorem Microblaze. Nasz projekt powinien składać się z elementów zestawionych w tabeli poniżej. 11
Nazwa komponentu Wer. Początek przestrzeni adresowej Koniec przestrzeni adresowej microblaze 4.00b lmb_bram_if_cntlr 1.00b 0x00000000 0x00001FFF lmb_bram_if_cntlr 1.00b 0x00000000 0x00001FFF bram_block 1.00a opb_uartlite 1.00b 0xFFFF4000 0xFFFF40FF rtccore 1.00a 0xFFFF5000 0xFFFF50FF Zmieniamy adres bazowy RTC_core na $FFFF5000 Należy zwrócić uwagę na fakt, że element rtccore nie jest integralnym składnikiem pakietu EDK, a jego dostępność na liście w oknie dialogowym IP Catalog wynika z obecności jego opisu w katalogu pcores/rtccore_v1_00_a. Zestawione w tabeli elementy łączymy ze sobą za pośrednictwem magistrali OPB_v20. Podłączamy sygnały W zakładce ports wybieramy sygnał stop i w kolumnie net wybieramy make external (spowoduje to, że ten port będzie zewnętrzny i będzie można do niego przypisać przycisk). Następnie rozwijamy External ports i sprawdzamy nazwę zewnętrznego portu stop (będzie nam ona potrzebna przy modyfikacji pliku ucf. Modyfikacja w pliku ucf Zakładamy, że nasz system będzie dysponował następującymi sygnałami: (fragment dostarczonego pliku ucf) #------------------------------------------------------------------------------ # Clock Period Constraints #------------------------------------------------------------------------------ NET "sys_clk" PERIOD = 20 ns ; # czestotliwosc 50MHz #------------------------------------------------------------------------------ # IO Pad Location Constraints #------------------------------------------------------------------------------ NET "sys_clk" LOC = "T9"; NET "sys_rst" LOC = "M13"; #Button 0 ## RS232 Interface NET "TX" LOC = "R13"; NET "RX" LOC = "T13"; #PUSHBUTTONS NET "rtccore_0_stop_pin" LOC = "M14"; #Button 1 Ważne jest, aby zachować właściwe nazwy sygnałów w celu późniejszej zgodności z użytym plikiem ucf. 12
Kompilacja systemu i kodu POLECENIE Skompilować projekt Hardware->Generate Netlist. Sprawdzić, czy operacja przebiegła poprawnie. Poprawić ewentualne błędy. Program dla MB Dołączyć do projektu program procesora microblaze, znajduje się on w pliku system.c dostępnym w pliku MBCores.zip. Teraz możemy skompilować biblioteki ( najpierw zaznaczamy przy naszym programie Mark to initialize BRAMs): Software->Generate Libraries and BSPs. Następnie kompilujemy nasz program: Software->Build All user applications. Sprawdzić, czy operacja przebiegła poprawnie. Poprawić ewentualne błędy. Tworzenie pliku programującego FPGA Po poprawnej kompilacji pozostało nam już tylko wygenerowanie plików system.bit i download.bit. Aby to zrobić wybieramy: Hardware->generate bitstream; Device configuration->update bitstream. HyperTerminal Uruchomić: Start->programy->akcesoria->komunikacja->HyperTerminal i zaznaczyć właściwości jak na poniższym rysunku: 13
Programowanie płytki: W celu zaprogramowania płytki uruchamiamy program Impact, i programujemy ją plikiem download.bit. Uruchomić: Start->Programy->Xilinx ISE 8.2i->Accessories->iMPACT i zaznaczyć jak poniżej: 14