speccy.pl
Facebook Like


WIKI SPECCY.PL

[WIKI SPECCY.PL]
Zaprzyjaźnione serwisy

PIXEL HEAVEN 2018
Forum ZX Spectrum
[SOFTWARE] Odp: Wersje "Copy Copy" wysłana przez rubikus Wczoraj o 19:53:08
[SOFTWARE] Odp: Wersje "Copy Copy" wysłana przez Gryzor Wczoraj o 19:27:29
[SOFTWARE] Odp: Wersje "Copy Copy" wysłana przez rubikus Wczoraj o 19:20:09
[POWITANIA] Odp: Witajcie wysłana przez skoti Wczoraj o 18:38:35
[ZX81] Odp: ZX81 wewnętrzne 32KB RAM wysłana przez Klaud Wczoraj o 15:33:52
[ZX81] Odp: ZX81 wewnętrzne 32KB RAM wysłana przez ZbyniuR Wczoraj o 14:27:16
[POWITANIA] Odp: Witajcie wysłana przez tooloudtoowide Wczoraj o 12:22:13
[NAPRAWY] Odp: Zasilacz do gumiaczka. wysłana przez Klaud Wczoraj o 12:10:55
Archiwum plików ZX Spectrum
[Gra] Dodano "Tajemnica Carmen Strasse 35" z roku 2017 dla komputera ZX Spectrum 48K Autor: smok.wawelski. Dodany przez smok.wawelski, 2018-01-10 09:03:51
[Gra] Dodano "Wunderwaffe" z roku 2017 dla komputera ZX Spectrum 48K Autor: Rafał Miazga. Dodany przez RafalM, 2018-01-09 20:42:39
[Gra] Dodano "Mózg Procesor" z roku 1989 dla komputera ZX Spectrum 48K Autorzy: Piotr Kucharski, Krzysztof Piwowarczyk, Wieslaw Florek. Dodany przez Skinner, 2017-12-20 19:55:10
[Demoscena] Dodano "Jan Hammer Crockett's Theme" z roku 2017 dla komputera ZX Spectrum 48K Autor: ZX Freeq. Dodany przez ZX Freeq, 2017-10-31 08:00:36
[Program użytkowy] Dodano "Kompetny Kurs Kodu Maszynowego TUTOR PL" z roku 1986 dla komputera ZX Spectrum Autorzy: tdu, Bajrasz Łukasz. Dodany przez TDu, 2017-09-11 14:50:57
[Demoscena] Dodano "Extra Life" z roku 2017 dla komputera ZX Spectrum 48K Autor: V0yager. Dodany przez Tygrys, 2017-08-28 23:13:36
[Demoscena] Dodano "Just Don't" z roku 2017 dla komputera ZX Spectrum 48K Autor: kya. Dodany przez Tygrys, 2017-08-28 23:10:44
[Demoscena] Dodano "Through The Dark" z roku 2017 dla komputera ZX Spectrum 48K Autor: tooloudtoowide. Dodany przez Tygrys, 2017-08-28 23:08:13
Więcej...
Nawigacja
Zróbmy sobie układ, część 2

HDL

Hardware Description Language. Język opisu sprzętu, czyli narzędzie, którym się można posłużyć przy projektowaniu układu, gdy nie chcemy składać całości z bramek i bloków funkcjonalnych.
Z Wojny Języków pomiędzy VHDL i Verilogiem obronną ręką wyszły… oba języki. I do dziś niepodzielnie dzierżą prymat. VHDL (Very High Speed Integrated Circuits Hardware Description Language) sięga swoimi korzeniami do Ady lub jak niektórzy twierdzą Pascala. Verilog ma dla odmiany strukturę zbliżoną do C. Oba mogą służyć zarówno do symulacji obwodów, jak i do ich syntezy.
Który wybrać? Warto znać oba. Od którego zacząć? Na pewno od tego który zna NajbliższaZnającaJakiśHDLOsoba ;)
Można także zobaczyć opis tego samego układu napisany w obu językach i po prostu wybrać ten z języków, który wydaje się bardziej zrozumiały.

Symulacja i synteza … czyli jedna z pułapek tworzenia układów programowalnych

HDL to języki pierwotnie służące do opisu i symulacji układów. Możliwość syntezy została w obu dodana później. A zasymulować można dużo. Zarówno loty FTL jak i kulista krowa o punktowej masie dadzą się matematycznie opisać, można stworzyć przeróżne ich modele i wykorzystać w symulacjach. Problemy zaczynają się, gdy ktoś postanowi taki model zmaterializować. Nagle okazuje się, że w najbliższym OBI zabrakło wymaganej ilości materii egzotycznej do silnika FTL (najbliższa dostawa gdzieś w 2257, zapraszamy), a nawet najbardziej spasiona krowa masę owszem ma, ale punktową być bynajmniej nie zamierza.
W przypadku HDL jest podobnie. Zasymulować można dużo, ale do syntezy można wykorzystać jedynie określony podzbiór języka.
Inną pułapką języków HDL, z którą musi się zmierzyć początkujący, jest ich podobieństwo do języków programowania. Pętle w HDL nie są tym, czym pętle w C/Pacalu. Kod nie opisuje kolejnych kroków, które wykonuje układ, ale jego zachowanie i reakcję na sygnały zewnętrzne, a poszczególne części kodu mogą działać – i działają - równolegle.
Uwaga na początek – jeśli gdzieś zobaczymy kod ‘#100 $display("%b",c);’ to nie liczmy na to, że maleńki CPLD automagicznie coś pośle po stu jednostkach czasu na wyświetlacz (czy nawet RSa), oraz pamiętajmy, że nie programujemy układu, ale opisujemy jego działanie.

