Menu

İlk Verilog Modülün: Adım Adım Bir Tur

Sıfırdan ilk tam Verilog modülünü yaz - tanımlama, portlar, bir kombinasyonel mantık parçası ve onu süren bir testbench. Browser'da çalıştırılabilir.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

Modül Verilog'un Birimidir

Verilog'daki her şey bir module'ün içinde yaşar. Bir modül bir devre parçasını sarmalar: hangi sinyallerin geldiğini, hangi sinyallerin çıktığını ve aralarındaki wire/register/mantığı tanımlar. Gördüğün her chip, vendor tarafından sağlanan gate primitive'lerine kadar diğer modülleri instantiate eden bir modüller ağacıdır.

Şekil her zaman aynıdır:

module name(port_list);
    // tanımlamalar: wire, reg, parameter
    // gövde: assign'lar, instantiation'lar, always blokları
endmodule

Tam bir modüle aşamalarla kuracağız.

En Küçük Yararlı Modül: İki Girişli Bir AND Gate

Basit ve kendi kendine yeterli bir şeye ihtiyacımız var. İki girişli bir AND gate mükemmel: iki giriş, bir çıkış, bir mantık satırı.

Run'a bas. Bir AND truth table'ının dört satırını görmelisin. Her parçaya bakalım.

Modül Tanımlamasını Okuma

module and_gate(
    input  wire a,
    input  wire b,
    output wire y
);
  • module and_gate, and_gate adlı bir modül tanımlar. Diğer modüllerin bunu instantiate etmek için kullanacağı isim.
  • Parantezli liste port listesidir - dışarıdan görünen sinyaller.
  • input wire a - a bir input portudur; bir wire'dır (dışarıdan sürülür).
  • output wire y - y modül içinde bir şey tarafından sürülen bir output portudur.

Kısa olmak istesen input wire a yerine input a yazabilirdin - yalnızca yön varsayılan tipi wire yapar. Ama açık olmak edinilmeye değer bir alışkanlıktır. Module Ports, tam port şekil setini kapsar.

Gövde

assign y = a & b;

Bu bir continuous assignment'tır. "Ne zaman a veya b değişirse, y'yi iki tanenin bitwise AND'i olarak yeniden hesapla" der. Saat yok, zamanlama yok - ilişki her zaman doğrudur. Bu saf kombinasyonel mantıktır.

endmodule bloğu kapatır. Modül bitti.

Testbench

and_gate'i tek başına çalıştıramazsın. Onun girişlerini süren ve çıkışlarını izleyen ikinci bir modüle ihtiyacın var. Bu testbench'tir ve genellikle test, tb veya <design>_tb olarak adlandırırız.

module test;
    reg  a, b;
    wire y;

    and_gate dut(.a(a), .b(b), .y(y));
    ...
endmodule

Dikkat edilecek üç şey:

  • Port listesi yok. Bir testbench simülasyonun tepesidir - dışarıda hiçbir şey yok.
  • reg a, b ve wire y. Design under test (DUT)'a girişler testbench'te reg'dir çünkü onları bir prosedürel bloktan sürüyoruz. Çıkış bir wire'dır çünkü DUT onu sürer.
  • and_gate dut(.a(a), .b(b), .y(y)). Bu instantiation'dır. and_gate'in bir kopyasını çıkarıyoruz ve ona dut (yaygın bir ad - "design under test") diyoruz. .a(a) sözdizimi "instance'taki a adlı portu yerel a adlı sinyale bağla" der. Module Instantiation daha derine iner.

Stimulus

initial begin
    a = 0; b = 0; #1 $display("a=%b b=%b y=%b", a, b, y);
    a = 0; b = 1; #1 $display("a=%b b=%b y=%b", a, b, y);
    a = 1; b = 0; #1 $display("a=%b b=%b y=%b", a, b, y);
    a = 1; b = 1; #1 $display("a=%b b=%b y=%b", a, b, y);
    $finish;
end

