İki Durum vs Dört Durum Mantığı
Yazılımda, bir bit 0 veya 1'dir. Verilog'da bir bit dört değerden biri olabilir:
0- wire düşük sürülür.1- wire yüksek sürülür.x- wire'ın değeri bilinmeyen'dir. Simülatör bilemez.z- wire yüksek empedans'tır. Hiçbir şey onu sürmüyor.
O dört durumlu model var çünkü donanımın aynı sorunu var. Gerçek bir wire düşüğe bağlanabilir, yükseğe bağlanabilir, tanımsız olabilir (birbirleriyle savaşan iki kaynak tarafından sürülür) veya yüzer olabilir (hiç sürücü yok). Simülatörün yararlı olması için dördünü de modellemesi gerekir.
x Nasıl Ortaya Çıkar
Bunu çalıştır ve çıktıya bak:
a tanımlı ama hiç yazılmamış, bu yüzden x'te oturur. x + 5 eklemek x üretir - bir bilinmeyenle herhangi bir aritmetik bir bilinmeyen üretir. Çıktı aaaa değerinde x'ler okur.
Tasarımlarında yaygın x kaynakları:
- Tanımlı ama asla reset edilmemiş bir
reg(sentezlenebilir Verilog'un çoğu onları temizlemek için açık bir reset kullanır). default'u olmayan, hiçbir case'in eşleşmediği bir giriş değeri tarafından vurulan bircaseifadesi.- Bir refactor'dan sonra tek sürücüsünü kaybeden bir
wire. - Bir dalın diğerinin atadığı bir sinyali atamadığı bir
if/elsezinciri (kapsanmazsaxlatch'ler). - Bir vector'ın veya array'in sonu ötesinde okuma.
X Yayılması: Küçük Bir Miktar x Her Şeyi Bozar
x hakkında acımasız olan şey, yayılmasıdır. Bir operand'da bir x bit sonucun tamamını x'e döndürür:
0 & x'in 0 (0 ile AND her zaman 0) ve 1 | x'in 1 (1 ile OR her zaman 1) olduğuna dikkat et. Simülatör bit-by-bit pesimisttir ama yine de identity'lere saygı duyar. Aritmetik ve karşılaştırma bu kadar cömert değildir.
İşte bu yüzden tek bir initialize edilmemiş register tüm bir çıkış bus'ını xxxx yapabilir. Herhangi bir x'ten geriye doğru izle ve kaynağı bulacaksın.
z Nasıl Ortaya Çıkar
z, kimsenin sürmediği bir wire'ın değeridir:
O snippet'te iki kalıp:
floatingsadece tanımlı ve asla sürülmemiş. Varsayılan olarakz'ye gider.data_outkasıtlı bir tri-state'tir.enabledüşük olduğunda, çıkış açıkçaz'ye serbest bırakılır. Bir bus sürücüsünün başka bir sürücünün devralabilmesi için "bırakma" şekli budur.
Dahili mantıkta z neredeyse her zaman yanlıştır. Çift yönlü bir pin'de veya paylaşılan bir bus'ta z tam olarak doğrudur.
== ile ==='i Karşılaştırma
Düzenli equality operatörü ==, herhangi bir operand'da bir x veya z bit olduğunda x döndürür:
=== (ve ortağı !==), x ve z dahil sıkı bir bit-by-bit karşılaştırma yapar. Bir testbench'te x/z'ye karşı veya için test etmen gerektiğinde her zaman bunu kullan. === sentezlenebilir değildir, ama bir testbench'in initial bloğunun içinde bu önemli değildir.
$isunknown(expr) system fonksiyonu, "bu ifade herhangi bir x veya z bit içeriyor mu?" demenin en temiz yoludur - evet ise 1, hayır ise 0 döndürür.
Kasıtlı Bir Don't-Care Olarak x Kullanma
Tartışmalı ama meşru bir kalıp: bir state machine'in default case'inde 'x, sentezleyiciye "bu state ulaşılamaz, serbest optimize et" der:
case (state)
IDLE: next_state = go ? RUNNING : IDLE;
RUNNING: next_state = done ? IDLE : RUNNING;
default: next_state = 'x; // ulaşılmaz
endcase
Sentezleyici, x'i state'leri birleştirmek ve gate sayısını azaltmak için kullanabilir. Simülasyonda, mantığın yanlışsa ve default'a gerçekten ulaşılırsa, x'in next_state'ten yayıldığını görürsün ve hata hemen görünür hale gelir.
Bunu yalnızca default'un gerçekten ulaşılamaz olup olmadığını düşündüğünde kullan. Düşünmediysen, default'u bunun yerine güvenli bir state'e ayarla.
Yaygın Debug Reçetesi
x'lerle dolu bir waveform'a bakıyorsun. Reçete:
- En erken
x'i bul. Waveform'u zaman içinde geri yürü.x'e giden en erken sinyal kaynağa en yakındır. - Sürücüsünü bul. Kaynağı aç. Bu sinyali ne atıyor? Bir
assign? Biralwaysbloğu? - Sürücünün girişlerini kontrol et. Sürücünün RHS'inde herhangi bir
xvarsa, yayılma yapması gerekeni yapıyor - hata yukarı akıştadır. - Sürücünün temiz girişleri var ama
xüretiyorsa, sürücü eksiktir. Default eksik bircase,elseeksik birif, reset eksik bir register.
Çoğu x-fırtınası hatası şunlardan birine çöker: eksik reset, eksik default veya bağlı olmayan bir alt modül.
Sırada Ne Var
Artık tam veri tipi hikayesine sahipsin: wire/reg, vector'lar, parametreler, sayı literal'leri ve dört durumlu mantık modeli. Bir sonraki bölüm hepsini ifadeler kurmak için kullanmaya başlar - her çeşit operatör, yazılımda anlamlı olmayacak bit düzeyi operatörleri dahil.
Sıkça Sorulan Sorular
Verilog'da x ne anlama gelir?
x, bilinmeyen değerdir. x olan bir sinyal 0 veya 1 olabilir - simülatör bilemez. Bir sinyal sürülmediğinde, iki sürücü çatıştığında, bir register reset'ten önce okunduğunda veya tanımsız davranışın sessizce yayılabileceği her yerde görünür. x'i bir hata sinyali olarak ele al; neredeyse hiç ne istediğin değildir.
Verilog'da z ne anlama gelir?
z, yüksek empedans değerdir - wire hiç sürülmüyor. Tri-state çıkışların (veri bus'ları, çift yönlü pin'ler) meşru durumudur, ama dahili sinyallerde z genellikle 'burada hiçbir şey bağlı değil' anlamına gelen bir hatadır. Sentezleyiciler, açık tri-state çıkış enable'larının dışındaki çoğu z kalıbını reddeder.
Verilog çıktım neden xxxx?
Neredeyse her zaman bir sinyal hiçbir şey tarafından sürülmediği veya bir işlem x'i başka bir sinyalden yaydığı için. Geriye doğru yürü: hangi sinyal x, onu ne besliyor, sürücü aktif mi? Yaygın suçlular case ifadelerinde eksik default case'ler, reset'lenmeyen register'lar ve bir refactor'dan sonra sürücüsünü kaybeden wire'lardır.
Verilog'da x veya z'yi nasıl kontrol edersin?
x ve z dahil bit-tam karşılaştıran === operatörünü kullan. a === 1'bx, a gerçekten x olduğunda doğrudur. Düzenli ==, herhangi bir operand'da bir x bit olduğunda x döndürür, bu da a == 1'bx'in asla istediğin cevap olmadığı anlamına gelir. Düzgün bir boolean olan $isunknown(a) de vardır.
Verilog'da varsayılan olarak x atayabilir misin?
Evet ve case ifadelerinde kasıtlı bir tekniktir: default: out = 'x;, sentezleyiciye 'bu case'in asla olmadığına söz veriyorum, serbest optimize et' der. Maliyet, simülasyonda olursa, x'in yayılması ve hatayı görmendir. Varsayılanın ulaşılamaz olduğunu zaten kanıtladığında kullan, case yazmaktan kaçınmak için değil.