VLSI Design - Verilog Wprowadzenie
Verilog to JĘZYK OPISU SPRZĘTU (HDL). Jest to język używany do opisu systemu cyfrowego, takiego jak przełącznik sieciowy, mikroprocesor, pamięć lub przerzutnik. Oznacza to, że używając HDL możemy opisać dowolny sprzęt cyfrowy na dowolnym poziomie. Projekty, które są opisane w HDL są niezależne od technologii, bardzo łatwe do projektowania i debugowania i są zwykle bardziej przydatne niż schematy, szczególnie w przypadku dużych obwodów.
Verilog obsługuje projekty na wielu poziomach abstrakcji. Trzy główne to -
- Poziom behawioralny
- Poziom przeniesienia rejestru
- Poziom bramy
Poziom behawioralny
Ten poziom opisuje system za pomocą współbieżnych algorytmów (behawioralnych). Każdy algorytm jest sekwencyjny, co oznacza, że składa się z zestawu instrukcji, które są wykonywane jedna po drugiej. Funkcje, zadania i bloki to główne elementy. Nie ma znaczenia konstrukcyjna realizacja projektu.
Rejestracja - poziom transferu
Projekty wykorzystujące Register-Transfer Level określają charakterystykę obwodu wykorzystując operacje i przesyłanie danych pomiędzy rejestrami. Współczesna definicja kodu RTL brzmi: „Każdy kod, który można syntetyzować, nazywa się kodem RTL”.
Poziom bramy
Na poziomie logicznym cechy systemu są opisywane przez łącza logiczne i ich właściwości czasowe. Wszystkie sygnały są sygnałami dyskretnymi. Mogą mieć tylko określone wartości logiczne („0”, „1”, „X”, „Z”). Użyteczne operacje to predefiniowane prymitywy logiczne (podstawowe bramki). Modelowanie na poziomie bramki może nie być dobrym pomysłem do projektowania logiki. Kod poziomu bramy jest generowany przy użyciu narzędzi takich jak narzędzia do syntezy, a jego lista sieci jest używana do symulacji poziomu bramy i do zaplecza.
Tokeny leksykalne
Źródłowe pliki tekstowe języka Verilog to strumień tokenów leksykalnych. Żeton składa się z jednego lub więcej znaków, a każdy pojedynczy znak znajduje się dokładnie w jednym żetonie.
Podstawowe tokeny leksykalne używane przez Verilog HDL są podobne do tych w języku programowania C. Verilog rozróżnia wielkość liter. Wszystkie słowa kluczowe są zapisane małymi literami.
Biała przestrzeń
Spacje mogą zawierać znaki spacji, tabulatorów, nowych wierszy i kanałów informacyjnych. Te postacie są ignorowane, z wyjątkiem sytuacji, gdy służą do oddzielnych żetonów.
Białe znaki to spacja, tabulatory, powrót karetki, nowy wiersz i wysuwy stron.
Komentarze
Istnieją dwa formularze do przedstawiania komentarzy
- 1) Komentarze jednowierszowe zaczynają się od tokena // i kończą znakiem powrotu karetki.
Np .: // to jest składnia jednowierszowa
- 2) Komentarze wielowierszowe zaczynają się od tokena / * i kończą tokenem * /
Np .: / * to jest składnia wielowierszowa * /
Liczby
Możesz podać liczbę w formacie binarnym, ósemkowym, dziesiętnym lub szesnastkowym. Liczby ujemne są reprezentowane przez liczby komplementów 2. Verilog dopuszcza liczby całkowite, liczby rzeczywiste oraz liczby ze znakiem i bez znaku.
Składnia jest określona przez - <rozmiar> <radix> <wartość>
Rozmiar lub liczbę bez rozmiaru można zdefiniować w <Rozmiar>, a <radix> określa, czy jest to liczba dwójkowa, ósemkowa, szesnastkowa czy dziesiętna.
Identyfikatory
Identyfikator to nazwa używana do zdefiniowania obiektu, takiego jak funkcja, moduł lub rejestr. Identyfikatory powinny zaczynać się od znaków alfabetu lub znaków podkreślenia. Dawny. A_Z, a_z, _
Identyfikatory to kombinacja znaków alfabetycznych, numerycznych, podkreślenia i $. Mogą mieć do 1024 znaków.
Operatorzy
Operatory są znakami specjalnymi używanymi do stawiania warunków lub do obsługi zmiennych. Jest jeden, dwa, a czasem trzy znaki używane do wykonywania operacji na zmiennych.
Dawny. >, +, ~, &! =.
Słowa kluczowe Verilog
Słowa, które mają specjalne znaczenie w Verilog, nazywane są słowami kluczowymi Verilog. Na przykład: assign, case, while, wire, reg, and, or, nand i module. Nie powinny być używane jako identyfikatory. Słowa kluczowe Verilog obejmują również dyrektywy kompilatora oraz zadania i funkcje systemowe.
Modelowanie poziomu bramy
Verilog ma wbudowane prymitywy, takie jak bramki logiczne, bramki transmisyjne i przełączniki. Są one rzadko używane w pracach projektowych, ale są używane w świecie postsyntezy do modelowania komórek ASIC / FPGA.
Modelowanie na poziomie bramy wykazuje dwie właściwości -
Drive strength- Siła bramek wyjściowych jest określana przez siłę napędu. Wyjście jest najsilniejsze, jeśli istnieje bezpośrednie połączenie ze źródłem. Siła maleje, jeśli połączenie jest realizowane przez tranzystor przewodzący, a przynajmniej w przypadku połączenia przez rezystor podwyższający / obniżający. Siła napędu zwykle nie jest określana, w takim przypadku wartości domyślne to strong1 i strong0.
Delays- Jeśli opóźnienia nie są określone, bramki nie mają opóźnień propagacji; jeśli określono dwa opóźnienia, to pierwsza reprezentuje opóźnienie narastania, a druga - opadania; jeśli określono tylko jedno opóźnienie, to zarówno wzrost, jak i spadek są równe. Opóźnienia można zignorować w syntezie.
Brama prymitywów
Podstawowe bramki logiczne wykorzystujące jedno wyjście i wiele wejść są używane w Verilog. GATE używa jednego ze słów kluczowych - and, nand, or, nor, xor, xnor do użycia w Verilog dla N liczby wejść i 1 wyjścia.
Example:
Module gate()
Wire ot0;
Wire ot1;
Wire ot2;
Reg in0,in1,in2,in3;
Not U1(ot0,in0);
Xor U2(ot1,in1,in2,in3);
And U3(ot2, in2,in3,in0)
Prymitywy bramy transmisyjnej
Prymitywy bramek transmisji obejmują zarówno bufory, jak i inwertery. Mają jedno wejście i jedno lub więcej wyjść. W przedstawionej poniżej składni tworzenia instancji bramki GATE oznacza słowo kluczowe buf lub NOT bramka.
Przykład: Not, buf, bufif0, bufif1, notif0, notif1
Nie - nie ma falownika
Buf - n bufor wyjściowy
Bufifo - bufor trójstanowy, aktywny stan niski
Bufif1 - bufor trójstanowy, aktywny stan wysoki
Notifo - falownik trójstanowy, aktywne niskie zezwolenie
Notif1 - falownik trójstanowy, aktywny stan wysoki
Example:
Module gate()
Wire out0;
Wire out1;
Reg in0,in1;
Not U1(out0,in0);
Buf U2(out0,in0);
Typy danych
Zestaw wartości
Verilog składa się głównie z czterech podstawowych wartości. Wszystkie typy danych Verilog, które są używane w Verilog, przechowują te wartości -
0 (logiczne zero lub warunek fałszywy)
1 (logiczny jeden lub prawdziwy warunek)
x (nieznana wartość logiczna)
z (stan wysokiej impedancji)
użycie x i z jest bardzo ograniczone do syntezy.
Drut
Przewód jest używany do reprezentowania fizycznego przewodu w obwodzie i służy do łączenia bramek lub modułów. Wartość przewodu można tylko odczytać i nie można jej przypisać w funkcji lub bloku. Przewód nie może przechowywać wartości, ale zawsze jest sterowany przez ciągłą instrukcję przypisania lub przez podłączenie przewodu do wyjścia bramki / modułu. Inne określone typy przewodów to -
Wand (wired-AND) - tutaj wartość Wand jest zależna od logicznego AND wszystkich sterowników urządzeń do niego podłączonych.
Wor (wired-OR) - tutaj wartość Wor zależy od logicznego LUB wszystkich sterowników urządzeń do niego podłączonych.
Tri (three-state) - tutaj wszystkie sterowniki podłączone do tri muszą być z, z wyjątkiem tylko jednego (który określa wartość tri).
Example:
Wire [msb:lsb] wire_variable_list;
Wirec // simple wire
Wand d;
Assign d = a; // value of d is the logical AND of
Assign d = b; // a and b
Wire [9:0] A; // a cable (vector) of 10 wires.
Wand [msb:lsb] wand_variable_list;
Wor [msb:lsb] wor_variable_list;
Tri [msb:lsb] tri_variable_list;
Zarejestrować
Reg (rejestr) to obiekt danych, który przechowuje wartość z jednego przypisania proceduralnego do następnego i jest używany tylko w różnych funkcjach i blokach proceduralnych. Reg jest prostym rejestrem Verilog typu zmiennego i nie może implikować rejestru fizycznego. W rejestrach wielobitowych dane są przechowywane w postaci liczb bez znaku i nie stosuje się rozszerzenia znaku.
Przykład -
reg c; // pojedyncza 1-bitowa zmienna rejestrowa
reg [5: 0] klejnot; // 6-bitowy wektor;
reg [6: 0] d, e; // dwie zmienne 7-bitowe
Wejście, wyjście, wejście
Te słowa kluczowe są używane do deklarowania portów wejściowych, wyjściowych i dwukierunkowych zadania lub modułu. Tutaj porty wejściowe i wejściowe, które są typu przewodowego, a port wyjściowy są skonfigurowane jako typu wire, reg, wand, wor lub tri. Zawsze domyślnie jest to typ przewodu.
Example
Module sample(a, c, b, d);
Input c; // An input where wire is used.
Output a, b; // Two outputs where wire is used.
Output [2:0] d; /* A three-bit output. One must declare type in a separate statement. */
reg [1:0] a; // The above ‘a’ port is for declaration in reg.
Liczba całkowita
Liczby całkowite są używane w zmiennych ogólnego przeznaczenia. Są używane głównie w pętlach - wskaźnikach, stałych i parametrach. Są to dane typu „reg”. Przechowują dane jako podpisane liczby, podczas gdy jawnie zadeklarowane typy reg przechowują je jako dane bez znaku. Jeśli liczba całkowita nie jest zdefiniowana w czasie kompilacji, domyślny rozmiar będzie wynosił 32 bity.
Jeśli liczba całkowita posiada stałą, syntezator dostosowuje je do minimalnej szerokości wymaganej w momencie kompilacji.
Example
Integer c; // single 32-bit integer
Assign a = 63; // 63 defaults to a 7-bit variable.
Dostawa0, Dostawa1
Zasilanie0 definiuje przewody powiązane z logiką 0 (uziemienie), a zasilanie1 określa przewody powiązane z logiką 1 (zasilanie).
Example
supply0 logic_0_wires;
supply0 gnd1; // equivalent to a wire assigned as 0
supply1 logic_1_wires;
supply1 c, s;
Czas
Czas to 64-bitowa wielkość, której można używać w połączeniu z zadaniem systemowym $ time do przechowywania czasu symulacji. Czas nie jest obsługiwany do syntezy i dlatego jest używany tylko do celów symulacji.
Example
time time_variable_list;
time c;
c = $time; //c = current simulation time
Parametr
Parametr definiuje stałą, którą można ustawić podczas korzystania z modułu, co umożliwia dostosowanie modułu podczas procesu tworzenia instancji.
Example
Parameter add = 3’b010, sub = 2’b11;
Parameter n = 3;
Parameter [2:0] param2 = 3’b110;
reg [n-1:0] jam; /* A 3-bit register with length of n or above. */
always @(z)
y = {{(add - sub){z}};
if (z)
begin
state = param2[1];
else
state = param2[2];
end
Operatorzy
Operatory arytmetyczne
Te operatory wykonują operacje arytmetyczne. + I −są używane jako operatory jednoargumentowe (x) lub binarne (z − y).
Operatory uwzględnione w operacji arytmetycznej to:
+ (dodawanie), - (odejmowanie), * (mnożenie), / (dzielenie),% (moduł)
Example -
parameter v = 5;
reg[3:0] b, d, h, i, count;
h = b + d;
i = d - v;
cnt = (cnt +1)%16; //Can count 0 thru 15.
Operatorzy relacyjni
Te operatory porównują dwa operandy i zwracają wynik w postaci jednego bitu, 1 lub 0.
Zmienne wire i reg są dodatnie. Zatem (−3'd001) = = 3'd111 i (−3b001)> 3b110.
Operatory uwzględnione w operacji relacyjnej to:
- == (równe)
- ! = (różne od)
- > (większe niż)
- > = (większe lub równe)
- <(mniej niż)
- <= (mniejsze lub równe)
Example
if (z = = y) c = 1;
else c = 0; // Compare in 2’s compliment; d>b
reg [3:0] d,b;
if (d[3]= = b[3]) d[2:0] > b[2:0];
else b[3];
Equivalent Statement
e = (z == y);
Operatory bitowe
Operatory bitowe, które dokonują porównania bit po bicie między dwoma operandami.
Operatory, które są uwzględnione w operacji bitowej to:
- & (bitowe AND)
- | (bitowe LUB)
- ~ (bitowe NIE)
- ^ (bitowy XOR)
- ~ ^ lub ^ ~ (bitowe XNOR)
Example
module and2 (d, b, c);
input [1:0] d, b;
output [1:0] c;
assign c = d & b;
end module
Operatory logiczne
Operatory logiczne są operatorami bitowymi i są używane tylko dla operandów jednobitowych. Zwracają wartość jednobitową, 0 lub 1. Mogą pracować na liczbach całkowitych lub grupach bitów, wyrażeniach i traktować wszystkie wartości niezerowe jako 1. Operatory logiczne są generalnie używane w instrukcjach warunkowych, ponieważ działają z wyrażeniami.
Operatory uwzględnione w operacji logicznej to -
- ! (logiczne NIE)
- && (logiczne AND)
- || (logiczne LUB)
Example
wire[7:0] a, b, c; // a, b and c are multibit variables.
reg x;
if ((a == b) && (c)) x = 1; //x = 1 if a equals b, and c is nonzero.
else x = !a; // x =0 if a is anything but zero.
Operatory redukcji
Operatory redukcji są jednoargumentową postacią operatorów bitowych i działają na wszystkich bitach wektora operandu. Te również zwracają wartość jednobitową.
Operatory uwzględnione w operacji redukcji to:
- & (redukcja AND)
- | (redukcja LUB)
- ~ & (redukcja NAND)
- ~ | (redukcja NOR)
- ^ (redukcja XOR)
- ~ ^ lub ^ ~ (redukcja XNOR)
Example
Module chk_zero (x, z);
Input [2:0] x;
Output z;
Assign z = & x; // Reduction AND
End module
Operatorzy zmianowi
Operatory przesunięcia, które przesuwają pierwszy operand o liczbę bitów określoną przez drugi operand w składni. Wolne pozycje są wypełnione zerami dla obu kierunków, przesunięć w lewo iw prawo (nie ma rozszerzenia znaku użycia).
Operatory uwzględnione w operacji Shift to:
- << (przesuń w lewo)
- >> (przesuń w prawo)
Example
Assign z = c << 3; /* z = c shifted left 3 bits;
Wolne pozycje są wypełnione zerami * /
Operator łączenia
Operator konkatenacji łączy dwa lub więcej operandów w celu utworzenia większego wektora.
Operator zawarty w operacji konkatenacji to - {} (konkatenacja)
Example
wire [1:0] a, h; wire [2:0] x; wire [3;0] y, Z;
assign x = {1’b0, a}; // x[2] = 0, x[1] = a[1], x[0] = a[0]
assign b = {a, h}; /* b[3] = a[1], b[2] = a[0], b[1] = h[1],
b[0] = h[0] */
assign {cout, b} = x + Z; // Concatenation of a result
Operator replikacji
Operator replikacji tworzy wiele kopii elementu.
Operator używany w operacji replikacji to - {n {element}} (n-krotna replikacja elementu)
Example
Wire [1:0] a, f; wire [4:0] x;
Assign x = {2{1’f0}, a}; // Equivalent to x = {0,0,a }
Assign y = {2{a}, 3{f}}; //Equivalent to y = {a,a,f,f}
For synthesis, Synopsis did not like a zero replication.
For example:-
Parameter l = 5, k = 5;
Assign x = {(l-k){a}}
Operator warunkowy
Operator warunkowy syntetyzuje do multipleksera. Jest tego samego rodzaju, co jest używane w C / C ++ i oblicza jedno z dwóch wyrażeń na podstawie warunku.
Operator używany w operacji warunkowej to -
(Stan: schorzenie) ? (Wynik, jeśli warunek jest prawdziwy) -
(wynik, jeśli warunek fałszywy)
Example
Assign x = (g) ? a : b;
Assign x = (inc = = 2) ? x+1 : x-1;
/* if (inc), x = x+1, else x = x-1 */
Operandy
Literały
Literały to operandy o stałej wartości, które są używane w wyrażeniach Verilog. Dwa powszechnie używane literały Verilog to -
String - Operand literału ciągu to jednowymiarowa tablica znaków ujęta w podwójne cudzysłowy ("").
Numeric - Operand stałej liczby jest określony w postaci liczby binarnej, ósemkowej, dziesiętnej lub szesnastkowej.
Example
n - liczba całkowita reprezentująca liczbę bitów
F - jeden z czterech możliwych formatów podstawowych -
b - zapis binarny, o - ósemkowy, d - dziesiętny, h - szesnastkowy.
“time is” // string literal
267 // 32-bit decimal number
2’b01 // 2-bit binary
20’hB36F // 20-bit hexadecimal number
‘062 // 32-bit octal number
Przewody, rejestry i parametry
Przewody, rejestry i parametry to typy danych używane jako operandy w wyrażeniach Verilog.
Wybór bitu „x [2]” i wybór części „x [4: 2]”
Selekcja bitów i selekcja części służą do wybierania odpowiednio jednego bitu i wielu bitów z drutu, wektora reg lub parametru za pomocą nawiasów kwadratowych „[]”. Zaznaczenia bitowe i zaznaczenia części są również używane jako operandy w wyrażeniach w taki sam sposób, jak używane są ich główne obiekty danych.
Example
reg [7:0] x, y;
reg [3:0] z;
reg a;
a = x[7] & y[7]; // bit-selects
z = x[7:4] + y[3:0]; // part-selects
Połączenia funkcyjne
W wywołaniach funkcji zwracana wartość funkcji jest używana bezpośrednio w wyrażeniu bez konieczności przypisywania jej najpierw do rejestru lub przewodu. Po prostu umieszcza wywołanie funkcji jako jeden z typów operandów. Jest to potrzebne, aby upewnić się, że znasz szerokość bitową wartości zwracanej przez wywołanie funkcji.
Example
Assign x = y & z & chk_yz(z, y); // chk_yz is a function
. . ./* Definition of the function */
Function chk_yz; // function definition
Input z,y;
chk_yz = y^z;
End function
Moduły
Deklaracja modułu
W Verilog moduł jest główną jednostką projektową. Wskazuje nazwę i listę portów (argumenty). Kolejnych kilka wierszy, które określają typ wejścia / wyjścia (wejście, wyjście lub inout) i szerokość każdego portu. Domyślna szerokość portu to tylko 1 bit. Zmienne portu muszą być zadeklarowane przez wire, wand. . ., rej. Domyślną zmienną portu jest wire. Zwykle wejścia są przewodowe, ponieważ ich dane są zablokowane poza modułem. Wyjścia są typu reg, jeśli ich sygnały są przechowywane w środku.
Example
module sub_add(add, in1, in2, out);
input add; // defaults to wire
input [7:0] in1, in2; wire in1, in2;
output [7:0] out; reg out;
... statements ...
End module
Ciągłe przypisanie
Ciągłe przypisanie w module służy do przypisywania wartości do przewodu, co jest normalnym przypisaniem używanym na zewnątrz bloków zawsze lub początkowych. To przypisanie jest wykonywane za pomocą jawnej instrukcji przypisania lub w celu przypisania wartości do przewodu podczas jego deklaracji. Ciągłe przypisanie jest wykonywane w sposób ciągły w czasie symulacji. Kolejność instrukcji przypisania nie ma na to wpływu. Jeśli dokonasz jakiejkolwiek zmiany w dowolnym sygnale wejściowym po prawej stronie, zmieni to sygnał wyjściowy po lewej stronie.
Example
Wire [1:0] x = 2’y01; // assigned on declaration
Assign y = c | d; // using assign statement
Assign d = a & b;
/* the order of the assign statements does not matter. */
Instancje modułów
Deklaracje modułów są szablonami do tworzenia rzeczywistych obiektów. Moduły są tworzone wewnątrz innych modułów, a każda instancja tworzy pojedynczy obiekt z tego szablonu. Wyjątkiem jest moduł najwyższego poziomu, który jest własną instancją. Porty modułu muszą być dopasowane do tych, które są zdefiniowane w szablonie. Jest określone -
By name, używając kropki „.template port name (nazwa przewodu podłączonego do portu)”. Lub
By position, umieszczając porty w tym samym miejscu na listach portów zarówno szablonu, jak i instancji.
Example
MODULE DEFINITION
Module and4 (x, y, z);
Input [3:0] x, y;
Output [3:0] z;
Assign z = x | y;
End module