Menu

Verilog wire vs reg: kiedy używać którego (z przykładami)

Dwa główne typy danych w Verilogu, wire do ciągłych połączeń i reg do przechowywania wartości w kodzie proceduralnym, oraz reguła, która za każdym razem pozwala wybrać właściwy.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Dwie nazwy, jedno zadanie

Każdy sygnał w Verilogu ma typ. Pierwsze dwa typy, które poznasz, to wire i reg. Oba mogą przechowywać wartość. Oba mogą być jednobitowe albo wielobitowe. Różnica nie dotyczy tego, czym sygnał jest, tylko tego, co nim steruje.

  • Sygnały wire są sterowane poza blokami proceduralnymi: przez instrukcje assign, przez wyjścia podmodułów albo przez porty wejściowe modułu.
  • Sygnały reg są sterowane wewnątrz bloków proceduralnych: initial lub always.

To cała reguła. Nazwy słów kluczowych są niezręczne, bo powstały, zanim wykształcił się nowoczesny sposób pisania w Verilogu. reg nie zawsze staje się rejestrem w sprzęcie. Czytaj dalej, żeby dowiedzieć się dlaczego.

Wire: połączenie ciągłe

wire to przewód elektryczny. Nieprzerwanie przenosi to, co wytwarza jego źródło (driver). Przewód może być sterowany na dwa sposoby:

Warto zauważyć trzy rzeczy:

  • y i z są zadeklarowane jako wire w module i ponownie jako wire w testbenchu.
  • Steruje nimi assign, czyli forma przypisania ciągłego. Prawa strona = jest obliczana na nowo, gdy zmieni się którykolwiek sygnał, który się w niej pojawia.
  • Nie możemy napisać y = a & b w bloku always, zostawiając y jako wire. Kompilator by to odrzucił.

Jeśli zapomnisz słowa kluczowego wire, Verilog niejawnie zadeklaruje sygnał jako jednobitowy wire. Czasem jest to wygodne, a czasem to cichy błąd. Większość zespołów włącza w narzędziu opcję, która zgłasza błąd przy niejawnych przewodach. Pisz jawnie i omiń tę pułapkę.

Reg: przechowywanie wartości w bloku proceduralnym

reg to sygnał, do którego przypisujesz wartość w initial lub always. Nazwa to relikt wczesnych lat języka, gdy "reg" kojarzyło się z "register". We współczesnym użyciu reg to po prostu typ każdego sygnału, do którego zapisuje kod proceduralny.

count jest typu reg w module (bo zapisuje do niego blok always) i typu wire w testbenchu (bo steruje nim port wyjściowy DUT). Ten sam sygnał, różne role, różne typy w każdym zasięgu.

Dlaczego "reg" nie zawsze oznacza "rejestr"

Oto najczęstsza pułapka początkujących. Ten moduł deklaruje y jako reg, ale zsyntezowany sprzęt nie zawiera przerzutnika:

Blok always @(*) reaguje na każdą zmianę wejścia. Jest kombinacyjny. Narzędzie do syntezy rozpoznaje ten wzorzec i tworzy bramkę AND: bez przerzutnika, bez zegara, sama logika. Słowo kluczowe reg jest tu wyłącznie wymogiem składni, bo y jest przypisywane w bloku always.

Żeby dostać prawdziwy przerzutnik, blok always musi reagować na zbocze zegara:

always @(posedge clk) begin
    q <= d;
end

To wzorzec "narzędzie do syntezy, zrób mi przerzutnik": lista czułości z zegarem i przypisanie nieblokujące. To samo słowo kluczowe reg, zupełnie inny sprzęt. To rozróżnienie omawiamy w częściach Blok always oraz Przypisania blokujące i nieblokujące.

Decyzja w praktyce

Za każdym razem, gdy deklarujesz sygnał, zapytaj: jak będę nim sterować?

  • Sterowanie przez assign? → wire.
  • Podłączenie do portu wyjściowego podmodułu? → wire.
  • Port wejściowy modułu? → wire. (Wejścia są zawsze typu wire.)
  • Sterowanie z initial lub always? → reg.
  • Port wyjściowy modułu sterowany kodem proceduralnym? → output reg.
  • Port wyjściowy modułu sterowany przez assign? → output wire. (Albo po prostu output, bo sam kierunek domyślnie oznacza wire.)

To drzewo decyzyjne obejmuje każdą sytuację, jaką napotkasz w zwykłym Verilogu.

Konflikty sterowania

Sygnały wire mogą teoretycznie mieć wiele źródeł. Tak działają magistrale trójstanowe, w których kilka modułów może sterować tym samym przewodem, a nieaktywne przechodzą w stan wysokiej impedancji (z). W zwykłej logice dwie instrukcje assign zapisujące ten sam przewód dają niezdefiniowane zachowanie:

assign y = a;
assign y = b;   // BAD - y has two drivers

Symulator może wybrać jedno z nich albo ustawić sygnał na X, zależnie od narzędzia. Tak czy inaczej to błąd. Jedno źródło na przewód, chyba że świadomie budujesz magistralę.

Sygnały reg mogą być sterowane tylko z jednego bloku proceduralnego. Dwa bloki always przypisujące ten sam reg to błąd syntezy i dziwne zachowanie w symulacji. Ta sama zasada: jedno źródło.

Nowość z SystemVeriloga: logic

SystemVerilog (nadzbiór, w który rozwinął się Verilog) dodaje jedno słowo kluczowe, które zastępuje oba: logic. Sygnałem logic może sterować assign albo blok proceduralny, ale nie oba naraz, a kompilator nie pozwoli ci przypadkiem stworzyć błędu z wieloma źródłami.

module modern(input logic a, input logic b, output logic y);
    assign y = a ^ b;
endmodule

Jeśli zaczynasz projekt od zera, a twoje narzędzie obsługuje SystemVerilog (edytor na tej stronie obsługuje, z -g2012), używanie wszędzie logic upraszcza reguły. Zwykłe pliki .v wciąż wymagają podziału na wire/reg, a w prawdziwym kodzie zawsze będziesz spotykać oba style.

Co dalej

Następna strona, Wektory i tablice, bierze te same dwa typy i pokazuje, jak zrobić z nich sygnały wielobitowe. Szerokości magistral, zakresy, wymiary packed, różnica między wektorem bitów a tablicą wektorów. Wszystko, czego potrzebujesz, zanim zbudujesz coś większego niż jednobitowy sumator.

Najczęściej zadawane pytania

Jaka jest różnica między wire a reg w Verilogu?

Zarówno wire, jak i reg przechowują wartość sygnału w każdej chwili symulacji, ale wybierasz między nimi na podstawie tego, co steruje sygnałem. wire jest sterowany spoza bloku proceduralnego: przez assign albo wyjście podmodułu. reg jest sterowany z wnętrza bloku initial lub always. Nazwy są historyczne i mylące: reg nie zawsze oznacza 'rejestr'.

Czy reg w Verilogu oznacza przerzutnik?

Niekoniecznie. reg syntezuje się do przerzutnika tylko wtedy, gdy jego blok always reaguje na zbocze zegara i używa przypisania nieblokującego. reg przypisywany w kombinacyjnym bloku always @(*) syntezuje się do zwykłej logiki kombinacyjnej. Słowo kluczowe wybiera typ danych Veriloga, a nie sprzęt.

Kiedy używać wire, a kiedy reg?

Prosta reguła: jeśli sygnałem będzie sterować assign albo podłączysz go do portu wyjściowego podmodułu, użyj wire. Jeśli będziesz go przypisywać w bloku always lub initial, użyj reg. Wejścia modułu są zawsze typu wire. Wyjścia są wire, gdy steruje nimi assign, i reg, gdy steruje nimi blok proceduralny.

Czy można przypisać wartość do wire w bloku always?

Nie, to błąd składni. Sygnałami wire mogą sterować tylko przypisania ciągłe (assign) albo podłączenie jako wyjście instancji podmodułu. Wszystko w initial lub always musi mieć za cel reg (albo w SystemVerilogu logic). Kompilator to wychwyci i zgłosi 'left-hand side type mismatch'.

Czym jest logic w SystemVerilogu?

logic to połączenie wire i reg w SystemVerilogu. Może nim sterować przypisanie ciągłe albo blok proceduralny (ale nie oba jednocześnie). Nowoczesny kod coraz częściej używa logic wszędzie i zapomina o rozróżnieniu wire/reg. W zwykłych plikach Verilog wciąż trzeba wybierać.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