Magistrale systemowe

   Współczesne układy cyfrowe zdominowane zostały przez mikroprocesory oraz w mniejszym stopniu przez układy FPGA lub inne sekwencyjne automaty stanów. Przez taki stan rzeczy prawie w każdym cyfrowym urządzeniu spotkać można jakąś postać przemysłowej lub dedykowanej magistrali systemowej. Magistral te mają ma kluczowe wpływ na wydajność opartych na nich systemach. Bardzo często są wąskim gardłem systemu i to najczęściej one określają czy dany układ scalony zostanie zastosowany w projektowanym systemie. W tym artykule poddano analizie zagadnienia związane z magistralami oraz dostarczono wskazówek umożliwiających na wybór najlepszej opcji przy projektowaniu systemów opartych o układy FPGA.

Podział magistral

   Do wyboru jest wiele magistral. Aby przybliżyć problem przedstawiono ogólne informacje o magistralach używanych w sprzęcie elektronicznym.

   Magistrale w zależności od zastosowań można podzielić na wiele kategorii. Jedną nich jest podział na magistrale zewnętrzne i wewnętrzne.

   Wewnętrzne magistrale systemowe to magistrale używane w układzie scalonym lub w modelu wgranym w układ FPGA. Używa się ich do wymiany danych pomiędzy blokami wewnątrz układu takimi jak procesor, kontroler VGA czy USB. Istnieje wiele typów magistral. Na początku magistrala miała charakter zbliżony do klasycznych magistral równoległych używanych w komunikacji między układami. Jednak z czasem, w celu poprawienia osiągów układów scalonych nastąpiło wyraźne oddzielenie się magistral wewnątrz układowych od standardów używanych na zewnątrz układu.

   Jedną z cech ułatwiająca łączenie magistral wewnątrz układów jest niewymuszony ale jednak brak bramek trójstanowych. Takie samo podejście można przyjąć w przypadku magistral zewnętrznych jednak dwukrotne poszerzenie magistrali danych na ogół jest zbyt kosztowne. W przypadku magistral bez buforów trójstanowych, w układach scalonych, dostęp realizuje się poprzez dwa oddzielne jednokierunkowe porty. Inna cecha to szerokość magistrali. Nierzadko zdarza się, że magistrala ma ponad 100 linii danych i adresowych. W układach scalonych szerokość magistrali nie jest krytycznym problemem przy tworzeniu struktury krzemowej dlatego też wiele standardów opiera się właśnie na szerokiej magistrali. Jednak coraz częściej zaczyna się obserwować trend minimalizowania szerokości połączeń wewnątrz układu. Spowodowane jest to tym, że przy dużych układach szeregowy interfejs zajmuje stosunkowo mało powierzchni krzemu więc niewielkim kosztem można znacznie ułatwić tworzenie całego układu.

   Za przykład magistral wewnętrznych może posłużyć magistrala AMBA firmy ARM czy magistrala Wishbone bardzo popularna w darmowych modelach dostępnych na stronie
