Verilog HDL cz 1 i 2


Verilog HDL
część I i II
Podstawowe cechy i zastosowania języka Verilog
Umo\liwia opisywanie zło\onych układów cyfrowych na wysokim
poziomie abstrakcji (podobnie jak język VHDL)
Podobnie jak inne języki HDL dla układów cyfrowych, mo\e być
stosowany zarówno do modelowania jak i syntezy
Poziom abstrakcji jest prawie tak wysoki jak w języku VHDL, ale nieco
ni\szy  mały krok w kierunku języków typu ABEL
Mo\liwy jest zarówno opis behawioralny (funkcjonalny), strukturalny
(komponentowy, hierarchiczny) jak i dowolny opis mieszany, będący ich
kombinacją
Oparty częściowo na składni języka C
Jest językiem przenośnym, obsługiwanym przez rozmaite
oprogramowanie:
Do budowania aplikacji w oparciu o układy programowalne, np., Active-HDL,
Synopsys, Synplify, ispLever, MaxPlus
Do projektowania i symulacji cyfrowych układów ASIC, np. Synopsys, Envisia,
Verilog-XL, Silicon Ensemble
Sposoby opisu sprzętu w języku Verilog
Opis behawioralny (funkcjonalny)
Opis algorytmiczny, wykorzystujący wysokopoziomowe konstrukcje
języka Verilog
Opis strukturalny:
Gate-level  opis na poziomie bramek logicznych oraz elementarnych
komórek cyfrowych definiowanych przez u\ytkownika (UDP)
Switch-level  opis na tranzystorów jako kluczy oraz pojemności jako
elementów pamiętających
Opis hierarchiczny, wielopoziomowy, RTL
Ogólna struktura modułu
module jk_flop_case (j, k, clock, rst, q, qb); nagłówek modułu
module
module
module
input j, k, clock, rst;
deklaracje sygnałów
output q, qb;
zewnętrznych i wewnętrznych
reg q;
część kombinacyjna 
assign qb = ~q;
przypisania ciągłe
always @ (posedge clock or posedge rst)
begin
if (rst == 1'b1)
q = 1'b0;
else
część sekwencyjna 
case ({j,k})
bloki proceduralne
2'b00: q = q;
2'b01: q = 1'b0;
2'b10: q = 1'b1;
2'b11: q = ~q;
endcase
end
koniec modułu
endmodule
endmodule
endmodule
endmodule
Stany logiczne i wyra\enia
Dopuszczalne stany logiczne
Stan wysoki (1)
assign high = 1'b1;
Stan niski (0)
wire low = 1'b0;
Stan nieokreślony (x)
bus = 4'bx;
Stan wysokiej impedancji (z)
tbus = 16'bz
Elementy składowe wyra\eń:
Sygnały
Zmienne
Stałe
Operatory
Stałe
liczby bez określonego rozmiaru w bitach (domyślnie zwykle 32-bit):
32767 // liczba w kodzie dziesiętnym (mo\na dodać prefiks  d)
'h0fa0 // liczba w kodzie szesnastkowym
'o7460 // liczba w kodzie ósemkowym
'b0101 // liczba w kodzie dwójkowym
liczby z określonym rozmiarem:
4'b1001 // 4-bitowa liczba w kodzie dwójkowym
8'd255 // 8-bitowa liczba w kodzie dziesiętnym (d mo\na pominąć)
3'b10x // 3-bit liczba z najmniej znaczącą cyfrą nieokreśloną
12'bx // nieokreślona liczba 12-bitowa
16'hz // stan wysokiej impedancji na 16 liniach
liczby ze znakiem i bez znaku:
4'd1 // 4-bitowa liczba 1 bez znaku
-4'd1 // 4-bitowa liczba -1 bez znaku (czyli tak naprawdę 15)
4'sd1 // 4-bitowa liczba 1 ze znakiem
-4'sd1 // 4-bitowa liczba -1 ze znakiem (traktowana jako  1)
liczby zmiennoprzecinkowe:
2301.15 // liczba zmiennoprzecinkowa w zwykłym formacie
1.30e-2 // liczba zmiennoprzecinkowa w formacie wykładniczym
łańcuchy tekstowe:
"hello" // łańcuch tekstowy
Znaki specjalne w łańcuchach tekstowych
Komentarze i makrodefinicje
Ignorowanie kodu od danego miejsca do końca linii:
wire w; // pominięcie kodu od tego miejsca do końca linii
// pominięcie całej linii
Ignorowanie całego fragmentu kodu:
/* pominięcie całego
fragmentu kodu */
Makrodefinicje (podstawienia):
`define wordsize 8
`define greeting "hello"
Typy sygnałów i zmiennych
sygnały  kombinacyjne typu net (wire, wor, wand, tri1, tri0, supply1, supply0)
wire a1, a2; // zwykłe sygnały kombinacyjne
wire
wire
wire
wand w1, w2; // sygnały typu iloczyn galwaniczny
wand
wand
wand
sygnały  rejestrowe typu reg
reg q1, q2; // wyjścia przerzutników
reg
reg
reg
sygnały związane z pamięciami ulotnymi typu trireg
wektory
wire [7:0] A1, A2; // magistrale
wire [7:0]
wire [7:0]
wire [7:0]
reg [0:3] R1, R2; // rejestry
reg [0:3]
reg [0:3]
reg [0:3]
pamięci
reg M1 [0:63]; // pamięć 64x1
reg [0:63]
reg [0:63]
reg [0:63]
łańcuchy tekstu
reg [8*14:1] stringvar; // tekst o dł. 13 znaków +  \0
reg [8*14:1]
reg [8*14:1]
reg [8*14:1]
zmienne całkowite typu integer
integer i; // 32-bit liczba całkowita ze znakiem
integer
integer
integer
zmienne zmiennoprzecinkowe typu real
real r; // liczba zmiennoprzecinkowa
real
real
real
zmienne czasowe typu time (czas dyskretny)
time t; // 64-bit liczba całkowita bez znaku
time
time
time
Zmienne typu  net
wire/tri (sprzeczne stany dają x) wand/triand  WIRED AND
wor/trior  WIRED OR tri0/tri1  słabe zero/jeden (pull0/pull1)
VDD
tri0 net
pull-up
pull-down
tri1 net
supply0/supply1  zawsze zero/jeden
Wektory i pamięci
Wektory
Umo\liwiają połączenie pojedynczych sygnałów w jeden ciąg:
wire [11:0] busA, busB; // 12-bitowe magistrale
wire [11:0]
wire [11:0]
wire [11:0]
reg [7:0] A, B; // 8-bitowe rejestry
reg [7:0]
reg [7:0]
reg [7:0]
Domyślnie, wektory są równowa\ne liczbom całkowitym bez znaku (unsigned)
Wektory mogą równie\ odpowiadać liczbom całkowitym ze znakiem (signed):
reg signed [7:0] A, B; // 8-bitowe rejestry ze znakiem
reg signed [7:0]
reg signed [7:0]
reg signed [7:0]
Konwersje wektorów na liczby całkowite i na odwrót są wykonywane automatycznie,
bez potrzeby korzystania z \adnych bibliotek dodatkowych
Mo\liwe jest wyłuskanie pojedynczych sygnałów lub całych fragmentów wektorów:
wire [3:0] AH = A[7:4]; // wyłuskanie bardziej znaczącej połowy
A[7:4];
A[7:4];
A[7:4];
wire A7 = A[7]; // wyłuskanie najbardziej znaczącego bitu
A[7]
A[7]
A[7]
Mo\liwe jest scalanie (konkatenacja) wektorów ze sobą i z pojedynczymi sygnałami:
reg [3:0] AH, AL; // deklaracja 4-bit rejestrów AH i AL
reg E; // deklaracja przerzutnika E
wire [8:0] EA = {E,AH,AL}; // połączenie w jeden 9-bit wektor EA
{E,AH,AL}
{E,AH,AL}
{E,AH,AL}
Pamięci
deklaracja pamięci:
reg mem1 [0:63]; // pamięć 63x1
reg [0:63]
reg [0:63]
reg [0:63]
reg [7:0] mem2 [0:255]; // pamięć 255x8
reg [7:0] [0:255]
reg [7:0] [0:255]
reg [7:0] [0:255]
Deklaracje portów (sygnałów zewnętrznych)
Rodzaje portów
porty wejściowe (input)
porty wyjściowe (output)
porty dwukierunkowe (inout)
końcówki modułu
module jkff (j, k, clock, rst, q, qb);
input j, k, clock, rst; // sygnały wejściowe
input
input
input
output q, qb; // sygnały wyjściowe
output
output
output
reg q; // bo sygnał q jest wyjściem przerzutnika
reg
reg
reg
...
endmodule
magistrale zewnętrzne
module mux21_4 (SEL, A, B, Y);
input [1:0] SEL; // magistrala sterująca
input [1:0]
input [1:0]
input [1:0]
input [3:0] A, B; // magistrale wejściowe
input [3:0]
input [3:0]
input [3:0]
output [3:0] Y; // magistrala wyjściowa
output [3:0]
output [3:0]
output [3:0]
...
endmodule
Deklaracje sygnałów wewnętrznych
Rodzaje sygnałów wewnętrznych:
sygnały kombinacyjne (nets)
sygnały rejestrowe (registers)
magistrale wewnętrzne
rejestry
pamięci
module datapath (clock, load, ctrl, din, dout);
input clock;
input [1:0] ctrl;
input [15:0] din;
output [15:0] dout;
reg [15:0] dout;
wire lda, ldb, add, nand; // sygnały wewnętrzne
wire
wire
wire
reg [15:0] A, B; // rejestry wewnętrzne
reg [15:0]
reg [15:0]
reg [15:0]
wire [15:0] busA, busB, busC; // magistrale wewnętrzne
wire [15:0]
wire [15:0]
wire [15:0]
...
endmodule
Operatory i ich priorytety
Operatory bitowe
Operatory redukcyjne
Przypisania ciągłe (kombinacyjne)
Składnia:
assign net1 = ... <,net2 = ..., net3 = ...>
lub razem z deklaracją sygnału wewnętrznego:
net_type net1 = ... <,net 2 = ..., net3 = ...>
trireg net1 = ... <,net 2 = ..., net3 = ...>
module andorinv(z, a, b, c, d);
input a, b, c, d;
output z;
assign z = ~(a & b | c & d); // przypisanie ciągłe
assign
assign
assign
endmodule
module andorinv(z, a, b, c, d);
input a, b, c, d;
output z;
wire ab = a & b, cd = c & d; // deklaracje z przypisaniami ciągłymi
wire
wire
wire
assign z = ~(ab | cd); // przypisanie ciągłe
assign
assign
assign
endmodule
Uwaga: Po lewej stronie przypisania kombinacyjnego mo\e występować tylko sygnał typu
net (wire, wand, wor, tri0, tri1) albo trireg!
Przykłady zastosowań przypisań ciągłych
Sumator 4-bitowy
module adder (sum_out, carry_out, carry_in, ina, inb);
output [3:0] sum_out;
input [3:0] ina, inb;
output carry_out;
input carry_in;
wire carry_out, carry_in;
wire[3:0] sum_out, ina, inb;
assign {carry_out, sum_out} = ina + inb + carry_in;
endmodule
Dekoder 2 na 4
module decoder24 (out, in);
output [3:0] out;
input [1:0] in;
assign out[0] = ~in[1] & ~in[0];
assign out[1] = ~in[1] & in[0];
assign out[2] = in[1] & ~in[0];
assign out[3] = in[1] & in[0];
endmodule
Siły wymuszania (drive strength)
domyślny dla stanu niskiego
domyślny dla stanu wysokiego
supply1 7 Su1
Przypisania ciągłe z siłą wymuszania i opóznieniem
Przypisania ciągłe z podanymi siłami wymuszania w stanie niskim i wysokim
składnia: (siła_dla_stanu_wys, siła_dla_stanu_nis) lub (siła_dla_stanu_nis, siła_dla_stanu_wys)
module open_drain(out, in1, in2); // z wyjściem typu otwarty dren
input in1, in2;
output out;
assign (pull1, strong0) out = in1; // przypisania silne w stanie niskim
(pull1, strong0)
(pull1, strong0)
(pull1, strong0)
assign (pull1, strong0) out = in2; // i słabe w stanie wysokim
(pull1, strong0)
(pull1, strong0)
(pull1, strong0)
endmodule
Przypisania ciągłe z opóznieniami
składnia: #(opózn_narastania <,opózń_opadania> <,opózń_do_st_wys_impedancji>)
module delay_inv_and(out, in1, in2);
input in1, in2;
output out;
wire #5 w1 = ~in1; // opóznienie 5 ns dla wszystkich zboczy
#5
#5
#5
wire #(5,3) w2 = ~in2; // 5 ns dla zb. dod. i 3 ns dla zb. ujemn.
#(5,3)
#(5,3)
#(5,3)
assign #(2,3,5) out = in1 & in2; // 5 ns przy przejściu w stan wys. imped.
#(2,3,5)
#(2,3,5)
#(2,3,5)
endmodule
Uwagi do opóznień
Wszelkie konstrukcje z opóznieniami są niesyntezowalne i mogą być
wykorzystywane jedynie do modelowania i symulacji opóznień!
Reguły stosowania opóznień są następujące:
Opóznienia są wyra\one w domyślnych jednostkach danego symulatora
Je\eli podano tylko jeden parametr, to będzie on stosowany do określenia
opóznienia na wszystkich mo\liwych zboczach, włącznie ze stanami przejścia
ze stanów x i z lub do stanów x i z;
Je\eli podano dwa parametry (pierwszy dla zbocza narastającego 0-1 i drugi
dla zbocza opadającego 1-0), to czas przejścia w stan wys. impedancji (z)
będzie równy dłu\szemu z tych czasów;
Czas przejścia ze stanu w stan nieokreślony (x) jest równy najkrótszemu z
podanych dwóch (trzech) czasów;
Opóznienia mają charakter inercyjny, czyli je\eli prawa strona wyra\enia po
zmianie powróci do swojej poprzedniej wartości przed upływem podanego
opóznienia, to wartość lewej strony wyra\enia nie ulegnie zmianie. Oznacza
to, \e impulsy o szerokości mniejszej od podanego opóznienia zostaną
odfiltrowane.
prawa strona
lewa strona
opóznienie
t
Przypisania ciągłe z operatorem warunkowym
Składnia:
assign net = condition ? value_if_true : value_if_false;
konstrukcję z operatorem warunkowym mo\na zagnie\d\ać w celu zbudowania konstrukcji
warunkowej wielowariantowej:
assign net = condition1 ? value_if_true :
condition2 ? value_if_true :
value_if_else;
module tristate_buffer(out, in, en); // bufor trójstanowy
input in, en;
output out;
assign out = en ? in : 1'bz; // przypisanie z operatorem warunkowym
? :
? :
? :
endmodule
module mux41(out, din, sel); // multiplekser 4 na 1
input [1:0] sel;
input [3:0] din;
output out;
assign out = (sel == 0) ? in[0] :
? :
? :
? :
(sel == 1) ? in[1] :
? :
? :
? :
(sel == 2) ? in[2] :
? :
? :
? :
(sel == 3) ? in[3] : 1'bx;
? :
? :
? :
endmodule
Bloki proceduralne
Bloki realizujące część sekwencyjną modelu  odpowiedniki procesów w
języku VHDL
Bloki proceduralne dzielą się na:
Sekwencyjne begin-end i równoległe fork-join
Wykonywane jednokrotnie initial (niesyntezowalne) i wielokrotnie always
Nazwane (z etykietą) i nie nazwane (bez etykiety)
Bloki proceduralne składają się z przypisań proceduralnych, realizujących
operacje sekwencyjne
Jeśli w jednym modelu jest wiele bloków proceduralnych, to będą one
wykonywane współbie\nie, tak jak procesy języka VHDL
Wykonanie bloku jest mo\e zostać wyzwolone:
Po upłynięciu danego czasu (konstrukcja niesyntezowalna)
Po wystąpieniu jakiegoś zdarzenia, np. zbocza sygnału lub tzw. zdarzenia
jawnego (nie wszystkie przypadki są syntezowalne)
Bloki proceduralne mogą zawierać opóznienia, jednak\e wówczas nie są
one syntezowalne i mogą być wykorzystywane jedynie do modelowania i
symulacji
Struktura bloku proceduralnego
Współbie\ne bloki proceduralne
module behave;
reg a,b;
initial
initial
initial
initial
begin
begin
begin
begin
przypisania sekwencyjne blok sekwencyjny initial
a = 1'b1;
bez opóznień
b = 1'b0;
end
end
end
end
always
always
always
always
begin
begin
begin
begin
przypisanie sekwencyjne blok sekwencyjny always
#50 a = ~a;
z opóznieniem
end
end
end
end
always
always
always
always
przypisanie sekwencyjne blok sekwencyjny always
begin
begin
begin
begin
z opóznieniem
#100 b = ~b;
end
end
end
end
endmodule
Uwaga: Słowa kluczowe begin i end mo\na pominąć, jeśli blok proceduralny
zawiera tylko jedno przypisanie proceduralne
Blok proceduralny initial
Wykonuje się tylko raz w momencie rozpoczęcia symulacji
Jest niesyntezowalny i wykorzystywany głównie w modułach testujących
zwanych test fixtures (odpowiednik testbench w języku VHDL)
Mo\e zawierać opóznienia (i zwykle zawiera), ale teoretycznie nie musi
Opóznienia są wyra\one w domyślnych jednostkach symulatora, zwykle
ps lub ns. Domyślną jednostkę mo\na zmienić dyrektywą `timescale :
`timescale /
`timescale 1 ns / 10 ps
initial
initial
initial
initial
begin
begin
begin
begin
inputs = 'b000000; // wymuszenie w chwili 0 ns
#10 inputs = 'b011001; // wymuszenie w chwili 10 ns
#10 inputs = 'b011011; // wymuszenie w chwili 20 ns
#10 inputs = 'b011000; // wymuszenie w chwili 30 ns
#10 inputs = 'b001000; // wymuszenie w chwili 40 ns
end
end
end
end
Blok proceduralny always
Wykonuje się  na okrągło , tak więc musi zawierać przynajmniej jedno
opóznienie lub instrukcję oczekiwania na zdarzenie:
Wyzwalany opóznieniem:
always #5
always #5
always #5
always #5
lub po prostu:
begin
clk = ~clk;
always #5 clk = ~clk;
always #5
always #5
always #5
end
lub ale nigdy:
always
always
always
always
begin
always clk = ~clk;
always
always
always
#5 clk = ~clk;
end
Wyzwalany zboczem narastającym, opadającym lub dowolnym:
always @ a always @(negedge clk)
always @ a always @(negedge clk)
always @ a always @(negedge clk)
always @ a always @(negedge clk)
begin begin
b = a; q = d;
end end
lub
always @(posedge clk) always
always @(posedge clk) always
always @(posedge clk) always
always @(posedge clk) always
begin begin
q = d; @(negedge clk) q = d;
@(negedge clk)
@(negedge clk)
@(negedge clk)
end end
Blok proceduralny always (c.d.)
Wyzwalany zboczami więcej ni\ jednego sygnału:
always @(posedge rst or posedge clk)
or
or
or
begin
always
if (rst)
begin
q = 1'b0;
@(posedge rst or posedge clk)
or
or
or
else
if (rst)
q = d;
lub
q = 1'b0;
end
else
q = d;
end
Z instrukcją oczekiwania:
always
begin
ale nigdy:
wait (ce);
wait
wait
wait
@(posedge clk) q = d;
end
always
begin
lub
wait (!latch) q = d;
wait
wait
wait
end
always
begin
wait (!ce);
wait
wait
wait
@(posedge clk) q = d;
end
Bloki instrukcji sekwencyjne i równoległe
Blok sekwencyjny begin-end
Przypisania są wykonywane po kolei
Opóznienie jest liczone od zakończenia poprzedniego przypisania
begin
begin
begin
begin
r = 4'h0; // t = 0
#10 r = 4'h2; // t = 10 ns
#10 r = 4'h4; // t = 20 ns
#10 r = 4'h8; // t = 30 ns
end
end
end
end
Blok równoległy fork-join
Przypisania są wykonywane współbie\nie
Wszystkie opóznienia są liczone względem początku bloku
fork
fork
fork
fork
r = 4'h0; // t = 0
#10 r = 4'h2; // t = 10 ns
#20 r = 4'h4; // t = 20 ns
#30 r = 4'h8; // t = 30 ns
join
join
join
join
Intra-assignments
Zastosowanie do zapobiegania wyścigom:
fork fork
fork fork
fork fork
fork fork
#5 a = b; // rezultat będzie a = #5 b; // nastąpi zamiana
#5 b = a; // przypadkowy b = #5 a; // wartości a i b
join join
join join
join join
join join
Przypisania nieblokujące
Wykonywanie tego przypisania nie wstrzymuje wykonywania następnych instrukcji
Przypisania nieblokujące (c.d.)
Mieszanie przypisań blokujących i nieblokujących
Pytanie: Czy obydwa przykłady są równowa\ne?
reg a, b; reg a, b;
begin fork
a <= b; a = b;
?
b <= a; b = a;
end join
Przypisania warunkowe
Instrukcja warunkowa if-else Konstrukcja wielowariantowa if-else-if
if (sel)
if
if
if
if (state == RED)
if
if
if
C = A + B;
begin
begin
begin
begin
else
else
else
else
RYG = 3'b100;
C = A - B;
state = RED_YELLOW;
end
end
end
end
else if (state == RED_YELLOW)
else if
else if
else if
begin
begin
begin
begin
RYG = 3'b110;
state = GREEN;
if (state == PASS1)
if
if
if
end
end
end
end
begin
begin
begin
begin
else if (state == GREEN)
else if
else if
else if
A = A1 + A2;
begin
begin
begin
begin
state = PASS2;
RYG = 3'b001;
end
end
end
end
state = YELLOW;
else
else
else
else
end
end
end
end
begin
begin
begin
begin
else
else
else
else
A = A + A1 + A2;
begin
begin
begin
begin
state = PASS1;
RYG = 3'b010;
end
end
end
end
state = RED;
end
end
end
end
Konstrukcje wielodecyzyjne case/casez/casex
Instrukcja case Instrukcja casez
przy porównaniu ignoruje bity w stanie z
reg [15:0] rega;
reg [9:0] result;
reg [7:0] ir;
...
...
case (rega)
case
case
case
casez (ir)
casez
casez
casez
16'd0: result = 10 b0111111111;
8'b1???????: instruction1(ir);
16'd1: result = 10 b1011111111;
8'b01??????: instruction2(ir);
16'd2: result = 10 b1101111111;
8'b00010???: instruction3(ir);
16'd3: result = 10 b1110111111;
8'b000001??: instruction4(ir);
16'd4: result = 10 b1111011111;
endcase
endcase
endcase
endcase
16'd5: result = 10 b1111101111;
16'd6: result = 10 b1111110111;
16'd7: result = 10 b1111111011;
Instrukcja casex
16'd8: result = 10 b1111111101;
przy porównaniu ignoruje bity w stanach z i x
16'd9: result = 10 b1111111110;
default result =  bx;
default
default
default
reg [7:0] r, mask;
endcase
endcase
endcase
endcase
...
mask = 8 bx0x0x0x0;
casex (r ^ mask)
casex
casex
casex
UWAGA: Instrukcja case traktuje stany z
8'b001100xx: stat1;
i x tak samo jak stany 0 i 1
8'b1100xx00: stat2;
8'b00xx0011: stat3;
8'bxx001100: stat4;
endcase
endcase
endcase
endcase
Przykłady zastosowania bloków proceduralnych
Przerzutnik D z kasowaniem
Przerzutnik JK z kasowaniem
asynchronicznym
asynchronicznym
module dffar (Q, nQ, rst, clk, D); module jkffar (Q, nQ, rst, clk, J, K);
output Q, nQ; output Q, nQ;
input rst, clk, D; input rst, clk, J, K;
reg Q; reg Q;
assign nQ = ~Q; assign nQ = ~Q;
always @(posedge rst or posedge clk) always @(posedge rst or posedge clk)
begin begin
if (rst) if (rst)
Q = 1'b0; Q = 1'b0;
else else
Q = D; case ({J,K})
end 2'b01: Q = 1'b0;
endmodule 2'b10: Q = 1'b1;
2'b11: Q = ~Q;
default Q = Q;
endcase
end
endmodule
Pętle
Pętla repeat Pętla while
initial always #10
begin begin
i = 0;
repeat (10)
repeat
repeat
repeat
begin while (i < 10)
while
while
while
$display("i= %d", i); begin
i = i + 1; $display("i= %d", i);
end i = i + 1;
end
end
end
Pętla forever Pętla for
initial always #10
begin begin
counter = 0;
for (i = 1; i < 16; i = i+1)
for
for
for
forever #10 counter = counter + 1; begin
forever
forever
forever
$display("i= %d", i);
end
end
end
Syntezowalny kod zawierający pętlę
Komparator z pętlą for, przerywaną instrukcją disable:
module comparator_with_loop (a, b, a_gt_b, a_lt_b, a_eq_b);
parameter size = 2;
input [size: 1] a, b;
output a_gt_b, a_lt_b, a_eq_b;
etykieta bloku jest wymagana
reg a_gt_b, a_lt_b, a_eq_b;
integer k;
always @ (a or b)
begin: compareLoop
for (k = size; k > 0; k = k-1) begin
for
for
for
if (a[k] != b[k]) begin
warunkowe przerwanie działania bloku compareLoop
a_gt_b = a[k];
a_lt_b = ~a[k];
a_eq_b = 0;
disable compareLoop;
disable
disable
disable
end // if
end // for loop
a_gt_b = 0;
a_lt_b = 0;
a_eq_b =1;
end // compare loop
endmodule
Proceduralne przypisania ciągłe
Konstrukcja assign-deassign
Stosowana do modelowania sprzętu, np. układów z asynchronicznym kasowaniem
module dff(q,d,clear,preset,clock);
output q;
input d,clear,preset,clock;
reg q;
always @(clear or preset)
begin
if (!clear)
assign q = 0; // asynchroniczne kasowanie
assign
assign
assign
else if (!preset)
assign q = 1; // asynchroniczne ustawianie
assign
assign
assign
else
deassign q; // odblokowanie przerzutnika po skasowaniu/ustawieniu
deassign
deassign
deassign
end
always @(posedge clock)
q = d; // klasyczne przypisanie proceduralne
endmodule
Konstrukcja force-release
Stosowana w symulacji do uruchamiania (debuggowania) projektów
Ma wy\szy priorytet ni\ assign-deassign
Modelowanie pamięci dynamicznych
Węzeł typu trireg:
Mo\e znajdować się w jednym z dwóch stanów:
Stan wymuszony (driven state), je\eli przynajmniej jedno z wymuszeń jest w stanie 0,
1 lub X. Wówczas węzeł propaguje stan wynikający z wymuszeń.
Stan pojemnościowy (capacitive state), kiedy wszystkie wymuszenia są w stanie wys.
impedancji (Z). Wówczas węzeł pamięta poprzedni stan.
Typ trireg stoi po lewej stronie przypisań ciągłych i dlatego jest często klasyfikowany jako
podtyp typu net
W stanie wymuszonym, siły wymuszeń mogą być ustawione na strong, pull albo weak
W stanie pojemnościowym, węzeł typu trireg mo\e stanowić wymuszenie o ró\nej sile
(charge strength): small, medium lub large, co jest bezpośrednio związane z wartością
pojemności komórki pamięci dynamicznej
W stanie pojemnościowym, stan węzła mo\e utrzymywać się w nieskończoność (pojemność
idealna) lub po pewnym czasie mo\e ulec zniszczeniu (charge decay), czyli przejściu w stan
nieokreślony (X) (pojemność z upływem)
1 0
wej = 0,1,x wyj = wej wyj = st. poprz.
nmos nmos
C C
(wł) (wył)
węzeł trireg w stanie węzeł trireg w stanie
wymuszonym pojemnościowym
Symulacja działania węzła typu trireg
Przykłady zastosowania węzła typu trireg
siła wymuszenia w stanie poj. (wielkość ładunku)
reg data1, data2, select; czas podtrzymania informacji w c2
trireg c1; // deklaracja węzła c1 o pojemności medium
trireg
trireg
trireg
// i o nieskończonym czasie podtrzymania
trireg (small) #(0,0,1000) c2; // deklaracja węzła c2 o pojemności small
trireg
trireg
trireg
// i z czasem podtrzymania 1000 ns
assign c1 = select ? data1 : 1'bz; // sygnal select przelacza c1 i c2 pomiedzy
assign c2 = select ? data2 : 1'bz; // stanem wymuszanym a pojemnościowym
initial
begin
data = 1'b1 // wymuszenie stanu 1 na węzłach c1 i c2
#0 select = 1'b1; // ustawienie c1 i c2 w stan wymuszany
#50 select = 1'b0; // przestawienie c1 i c2 w stan pojemnościowy
// (zapamiętany stan 1) po 50 ns
end
Modelowanie pamięci dynamicznych (przykład)
Komórka pamięci dynamicznej
`timescale 1ns / 10 ps
module dram_cell(data, wl, rw);
inout data; // wejście/wyjście danych
input wl; // selektor komórki (word line)
input rw; // 1  zapis, 0 - odczyt
wire bit;
trireg #(0,0,8000) mem; // deklaracja komórki pamięci
assign mem = wl ? bit : 1'bz; // zapis do komórki
assign (weak0,weak1) bit = wl ? mem : 1'bz; // odczyt z komórki
assign bit = rw ? data : 1'bz;
assign data = rw ? 1'bz : bit;
endmodule
Symulacja działania sieci pojemnościowej
1. At simulation time 0, wire a and wire b have a value of 1. The wire c drives a value of 1 into
triregs la and sm, wire d drives a value of 1 into triregs me1 and me2.
2. At simulation time 10, the value of wire b changes to 0, disconnecting trireg sm and me2 from
their drivers. These triregs enter the capacitive state and store the value 1; their last driven value.
3. At simulation time 20, wire c drives a value of 0 into trireg la.
4. At simulation time 30, wire d drives a value of 0 into trireg me1.
5. At simulation time 40, the value of wire a changes to 0, disconnecting trireg la and me1 from
their drivers. These triregs enter the capacitive state and store the value 0.
6. At simulation time 50, the value of wire b changes to 1. This change of value in wire b connects
trireg sm to trireg la; these triregs have different sizes and stored different values. This
connection causes the smaller trireg to store the larger trireg value and trireg sm now stores
a value of 0.This change of value in wire b also connects trireg me1 to trireg me2; these
triregs have the same size and stored different values. The connection causes both trireg me1
and me2 to change value to x.
Symulacja współdzielenia ładunku
1. At simulation time 0, the value of wire a, b, and c is 1 and wire a drives a strong 1 into
trireg la and sm.
2. At simulation time 10, the value of wire b changes to 0, disconnecting trireg la andsm from
wire a. The triregs la and sm enter the capacitive state. Both triregs share the large
charge of trireg la because they remain connected throughtranif2.
3. At simulation time 20, the value of wire c changes to 0, disconnecting trireg sm fromtrireg
la. The trireg sm no longer shares the large charge of trireg la and now stores a small
charge.
4. At simulation time 30, the value of wire c changes to 1, connecting the two triregs. These
triregs now share the same charge.
5. At simulation time 40, the value of wire c changes again to 0, disconnecting trireg sm from
trireg la. Once again, trireg sm no longer shares the large value oftrireg la and now
stores a small charge.
Zadania
Są to procedury składające się z instrukcji sekwencyjnych, takich jakie występują w blokach
proceduralnych
Mogą przyjmować zero lub więcej argumentów dowolnego typu: input, output lub inout
Przy wywołaniu zadania, jeśli argument jest typu input, mo\e zostać do niego podstawiony
dowolny rodzaj danej, wyra\enie lub stała
Jeśli argument jest typu inout lub output, podstawiona dana jest ograniczona do tylko tych
typów, które mogą znajdować się po lewej stronie przypisania proceduralnego, a więc
rejestrów, odwołań do pamięci oraz ich dowolnych fragmentów i połączeń (konkatenacji)
Definicja zadania:
module this_task;
task my_task;
task
task
task
input a, b;
inout c;
output d, e;
reg foo1, foo2, foo3;
begin
// the set of statements that performs the work of the task
c = foo1; // the assignments that initialize
d = foo2; // the results variables
e = foo3;
end
endtask
endtask
endtask
endtask
endmodule
Wywołanie zadania:
my_task (v, w, x, y, z);
Zadania - przykład
module SHREG4(CLK, S, IN, IL, IR, Q);
input [3:0] IN;
input [1:0] S;
input CLK, IL, IR;
output [3:0] Q;
reg [3:0] Q;
parameter left = 0, right = 1;
task load;
task
task
task
Q = IN; // load contents into the register
endtask
endtask
endtask
endtask
task shift;
task
task
task
input direction; // 0 - shift left, 1 - shift right
begin
if (direction)
Q = {IL,Q[3:1]}; // shift right register contents
else
Q = {Q[2:0],IR}; // shift left register contents
end
endtask
endtask
endtask
endtask
always @(posedge CLK) // main procedural block
begin
case (S)
2'b00: ; // do nothing
2'b11: load; // load contents
2'b01: shift(right); // shift right
2'b10: shift(left); // shift left
default: Q = 4'bx; // unhandled states
endcase
end
endmodule
Funkcje  przykład 1
Funkcja obliczająca liczbę jedynek w 4-bitowym słowie  przykład syntezowalny
module test_ones (in, out);
input [3:0] in;
output [2:0] out;
function [2:0] get_ones;
function
function
function
input [3:0] operand;
get_ones = operand[0] + operand[1] + operand[2] + operand[3];
endfunction
endfunction
endfunction
endfunction
assign out = get_ones(in);
endmodule
Funkcje  przykład 2
Funkcja obliczająca 2n  przykład niesyntezowalny
module test_power2;
reg [4:0] value;
reg [5:0] n;
function [31:0] power2;
function
function
function
input [4:0] exponent;
reg [4:0] index;
begin
power2 = 1;
for(index = 0; index < exponent; index = index + 1)
power2 = power2 * 2;
end
endfunction
endfunction
endfunction
endfunction
initial
begin
for(n = 0; n <= 31; n = n + 1)
$display("2^%0d = %0d", n, power2(n));
end
endmodule
Ograniczenia funkcji
Funkcje nie mogą zawierać \adnych instrukcji sterowanych przez czas,
czyli \adnych instrukcji poprzedzonych przez #, @, lub wait.
Funkcje nie mogą uruchamiać zadań.
Funkcje muszą posiadać przynajmniej jeden argument typu input.
Lista argumentów funkcji nie mo\e zawierać argumentów typu inout ani
output.
Funkcja musi zawierać przypisanie wyniku funkcji do wewnętrznej
(lokalnej) zmiennej o takiej samej nazwie co nazwa funkcji (przypisanie
to jest zwykle na końcu).
Zadania a funkcje:
Funkcja musi się wykonać w jednej chwili czasowej symulacji, natomiast
zadanie mo\e zawierać instrukcje czasowe (#, @, lub wait).
Podczas gdy funkcja nie mo\e uruchamiać zadania, zadanie mo\e
uruchamiać funkcje i inne zadania.
Funkcja musi mieć przynajmniej jeden argument typu input, natomiast
zadanie mo\e mieć zero lub więcej argumentów dowolnego typu.
Funkcja zwraca wartość, natomiast zadanie nie zwraca \adnej wartości.
Zdarzenia jawne
Wykorzystywane jako semafory synchronizujące współbie\ne bloki proceduralne:
module test_ones (dl, din, dout);
input dl;
input [7:0] din;
output [7:0] dout;
event latch; deklaracja zdarzenia jawnego
event
event
event
always @(posedge dl)
begin
->
->
->latch;
->
wywołanie zdarzenia jawnego
end
always @(posedge clk)
begin
@latch dout = din;
instrukcja oczekująca na zdarzenie jawne
end
endmodule
Opis strukturalny
Rodzaje opisu strukturalnego: Wbudowane elementy podstawowe:
Opis na poziomie bramek logicznych Bramki AND, OR, NAND, NOR, XOR,
i kluczy (gate- and switch-level XNOR
description)
Inwertery i bufory dwustanowe i
Modelowanie z wykorzystaniem trójstanowe
prostych układów kombinacyjnych
Klucze MOS i CMOS
lub sekwencyjnych definiowanych
Dwukierunkowe bramki transmisyjne
przez u\ytkownika (UDP)
Rezystory pull-up i pull-down
Opis hierarchiczny (wielopoziomowy)
Makromoduły
Składnia opisu na poziomie bramek i kluczy
Z etykietami i jawną deklaracją
Bez etykiet i niejawną deklaracją
sygnałów wewnętrznych
sygnałów wewnętrznych
a ab
a ab
and1
b
b
or1 y
y
c
c
d and2
d
cd
cd
module and_or (y, a, b, c, d); module and_or (y, a, b, c, d);
output y; output y;
input a, b, c, d; input a, b, c, d;
wire ab, cd;
deklaracje sygnałów wew.
and (ab, a, b);
and
and
and
etykieta elementu (opcjonalna) and (cd, c, d);
and
and
and
or (y, ab, cd);
or
or
or
and and1 (ab, a, b);
and
and
and
and and2 (cd, c, d);
and
and
and
endmodule
or or1 (y, ab, cd);
or
or
or
sygnały wejściowe
endmodule
sygnał wyjściowy
Składnia opisu na poziomie bramek i kluczy
Komponenty z opóznieniami i ró\nymi siłami wymuszania
#(5,3)
a ab
and1 #(5,5)
b
or1 y
c
d and2
cd
#(5,3)
module and_or (y, a, b, c, d);
output y;
input a, b, c, d;
wire ab, cd;
opóznienie przy przejściu w stan wysoki i niski
and (strong0,strong1) #(5,3) and1 (ab, a, b);
and
and
and
and (strong0,strong1) #(5,3) and2 (cd, c, d);
and
and
and
or (strong0,strong1) #5 or1 (y, ab, cd);
or
or
or
siła wymuszenia przy przejściu z w stan wysoki
endmodule
siła wymuszenia przy przejściu z w stan niski
Ciągi elementów
Bez ciągów elementów Z ciągiem elementów
en
in[3] out[3]
ar3
en
in[2] out[2]
ar2
in[3:0] out[3:0] in[3:0] out[3:0]
in[1] out[1]
ar1
ar[3:0]
in[0] out[0]
ar0
module driver (in, out, en);
module driver (in, out, en);
input [3:0] in;
input [3:0] in;
output [3:0] out;
output [3:0] out;
input en;
input en;
bufif0 ar3 (out[3], in[3], en);
bufif0 ar[3:0] (out, in, en);
bufif0 ar2 (out[2], in[2], en);
bufif0 ar1 (out[1], in[1], en);
endmodule
bufif0 ar0 (out[0], in[0], en);
endmodule
Bramki logiczne (1)
Bramki AND, OR, NAND, NOR, XOR
and AND1 (z, a, b); // 2-wejściowa bramka AND z etykietą AND1
and
and
and
nand NA1 (z, a, b, c); // 3-wejściowa bramka NAND z etykietą NA1
nand
nand
nand
xnor (y, v, w); // 2-wejściowa bramka XNOR bez etykiety
xnor
xnor
xnor
nor #(1,2) (z, a, b); // 2-wejściowa bramka NOR z opóznieniami
nor
nor
nor
or (strong0,pull1) (z, a, b) // 2-wejściowa bramka OR z siłami wymuszania
or
or
or
Bramki logiczne (2)
Inwertery i bufory
not NEG1 (out, in); // pojedynczy inwerter z etykietą NEG1
not
not
not
buf (out1,out2,in); // pojedynczy bufor bez etykiety
buf
buf
buf
not NEG[3:0] (C, A[3:0]); // 4 równoległe inwertery
not
not
not
buf (o1, o2, o3, o4, i); // bufor z czterema wyjściami i jednym wyjściem
buf
buf
buf
Bramki logiczne (3)
Bufory i inwertery trójstanowe
bufif0 (weak1,pull0) #(4,5,3) (data_out, data_in, ctrl);
bufif0
bufif0
bufif0
sygnał wyjściowy sygnał sterujący
sygnał wejściowy
Klucze MOS
Klucze NMOS i PMOS
bez rezystancji (nmos, pmos)
z rezystancją (rnmos, rpmos)  redukują siłę sygnału
pmos (w, datain, pcontrol); // klucz PMOS bez rezystancji
pmos
pmos
pmos
sygnał sterujący
sygnał wyjściowy
sygnał wejściowy
Klucze CMOS (cmos, rcmos)
pcontrol
cmos (w, datain, ncontrol, pcontrol);
cmos
cmos
cmos
jest równowa\ne zapisowi:
datain w
nmos (w, datain, ncontrol);
nmos
nmos
nmos
ncontrol
pmos (w, datain, pcontrol);
pmos
pmos
pmos
Przykład zastosowania kluczy MOS
3-wejściowa bramka NAND
a
module nand3 (z, a, b, c);
b z
output z; // wyjście
c
input a, b, c; // wejścia
supply0 gnd; // masa
supply1 pwr; // zasilanie
MP1 MP2 MP3
nmos MN1 (z, i12, a); // sekcja
nmos
nmos
nmos
z
a
nmos MN2 (i12, i23, b); // pull-down
nmos
nmos
nmos
MN1
nmos MN3 (i23, gnd, c);
nmos
nmos
nmos
b
MN2
pmos MP1 (z, pwr, a); // sekcja
pmos
pmos
pmos
pmos MP2 (z, pwr, b); // pull-up
pmos
pmos
pmos
c
pmos MP3 (z, pwr, c);
pmos
pmos
pmos
MN3
endmodule
Dwukierunkowe bramki transmisyjne
Nie przyjmują specyfikacji siły wymuszania
Rodzaje dwukierunkowych bramek transmisyjnych:
Dwukierunkowe bramki przewodzące przez cały czas (nie przyjmują opóznień):
tran  redukuje siłę supply na strong, a pozostałe pozostawia bez zmian
rtran  redukuje siłę supply na pull, pull na weak, itd.
Klucze aktywne stanem niskim (tranif0, rtranif0)
Klucze aktywne stanem wysokim (tranif1, rtranif1)
tran tr1 (inout1, inout2);
tran
tran
tran
tranif1 #100 trf1 (inout1,inout2, control);
tranif1
tranif1
tranif1
sygnał sterujący
control
sygnały dwukierunkowe
inout1 inout2
trf1
Elementy definiowane przez u\ytkownika (UDP)
// Description of an AND-OR gate.
UDP są prostymi układami
// out = (a1 & a2 & a3) | (b1 & b2).
kombinacyjnymi lub sekwencyjnymi
wyjście
definiowanymi przez u\ytkownika,
wejścia
których u\ywa się w taki sam sposób
primitive and_or(out, a1,a2,a3,b1,b2);
primitive
primitive
primitive
jak elementów wbudowanych
output out;
Mogą posiadać tylko jedno wyjście input a1,a2,a3, b1,b2;
(pojedynczy sygnał), a wejścia mogą
table
table
table
table
być jedynie pojedynczymi sygnałami
// a b : out ;
(nie mogą być magistralami)
111 ?? : 1 ;
??? 11 : 1 ;
Dla sekwencyjnego UDP, jego stan
0?? 0? : 0 ;
odpowiada stanowi pojedynczego
0?? ?0 : 0 ;
przerzutnika (0, 1 lub x) i jest ?0? 0? : 0 ;
?0? ?0 : 0 ;
jednocześnie sygnałem wyjściowym
??0 0? : 0 ;
Działanie kombinacyjnego UDP
??0 ?0 : 0 ;
endtable
endtable
endtable
endtable
określa się tablicą prawdy, a
sekwencyjnego UDP  tablicą przejść
endprimitive
endprimitive
endprimitive
endprimitive
Oznaczenia występujące w tablicach UDP
Kombinacyjne UDP
Multiplekser 2 na 1
primitive multiplexer(mux, control, dataA, dataB );
output mux;
input control, dataA, dataB;
table
table
table
table
// control dataA dataB mux
0 1 0 : 1 ;
0 1 1 : 1 ;
0 1 x : 1 ;
0 0 0 : 0 ;
0 0 1 : 0 ;
0 0 x : 0 ;
1 0 1 : 1 ;
tablica prawdy
1 1 1 : 1 ;
1 x 1 : 1 ;
1 0 0 : 0 ;
1 1 0 : 0 ;
1 x 0 : 0 ;
x 0 0 : 0 ;
x 1 1 : 1 ;
endtable
endtable
endtable
endtable
endprimitive
Kombinacyjne UDP ze skróconym opisem
Ten sam multiplekser 2 na 1
primitive multiplexer(mux,control,dataA,dataB );
output mux;
input control, dataA, dataB;
table
// control dataA dataB mux
0 1 ? : 1 ; // ? = 0,1,x
?
?
?
0 0 ? : 0 ;
?
?
?
1 ? 1 : 1 ;
?
?
?
1 ? 0 : 0 ;
x 0 0 : 0 ;
x 1 1 : 1 ;
endtable
endprimitive
? = dowolny stan: 0, 1 lub x
Sekwencyjne UDP wra\liwe na poziomy
Zatrzask (przerzutnik D wyzwalany poziomem)
primitive latch(q, clock, data);
output q;
reg q;
reg
reg
reg
deklaracja stanu
input clock, data;
table
// clock data q q+
0 1 : ? : 1 ;
tablica przejść
0 0 : ? : 0 ;
1 ? : ? : - ; // - = no change
endtable
endprimitive
Sekwencyjne UDP wra\liwe na zbocza
Przerzutnik D wyzwalany zboczem narastającym
primitive d_edge_ff(q, clock, data);
output q;
reg q;
input clock, data;
table
// obtain output on rising edge of clock
// clock data q q+
(01) 0 : ? : 0 ;
(01) 1 : ? : 1 ;
(0?) 1 : 1 : 1 ;
(0?) 0 : 0 : 0 ;
// ignore negative edge of clock
(?0) ? : ? : - ;
// ignore data changes on steady clock
? (??) : ? : - ;
endtable
endprimitive
UDP wra\liwe zarówno na poziomy jak i zbocza
Przerzutnik D wyzwalany zboczem narastającym i ustawianiem i kasowaniem
primitive jk_edge_ff(q, clock, j, k, preset, clear);
output q;
reg q;
input clock, j, k, preset, clear;
table
//clock jk pc state output/next state
? ?? 01 : ? : 1 ; //preset logic
? ?? *1 : 1 : 1 ;
? ?? 10 : ? : 0 ; //clear logic
? ?? 1* : 0 : 0 ;
r 00 00 : 0 : 1 ; //normal clocking cases
r 00 11 : ? : - ;
r 01 11 : ? : 0 ;
r 10 11 : ? : 1 ;
r 11 11 : 0 : 1 ;
r 11 11 : 1 : 0 ;
f ?? ?? : ? : - ;
b *? ?? : ? : - ; //j and k transition cases
b ?* ?? : ? : - ;
endtable
endprimitive
Zmniejszanie pesymizmu w UDP
Zatrzask typu D Przerzutnik JK
primitive jk_edge_ff(q, clock, j, k, preset, clear);
output q; reg q;
input clock, j, k, preset, clear;
primitive latch(q, clock, data);
table
output q; reg q ;
// clock jk pc state output/next state
// preset logic
input clock, data ;
? ?? 01 : ? : 1 ;
table
? ?? *1 : 1 : 1 ;
// clock data state output/next state
// clear logic
0 1 : ? : 1 ;
? ?? 10 : ? : 0 ;
0 0 : ? : 0 ;
? ?? 1* : 0 : 0 ;
// normal clocking cases
1 ? : ? : - ; // - = no change
r 00 00 : 0 : 1 ;
// ignore x on clock when data equals state
r 00 11 : ? : - ;
x 0 : 0 : - ; r 01 11 : ? : 0 ;
r 10 11 : ? : 1 ;
x 1 : 1 : - ;
r 11 11 : 0 : 1 ;
endtable r 11 11 : 1 : 0 ;
f ?? ?? : ? : - ;
endprimitive
// j and k cases
b *? ?? : ? : - ;
b ?* ?? : ? : - ;
// cases reducing pessimism
p 00 11 : ? : - ;
p 0? 1? : 0 : - ;
p ?0 ?1 : 1 : - ;
(?0)?? ?? : ? : - ;
(1x)00 11 : ? : - ;
(1x)0? 1? : 0 : - ;
(1x)?0 ?1 : 1 : - ;
x *0 ?1 : 1 : - ;
x 0* 1? : 0 : - ;
endtable
endprimitive
Struktury hierarchiczne (wielopoziomowe)
Moduły na ni\szym poziomie hierarchii: Moduł na wy\szym poziomie hierarchii:
Niejawne mapowanie portów (przez
zachowanie tej samej kolejności portów i
module AND (out, in1, in2);
odpowiadających im sygnałów)
output out;
input in1, in2;
module AND_OR (y, x1,x2, x3, x4);
output y;
assign out = in1 & in2;
input x1, x2, x3, x4;
endmodule
AND A1 (x12, x1, x2);
AND A2 (x34, x3, x4);
OR O1 (y, x12, x34);
module OR (out, in1, in2);
output out;
endmodule
input in1, in2;
Jawne mapowanie portów (przez
assign out = in1 | in2;
określenie które porty mają być
endmodule
podłączone do których sygnałów)
module AND_OR (y, x1,x2, x3, x4);
output y;
input x1, x2, x3, x4;
AND A1 (.in1(x1), .in2(x2), .out(x12));
AND A2 (.in1(x3), .in2(x4), .out(x34));
OR O1 (.in1(x12), .in2(x34), .out(y));
endmodule
Moduły parametryzowane
Moduł na wy\szym poziomie hierarchii
Moduł na ni\szym poziomie hierarchii z
deklarujący komponenty z parametrami:
parametrami size i delay:
module vdff (out, in, clk); module m;
reg clk;
parameter size = 1, delay = 1;
wire[1:10] out_a, in_a;
input [0:siz wire[1:5] out_b, in_b;
size-1] in;
siz
siz
input clk;
// create an instance and set
output [0:size out;
size-1]
size
size
parameters
reg [0:size out;
size-1]
size
size
vdff #(10,15) mod_a(out_a, in_a, clk);
// create an instance leaving default
always @(posedge clk)
values
# delay out = in;
delay
delay
delay
vdff mod_b(out_b, in_b, clk);
endmodule
endmodule
Makromoduły
module topmod;
Są  spłaszczane w celu przyspieszenia
wire [4:0] v;
wykonywania symulacji, czyli nie otrzymują
wire a,b,c,w;
nazwy instancji, nie ma podłączenia portów
do sygnałów i makro znajduje się na tym
modB b1 (v[0], v[3], w, v[4]);
samym poziomie hierarchii co moduł
nadrzędny
initial $list;
Podlegają pewnym ograniczeniom
endmodule
Nie mo\na w nich deklarować rejestrów ani
stosować przypisań proceduralnych
macromodule modB(wa, wb, c, d);
macromodule
macromodule
macromodule
W listach sygnałów wbudowanych bramek i
inout wa, wb;
elementów UDP nie mogą znajdować się
input c, d;
wyra\enia, lecz jedynie pojedyncze sygnały
parameter d1=6, d2=5;
parameter d3=2, d4=6;
Jedynym dopuszczalnym wykorzystaniem
parametrów jest u\ycie ich do określania
tranif1 g1(wa, wb, cinvert);
opóznień w makromodule
not #(d3, d4) (cinvert, int);
and #(d1, d2) g2(int, c, d);
endmodule
endmodule
endmodule
endmodule


Wyszukiwarka