Yükselen kenar dedektörü

Bir girişin tek bir yükselen kenarı, tam olarak bir clock periyodu boyunca çıkış üretir. Son çevrimi hatırlayan flip-flop ve karşılaştıran kapı.

Seviye
rtl
Kod
rising-edge-detector
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.

Bu sayfayı İngilizce oku

Yükselen kenar dedektörü bir seviyeyi olaya çevirir: sig_in yüksek kaldığı sürece çıkış pulse yalnızca bir clock periyodu boyunca yüksek olur, yükselişten sonraki çevrimde. Senkron bir tasarımda "şu olduğunda şunu bir kez yap" diyen her şeyin arkasındaki devre budur — bir buton basışı, bir FIFO yazması, bir start sinyali.

Devrenin tamamı bir flip-flop ile bir kapıdan ibarettir. Flip-flop sig_in'in bir çevrim önce ne olduğunu hatırlar; kapı ise şimdi yüksek olup olmadığını ve o zaman olmadığını sorar.

sig_in 0clk 0rst_n 1DQrst15–21. satır024. satırpulse 0sig_d~sig_d

“Çalıştır” bu senaryoyu baştan oynatır; bir girişe basmak buradan devam eder.

Çalışan bir devre: şeması ve dalga biçimi aynı zaman ekseninde. Girişler: sig_in, rst_n. Çıkışlar: pulse. clk periyodu 8 tick. Şunlardan kurulu: 1 D flip-flop, 1 çevirici, 1 AND kapısı. Dalga biçimi şunları gösteriyor: clk, rst_n, sig_in, sig_d, pulse.

Şekil 1. “Çalıştır”a basın. sig_in ikinci kenarda yükselir; pulse ardından gelen tek periyot boyunca yüksek kalır.

Nasıl çalışır, kenar kenar

Çizimin altındaki dalga biçimini izleyin. İlk yükselen kenardan önce sig_d X'tir: flip-flop'u hiçbir şey sıfırlamamıştır ve henüz bir kenar gelmemiştir, dolayısıyla hiçbir değer tutmaz — reset'in devrenin bir parçası olmasının, sonradan eklenen bir şey olmamasının sebebi de budur.

İlk kenarda sig_d, sig_in'in tuttuğu 0'ı alır ve pulse 0 kalır, çünkü sig_in henüz 0'dır.

sig_in ikinci kenarda yükselir, ama o kenar sig_in'in hemen önceki değerini, 0'ı örnekler. Artık sig_in 1 iken sig_d hâlâ flip-flop'un yakaladığı 0'dır; ~sig_d 1 olur ve pulse yükselir. Üçüncü kenarda flip-flop yetişir, sig_d 1 olur ve pulse düşer — yükselmesinden tam bir clock periyodu sonra.

Kod

rising_edge_detector.sv
// One rising edge of sig_in produces one clock period of pulse.
//
// 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 rising_edge_detector (
    input  logic clk,
    input  logic rst_n,
    input  logic sig_in,
    output logic pulse
);

  // The value sig_in had one clock period ago.
  logic sig_d;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      sig_d <= 1'b0;
    end else begin
      sig_d <= sig_in;
    end
  end

  // High for exactly one clock period, on the cycle after sig_in rises.
  assign pulse = sig_in & ~sig_d;

endmodule

Reset biçimi dosyanın başında belirtilir ve bir kez kullanılır: asenkron, aktif düşük. Çizimdeki flip-flop always_ff bloğudur, assign ise tersleyen girişiyle birlikte AND kapısıdır.

Sentez sonucu

rising_edge_detector.sv, Yosys'un genel sentezinde 2 hücre olur; 1 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.

synth -nofsm sonrası hücreler, türe göre
HücreNe olduğuAdet
$_DFF_PN0_yükselen kenarda D flip-flop, 0 değerine aktif düşük asenkron reset1
$_ANDNOT_ikinci girişi terslenmiş AND, A & ~B1
Toplam2

Lint Verilator 5.052 ile, testbench Icarus Verilog 13.0 ile, sentez Yosys 0.66 ile yapıldı.

Icarus bu sayfanın iki senaryosunu da bu kod üzerinde yeniden oynattı ve dalga biçiminin çizdiği 340 değerin hepsi tutuyor.

Sentezden önceki netlist

Yosys prep'in rising_edge_detector.sv dosyasında okuduğu yapı, henüz hiçbir kapı seçilmeden; netlistsvg 1.0.2 ile çizildi.

$adffARSTCLKDQclkrst_nsig_inpulse

Tuzaklar

Asenkron bir giriş. sig_in başka bir clock domain'inden geliyorsa, onu koymanın yeri bu devre değildir. Flip-flop sig_in'i tam değiştiği anda örnekleyip metastable (yarı kararlı) olabilir ve AND kapısı bir clock periyodundan çok daha kısa bir pulse üretebilir — bir sonraki aşamanın kaçıracağı ya da bir kenarda yakalayıp diğerinde kaçıracağı kadar kısa. Önce senkronlayın, sonra kenarı yakalayın.

Devrenin yalnızca yarısına ulaşan reset. sig_d reset'lenir; pulse reset'lenmez, çünkü kombinasyoneldir. sig_in zaten yüksekken reset'ten çıkmak hemen bir pulse üretir. Çoğu zaman istenen de budur, ama bu hiçbir zaman kazara olmamalıdır.

Kendinizi sınayın

pulse neden sig_in yüksek kaldığı sürece değil de tam olarak bir clock periyodu boyunca yüksek kalır?
Çünkü flip-flop yetişir. sig_in yükseldikten bir kenar sonra sig_d de 1 olur, bu yüzden sig_in & ~sig_d yeniden 0'a döner — sig_in ne kadar uzun süre yüksek kalırsa kalsın.
Bu devre clk'ye senkron olmayan bir girişle ne yapar?
Bir clock periyodu uzunluğunda olmayan bir pulse üretir, hatta hiç üretmeyebilir. Flip-flop bir değişikliği tam olurken örnekleyebilir ve AND kapısı bir glitch görür. Asenkron bir girişin bu devreden sonra değil, önce bir senkronlayıcıya (synchronizer) ihtiyacı vardır.

Görev: Üç pulse

1, 3 ve 6 numaralı kenarlarda pulse 1 olsun. Yalnızca sig_in girişini siz sürersiniz.

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
  • 1 numaralı kenarda pulse değeri 1.
  • 3 numaralı kenarda pulse değeri 1.
  • 6 numaralı kenarda pulse değeri 1.

JavaScript açıkken “Başla” bu görevi şekilde oynatır.

Tüm görevler

Etiketler rtl flip-flop edge-detection

Bir hata mı buldunuz? Düzeltme gönderin