www.opencores.org. Podczas tworzenia prostych projektów nie ma potrzeby używania żadnej skomplikowanej magistrali komunikacyjnej wewnątrz układu FPGA.

   Wybierając magistralę jaką należy zastosować w prostym układzie trzeba określić kilka czynników. Dopiero po dokładnej analizie można określić jaki interfejs będzie najlepszy. Pewne pomocne wskazówki umieszczono poniżej:

  • Wskazane jest stosowanie magistral wewnętrznych synchronicznych. Ułatwia to projektowanie układu, a następnie jego symulacje i optymalizacje. Wprawdzie coraz popularniejsze asynchroniczne rozwiązania pobierają o ok. połowę mniej mocy jednak ze względu na stopień skomplikowania nie są używane w prostych modelach w FPGA
  • W przypadku gdy bloki pracują w dwóch różnych domenach zegarowych najłatwiej jest użyć FIFO wygenerowane w przypadku firmy Xilinx narzędziem CoreGenerator
  • Gdy z jakiś powodów należy użyć modelu w którym magistrala została określona prze dostawcę, konieczne jest albo przestawienie się na ten typ komunikacji lub wymagane jest użycie konwertera zwanego wrapper’em
  • Z reguły nie stosuje się transmisji danych wewnątrz układów FPGA w postaci szeregowej, Ze względu na charakter układu FPGA w większości przypadków nie przyśpiesza to wymiany danych pomiędzy modułami

   W przypadku magistral zewnętrznych ilość standardów umożliwiających połączenie układów jest dużo większa niż w przypadku magistral wykorzystywanych wewnątrz układów scalonych czy układów FPGA. Prawie każdy elektronik słyszał o magistralach ISA, PCI, RS232, USB czy SPI. Od początku istnienia cyfrowych układów elektronicznych istniały magistrale wymiany danych pomiędzy modułami. Bardzo szybko okazało się że standardy w tym przypadku są bardzo opłacalne. Standaryzacja magistral, czyli sposoby wymiany danych, poziomów napięć, ograniczeń czasowych bardzo przyśpieszyła rozwój elektroniki. Jest to sprawa oczywista. Niestety na przestrzeni lat nie udało się stworzyć jednej uniwersalnej magistrali wymiany danych, W prawdzie na rynku istnieją wiodące standardy takie jak PCI jednak w tym przypadku każda z nich nadaje się do innych zastosowań. Analizując obecny trend w zewnętrznych magistralach systemowych zauważyć można rozwój ukierunkowany na szybkie szeregowe interfejsy oparte na wspólnej warstwie fizycznej, będącej rozwinięciem standardu LVDS czy CML. Dotyczy to rynku multimediów czyli obejmuje standardy DVI, HDMI czy nowy Display Port oraz inne standardy lub dziedziny gdzie coraz częściej stosuje się serializery/deserializery zwane serdes’ami. We wspomnianych interfejsach często występuje kilka linii szeregowych, jednak nie będzie nadużyciem jeśli magistrale te zostaną zakwalifikowane do magistral szeregowych [2].
   W przypadku wolnozmiennych sygnałów nadal popularnych jest wiele typów przeróżnych interfejsów.

Przykład magistrali systemowej

   W przykładowym układzie jako magistralę zewnętrzną, łączącej mikroprocesor z FPGA i modułem USB, zdecydowano się na klasyczną synchroniczną magistralę adresowo-danych z dodatkowym sygnałem zerującym. Omawianym układem jest system lpc_xc2s_ftdi którego wygląd i schemat blokowy przedstawiono na rysunkach 1 i 2:


Rys 1. Widok zmontowanego systemu


Rys 2. schemat blokowy układu

   Jak widać jest to prosta i wydajna magistrala. Jedyną jej wadą jest stosunkowo duża ilość zajmowanych bitów co może niekiedy być źródłem problemów. Jako alternatywę można użyć prostego interfejsu SPI i komunikację z modułem oprzeć na wbudowanym w mikrokontroler kontrolerze Host-SPI. Jednak zaprojektowanie Device-SPI wewnątrz układu FPGA wcale nie jest takie łatwe, a ze względu na szeregowy charakter magistrali prędkości transmisji również nie należy do najszybszych. Godnym uwagi pomysłem jest połączenie magistrali danych i adresowej na zasadach podobnych jak to ma miejsce w modułach LCD 2x16 i układach pamięciowych takich jak NAND-Flash [1]. Przez takie połączenie uzyskiwane jest zmniejszenie ilości zajmowanych bitów przy jednocześnie niewielkim spadku prędkości.

   W tym przypadku najlepszym połączeniem okazało się rozwiązanie z osobną magistralą adresową i danych. Za tym rozwiązaniem przemawia również fakt, że magistrala danych jest współdzielona z układem odpowiedzialnym za transmisję USB, co przy połączeniu z magistralą adresową utrudniłoby transmisje DMA pomiędzy modelem a układem USB. Zrealizowany na tym urządzeniu przykładowy układ okresomierza i częstościomierza nie wymaga dużych transferów danych, jednak projektując system postawiono na uniwersalność rozwiązania. Innym czynnikiem który zadecydował o wyborze magistrali jest duży zapas niewykorzystanych pinów w układach mikrokontrolera i układu FPGA.
Główna magistrala danych systemu przedstawiona została na rysunku:


Rys 3. Magistrala systemowa układu

