Języki Opisu Sprzętu Prowadzący: dr inż. Andrzej Skoczeń Współrzędne: D-10 222, tel. w. 28-72, e-mail: skoczen@fis.agh.edu.pl Dwa oblicza systemu cyfrowego Opcje projektowe dla systemu cyfrowego Wykład 2 2018 8 październik 2018 Przykład syntezy Typy danych do Veriloga Modelowanie na poziomie bramek http://www.fis.agh.edu.pl/~skoczen/hdl AGH WFiIS Informatyka Stosowana Języki Opisu Sprzętu 1
Współprojektowanie sprzętu i oprogramowania System Sprzęt Program Hardware/Software codesign Współprojektowanie oprogramowania i sprzętu to projektowanie współpracujących składników sprzętowych i programowych w jednym zadaniu projektowym. Sprzęt (hardware) Oprogramowanie (software) Sztywny (fixed) Elastyczny (flexible) Współprojektowanie oprogramowania i sprzętu to podział projektu aplikacji na część stałą i elastyczną.
Opcje projektowe układu cyfrowego Układ cyfrowy może być zaprojektowany jako: ASP Application-Specific Processors CSPP Computing Systems with Programmable Procedure RCS Reconfigurable Computing Systems ASIC µp µc DSP Układ programowalny Fullcustom Cellbased Gate Array GA PLD FPGA CPLD SCL Biblioteka komórek standardowych Makra skompilowane RAM/ROM/PLA Platformy IP ROM PLA PAL Czyste FPGA Słowniczek: SCL Standard Cell Library ASIC Application Specific Integrated Circuits µc microcontroller PLD Programmable Logic Device µp microprocessor CPLD Complex Programmable Logic Device DSP Digital Signal Processor IP Intellectual Property PLA Programmable Logic Array PAL Programmable Array Logic SoC System-on-Chip SoPC System-on-Programmable-Chip DSP FPGA Platformy FPGA dla SoPC 3
Synteza Kod RTL licznika 4-bitowego w Verilogu: Rozwiniecie tego kodu w syntezatorze w postaci schematu: module count (input clk, rst, output reg [3:0] q); always @(posedge clk) if(rst) q <= 4 b0; else q <= q + 1 b1; endmodule Synplify, Synopsys
module count (clk, rst, q); input clk, rst ; output [3:0] q ; wire clk, rst ; wire [3:1] q_rno; wire [0:0] q_i; wire GND_x, VCC_x, GND, VCC ; // @6:7 LUT2_L q_rno[1] (.I0(q[0]),.I1(q[1]),.LO(q_RNO[1])); defparam q_rno[1].init=4'h6; // @6:3 LUT1_L q_i[0] (.I0(q[0]),.LO(q_i[0])); defparam q_i[0].init=2'h1; // @6:7 LUT3_L q_rno[2] (.I0(q[0]),.I1(q[1]),.I2(q[2]),.LO(q_RNO[2])); defparam q_rno[2].init=8'h78; // @6:7 LUT4_L q_rno[3] (.I0(q[0]),.I1(q[1]),.I2(q[2]),.I3(q[3]),.LO(q_RNO[3])); defparam q_rno[3].init=16'h7f80; // @6:3 FDR q[3] (.Q(q[3]),.D(q_RNO[3]),.C(clk),.R(rst)); // @6:3 FDR q[2] (.Q(q[2]),.D(q_RNO[2]),.C(clk),.R(rst)); // @6:3 FDR q[1] (.Q(q[1]),.D(q_RNO[1]),.C(clk),.R(rst)); // @6:3 FDR q[0] (.Q(q[0]),.D(q_i[0]),.C(clk),.R(rst)); GND GND_cZ (.G(GND)); VCC VCC_cZ (.P(VCC)); endmodule /* count */ Synteza Synplify, Synopsys 5
Węzeł (net) Jest to klasa typów danych, z których największe znaczenie ma typ wire. Słowo net nie jest słowem kluczowym. Węzeł reprezentuje połączenie między elementami sprzętu. Węzeł ma wartość w sposób ciągły sterowaną przez wyjście przyrządu (driver), do którego jest połączony (gate level). Przypisania do zmiennych węzłowych mogą się odbywać jedynie za pomocą przypisania ciągłego assign (data flow level). Najczęściej używanym typem węzła jest wire. Domyślną wartością węzła jest z. Typ wire jest typem domyślnym. wire a; wire [3:0] b; wire d = 1 b0; Uproszczona wersja przypisania ciągłego Inne typy węzłowe: wand wor tri triand Montażowy AND (open kolektor) Montażowy OR Typy danych Veriloga Typ podobny do wire ale umożliwiający użycie na nim więcej niż jednego sterownika Montażowy AND (open kolektor) //deklaracja węzła a //deklaracja magistrali czterobitowej //deklaracja i ustawienie na stałe //wartości zero trior tri0 tri1 trireg Montażowy OR Domyślne 0 gdy węzeł nie jest sterowany Domyślne 1 gdy węzeł nie jest sterowany Węzeł utrzymujący wartość Typy wire i tri są identyczne składniowo i funkcjonalnie. Standard definiuje dwie nazwy aby nazwa typu węzła wskazywała na role tego węzła w modelu. Węzeł typu wire należy używać dla węzłów sterowanych jedną bramką lub przypisaniem ciągłym. Węzeł typu tri należy używać tam gdzie wiele sterowników steruje węzłem. 6
module closedrain(input w, x, y, z, output wire f); nand n1 (f, w, x); nand n2 (f, y, z); endmodule Typy danych Veriloga wire 0 1 x z 0 0 x x 0 1 x 1 x 1 x x x x x z 0 1 x z Tabela prawdy rozwiązywania konfliktów dwóch sterowników (o tej samej mocy sygnału) dla węzła typu wire i tri. Incisive, Cadence f w x y z 7
wire 8
module tb; reg w, x, y, z; wire f; module opendrain(input w, x, y, z, output wand f); nand n1 (f, w, x); nand n2 (f, y, z); endmodule opendrain uut (.w(w),.x(x),.y(y),.z(z),.f(f)); initial begin w = 1'b0; x = 1'b0; y = 1'b0; z = 1'b0; #10 x = 1'b1; #10 w = 1'b1; #40 $finish; end endmodule Typy danych Veriloga wand 0 1 x z 0 0 0 0 0 1 0 1 x 1 x 0 x x x z 0 1 x z Tabela prawdy rozwiązywania konfliktów dwóch sterowników (o tej samej mocy sygnału) dla węzła typu wand i triand Incisive, Cadence f w x y z 9
wand open drain open drain 10
Incisive, Cadence Typy danych Veriloga module opendrain(input w, x, y, z, output wor f); nor n1 (f, w, x); nor n2 (f, y, z); endmodule wor 0 1 x z 0 0 1 x 0 1 1 1 1 1 x x 1 x x z 0 1 x z Tabela prawdy rozwiązywania konfliktów dwóch sterowników (o tej samej mocy sygnału) dla węzła typu wor i trior f w x y z wire f w x y z wor 11
wor 12
Rejestr (reg) Reprezentuje element przechowujący informację. Należy rozróżnić dwie rzeczy: rejestr sprzętowy zbudowany z przerzutników, rejestr w Verilog-u czyli zmienną utrzymującą wartość. Rejestry w przeciwieństwie do węzłów nie potrzebują układów sterujących. Zmienna typu reg może zmieniać wartość w każdej chwili symulacji ale wyłącznie za pomocą przypisania proceduralnego (behavioral level). Domyślną wartością zmiennej typu reg jest x. reg reset; Typy danych Veriloga //deklaracja zmiennej reset initial begin reset = 1 b1; //inicjacja zmiennej reset na 1 #100 reset = 1 b0; //po 100 jednostkach czasu reset jest //zerowany end 13
Typy danych Veriloga Wektory Węzły i zmienne typu reg mogą być deklarowane jako wektory. Nawiasy kwadratowe pomiędzy słowem kluczowym a nazwą zmiennej określają ilość bitów i ich kolejność. Pierwsza liczba w nawiasach zawsze oznacza najbardziej znaczący bit. wire [7:0] bus; //deklaracja magistrali 8-bitowej bus wire [31:0] busa, busb, busc; //trzy magistrale 32-bitowe reg [0:40] virtual_addr; //wektor rejestrowy 41-bitowy Jak odwoływać się do tak zadeklarowanych zmiennych? bus[7] //najbardziej znaczący bit magistrali bus busa[31] //najbardziej znaczący bit magistrali busa bus[2:0] //trzy najmniej znaczące bity wektora bus bus[0:2] //niepoprawne odwołanie gdyż najbardziej //znaczący bit zawsze musi stać po lewej //stronie zakresu specyfikacji virtual_addr[0:1] //dwa najbardziej znaczące bity wektora //virtual_addr 14
Typ rejestrowy integer Wartości typu reg są bez znaku (unsigned). Wartości typu integer są ze znakiem (signed). Wygodniejsze np. do zliczania. Typowa szerokość: 32 bity. integer counter; initial counter = -1; Typy danych Veriloga //deklaracja zmiennej counter //-1 wpisano do counter Typ rejestrowy real Liczby rzeczywiste mogą być w notacji dziesiętnej (decimal) lub naukowej (scientific). Kiedy wartość zmiennej real jest przypisywana do zmiennej typu integer jest ona zaokrąglana do najbliższej wartości całkowitej. real delta; //deklaracja zmiennej rzeczywistej initial begin delta = 4e10; //przypisanie w notacji naukowej delta = 2.13; //przypisanie w notacji dziesiętnej end integer i; initial i = delta; //i otrzymuje wartość 2 (zaokrąglone 2.13) Wynik otrzymany w symulatorze Incisive : 0ns delta=2.13 i=2 15
Typ rejestrowy time Typy danych Veriloga Symulacje prowadzone są względem czasu symulacji. Jest on przechowywany w specjalnym rejestrze time. Jest on co najmniej 64-bitowy. Funkcja systemowa $time służy do określania bieżącego czasu symulacji. Czas symulacji jest mierzony w sekundach symulacyjnych. Związanie tego czasu z rzeczywistym czasem upływającym w prawdziwym układzie cyfrowym odbywa się przez zdefiniowanie skali czasowej. Można to zrobić oddzielnie dla każdego modułu za pomocą dyrektywy kompilatora `timescale. time save_sim_time; initial save_sim_time = $time; //deklaracja zmiennej czasowej //zapamiętaj bieżący czas symulacji Typ rejestrowy realtime Przechowuje czas symulacji w postaci zmiennej rzeczywistej Typ indeksowy genvar Podobny do integer, ale o specjalnym zastosowaniu do indeksowania pętli generate. 16
Tablice (arrays) W Verilogu-95 możliwe są tylko tablice jednowymiarowe zmiennych rejestrowych. Zmienne węzłowe w ogóle nie mogą występować w postaci tablic. Należy je odróżnić od wektorów. Wektor to element n-bitowy, podczas gdy tablica jest obiektem wieloelementowym złożonym z 1- lub n-bitowych elementów. integer count[0:7] //zmienna tablicowa o 8-u elementach //integer reg bool[31:0] //zmienna tablicowa o 32-u //elementach reg skalarnych time chk_point[1:100] //tablica 100 punktów czasowych reg [4:0] port_id[0:7] count[5] Typy danych Veriloga //tablica 8 wektorów 5-bitowych //typu reg //wartość 5-ego elementu w tablicy count chk_point[100] //wartość 100-ego elementu czasowego w //tablicy chk_point port_id[3] //5-bitowa wartość 3-ego elementu w tablicy //port_id 17
Typy danych Veriloga Pamięci (memories) Są to tablice rejestrów. Każdy element tablicy to jedno słowo. Słowo jest dostępne poprzez adres, którym jest indeks tablicy. Verilog-1995 reg mem1bit[0:1023] //pamięć o pojemności 1K 1-bitowych słów reg [7:0] membyte[0:1023] //pamięć o pojemności 1K 8- //bitowych słów membyte[511] //pobranie 1 bajtowego słowa spod adresu 511 18
Tablice wielowymiarowe W Verilog-2001, - zarówno zmienne węzłowe jak i rejestrowe mogą być deklarowane w postaci wielowymiarowych tablic: reg [31:0] array2[0:255][0:15]; wire [7:0] array3[0:255][0:255][0:255]; trój-wymiarowa tablica ośmiobitowych węzłów dwu-wymiarowa tablica 32-bitowych wektorów rejestrowych Verilog-2001 Dostęp do takich danych jest możliwy zarówno do całego słowa jak i do jednego bitu jaki i do części jednego słowa: wire [7:0] out3 = array3[addr1][addr2][addr3]; do całego słowa wire [7:0] out2 = array2[100][7][31:24]; najbardziejznaczący bajt jednego słowa w dwu-wymiarowej tablicy 19
Poziom bramek Poziom bramek - gate level Moduł jest tutaj opisywany z użyciem konkretyzacji innych modułów tzn. bramek logicznych i połączeń między nimi. Ten poziom jest bardzo podobny do tworzenia schematu układu z użyciem bramek logicznych. Realizacje modułów - Instances Moduł jest wzorcem, z którego można stworzyć rzeczywisty obiekt. Kiedy chcemy wykorzystać istniejący moduł, Verilog kreuje unikalny obiekt według wzorca zawartego w module. Ten proces kreowania obiektów z wzorcowych modułów nazywa się urealnianiem instantiation. Powstałe w ten sposób obiekty nazywa się urealnieniami (konkretyzacjami, aktualizacjami, urzeczywistnieniami, realizacjami, instancjami) instances. gate level 20
Urealnienia z parametrami gate level modulename [#(listaparam)] instancename (portconnect); Indywidualizacja instancji przez przypisanie parametrom wartości. Elementy tej listy:.paramname_module(value),... Wartość parametru value może być podana: Bezpośrednio liczbą Za pomocą lokalnego parametru localparam lub dostarczonego z wyższego poziomu hierarchii poprzez parametr. 21
Instancja (urealnienie) Lista parametrów kolejność lub przez nazwy.nazwa(wartość) gate level instances modulename #(paramters) instancename (portconnect); Nazwa urealnianego modułu Nazwa urealnienia Lista połączeń specyfikowana przez kolejność lub przez nazwy.name_module(name_instance) 22
Bufory predefiniowane Verilog posiada predefiniowane bufory (proste i odwracające). Nie potrzebują one definicji modułów ale można je urealniać w taki sposób jak inne moduły. gate level Bufory Invertery buf not zwykłe bufif1 notif1 Trójstanowe sterowane stanem wysokim bifif0 notif0 Trójstanowe sterowane stanem niskim Mogą mieć wiele wyjść ale dokładnie jedno wejście. Ostatni port jest wejściem, a pozostałe wyjściami. Jeśli występuje dodatkowy port sterujący to on jest ostatni. wire OUT1, OUT2, IN, CTRL; buf b1(out1, IN); buf b1_2out(out1, OUT2, IN); bufif1 b1(out1, IN, CTRL); Tabele prawdy tych elementów uwzględniają wartości x i z na wejściach. 23
not Bufory predefiniowane in out not in out 0 1 1 0 gate level X Z X X buf in out buf in out 0 0 1 1 X Z X X 24
notif1 in Bufory predefiniowane ctrl out ctrl notif1 0 1 X Z 0 Z 1 H H 1 Z 0 L L in X Z X X X gate level Z Z X X X bufif1 in out ctrl bufif1 0 1 X Z 0 Z 0 L L ctrl in 1 Z 1 H H X Z X X X Z Z X X X 25
notif0 in Bufory predefiniowane ctrl out ctrl notif0 0 1 X Z 0 1 Z H H 1 0 Z L L in X X Z X X gate level Z X Z X X bufif0 in out ctrl bufif0 0 1 X Z 0 0 Z L L ctrl in 1 1 Z H H X X Z X X Z X Z X X 26
Multiplekser 2-do-1 i0 i1 out module mux (output tri out, input i0, i1, s); bufif0 b0 (out, i0, s); bufif1 b1 (out, i1, s); endmodule s i0 Incisive, Cadence i1 out s 27
Bramki predefiniowane gate level Verilog posiada predefiniowane bramki. Nie potrzebują one definicji modułów ale można je urealniać w taki sposób jak inne moduły. and or xor nand nor xnor N-wejściowe bramki: Pierwszy port jest wyjściem, a następne wejściami. wire OUT, IN1, IN2, IN3; and a1 (OUT, IN1, IN2); nand na1_3 (OUT, IN1, IN2, IN3); //urealnianie bez nazwy jest także poprawne and (OUT, IN1, IN2); Tabele prawdy tych elementów uwzględniają wartości x i z na wejściach. 28
Bramki predefiniowane i1 gate level nand i1 i2 out i2 nand 0 1 X Z 0 1 1 1 1 1 1 0 X X X 1 X X X Z 1 X X X i1 and i1 i2 out i2 and 0 1 X Z 0 0 0 0 0 1 0 1 X X X 0 X X X Z 0 X X X 29
nor Bramki predefiniowane i1 out i2 i1 nor 0 1 X Z 0 1 0 X X i2 1 0 0 0 0 X X 0 X X Z X 0 X X gate level i1 or i1 i2 out or 0 1 X Z 0 0 1 X X i2 1 1 1 1 1 X X 1 X X Z X 1 X X 30
Bramki predefiniowane xnor i1 i2 out i1 xnor 0 1 X Z 0 1 0 X X i2 1 0 1 X X X X X X X Z X X X X gate level i1 xor i1 i2 out xor 0 1 X Z 0 0 1 X X i2 1 1 0 X X X X X X X Z X X X X 31
Multiplekser 2-do-1 i0 i1 s out 0 0 0 0 0 1 0 0 1 0 2 0 1 0 0 3 0 1 1 1 4 1 0 0 1 5 1 0 1 0 6 1 1 0 1 7 1 1 1 1 s i0 i1 00 01 11 10 s 0 0 2 6 4 1 1 3 7 5 i0 i1 00 01 11 10 0 0 0 1 1 1 0 1 1 0 out = s i0 + s i1 a0 a1 32
i0 sbar Multiplekser 2-do-1 a0 i1 out s a1 module mymux (output out, input s, i0, i1); wire sbar; not (sbar, s); and (a0, i0, sbar); and (a1, i1, s); or (out, a1, a0); endmodule 33
i0 sbar Multiplekser 2-do-1 a0 i1 a1 out s Incisive, Cadence i0 i1 out s 34
Multiplekser D 0 D 1 D 2 D 3 Z D 0... D n Z A 0...A m A 0 A 1 Multiplekser 4-do-1 Potrzebuje dwa wejścia adresowe do zakodowania czterech różnych adresów Multiplekser n-do-1 gdzie n=2 m -1 gdzie m jest liczbą bitów wejścia adresowego 35
module mux4_to_1(output out, wire s1n, s0n; wire y0, y1, y2, y3; not (s1n, s1); not (s0n, s0); and (y0, i0, s1n, s0n); and (y1, i1, s1n, s0); and (y2, i2, s1, s0n); and (y3, i3, s1, s0); or (out, y0, y1, y2, y3); endmodule Multiplekser 4 do 1 input i0, i1, i2, i3, s1, s0); Uwaga Bramki podstawowe nie wymagają nazw urealnień (instancji). Instancje modułów definiowanych przez nas muszą mieć unikalne nazwy. gate level To jest nie konieczne gdyż sygnały jednobitowe domyślnie są typu wire. 36
Opóźnienia Inercyjne Właściwe dla bramek i przypisań ciągłych. Sygnał krótszy od opóźnienia bramki w ogóle nie jest przez bramkę propagowany. in in t p =3 out 0 2 4 6 8 10 12 14 out Inercyjne Transportowe Każdy sygnał krótszy jest przez połączenie propagowany. Transportowe AGH, WFiIS, IS, st.i, HDL 37
Parametry czasowe bramek gate level Czas narastania narast Potrzebny na przejście wyjścia bramki dostanu 1 Czas opadania opad Potrzebny na przejście wyjścia bramki dostanu 0 Czas wyłączenia wył Potrzebny na przejście wyjścia bramki dostanu z 0, x, z 1, x, z Dla przejścia do wartości x działa najmniejsza z trzech wartości. and #(czas) a1(out, i1, i2); and #(narast, opad) a1(out, i1, i2); narast opad 1 0 bufif0 #(narast, opad, wył) b1(out1, out2, in, control); Dodatkowo każdy z trzech czasów może być podany za pomocą trzech liczb rozdzielonych dwukropkami: min:typ:max. Odpowiednia wartość jest wybierana w zależności od opcji linii komend elaboratora. bufif0 #(2:3:4, 3:4:5, 4:5:6) b1(out1, out2, in, control); AGH, WFiIS, IS, st.i, HDL 38
Opóźnienia bramek max/typ/min gate level Opóźnienia mogą być maksymalne, typowe lub minimalne. Wyboru można dokonywać w czasie wykonania za pomocą opcji elaboratora: -maxdelays, -typdelays, -mindelays. Domyślnie przyjmowane są wartości typowe. //if -mindelays, opóźnienie=4 //if -typdelays, opóźnienie=5 //if -maxdelays, opóźnienie=6 and #(4:5:6) a1(out, i1, i2); //if -mindelays, narast=3, opad=5, wył=min(3,5) //if -typdelays, narast=4, opad=6, wył=min(4,6) //if -maxdelays, narast=5, opad=7, wył=min(5,7) and #(3:4:5, 5:6:7) a1(out, i1, i2); Incisive, Cadence irun maxdelays *.v //if -mindelays, narast=2, opad=3, wył=4 //if -typdelays, narast=3, opad=4, wył=5 //if -maxdelays, narast=4, opad=5, wył=6 bufif0 #(2:3:4, 3:4:5, 4:5:6) b1(out1, out2, in, control); AGH, WFiIS, IS, st.i, HDL 39
Opóźnienia bramek i węzłów module del(); reg i1, i2; wire #(2) in2 = i2; wire #(1) in1 = i1; and #(5) a1 (o1, in1, in2); Incisive, Cadence initial begin i2 = 1'b1; i1 = 1'b0; #3 i1 = 1'b1; #6 i1 = 1'b0; #1 i1 = 1'b1; #5 i1 = 1'b0; #6 i1 = 1'b1; end endmodule i1 i2 in1 in2 o1 Inercyjne AGH, WFiIS, IS, st.i, HDL 40
Opóźnienia bramek i węzłów module del(); reg i1, i2; wire #(3) in2 = i2; wire #(2) in1 = i1; and #(5) a1 (o1, in1, in2); i1 Incisive, Cadence initial begin i2 = 1'b1; i1 = 1'b0; #3 i1 = 1'b1; #6 i1 = 1'b0; #1 i1 = 1'b1; #5 i1 = 1'b0; #6 i1 = 1'b1; end endmodule i2 in1 in2 o1 Inercyjne AGH, WFiIS, IS, st.i, HDL 41
Opóźnienia bramek i węzłów module buf3del(); reg i, ctrl; bufif1 #(2) b1 (o1, i, ctrl); bufif1 #(2,3) b2 (o2, i, ctrl); bufif1 #(2,3,1) b3 (o3, i, ctrl); Incisive, Cadence initial begin i = 1'b0; ctrl = 1'b0; #2 ctrl = 1'b1; #6 i = 1'b1; #4 i = 1'b0; #6 i = 1'b1; #7 ctrl = 1'b0; end endmodule ctrl i o1 o2 o3 AGH, WFiIS, IS, st.i, HDL 42