1011 dizi dedektörü
Seri bir bit akışında 1011'i örtüşmeleriyle birlikte bulan bir Moore state machine'i. Beş state, on ok ve eşleşmeyi bildiren tek state.
- Seviye
- rtl
- Kod
- sequence-detector-1011
- Kontrol edildi
- Verilator 5.052, Icarus Verilog 13.0, Yosys 0.66
- Yayımlandı
- Yazarlık
- Taslağı yapay zekâ desteğiyle hazırlandı
- Durum
- Yapım aşamasında — gözden geçirilsin diye yayında, bitmiş değil.
Bir dizi dedektörü (sequence detector) sig_in üzerinde her clock'ta bir bit izler ve son
birkaç bit bir deseni oluşturduğunda bunu söyler — burada 1011. Her state (durum), makinenin desenden
o ana kadar ne kadarını gördüğüdür: hiçbir şey (IDLE), ardından 1, 10, 101 ve 1011.
Bu bir Moore state machine'idir (durum makinesi): found yalnızca S1011 state'inin bir
özelliğidir, bu yüzden makine orada kaldığı tek clock periyodu boyunca yüksektir.
Oklar, onları seçtiren sig_in değeriyle etiketlenmiştir, 1 ya da 0; kod aynı yerlerde
sig_in ve !sig_in koşullarını sınar.
“Çalıştır” bu senaryoyu baştan oynatır; bir girişe basmak buradan devam eder.
Çalışan bir state machine (durum makinesi): state diyagramı ve dalga biçimi aynı zaman ekseninde. Girişler: rst_n, sig_in. Çıkışlar: found. clk periyodu 8 tick. Makinenin 5 state'i var: IDLE, S1, S10, S101 ve S1011; reset ile IDLE state'inde başlar; 10 geçişi var. Dalga biçimi şunları gösteriyor: clk, rst_n, sig_in, state, found.
Şekil 1. “Çalıştır”a basın. sig_in dört yükselen kenara 1, 0, 1 ve 1 taşır; yanan state deseni S1011'e kadar yürür.
Nasıl çalışır, kenar kenar
Başlangıçta rst_n düşüktür ve reset asenkrondur: register hiçbir clock kenarı beklemeden
hemen IDLE olur. Reset, iki kenar arasında, 2. tick'te bırakılır; ilk yükselen kenara kadar
hiçbir şey kıpırdamaz.
Kenar 0'da sig_in 1'dir ve makine IDLE'dan S1'e giden oku alır. O ok bir sonraki kenara
kadar kalın çizilir: ateşlenen geçiş odur. Dalga biçiminin state satırı state'in adını yazar;
karşılık geldiği rakamlar kodlamadır, yani state'leri kodda tanımlandıkları sırayla sayan üç
bit.
Kenar 1 ve 2'de bitler 0 ve 1'dir; makine önce S10'a, sonra S101'e ulaşır. Kenar 3'te
dördüncü bit, bir 1, onu S1011'e götürür ve found onunla birlikte yükselir. Ne zaman
yükseldiğine bakın: dördüncü bit sig_in üzerindeyken değil, onu örnekleyen kenarda. Bir Moore
çıkışı state'i bekler.
Örtüşme 1011011'i oynatır. İlk eşleşmeden sonra gelen bit 0'dır ve makine IDLE'a değil
S10'a gider: 1011'in sonundaki 1 ile ardından gelen 0, bir sonraki 1011'in başıdır. Üç
kenar sonra desen yeniden bulunur; ikincisi birincinin son bitinde başlar.
Reset yok senaryosu rst_n'i hiç etkinleştirmez. Register bilinen bir değer tutmaz, bu yüzden
her state kesikli çizilir — register onların kodlarından herhangi birini ya da hiçbir state'i
adlandırmayan üç koddan birini tutabilir — ve state satırı taralıdır. found da X'tir, çünkü o
state'lerden biri S1011'dir. sig_in 1 kaldıkça hiçbir şey değişmez: bir 1, makinenin nerede
olduğuna göre S1, S101 ya da S1011'e götürür ve bunların kodları, 001, 011 ve 100,
her bitte farklıdır; bu yüzden register X kalır. sig_in'e bir kez basıp 0 yapın ve iki kenar
geçsin: iki 0'da her state IDLE'a gider ve makine reset olmadan X'ten çıkar. 00 bu makine için
en kısa synchronizing sequence'tir (senkronlama dizisi) ve iki bitlik tek dizidir: register hangi
kodla başlarsa başlasın, S1011 ya da hiçbir state'i adlandırmayan bir kod, bu iki bit onu
IDLE'da bırakır. Bu, reset'ler hakkında değil, bu makine hakkında bir şey söyler.
Kod
// Detects the bit sequence 1011 on sig_in, with overlap: 1011011 is found twice.
//
// Reset style for this module: asynchronous, active low. One style per page,
// stated up front, so nothing on the page has to be read twice.
module sequence_detector (
input logic clk,
input logic rst_n,
input logic sig_in,
output logic found
);
typedef enum logic [2:0] {
IDLE = 3'd0,
S1 = 3'd1,
S10 = 3'd2,
S101 = 3'd3,
S1011 = 3'd4
} state_t;
state_t state, next;
// The state register: the only flip-flops in the module.
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
end else begin
state <= next;
end
end
// Next state. The default assignment holds the state when no branch fires,
// so no arm can leave a latch behind.
always_comb begin
next = state;
unique case (state)
IDLE: begin
if (sig_in) next = S1;
else if (!sig_in) next = IDLE;
end
S1: begin
if (!sig_in) next = S10;
else if (sig_in) next = S1;
end
S10: begin
if (sig_in) next = S101;
else if (!sig_in) next = IDLE;
end
S101: begin
if (sig_in) next = S1011;
else if (!sig_in) next = S10;
end
S1011: begin
if (!sig_in) next = S10;
else if (sig_in) next = S1;
end
default: next = IDLE;
endcase
end
// Moore output: a function of the state alone.
always_comb begin
found = 1'b0;
unique case (state)
S1011: found = 1'b1;
default: found = 1'b0;
endcase
end
endmoduleKod ile çizim tek bir şeydir. typedef enum state'leri listeler, always_ff bloğu makinenin
tek register'ıdır, ilk case'in her kolu bir state, her if ya da else if satırı bir oktur.
Bir state'in üzerine gelin, kolu yanar; bir okun üzerine gelin, satırı yanar; reset işareti
register'ı yakar. FSM görüntüleyici, kendi durum makinenizi kodundan aynı
biçimde, aynı bağlarla çizer.
Next-state bloğu next = state; ile açılır; böylece koşullarının hepsi yanlış olan bir state,
arkasında bir latch bırakmak yerine kendi state'ini korur. Burada her state iki okunu da
çizdiği için bu varsayılan atama hiçbir şeye karar vermez; hiçbir kol unutmasın diye oradadır.
Çıkış bloğu ayrıdır ve yalnızca state'i okur: found'u bir Moore çıkışı yapan budur.
Sentez sonucu
sequence_detector.sv, Yosys'un genel sentezinde 17 hücre olur; 3 tanesi flip-flop. Hücreler Yosys'un kendi kapı kütüphanesinden; bir FPGA'nın ya da standart hücre kütüphanesinin değil. Sayı herhangi bir çipin alanını değil, mantığı ölçer.
Kod state için 3 bitlik bir kodlama seçer ve bu sayılar onu korur. Yosys kendi fsm pass'ine bırakılırsa onu one-hot olarak yeniden kodlar: 5 flip-flop, toplamda 14 hücre.
| Hücre | Ne olduğu | Adet |
|---|---|---|
$_DFF_PN0_ | yükselen kenarda D flip-flop, 0 değerine aktif düşük asenkron reset | 3 |
$_AND_ | 2 girişli AND | 2 |
$_ANDNOT_ | ikinci girişi terslenmiş AND, A & ~B | 4 |
$_NAND_ | 2 girişli NAND | 5 |
$_NOR_ | 2 girişli NOR | 2 |
$_OR_ | 2 girişli OR | 1 |
| Toplam | 17 | |
Lint Verilator 5.052 ile, testbench Icarus Verilog 13.0 ile, sentez Yosys 0.66 ile yapıldı.
Icarus bu sayfanın üç senaryosundan iki tanesini bu kod üzerinde yeniden oynattı ve dalga biçiminin bunlar için çizdiği 470 değerin hepsi tutuyor. Reset yok dışarıda kaldı: bilinmeyen bir register'dan başlıyor ve bir RTL simülasyonu bunu bu motordan daha iyimser okur.
Sentezden önceki netlist
sequence_detector.sv dosyasının netlistsvg 1.0.2 ile çizilen netlist'i 760 × 765 px boyutunda, sayfanın içinde okunamayacak kadar büyük: tek başına açın, tarayıcı orada yakınlaştırabilir.
Tuzaklar
Örtüşmeyi unutmak. S1011'den 0 ile IDLE'a dönen bir ok daha derli toplu görünür ve
1011011'i yalnızca bir kez bulur. Kısmi bir eşleşmeden çıkan her ok, o ana kadar görülenin
hâlâ desenin bir öneki (prefix) olan en uzun sonekine (suffix) gitmelidir. Başka bir desen için
dizi dedektörü üreteci makineyi bu kuralla kurar:
örtüşen ya da örtüşmeyen, Moore ya da Mealy, koduyla birlikte.
found'u bir çevrim erken beklemek. found'u S101'den 1 ile çıkan okun üzerine koyan bir
Mealy sürümü, onu dördüncü bit hâlâ gelirken, bir clock periyodu önce yükseltirdi — üstelik
sig_in'den kombinasyonel olarak, bu yüzden girişteki her glitch çıkışa ulaşır.
Reset yok. Bu figürün cevabı X'tir; bir RTL simülasyonu başka bir cevap verir. Aynı kodu
rst_n hiç etkinleştirilmeden çalıştırın: X olan state hiçbir case maddesine uymaz, bu yüzden
default: kolu seçilir. next zaman 0'dan itibaren IDLE ve found 0'dır; register ilk kenara
kadar X, ondan sonra IDLE'dır. Simülasyon sağlıklı görünür. Bir ASIC'te register güç
verildiğinde herhangi bir kodla başlar, kullanılmayan üç kod dahil; S1011'de başlarsa daha tek
bir bit görmeden bir periyot boyunca found bildirir. Çoğu FPGA'da ise konfigürasyon her
flip-flop'un başlangıç değerini yükler, kod başka bir değer vermedikçe 0; bu yüzden bu makine
IDLE'da başlar. Ama bu değer bir kez, konfigürasyon sırasında yüklenir ve tasarımın
uygulayabileceği bir reset değildir. Eksik bir reset'in RTL simülasyonundan sağ çıkmasının nedeni bu
X-optimism'dir (X-iyimserliği).
Kendinizi sınayın
- Makine S1011'de ve sıradaki bit 0. Neden IDLE'a değil de S10'a gider?
- Çünkü gördüğü son iki bit, önce 1 sonra 0, yeniden 1011'in ilk iki bitidir. IDLE'a gitmek onları atar ve 1011011 iki kez değil bir kez bulunur. Örtüşme (overlap) budur.
- Desenin dördüncü biti bütün bir clock periyodu boyunca sig_in üzerinde. found neden o periyodun sonundaki kenara kadar yükselmez?
- Çünkü found bir Moore çıkışıdır, yalnızca state'in bir fonksiyonudur. Makine S1011'e dördüncü biti örnekleyen kenarda girer ve found state'i izler; bu yüzden bit gelirken değil, o kenarda yükselir.
- “Reset yok” senaryosunda found 0 değil X. Neden?
- Register'ı hiçbir şey bilinen bir state'e koymamıştır, bu yüzden makine beş state'inin herhangi birinde ya da hiçbirini adlandırmayan üç koddan birinde olabilir; aralarında found'un 1 olduğu S1011 de vardır. Bunların bazılarında 0, birinde 1 olan bir çıkış bilinmezdir.
Görev: İki kez S101
Yalnızca sig_in girişini siz sürersiniz. Makine 3 ve 5 numaralı kenarlarda S101 state'inde, found da 6 numaralı kenarda 1 olmalı.
- Sizin girişiniz
-
- sig_in, başlangıçta 0
- Betik
-
- rst_n başlangıçta 0.
- rst_n, 0 numaralı kenardan önce 1 olur.
- Hedef
-
- 3 numaralı kenarda state değeri S101.
- 5 numaralı kenarda state değeri S101.
- 6 numaralı kenarda found değeri 1.
JavaScript açıkken “Başla” bu görevi şekilde oynatır.