Jak widać na rysunku 3, do komunikacji mikrokontrolera LPC2148 z FPGA użyto następujących linii sterujących:

  • uc_clk. Sygnał taktujący wszelkie operacje zapisu odczytu przeprowadzane pomiędzy mikrokontrolerem LPC2148 a układem FPGA
  • uc_rst. Sygnał zerujący. Gdy ten sygnał jest ustawiony to następuje ustawienie do wartości początkowej wszystkich wewnętrznych rejestrów procesora. Sygnał zerujący musi trwać przynajmniej jeden cykl zegarowy
  • uc_wr. Sygnał określający kierunek wymiany danych. Mikrokontroler zapisuje dane do układu FPGA
  • uc_rd. Sygnał określający kierunek wymiany danych. Mikrokontroler odczytuje dane z układu FPGA
  • uc_address. Magistrala adresowa, wskazuje rejestr wewnętrzny w układzie FPGA na którym będzie przeprowadzona operacja zapisu/odczytu
  • data. Magistrala danych. Współdzielona z interfejsem USB.

Połączenie Mikrokontroler - USB

   W zaprojektowanym układzie mikrokontroler może komunikować się z układem odpowiedzialnym za wymianę danych pomiędzy urządzeniem pomiarowym a komputerem PC. W układzie użyto układu FT245BM firmy FTDI o asynchronicznym interfejsie wymiany danych. Znaczenie sygnałów modułu USB jest następujące:

  • usb_rxf. Sygnał informujący o danych w module USB, które są do odebrania przez mikrokontroler
  • usb_txe. Sygnał informujący o możliwości przyjęcia przez moduł USB kolejnych danych do wysłania do komputera PC
  • usb_wr. Sygnał żądania zapisu danych do modułu USB
  • usb_rd. Sygnał żądania odczytu z modułu USB
  • data. Magistrala danych

   Na rysunku 4 przedstawiono przebieg sygnałów przy zapisie i odczycie danych do i z układu USB FT245BM przez mikrokontroler:

image004_s480.png
Rys 4. Wykresy czasowe operacji odczytu i zapisu dla modułu USB

Zależności czasowe przedstawionych przebiegów dostępne są w dokumentacji układu FT245BM [3].

   Fragment kodu źródłowego umożliwiającego komunikację mikrokontrolera
z rejestrami modelu urządzenia pomiarowego przedstawiono na listingu 1:

always@(posedge uc_clk)
begin
   if (sys_rst == 1'b1)
      begin
         //resetowanie_sygnalow_wewnetrznych
      end
   else
   case (uc_adr)
      Adres_A:
         begin
           dane_dla_uc <= rejestr_wewnetrzny_X;
         end
      Adres_B:
         begin
            dane_dla_uc <= rejestr_wewnetrzny_Y;
            if (uc_wr_n == 1'b0)
            begin
               rejestr_wewnetrzny_Z <= dane_z_uc;
            end
         end
   endcase
end
List.1. Przykładowy interfejs wymiany danych pomiędzy modelem a mikrokontrolerem

   Poza znanymi już konstrukcjami języka Verilog komentarza wymagają konstrukcje ściśle powiązane z przykładowym interfejsem przedstawionym na listingu 1.
Zasadę zaprezentowanego modułu można opisać w następujący sposób:

  • sys_rst == 1'b1. W przypadku aktywnego sygnału zerującego sys_rst wszystkie rejestry wewnętrzne ustawiane są do wartości początkowej. W przeciwnym przypadku układ pracuje wg ustalonego algorytmu
  • Adres_A, Adres_B. W zależności od pojawienia się któregoś z tych adresów na magistrali adresowej modułu, wykonywany zostaje kod zawarty pomiędzy słowami kluczowymi begin/end
  • dane_dla_uc <= rejestr_wewnetrzny_Y. Dane z rejestru wewnętrznego przepisywane są do rejestru wyjściowego modułu. W tym przypadku nie jest konieczne badanie stanu sygnału uc_rd, ponieważ na wyjściu układu znajduje się zespół 8 bramek trójstanowych, które wystawiają zawartość rejestru dane_dla_uc tylko w przypadku gdy sygnał uc_rd jest aktywny
  • rejestr_wewnetrzny_Z. Rejestr modułu pomiarowego, który nadpisywany jest wartością rejestru dane_z_uc w przypadku, gdy adres uc_adr i sygnał zapisu uc_wr mają odpowiednie wartości [4].

Kod na Mikrokontroler

   Kod części odpowiedzialnej za komunikację modułu po stronie mikrokontrolera przedstawiono poniżej:

//Stan poczatowy w modelu. Reset modelu
void CoreResetFpga(void){
   FIOSET1 = uc_rst | uc_wr | uc_rd;
   FIOCLR1 = uc_clk;
   FIOSET1 = uc_clk;
   FIOCLR1 = uc_rst;
   FIOCLR1 = uc_clk;
   FIOSET1 = uc_clk;
}

//Zapis do rejestru modelu
void CoreWriteByteToFpga(unsigned char address, unsigned char value){
   SYS_DATA_DIR = sys_data_out;
   UC_ADR_PIN = address;
   SYS_DATA_PIN = value;
   FIOSET1 = uc_rd;
    FIOCLR1 = uc_rst | uc_wr | uc_clk;
   FIOSET1 = uc_clk;
   FIOSET1 = uc_wr;
   SYS_DATA_DIR = sys_data_in;
}

//Odczyt z rejestru modelu FPGA
void CoreReadByteFromFpga(unsigned char address, unsigned char *value){
   SYS_DATA_DIR = sys_data_in;
   UC_ADR_PIN = address;
   FIOSET1 = uc_wr | uc_rd;
   FIOCLR1 = uc_rst | uc_rd | uc_clk;
   FIOSET1 = uc_clk;
    *value = SYS_DATA_PIN;
   FIOSET1 = uc_rd;
}

W powyzszych przykładach pojawiaja się przypisania zawierające FIOCLR1, UC_ADR_PIN itd. Okreslaja one rejestry mikroprocesora i kryja pod soba definicje:

#define UC_ADR_PIN (*((volatile unsigned char *) 0x3FFFC036))
#define FIOCLR1 (*(volatile unsigned long *) (0x3FFFC03C))

Odpowiednie adresy znajduja się w specyfikacji procesora LPC2148

W przypadku wartości uc_clk, uc_rd itd. ich prawdziwe znaczenie to definicje:

#define uc_clk 0x01000000
#define uc_rd 0x10000000

i oznaczają bit w rejestrze który należy ustawić lub wyzerować

W przypadku wymiany danych pomiedzy mikrokontrolerem a modułem USB przydatne okazują się funkcje:

//Odczytanie pojedynczego bajtu z USB
unsigned char ReadByteFromUsb (void){
   unsigned char tmp;
   SYS_DATA_DIR = sys_data_in;
   while(FIOPIN0 & usb_rxf);
   FIOCLR0 = usb_rd;
   FIOCLR0 = usb_rd;
   FIOCLR0 = usb_rd;
   FIOCLR0 = usb_rd;
   FIOCLR0 = usb_rd;
   tmp = SYS_DATA_PIN;
   FIOSET0 = usb_rd;
   return tmp;
}

//Zapisanie pojedynczego bajtu do USB
void WriteByteToUsb (unsigned char byte){
   SYS_DATA_DIR = sys_data_out;
   while(FIOPIN0 & usb_txe);
   FIOSET0 = usb_wr;
   FIOSET0 = usb_wr;
   SYS_DATA_PIN = byte;
   FIOCLR0 = usb_wr;
   FIOCLR0 = usb_wr;
   SYS_DATA_DIR = sys_data_in;
}

Podsumowanie i literatura

    Nie da się uciec przed magistralami w cyfrowych układach elektronicznych. Stanowią one szkielet prawie każdego zaawansowanego jak i prostego urządzenia. Ich zaprojektowanie wymaga w przypadku dużych projektów wyjątkowej wiedzy, gdyż to właśnie one tworzą szkielet konstrukcji i zapewniają przepływ informacji bez szkodliwych dla systemu wąskich gardeł. Dobrą wiadomością jest to, że bez względu na stopień złożoności projektowanego często to nie one stanowią wyzwanie konstruktora a w przypadku prostych układów są nawet niezauważalne.

Pozycje wykorzystane bezpośrednio do opracowania treści artykułu:

  • [1] Wikipedia. Wydanie angielskie, www. en.wikipedia.org. Pojęcia: Integrated_circuit, Flash_memory, USB, FireWire
  • [2] LVDS Owner’s Manual Including High-Speed CML and Signal Conditioning. Fourth Edition, National Semiconductor 2008
  • [3] FT245BM USB FIFO IC Data Sheet. Revision 1.8, FTDI CHIP, 2008
  • [4] J.Bhasker, Verilog HDL Synthesis, Star Galaxy Publishing, Allentown 1989

Autorem artykułu jest mgr inż. Krzysztof Fijak