Verilog...w przykładach.

Na początek – bramka w czterech smakach. Zaczynamy nowy projekt, wybierając jako ‘Top-Level source type’ opcję HDL. Teraz ‘New source’, ’verilog module’, podajemy nazwę (bramki) i naciskając ‘next’ pomijamy wizarda.

module bramki(
    );
endmodule

Tak wygląda pusty moduł w Verilogu.

module bramki(
    input clk,
    input x,
    input y,
    output out_a,
    output out_b,
    output out_c,
    output reg out_d
    );
endmodule


Ponieważ układ musi się komunikować ze światem zewnętrznym, trzeba dodać jakieś sygnały we/wy.
input i output określają kierunek sygnału. reg oznacza, że wyjście out_d przechodzi dodatkowo przez zatrzask.

Pora teraz wypełnić moduł treścią – czyli opisać działanie układu.

module bramki(
    input clk,
    input x,
    input y,
    output out_a,
    output out_b,
    output out_c,
    output reg out_d
    );

// nowy sygnał o nazwie iloczyn
// który przybiera wartość będącą iloczynem sygnałów x i y.
    wire iloczyn;
    assign iloczyn = x & y;

// nowy sygnał my_and 
// któremu od razu przypisujemy taką samą funkcję.
    wire my_and = x & y;

// zatrzask / rejestr / pamięć o wielkości 1bit,
// której wyjście wystawiamy na świat jako out_c
    reg r_out_c;
    assign out_c = r_out_c;

// wartości początkowe zatrzasków
initial begin
    out_d = 0;
    r_out_c = 0;
end

// ale co robi układ?
// do wyjścia out_a podpinamy bloczek o nazwie brAnd,
// typu AND2 (wzięty wprost z biblioteki elementów).
    AND2 brAnd(out_a,x,y);
    
// wyjście out_b zwieramy z sygnałem iloczyn 
// (który został wyżej zdefiniowany jako x & y)
    assign out_b = iloczyn;
    
// przy każdej zmianie sygnału x lub y,
// zatrzask r_out_c przyjmuje wartość x & y
    always@(x or y) r_out_c = x & y;
    
// przy każdej zmianie sygnału clk z 0 na 1 (zbocze narastające) 
// zatrzask/wyjście out_d przyjmuje wartość my_and
    always@(posedge clk) out_d <= my_and;

endmodule

Moduł ma trzy sygnały wejściowe (zegar clk i dane x,y) oraz cztery wyjścia (out_a..d) z czego jedno jawnie posiada zatrzask (out_d), a jedno jest podpięte do zatrzasku zdefiniowanego w module (out_c).
Pojedyncze sygnały definiujemy przez wire. Dwa inne dające się zsyntetyzować rodzaje linii/sygnałów, to wand i wor (wired-and wired-or) czyli iloczyn i suma sygnałów ‘po drucie’.
O tym do czego się mogą przydać jeszcze wrócimy.


‘Wartość‘ sygnałów definiujemy przez assign - po prostu przypisujemy do sygnału wymaganą funkcję logiczną (tu: x & y). Można to zrobić od razu podczas deklarowania sygnału, można w dwóch krokach.


Blok initial określa wartości początkowe zatrzasków. Nie zawsze daje się on zsyntetyzować, zależy to od układu (xilinxy dają radę).


I wreszcie definicja czterech sygnałów wyjściowych.


Trzy układy kombinatoryczne:
Wyjście out_a zostało podpięte pod bramkę AND2 zdefiniowaną w bibliotece elementów (patrz poprzednia część). Warto jednak zawsze pamiętać starą zasadę – lepiej niepotrzebnie nie mieszać. Zwłaszcza że taki bloczek jest wpinany as-is, będzie to widać za chwilę.

Wyjście out_b zostało zwarte ze zdefiniowanym wcześniej sygnałem ‘iloczyn’. Oczywiście można by zapisać po prostu ‘assign out_b = x & y;’ ale skoro jest gotowy sygnał, czemu z niego skorzystać.

Wyjście out_c odzwierciedla stan zatrzasku r_out_c. Natomiast sam zatrzask przyjmuje wartość (x & y) za każdym razem gdy zmieni się stan któregoś z wejść x lub y ( ‘[email protected](x or y)’ można zastąpić bardziej uniwersalnym '[email protected](*)' ) )


Jeden układ synchroniczny :
Wyjście/zatrzask out_d przyjmuje wartość (x & y) przy każdym narastającym zboczu zegarowym.




Zobaczmy teraz, co z tego opisu zrobił układ syntezy :

Jak widać element z biblioteki został wbudowany w układ i pozostawiony bez dalszej optymalizacji.

Widać też, że w przypadku pozostałej części układu, ‘syntezator’ wykazał się pewnym sprytem.
Zauważył, że tak naprawdę cały czas operujemy na tym samym sygnale (x & y), oraz że zatrzask r_out_c nic nie daje (oprócz zbędnych opóźnień) – więc go wyeliminował.




Zobaczmy teraz jak będzie wyglądał układ fizyczny :

Kolejna niespodzianka - i coś co trzeba zapamiętać – do wejść / wyjść, które są połączone ze światem zewnętrznym, zawsze zostaną dodane bufory I/O i trzeba to brać pod uwagę. Dlatego jeśli ktoś wpadnie na pomysł żeby sobie zbudować generator pierścieniowy z trzech, czy pięciu bramek, to nie ma sprawy, będzie działać (pomińmy kwestie stabilności i temperatur… i jakby co – u mnie działał :) Jeśli ktoś wpadnie na pomysł żeby sobie wyprowadzić bramki na zewnątrz, zlinearyzować i podpiąć kwarc, powinien jeszcze raz przemyśleć układ, bo ten pomysł raczej nie zadziała.



module bramki_tb;

    // Inputs
    reg clk;
    reg x;
    reg y;

    // Outputs
    wire out_a;
    wire out_b;
    wire out_c;
    wire out_d;

    // Instantiate 
    // the Unit Under Test (UUT)
    bramki uut (
        .clk(clk), 
        .x(x), 
        .y(y), 
        .out_a(out_a), 
        .out_b(out_b), 
        .out_c(out_c), 
        .out_d(out_d)
    );

    initial begin
        // Initialize Inputs
        clk = 0;
        x = 0;
        y = 0;

        // Wait 100 ns for 
        // global reset to finish
        #100;
        
        // Add stimulus here
    end

    always #10 clk <= !clk;
    always #25 {x,y} <= {x,y}+1;
endmodule

Zdefiniowany powyżej moduł można także wykorzystać jako bloczek - element większego układu albo w czymś, co nazywa się test bench i pozwala dokonać symulacji naszego układu.
Startujemy - ‘New source’ - ‘Verilog test fixture’ - nazwa ‘bramki_tb’ i jako source wybieramy ‘bramki’.
Program stworzył nam nowy moduł bramki_tb bez wejść i wyjść, z trzema zatrzaskami (po jednym na każde wejście badanego układu), czterema sygnałami out_* (po jednym na wyjście) oraz wstawił od razu instancję naszego modułu nazywając ją uut.
Warto i trzeba zauważyć, że przy wstawianiu ISE wykorzystał drugą metodę ‘podłączania’ modułu. Przy wstawianiu bramki (moduł biblioteczny AND2) wykorzystałem wiedzę, że sygnały modułu zostały zdefiniowane w postaci wyjście-wejście-wejście. ISE stosuje bezpieczniejszą metodę, nazywając wprost wejścia/wyjścia do których podpina sygnały (.x(sigX) – wejście .x układu łączymy z sygnałem sigX )
Jedyne co nam pozostało to dodanie sygnału zegarowego oraz zadbanie o zmianę sygnałów x i y.
Jak? Zegar najprościej przez ‘always #20 clk <= !clk;’ (nie, to się nie syntetyzuje!)
A sygnały... Sygnały omówimy w następnym odcinku :)

Teraz, po kliknięciu w ‘simulation’ (nad okienkiem z drzewkiem plików), wybraniu poniżej ‘bramki_tb’ można wreszcie kliknąć na proces ‘iSim simulator’ by otrzymać wynik jak poniżej.


Jak widać, układ działa zgodnie z założeniami, a sygnał zegarowy jest zbyt wolny :)
Uwaga: iSim uruchamia symulację jedynie na okres czasu zdefiniowany w tym polu:
Można kontynuować symulacje po kawałeczku klikając na przyciski obok tego pola, lub wpisać w nie od razu dłuższy czas symulacji.

Garść linków

Czyli lektura dla chętnych.

Internet jest pełen przeróżnej dokumentacji dotyczącej zarówno VHDLa jak i Veriloga. Nie krępujcie się szukać!

Co dalej

W kolejnej części rzucimy się na głęboką wodę – będą busy, rejestry, zagrzebiemy tristejta i stworzymy projekt czegoś bardziej praktycznego niż bramka logiczna.


steev
Brak komentarzy. Może czas dodać swój?
Dodaj komentarz
Nick:

Kod potwierdzający:
Kod potwierdzający


Oceny
Tylko zarejestrowani użytkownicy mogą oceniać zawartość strony
Zaloguj się , żeby móc zagłosować.

Brak ocen. Może czas dodać swoją?