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 Przypisania nieblokujące Stosowanie opóźnień w przypisaniach Wykład 4 2018 15 październik 2018 Proceduralne przypisania ciągłe Operatory w Verilogu Dyrektywy kompilatora Veriologa Instrukcje sterujące - wprowadzenie http://www.fis.agh.edu.pl/~skoczen/hdl AGH WFiIS Informatyka Stosowana Języki Opisu Sprzętu 1
Reguły stosowania przypisań blokujących i nieblokujących Podstawowe zasady syntezowalności kodu Zawsze używaj przypisań blokujących (=) w blokach always przeznaczonych do tworzenia układów kombinacyjnych, Zawsze używaj przypisań nieblokujących (<=) w blokach always przeznaczonych do tworzenia układów sekwencyjnych, Nie mieszaj obu typów przypisań w jednym bloku always, Nie wykonuj przypisań do tej samej zmiennej w dwóch różnych blokach always. AGH, WFiIS, HDL 2
reg x, y,z; initial begin x = #5 1'b0; //x otrzymuje wartość 0 w chwili 5 y = #3 1'b1; //y otrzymuje wartość 1 w chwili 8 z = #6 1'b0; //z otrzymuje wartość 0 w chwili 14 end x y z Incisive, Cadence AGH, WFiIS, HDL 3
reg x, y,z; initial begin x <= #5 1'b0; //x otrzymuje wartość 0 w chwili 5 y <= #3 1'b1; //y otrzymuje wartość 1 w chwili 3 z <= #6 1'b0; //z otrzymuje wartość 0 w chwili 6 end x y z Incisive, Cadence AGH, WFiIS, HDL 4
reg a, b,c, d; initial begin a <= #5 1'b0; //a otrzymuje wartość 0 w chwili 5 b = #3 1'b1; //b otrzymuje wartość 1 w chwili 3 c <= #6 1'b0; //c otrzymuje wartość 0 w chwili 9 d = #7 1'b0; //d otrzymuje wartość 0 w chwili 10 end a b c d Incisive, Cadence AGH, WFiIS, HDL 5
reg a, b,c, d; initial begin a = #5 1'b0; //a otrzymuje wartość 0 w chwili 5 b <= #3 1'b1; //b otrzymuje wartość 1 w chwili 8 c = #6 1'b0; //c otrzymuje wartość 0 w chwili 11 d <= #7 1'b0; //d otrzymuje wartość 0 w chwili 18 end a b c d Incisive, Cadence AGH, WFiIS, HDL 6
Nieblokujące przypisanie proceduralne (c.d.) Stosowane są jako metoda modelowania równoczesnego transferu danych kilkoma różnymi drogami zachodzącego w momencie wystąpienia pewnego zdarzenia. always @ (posedge clock) begin reg1 <= #1 in1; reg2 <= @(negedge clock) in2 ^ in3; reg3 <= #1 reg1; //stara wartość reg1 end Przy każdym narastającym zboczu zegara zachodzi następująca sekwencja zdarzeń: Odczytane zostają wartości zmiennych in1, in2, in3, reg1 występujących po stronie prawej przypisań. Wyrażenia występujące z prawej strony są obliczane, a ich wyniki zapamiętywane w tymczasowych zmiennych symulatora. Operacje wpisania uzyskanych wyników do strony lewej są umieszczane w kolejce wykonania pod czasami określonymi w instrukcjach. Tzn. zapis zmiennych reg1 i reg3 jest zaplanowany na chwilę czasu 1 po narastającym zboczu zegara, a zapis zmiennej reg2 odbędzie się w chwili wystąpienia opadającego zbocza zegara. Operacje przypisania są wykonywane w przewidzianym czasie. Faktyczna kolejność przestaje być istotna gdyż przypisywane wartości są już obliczone i czekają. W ten sposób wiadomo, że w reg3 znajdzie się stara wartość reg1 nawet jeśli przypisanie do reg1 nastąpi wcześniej. AGH, WFiIS, HDL 7
Nieblokujące przypisanie proceduralne (c.d.) Dwa równoczesne bloki always z przypisaniami sekwencyjnymi always @(posedge clock) a = b; always @(posedge clock) b = a; Występuje hazard. Nie wiemy, która z operacji zostanie wykonana wcześniej. Zawartości rejestrów nie zostaną wymienione, ale w obydwu znajdzie się ta sama wartość tzn. początkowa wartość a lub b, zależnie od konkretnej implementacji Veriloga. AGH, WFiIS, HDL 8
Nieblokujące przypisanie proceduralne (c.d.) Dwa równoczesne bloki always z przypisaniami równoczesnymi always @(posedge clock) a <= b; always @(posedge clock) b <= a; Zawartości zmiennych a i b zostaną zamienione na każdym narastającym zboczu zegara, gdyż operacje są wykonywane z pośredniczeniem przez zmienne tymczasowe. To samo można osiągnąć inaczej, ale dłużej przy użyciu zmiennych tymczasowych. AGH, WFiIS, HDL 9
Nieblokujące przypisanie proceduralne (c.d.) Stosowanie przypisań nie blokujących wyklucza potrzebę używania zmiennych tymczasowych. always @(posedge clock) begin temp_a = a; temp_b = b; a = temp_b; b = temp_a; end Stosowanie przypisań równoczesnych jest rekomendowane gdyż zabezpiecza przed powstaniem hazardu tzn. rezultat nie zależy od kolejności wykonania operacji. Z drugiej strony przypisania równoczesne mogą spowodować spowolnienie symulacji i większe zużycie pamięci. AGH, WFiIS, HDL 10
Przypisania z opóźnieniami Pięć przypadków: always @* #d a = b; LHS Blocking Left Hand Side always @* a = #d b; RHS Blocking Right Hand Side always @* #d a <= b; LHS Nonblocking Left Hand Side always @* a <= #d b; RHS Nonblocking Right Hand Side assign #d a = b; Continuous AGH, WFiIS, HDL 11
Blocking assignment delay models module adder_lhs_b (input [3:0] a, b, input ci, output reg co, output reg [3:0] sum); always @* #12 {co, sum} = a + b + ci; LHS Blocking Assignment endmodule ISim, Xilinx WARNING:Xst:916 - adder_lhs_b.v" line 8: Delay is ignored for synthesis. Symulacja po syntezie będzie zupełnie odmienna. #12 a b ci sum co ISim, Xilinx Model błędny! Nie istnieje odpowiedni sprzęt. Opóźnienie #12 jest obliczane od pierwszej zmiany na wejściach, a wynik jest obliczany w oparciu o bieżące wartości sygnałów. AGH, WFiIS, HDL 12
LHS Blocking Assignment Rekomendacje do modelowania: Nie stawiaj opóźnień z lewej strony przypisania blokującego w modelach układów kombinacyjnych. To jest zły styl kodowania. Rekomendacje do modułów testujących: Używanie opóźnień z lewej strony przypisania blokującego w modułach testujących jest właściwe. To jest poprawny sposób modelowania odstępów czasowych pomiędzy kolejnymi zdarzeniami wymuszeń na wejściach testowanego modułu. AGH, WFiIS, HDL 13
Blocking assignment delay models RHS Blocking Assignment module adder_rhs_b (input [3:0] a, b, input ci, output reg co, output reg [3:0] sum); endmodule always @* {co, sum} = #12 a + b + ci; #12 a b ci sum co Model błędny! Nie istnieje odpowiedni sprzęt. Opóźnienie #12 jest obliczane od pierwszej zmiany na wejściach, a wynik jest obliczany w oparciu o stare wartości AGH, WFiIS, HDL 14 sygnałów. ISim, Xilinx
RHS Blocking Assignment Rekomendacje do modelowania: Nie stawiaj opóźnień z prawej strony przypisania blokującego w modelach układów kombinacyjnych. To jest zły styl kodowania. Rekomendacje do modułów testujących: Nie stawiaj opóźnień z prawej strony przypisania blokującego w modułach testujących. Ogólna rekomendacja: Używanie opóźnień z prawej strony przypisania blokującego jest zarówno mylące jak i w złym stylu. Należy unikać! AGH, WFiIS, HDL 15
Nonblocking assignment delay models module adder_lhs_nb (input [3:0] a, b, input ci, output reg co, output reg [3:0] sum); endmodule always @* #12 {co, sum} <= a + b + ci; LHS Nonblocking Assignment #12 a b ci sum co Model błędny! Nie istnieje odpowiedni sprzęt. ISim, Xilinx Opóźnienie #12 jest obliczane od pierwszej zmiany na wejściach, a wynik jest obliczany w oparciu o bieżące wartości sygnałów. AGH, WFiIS, HDL 16
LHS Nonblocking Assignment Rekomendacje do modelowania: Nie stawiaj opóźnień z lewej strony przypisania nieblokującego w modelach układów kombinacyjnych. To jest zły styl kodowania. Rekomendacje do modułów testujących: Przypisania nieblokujące są mniej efektywne niż przypisania blokujące. Dlatego generalnie odradza się stosowania opóźnień po lewej stronie przypisań nieblokujących zarówno w modelach jak i modułach testujących. AGH, WFiIS, HDL 17
Nonblocking assignment delay models module adder_rhs_nb (input [3:0] a, b, input ci, output reg co, output reg [3:0] sum); endmodule always @* {co, sum} <= #12 a + b + ci; RHS Nonblocking Assignment #12 a b ci sum co Poprawne modelowanie logiki transportowej ISim, Xilinx AGH, WFiIS, HDL 18
RHS Nonblocking Assignment Rekomendacje do modelowania: Używaj opóźnień z prawej strony przypisania nieblokującego do modelowania cyfrowej linii opóźniającej. To jest dobry styl kodowania. Rekomendacje do modułów testujących: Ten styl jest często stosowany w modułach testujących kiedy wymuszenie musi być zaplanowane na przyszłych krawędziach zegara lub po ustalonym opóźnieniu, nie blokując przydziału kolejnych zdarzeń wymuszających w tym samym bloku proceduralnym. Ogólna rekomendacja: Stosuj opóźnienia z prawej strony przypisania nieblokującego tylko przy modelowaniu propagacji sygnałów wyjściowych o zachowaniu transportowym. Ten styl kodowania będzie dokładnie modelował linie opóźniające i logikę kombinacyjną z czysto transportowymi opóźnieniami. Jednak ten styl powoduje spowolnienie symulacji. AGH, WFiIS, HDL 19
Continuous assignment delay models module adder_lhs_cont (input [3:0] a, b, input ci, output reg co, output reg [3:0] sum); endmodule assign #12 {co, sum} = a + b + ci; LHS Continuous Assignment #12 a b ci sum co Poprawne modelowanie logiki inercyjnej ISim, Xilinx AGH, WFiIS, HDL 20
LHS Continuous Assignment Rekomendacje do modelowania: Używaj opóźnień z prawej strony przypisania ciągłego do modelowania prostej logiki kombinacyjnej. To jest dobry styl kodowania do poprawnego modelowania logiki kombinacyjnej z opóźnieniem inercyjnym. Rekomendacje do modułów testujących: Ciągłe przypisania mogą być używane w dowolnym miejscu w modułach testujących, aby sterować wartościami wymuszeń na portach wejściowych i dwukierunkowych portach instancji modułów testowanych. Ogólna rekomendacja: Do modelowania złożonej logiki kombinacyjnej z użyciem konstrukcji typu casecasez-casex lub if-else należy zawsze używać bloków always bez opóźnień. Wyjścia z takich bloków mogą być następnie skierowane do przypisania ciągłego w celu zastosowania opóźnień do takich modeli. Taki styl kodowania poprawnie modeluje złożoną logikę kombinacyjną z opóźnieniem inercyjnym. AGH, WFiIS, HDL 21
Zestawienie rekomendacji stosowania przypisań z opóźnieniami RTL TB blocking LHS error correct blocking RHS error avoid nonblocking LHS error avoid nonblocking RHS transport correct continuous LHS inertial correct AGH, WFiIS, HDL 22
module blk (input clk, d, output reg [1:0] r); always @(posedge clk) begin r[0] = d; r[1] = r[0]; end endmodule Na każdym zboczu narastającym zegara wartość z wejścia d zostanie przypisana do obu bitów rejestru r. Jeśli d=1 b1 to początkowo niezainicjowany rejestr r=2 bxx zmieni wartość na r=2 b11. module NONblk (input clk, d, output reg [1:0] r); always @(posedge clk) begin r[0] <= d; r[1] <= r[0]; end endmodule Na każdym zboczu narastającym zegara wartości wejścia d i mniejznaczącego bitu rejestru r zostaną zapamiętane w zmiennych tymczasowych, a następnie przypisane. Jeśli d=1 b1 to początkowo niezainicjowany rejestr r=2 bxx na pierwszym narastającym zboczu zegara zmieni wartość na r=2 bx1., a na drugim na r=2 b11. AGH, WFiIS, HDL 23
module blk (input clk, d, output reg [1:0] r); always @(posedge clk) begin r[0] = d; r[1] = r[0]; end endmodule Incisive, Cadence r clk d Wynik syntezy: Encounter RTL Compiler, Cadence AGH, WFiIS, HDL 24
module NONblk (input clk, d, output reg [1:0] r); always @(posedge clk) begin r[0] <= d; r[1] <= r[0]; end endmodule r Incisive, Cadence r[1] r[0] clk Wynik syntezy: d AGH, WFiIS, HDL Encounter RTL Compiler, Cadence 25
Układ sekwencyjny Układ kombinacyjny Przypisania ciągłe module xx (...); wire [4:0] komb_out; wire [4:0] c; reg [4:0] a, b; assign komb_out = a (b & c); endmodule Przypisania proceduralne module xx (...); reg [4:0] komb_out; wire [4:0] c; reg [4:0] a, b; always @* komb_out = a (b & c); endmodule module xx (...); reg [4:0] seq_out; wire [4:0] c; reg [4:0] a, b; always @(posedge clk) seq_out <= a (b & c); endmodule AGH, WFiIS, HDL 26
Proceduralne przypisanie ciągłe module xx (...); reg [4:0] komb_out; wire [4:0] c; reg [4:0] a, b; always @* assign komb_out = a (b & c); endmodule Taka składnia jest także poprawna ale znaczenie jest odmienne. AGH, WFiIS, HDL 27
Proceduralne przypisanie ciągłe Jest to przypisanie ciągłe do: Zmiennej rejestrowej, Pozostaje ważne tylko przez czas określony jego odwołaniem, Jest nadrzędne w stosunku do zwykłego przypisania proceduralnego. W sposób ciągły przypisuje wartość do zmiennej rejestrowej z priorytetem wyższym niż zwykłe przypisanie proceduralne. Po jego odwołaniu przez deassign zmienna rejestrowa nadal utrzymuje uzyskaną wartość, aż do chwili wystąpienia zwykłego przypisania proceduralnego. assign zmienna_reg = wyrazenie;... deassign zmienna_reg; Lewa strona przypisania może być zmienną lub połączeniem zmiennych. Nie może być słowem pamięci lub tablicy i nie może być bitem lub grupą bitów wektora. AGH, WFiIS, HDL 28
module assigntry(input clk, rst, set, d, output reg q); always @* Przy przejściu rst w stan niski wyjście q otrzyma stan niski. if(~rst) assign q = 1'b0; else Przy przejściu set w stan niski wyjście q otrzyma stan wysoki. if(~set) assign q = 1'b1; else deassign q; always @(posedge clk) q <= d; endmodule Jeżeli żadne z wejść set, rst nie jest w stanie niskim wyjście zostanie uwolnione i kontrolę nad nim przejmie zwykłe przypisanie proceduralne w drugim always. Komunikaty o błędach w czasie syntezy za pomocą RTL Compiler (Cadence): if(~rst) assign q = 1'b0; Error : Unsupported procedural assignment. [VLOGPT-39] [read_hdl] : Procedural assign in file 'assign.v' on line 7, column 16. : 'assign' and 'deassign' statements within a sequential statement are not supported for synthesis. Synteza jest poprawna w XST w nawigatorze ISE: Process "Synthesize - XST" completed successfully XST, Xilinx Encounter RTL Compiler, Cadence AGH, WFiIS, HDL 29
module assigntry( input clk, rst, set, d, output reg q); always @(posedge clk) q <= d; always @* if(~rst) assign q = 1'b0; else if(~set) assign q = 1'b1; else deassign q; endmodule Symulacja RTL (behavioral) ISim, Xilinx AGH, WFiIS, HDL 30
XST, Xilinx module assigntry (input clk, rst, d, set, output q); wire rst_inv; wire set_inv; wire VCC; X_FF #(.INIT ( 1'b0 )) q_1 (.CLK(clk),.RST(rst_inv),.I(d),.SET(set_inv),.O(q),.CE(VCC)); X_INV X_INV X_ONE endmodule ISim, Xilinx set_inv1_inv_0 (.I(set),.O(set_inv)); rst_inv1_inv_0 (.I(rst),.O(rst_inv)); NlwBlock_assigntry_VCC (.O(VCC)); Symulacja Post-Translate module tb; reg clk, rst, set, d; wire q; assigntry uut (.clk(clk),.rst(rst),.set(set),.d(d),.q(q)); wire GSR = glbl.gsr; initial begin clk = 0; forever #40 clk = ~clk; end initial begin @(negedge GSR); rst = 1'b1; set = 1'b1; d = 1'b1; #100 rst = 1'b0; #120 rst = 1'b1; #110 set = 1'b0; #110 set = 1'b1; #150 set = 1'b0; #10 rst = 1'b0; #100 rst = 1'b1; #10 set = 1'b1; #100 d = 1'b0; end initial #1000 $finish; endmodule AGH, WFiIS, HDL 31
Proceduralne przypisanie ciągłe Są to konstrukcje przeznaczone do tworzenie modeli symulacyjnych i pisania modułów testowych (test-bench). Dwa rodzaje: Do zmiennej rejestrowej uważana za zły styl kodowania, assign... deassign ; Do zmiennej węzłowej lub rejestrowej force... release ; zastosowanie ograniczone do generacji wymuszeń i dubugowania. AGH, WFiIS, HDL 32
Proceduralne przypisanie ciągłe force zmienna_reg_net = wyrazenie;... release zmienna_reg_net; Na zmiennych rejestrowych działa tak jak assign ale ma jeszcze wyższy priorytet. Na zmiennych węzłowych nadpisuje przypisania ciągłe i wyjścia instancji na czas określony przez wystąpienie instrukcji release. AGH, WFiIS, HDL 33
`timescale 1 ns / 100 ps module force_release_tb; reg w, x, y; wire f; and and_1 (f, w, x, y); initial begin $monitor("%d ns, f=%b", $time,f); end endmodule w = 1 b1; x = 1 b0; y = 1 b1; #10 force f = w x y; #10 release f; #10 $finish; Bramka and na 10 jednostek czasu zostaje zastąpiona przez funktor LUB modelowany przypisaniem force Wynik symulacji : 0 ns, f=0 10 ns, f=1 20 ns, f=0 Incisive, Cadence AGH, WFiIS, HDL 34
Zestawienie różnych przypisań Typ danych Wyjście instancji Ciągłe Proceduralne priorytet Proceduralne ciągłe assign force Węzłowe X X Rejestrowe X X AGH, WFiIS, HDL 35
Reguły stosowania przypisań blokujących i nieblokujących Podstawowe zasady syntezowalności kodu Zawsze używaj przypisań blokujących (=) w blokach always przeznaczonych do tworzenia układów kombinacyjnych, Zawsze używaj przypisań nieblokujących (<=) w blokach always przeznaczonych do tworzenia układów sekwencyjnych, Nie mieszaj obu typów przypisań w jednym bloku always, Nie wykonuj przypisań do tej samej zmiennej w dwóch różnych blokach always. AGH, WFiIS, HDL 36
Modelowanie za pomocą bloku always Modelowanie układów sekwencyjnych Na liście wrażliwości znajduje się aktywne zbocze sygnału zegarowego i ewentualnie aktywne zbocze asynchronicznego sygnału kasowania: always @(posedge clk, posedge rst) Zatrzaski Są sekwencyjne gdyż trudno nie przyznać, że są to elementy pamięciowe Są kombinacyjne, gdyż powstają przy błędnym modelowaniu układów kombinacyjnych Modelowanie układów kombinacyjnych Na liście wrażliwości znajdują się zmiany wartości wszystkich sygnałów występujących po stronie prawej przypisań w tym bloku: always @* AGH, WFiIS, HDL 37
Operatory arytmetyczne Operatory dwuargumentowe: (**) potęgowanie, (*) mnożenie, (/) dzielenie, (+) dodawanie, (-) odejmowanie, (%) modulo. Jeśli jakikolwiek bit argumentów ma wartość nieokreśloną x to cały wynik jest nieokreślony. Operatory jednoargumentowe (+) i (-) określają znak argumentu. reg [3:0] A, B; integer D, E; //A = 4 b0011; B = 4 b0100; D = 6; E = 4; A + B //wynik 4 b0111 D/E //wynik 1; obcina czesc ułamkową A * B //wynik 4 b1100 B A //wynik 4b 0001 Wynikiem operacji będzie real jeśli jeden z argumentów jest real. Jeśli obydwa argumenty są bez znaku to wynik także jest bez znaku. data flow level AGH, WFiIS, HDL 38
Operatory logiczne data flow level Operatory dwuargumentowe: ( ) logiczne-lub, (&&) logiczne-i. Operatory jednoargumentowe: (!) logiczne-nie. Wynikiem zawsze jest wartość jednobitowa: 0 fałsz, 1 prawda lub x nieokreślony. Wynik różny od zera jest traktowany jak prawda. //A = 3; B = 0; A && B //daje falsz A B //daje prawda!a //daje falsz!b //daje prawda //A = 2 b0x; B = 2 b10; A && B //daje x AGH, WFiIS, HDL 39
Operatory relacyjne data flow level (>) większy, (<) mniejszy, (>=) większy-lub-równy, (>=) mniejszy-lub-równy. Jeśli argument jest x lub z to wynik jest x. //A = 4; B = 3; X = 4 b1010; Y = 4 b1101; Z = 4 b1xxx; A <= B A > B Y >= X Y < Z //wynik 0-falsz //wynik 1-prawda //wynik 1-prawda //wynik x AGH, WFiIS, HDL 40
Operatory równości Operatory dwuargumentowe: (==) równość, (!=) nierówność oraz wersje z uwzględnieniem x i z (===) i (!==). Wynikiem zawsze jest wartość jednobitowa: 0 fałsz, 1 prawda, a wartość x nieokreślony może się pojawić tylko w przypadkach (==) i (!=). //A = 4; B = 3; //X = 4 b1010; Y = 4 b1101; //Z = 4 b1xxz; M = 4 b1xxz; N = 4 b1xxx; A == B A!= B X == Z Z === M Z === N M!== N //daje falsz //daje prawda //daje x //daje prawda //daje falsz //daje prawda data flow level Używać oszczędnie w zastosowaniu do syntezy: reg a; if (a == 1 b1)... ; //jest równoważne if(a)... ; AGH, WFiIS, HDL 41
Operatory bitowe Operatory dwuargumentowe: ( ) bitowe-lub, (&) bitowe-i, (^) bitowe-xor, (~^ lub ^~) bitowe-xnor. data flow level Operatory jednoargumentowe: (~) bitowe-nie. Jeśli argumenty są różnych rozmiarów to krótszy uzupełniany jest zerami z przodu. & 0 1 x 0 0 0 0 1 0 1 x x 0 x x 0 1 x 0 0 1 x 1 1 1 1 x x 1 x ^ 0 1 x 0 0 1 x 1 1 0 x x x x x ^~ 0 1 x 0 1 0 x 1 0 1 x x x x x //X = 4 b1010; Y = 4 b1101; z jest traktowane jak x. //Z = 4 b10x1; ~X //daje 4 b0101 X & Y //daje 4 b1000 X Y //daje 4 b1111 a X Y daje 1 b1 X ^ Y //bitowy xor daje 4 b0111 X ~^ Y //bitowy xnor daje 4 b1000 X & Z //daje 4 b10x0 ~ 0 1 1 0 x x AGH, WFiIS, HDL 42
Operatory redukcyjne Operatory jednoargumentowe : ( ) or, (&) and, (^) xor, (~ ) nor, (~&) nand, (~^ lub ^~) xnor. data flow level //X = 4 b1010; &X //1 & 0 & 1 & 0 daje 1 b0 X //1 0 1 0 daje 1 b1 ^X //1 ^ 0 ^ 1 ^ 0 daje 1 b0 AGH, WFiIS, HDL 43
Operatory przesunięć Operatory dwuargumentowe: (>>) w prawo, (<<) w lewo. data flow level działają na wektorach, przesuwają określoną w drugim argumencie ilość bitów, powstające miejsce zapełniają zawsze zerami (nie ma zawijania). //X = 4 b1100; Y = X >> 1; //daje 4 b0110 Y = X << 1; //daje 4 b1000 Y = X << 2; //daje 4 b0000 AGH, WFiIS, HDL 44
Operator dołączania Operatory wieloargumentowy: ({}) łączenie. Działa na argumentach o znanym rozmiarze. data flow level //A=1 b1, B=2 b00, C=2 b10, D=3 b110 reg [3:0] Y0; reg [10:0] Y1; reg [2:0] Y2; Y0 = {B,C}; //daje 4 b0010 Y1 = {A,B,C,D,3 b001}; //daje 11 b10010110001 Y2 = {A,B[0],C[1]}; //daje 3 b101 AGH, WFiIS, HDL 45
Operator powtarzania data flow level Polega na wielokrotnym łączeniu tyle razy ile określono w stałej replikacji {stala_repli{arg}} reg A; reg [1:0] B, C; reg [2:0] D; //A=1 b1; B=2 b00; C=2 b10; reg [3:0] Y0; reg [7:0] Y1; reg [9:0] Y2; Y0 = { 4{A} }; //daje 4 b1111 Y1 = { {4{A}}, {2{B}} }; //daje 8 b11110000 Y2 = { {4{A}}, {2{B}}, C}; //daje 10 b1111000010 AGH, WFiIS, HDL 46
Operator warunkowy Zastępuje instrukcję if, Dostarcza konstrukcji multipleksera 2 do 1: data flow level warunek? wyraz_prawda : wyraz_falsz //bufor trójstanowy trzy-bitowego wire [2:0] addr_bus, adrr_out; assign addr_bus = driver_enable? adrr_out : 3 bz; //2-do-1 mux assign out = control? in1 : in2; //zagniezdzanie assign out = (A==3)? (control?x:y) : (control?m:n); AGH, WFiIS, HDL 47
Dyrektywy kompilatora Definiuje się w postaci : `<słowo_kluczowe> Słowa kluczowe: omówimy `define `undef `include `ifdef `else `elsif `endif `ifndef `timescale niektóre inne: `celldefine `endcelldefine `line `default_nettype `unconnected_drive `unconnected_drive `resetall AGH, WFiIS, HDL 48
Dyrektywa `define Definiowanie makra tekstowego `define <nazwa_makra> <wartość> Rola i działanie podobne jak #define w C. Odwołanie: `<nazwa_makra> `define WORD_SIZE 32 definicja makra określającego domyślną długość słowa; wywołanie: `WORD_SIZE `define S $stop alias gdziekolwiek pojawi się `S wstawione zostanie $stop `define WORD_REG reg [WORD_SIZE-1:0] często używany ciąg znaków deklaracja 32-bitowego rejestru: `WORD_REG reg32; AGH, WFiIS, HDL 49
Dyrektywa `include Wstawianie pliku źródłowego `include <nazwa_pliku> Rola i działanie podobne jak #include w C. //wstaw plik header.v zawierający deklaracje `include header.v... <kod Verilog a>... Należy unikać umieszczania modułów w plikach włączanych za pomocą dyrektywy `include. Najlepszym użyciem tej dyrektywy jest stosowanie jej do współdzielenia informacji sterującej zawartej w dyrektywach `define, `timescale, i im podobnych. AGH, WFiIS, HDL 50
Dyrektywa `timescale `timescale <jednostka> / <dokładność> `timescale 10 ns / 1 ns module test #(parameter d = 1.55); reg set; initial begin end endmodule #d set = 1 b0; #d set = 1 b1; #d $finish; W tym przykładzie dyrektywa `timescale 10 ns / 1 ns określa jednostkę czasu dla modułu test na 10ns. W rezultacie wartości czasu w module są mnożone przez 10ns z zaokrągleniem do najbliższej 1ns. Parametr d jest typu real, gdyż taka stała jest do niego wpisana. Dlatego wartość parametru d jest skalowana do 16ns. Wartość 0 jest przypisywana do rejestru set w chwili czasu symulacji 16ns i wartość 1 w chwili 32ns. W argumentach dozwolone są tylko potęgi liczby 10: Dozwolone liczby całkowite: 1, 10, and 100. Dozwolone ciągi znaków określających jednostki pomiaru czasu: s, ms, us, ns, ps, fs. AGH, WFiIS, HDL 51
Dyrektywy `ifdef, `else, `endif Kompilacja warunkowa umożliwia zastosowanie tego samego kodu w dwóch różnych sytuacjach indywidualizując go w czasie kompilacji projektu. initial begin `ifdef GL $shm_open("seqdetgl.shm"); `else $shm_open("seqdet.shm"); `endif $shm_probe("as"); #220 $shm_close(); $finish; end Makro GL może być zdefiniowane dyrektywą `define w pliku lub opcją define w linii poleceń. Przy wywołaniu symulatora: $ irun define GL test.v... będą wykonane te linie matomiast jeśli zrobimy to tak: $ irun test.v... wykonana będzie tylko ta linie initial begin `ifdef GL $sdf_annotate("seqdet.sdf",test,,"seqdet_sdf.log","maximum",,); `endif end Incisive, Cadence Sposób na to żeby dokładnie ten sam moduł testowy używać do symulacji przed i po syntezie. AGH, WFiIS, HDL 52
Instrukcje sterujące Instrukcja warunkowa Instrukcja wyboru if case, casex, casez Pętla Pętla Pętla Pętla while for repeat forever AGH, WFiIS, HDL 53