thought Selam, foruma gelen bu soru aslında yeni başlayanların sıkça düştüğü klasik bir "yarış durumu" (race condition) ve mantık döngüsü hatası. Kullanıcı, kombinasyonel bir yapı ile ardışıl (sequential) bir davranış elde etmeye çalışıyor ancak donanımın nasıl çalıştığını (propagation delay) hesaba katmıyor.
İşte senin ağzından, hem açıklayıcı hem de çözüm odaklı cevap taslağı:
Forum Yanıtı
Selamlar, aramıza hoş geldin! FPGA ve Verilog dünyasına adım atarken bu tarz "mantıksal döngü" hatalarıyla karşılaşman çok normal. Sorunun kaynağı ve çözümüyle ilgili birkaç noktaya değineyim:
- Sorun: "Sonsuz Yarış" Durumu
Yazdığın kodda nand kapılarıyla kurduğun yapı tamamen kombinasyoneldir. Yani bir always @(posedge Clk) bloğu kullanmadığın için devre, girişlerdeki değişime anlık (nanosaniyeler mertebesinde) tepki verir.
Sen çıkışları (Q ve nQ) tekrar girişe bağladığında, devre bir "feedback loop" (geribesleme döngüsü) oluşturuyor.
J=1, K=1 olduğunu düşünelim: Çıkış konum değiştirmek isteyecek (toggle).
Çıkış değiştiği anda, bu yeni değer anında tekrar girişe gidecek.
Bu durum, saat darbesi (Clk) yüksek olduğu sürece çıkışların belirsiz bir hızda sürekli 0 ve 1 arasında gidip gelmesine (salınım/oscillation) neden olur.
- Çözüm: Register (Yazmaç) Mantığı
Gerçek hayatta ve FPGA tasarımında bu sorunu Flip-Flop kullanarak çözeriz. Flip-flop'lar sadece saatin yükselen kenarında (posedge) girişleri örnekler. Bu sayede çıkış değişse bile, bir sonraki saat kenarına kadar o değişim girişi etkilemez.
Verilog'da bunu kapı seviyesinde (gate-level) nand ile kurmak yerine, donanımın içindeki hazır D-Flip-Flop (DFF) yapılarını kullanacak şekilde behavioral (davranışsal) kod yazmalısın.
- Kodun Doğru Yazımı
Verilog'da JK Flip-Flop en sağlıklı şu şekilde tanımlanır:
`
timescale 1ns / 1ps
module jk_flip_flop(
input J, K, Clk, Reset,
output reg Q,
output nQ
);
assign nQ = ~Q; // nQ her zaman Q'nun tersidir
always @(posedge Clk or posedge Reset) begin
if (Reset) begin
Q <= 1'b0;
end else begin
case ({J, K})
2'b00: Q <= Q; // Koruma (Hold)
2'b01: Q <= 1'b0; // Sıfırla (Reset)
2'b10: Q <= 1'b1; // Set
2'b11: Q <= ~Q; // Tersle (Toggle)
endcase
end
end
endmodule
`