initial bloğu simülasyon başlangıcında bir kez çalışır. İçinde:

  • a = 0; b = 0; girişleri sürer. Bunlar blocking atamalardır - sıra önemlidir ve her biri bir sonrakinden önce gerçekleşir.
  • #1 simüle edilen zamanı 1 birim ilerletir. Buna ihtiyacımız var ki y'nin giriş değişikliklerinden sonra yerleşmek için zamanı olsun. #1 olmadan, $display y'nin eski değerini yazdırırdı.
  • $display(...) simülasyon konsoluna yazdırır. Format string C'nin printf'ı gibi çalışır: %b binary, %d decimal, %h hex, %t simülasyon zamanı.
  • $finish simülasyonu bitirir. Onsuz simülatör asla gelmeyen bir olayı bekleyerek zamanı ilerletmeye devam ederdi.

Kırmayı Dene

Modülü bir OR gate olacak şekilde değiştir (&'yi |'a değiştir) ve yeniden çalıştır. Truth table flip'lenir. Şimdi bir XOR dene:

Aynı iskelet. Farklı operatör. Kombinasyonel mantık için tüm oyun budur - portları tanımla, assign'lar yaz, girişleri süpür, çıkışları gözle.

İki Çıkışlı Bir Modül

Modüllerin birden fazla çıkışı olabilir. İşte bir half-adder - iki giriş, sum ve carry-out:

İki assign ifadesi yan yana yaşar ama paralel olarak gerçekleşir - "önce sum'ı hesapla sonra carry'yi hesapla" diye bir şey yoktur. Her ikisi de her zaman doğrudur. Bu, Hardware vs Software bölümünde konuştuğumuz eşzamanlılıktır, somut hale getirilmiş.

Şimdi Bildiğin Şey

Bir Verilog dosyasının tüm iskeletini gördün: tanımlı portları ve gövdesi olan bir tasarım modülü, artı onu instantiate eden, bir initial bloğunda girişlerini süren ve sonuçları raporlayan bir testbench modülü. Okuyacağın hemen hemen her Verilog kaynak dosyası bu şablona uyar. Dilin geri kalanı sadece daha zengin mantık, çok bitli sinyaller, saatli davranış ve daha büyük testbench'lerle doldurmaktır.

Sırada: modüllerin büyüdükçe okunabilir kalması için yorumlar ve kod stili.

Sıkça Sorulan Sorular

En basit Verilog modülü nedir?

En küçük yasal Verilog modülü sadece module name; endmodule'dür - port yok, gövde yok. En küçük yararlı olan, bir çıkışlı modüldür: module and_gate(input wire a, input wire b, output wire y); assign y = a & b; endmodule. Bu, herhangi bir daha büyük tasarıma bırakabileceğin gerçek bir kombinasyonel mantık parçasıdır.

Bir Verilog modülünü nasıl çalıştırırım?

Bir modülü tek başına çalıştıramazsın - bu bir devre tanımıdır, bir program değil. Tasarımını instantiate eden ve girişlerini süren bir testbench modülü yazarsın, sonra ikisini iverilog -o sim design.v test.v ile derler ve vvp sim çalıştırırsın. Bu sayfadaki browser editör, Run'a bastığında her iki adımı senin için yapar.

Verilog'da bir testbench nedir?

Bir testbench, ikinci bir modüldür - genellikle portsuz - işi tasarımını çalıştırmaktır. Tasarımı instantiate eder, bir initial bloğu aracılığıyla girişlerini salınır, çıkışlarını $display veya $monitor ile gözlemler ve bittiğinde $finish çağırır. Testbench'ler sentezlenebilir değildir; yalnızca davranışı doğrulamak için vardırlar.

Verilog kodumun neden $finish'e ihtiyacı var?

Çünkü donanım asla durmaz. Bir simülatör zamanın geçtiğini farz eder ve açık bir $finish olmadan yeni olaylar bekleyerek sonsuza kadar ilerlemeye devam ederdi. $finish simülatöre 'bittik, temiz çık' der. Bir testbench'te bu initial bloğunun son satırıdır - testi çalıştır, sonra finish.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA