A- Giriş:

Bu uygulamada S3E SK nın üzerinde bulunan LED leri ve düğmeleri kullanacağız. LED ler bir sayıyı göstermeye yarayacak ve düğmeler de bu sayı üzerinde oynama yapmaya yarayacak.

Kullanacağımız LED ler S3E SK kullanım kılavuzunda “Discrete LEDs” olarak geçen LEDlerdir. Bu LED leri S3E SK’nın sağ alt köşesinde bulabilirsiniz.

s1_1_ledler.JPG

Kullanım klavuzundan alınan yukarıdaki resimde LEDler gösterilmiştir. Ayrıca iğne bilgileri de verilmiştir (F9 – D9 – D11 – C11 – F11 – E11 – E12 – F12).

Kullanacağımız düğmeler ise kullanım kılavuzunda “Push Button Switches” olarak geçen düğmelerdir.

s1_1_butonlar.JPG

Aynı şekilde kullanım kılavuzundan alınan yukarıdaki resimde düğmeleri ve ilgili iğne bilgilerini görebiliyoruz. Biz bu uygulamada yukarıdaki BTN_NORTH, BTN_EAST, BTN_SOUTH ve BTN_WEST düğmelerinikullanacağız. ROT_A, ROT_B ve ROT_CENTER‘ı bir sonraki uygulamamızda kullanacağız.

Ayrıca LEDler üzerinde değişiklik yaparken düzgün bir şey görebilmek için LEDleri saniyede bir kez yenileyeceğiz. Aksi takdirde S3E SK’nın saat darbesine göre çalışırsak düzgün sonuçlar elde etsek bile göremeyeceğiz. Bunun için S3E SK saat darbesini kullanarak 52000000 da bir ledlerin durumlarını değiştireceğiz. S3E SK nin saat darbesini 50Mhz olduğu için 52000000 sayısını kullanıyoruz. Aslında bu sayı yaklaşık bir sayıdır. Tam olarak 1 saniyede bir tetiklenmeyecektir. Kullanacağımız aat darbesi kullanım kılavuzunda CLK_50MHZ olarak tanımlanan saat darbesi iğnesidir. Aşağıdaki resimde saat darbesini üretmekte kullanılan 50Mhz lik kristali görebilirsiniz (IC17 etiketli devre elemanı).

s1_1_clk.JPG

B- Uygulama:

Yeni bir proje oluşturalım ve gerekli ayarları yapalım (seviye 0 daki bilgileri kullanarak). Yeni bir Verilog dosyası oluşturalım ve projeye ekleyelim. Ben “ana.v” adında bir dosya oluşturdum. Siz farklı birşey yapabilirsiniz. Sayfanın altındaki .rar’in içinde ana.v olarak benim dosyamı bulabilirsiniz.

İlk olarak kullanacağımız girdi-çıktı kapılarımızı ve yazmaçlarımızı tanımlayalım ve modül iğne listesine ekleyelim.

S3E SK saat darbesini CLK iğnesinden alacağız. Kullanacağımız dört düğmeyi
DUGME1, DUGME2, DUGME3 ve DUGME4 iğnelerinden okuyacağız.

Kullanacağımız LEDleri ise yedi bitlik LED veriyolundan yöneteceğiz. Tüm bunları yapacak olursak aşağıdaki kodu elde ederiz:

  1. `timescale 1ns / 1ps
  2. module ana(CLK, DUGME1,DUGME2,DUGME3,DUGME4,LED); // modül başı
  3. // Girdi kapıları
  4. input CLK;        // Saat darbesi
  5. input DUGME1;     // Doğu düğmesi
  6. input DUGME2;     // Batı düğmesi
  7. input DUGME3;     // Kuzey düğmesi
  8. input DUGME4;     // Güney düğmesi
  9. // Çıktı kapıları
  10. output [7:0] LED; // S3E SK ledleri
  11. // Yazmaçlar
  12. reg [7:0] ledler;
  13. reg [25:0] saat_sayac;
  14. //
  15. // Kodumuzun devamını buraya yazacağız
  16. //
  17. endmodule // modülü sonlandır

Kullanacağımız saat sayacına ilk değeri verelim. Bunu yapmak için initial komutunu kullanabiliriz.

  1. initial begin
  2. saat_sayac <= 26’b00000000000000000000000000;
  3. end

Elli iki milyonda bir kez düğmelerin durumunu kontrol edip ona göre işlem yapan kodumuz aşağıdadır.

  1. always @ (posedge CLK) begin
  2. if(saat_sayac == 26’b11000110010111010100000000) begin
  3. if(DUGME1) begin
  4. ledler <= ledler + 8’b00000001;// ledler yazmacını bir arttır
  5. end
  6. else if (DUGME2) begin
  7. ledler <= ledler – 8’b00000001;// ledler yazmacını bir azalt
  8. end
  9. else if (DUGME3) begin
  10. ledler <= ~ledler;// ledler yazmacını tersle
  11. end
  12. else if (DUGME4) begin
  13. ledler <= 8’b00000000;// ledler yazmacını sıfırla
  14. end
  15. else begin
  16. ledler <= ledler;// ledler değerlerini korusun
  17. end
  18. saat_sayac <= 26’b00000000000000000000000000;// saat sayacını sıfırla
  19. end
  20. else begin
  21. saat_sayac <= saat_sayac + 1;// saat sayacının değerini arttır
  22. end
  23. end

Yukarıdaki kod saat darbesinin artan kenarında tetiklenmekte ve gerçeklenmektedir. saat_sayac yazmacının değerinin 52000000′a eşit olup olmadığı kontrol edilmektedir. Eğer eşit ise o zaman bu sayaç sıfırlanmakta ve düğme durumları kontrol edilmektedir. Aksi halde ise saat_sayac yazmacının değeri arttırılmaktadır.

Kodda görüldüğü gibi DUGME1, DUGME2, DUGME3 ve DUGME4‘ün değerleri ayrı ayrı kontrol edilmektedir ve uygun işlemler yapılmaktadır. DUGME1‘e basıldığı zaman ledler yazmacının değeri bir artarken, DUGME2‘ye basıldığında bir azalmaktadır. Aynı şekilde DUGME3‘e basıldığında ledler yazmacı terslenmektedir.

DUGME4′e basıldığında ise ledler yazmacı sıfırlanmaktadır. Diğer durumlarda ise ledler yazmacının değerini korunmaktadır.

Sırada yapmamız gereken işlem ledler yazmacını LED veriyoluna bağlamaktır. Bunun için assign komutunu kullanabiliriz.

  1. assign LED = ledler; // ledler yazmacını LED iğnelerine bağla

Kodumuzu sentezleyip gerçekleştirebiliriz. Kodu S3E SK’ya yükleyince elde edeceğiniz sonucu aşağıdaki vidyoda görebilirsiniz.

C– UCF dosyasının oluşturulması (Xilinx ISE):

Burada sadece bu uygulamaya özel olarak (sonraki uygulamalarda artık bu konuya değinmeyeceğiz) UCF dosyasının nasıl oluşturulacağını göreceğiz. Öncelikle girdi-çıktı iğnelerimizi ve veriyollarımızı listeleyelim ve yanlarına bu iğnelerin ne için kullandığımızı yazalım:

CLK : Saat darbesi
DUGME1: Düğme
DUGME2: Düğme
DUGME3: Düğme
DUGME4: Düğme

LED: 8 adet LED

Şimdi bütün bunları ortaya koyduktan sonra S3E SK kullanım kılavuzunu açalım ve saat darbesi için ne kullanabileceğimize bakalım. “Clock Sources” adlı bölümün “UCF Constraints” adlı alt bölümünü açalım. Orada aşağıdaki UCF bilgilerini görüyoruz:

  1. NET “CLK_50MHZ” LOC= “C9” | IOSTANDARD= LVCMOS33 ;
  2. NET “CLK_SMA” LOC= “A10” | IOSTANDARD= LVCMOS33 ;
  3. NET “CLK_AUX” LOC = “B8” | IOSTANDARD = LVCMOS33 ;

S3E SK’da 50Mhz lik kristal hazır geldiğinden ve SMA ve AUX’a herhangi bir sinyal üreteci veya kristal takmadığımızdan CLK iğnemiz için aşağıdaki UCF kısıtını kullanacağız. (Not: Yukarıdaki CLK_50MHZ etiketini kendi projemizde kullandığımız CLK etiketi ile değiştirmeyi unumayınız.)

  1. NET “CLK” LOC= “C9” | IOSTANDARD = LVCMOS33 ;


Kullanmak istediğimiz düğmeler ise sayfanın başında belirttiğimiz gibi
BTN_NORTH, BTN_EAST, BTN_SOUTH ve BTN_WEST düğmeleridir. Bu düğmelerin UCF kısıtlarını öğrenebilmek için “Switches, buttons, knob” başlığının “Push-button switches” alt başlığının “UCF Constraints” alt başlığını açalım. Aşağıdaki değerlerle karşılaşıyoruz:

  1. NET “BTN_EAST” LOC= “H13” | IOSTANDARD = LVTTL | PULLDOWN ;
  2. NET “BTN_NORTH” LOC = “V4” | IOSTANDARD = LVTTL | PULLDOWN ;
  3. NET “BTN_SOUTH” LOC = “K17” | IOSTANDARD = LVTTL | PULLDOWN ;
  4. NET “BTN_WEST” LOC = “D18” | IOSTANDARD = LVTTL | PULLDOWN ;

Kullanmak istediğimiz UCF kısıtları da zaten bunlar olduklarından etiketlerini kendi projemize uyarlıyoruz:

  1. NET “DUGME1” LOC = “H13” | IOSTANDARD = LVTTL | PULLDOWN;
  2. NET “DUGME3” LOC = “V4” | IOSTANDARD = LVTTL | PULLDOWN ;
  3. NET “DUGME4” LOC = “K17” | IOSTANDARD = LVTTL | PULLDOWN ;
  4. NET “DUGME2” LOC = “D18” | IOSTANDARD = LVTTL | PULLDOWN ;

Kullanacağımız LEDlerin UCF kısıtlarını öğrenmek için ise kullanım kılavuzunun “Switches,Buttons, and Knob” başlığının “Dicrete LEDs” alt başlığının “UCF Constraints” başlığını açalım. Aşağıdaki UCF kısıtları ile karşılaşıyoruz:

  1. NET “LED<7>” LOC = “F9” | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;
  2. NET”LED<6>” LOC = “E9” | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;
  3. NET “LED<5>” LOC = “D11” | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;
  4. NET “LED<4>” LOC = “C11” | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;
  5. NET “LED<3>” LOC = “F11” | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;
  6. NET “LED<2>” LOC = “E11” | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;
  7. NET “LED<1>” LOC = “E12” | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;
  8. NET “LED<0>” LOC = “F12” | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;

Yukarıdaki UCF kısıtları bizim kullanmak istediğimiz kısıtlardır. Neden mi? Çünkü S3E SK üzerinde kullanabileceğimiz başka LED yok. LED<7> etiketinin anlamı LED adlı bir veriyolunun sekizinci bitidir. Eğer her LED’e arklı bir etiket verirsek o zaman projemizde bu LEDlerin değerlerini tek tek değiştirmemiz gerekir. Biz uygulamamız da LED çıkışını tanımlarken:

  1. output [7:0] LED;

ifadesini kullandığımızdan LED adında 8 bitlik bir veri yolunu çıkış olarak tanımlamış olduk. Kullanım kılavuzunda da aynı şekilde LED adında bir veri yolu kullanıldığından etiketlerde herhangi bir değişiklik yapmadan kullanabileceğiz. Ama biz LED yerine LAMBA etiketini kullansaydık o zaman aşağıdakine benzer bir değişiklik yapmamız gerekirdi:

  1. NET “LAMBA<7>” LOC = “F9” | IOSTANDARD = LVTTL | SLEW =SLOW | DRIVE = 8;
  2. NET “LAMBA<6>” LOC = “E9” | IOSTANDARD = LVTTL | SLEW =SLOW | DRIVE = 8;
  3. NET “LAMBA<5>” LOC = “D11” | IOSTANDARD = LVTTL | SLEW =SLOW | DRIVE= 8;
  4. NET “LAMBA<4>” LOC = “C11” | IOSTANDARD = LVTTL | SLEW =SLOW | DRIVE= 8;
  5. NET “LAMBA<3>” LOC = “F11” | IOSTANDARD = LVTTL | SLEW =SLOW | DRIVE= 8;
  6. NET “LAMBA<2>” LOC = “E11” | IOSTANDARD = LVTTL | SLEW =SLOW | DRIVE= 8;
  7. NET “LAMBA<1>” LOC = “E12” | IOSTANDARD = LVTTL | SLEW =SLOW | DRIVE= 8;
  8. NET “LAMBA<0>” LOC = “F12” | IOSTANDARD = LVTTL | SLEW =SLOW | DRIVE= 8;

Tabii ki LAMBA değil LED kullandığımızdan böyle bir değişiklik yapmaya ihtiyacımız yok.

UCF dosyasının tamamını görmek için aşağıdaki proje dosyasını bilgisayarınıza indirip inceleyebilirsiniz.

UCF dosyaları hazırlanırken dikkat edilmesi gereken en önemli şey aslında LOC özelliğidir. LOC bir etiketin hangi iğneye bağlanacağını belirtir. Mesela LED<7> iğnesi gerçekte F9 iğnesine bağlı olacaktır. “LED<7> iğnesi” kullanımı burda biraz kafaları karıştırabilir. Burada kastedilen LED<7> iğne etiketidir. Yani donanımsal olarak bir iğne temsil etmez. Ama F9 donanımsal bir iğnedir. FPGA entegresinin belirli, görünen, “gerçek” bir iğnesidir. FPGA dış dünya ile bu iğne sayesinde iletişir.

Eğer kullandığınız FPGA geliştirme kiti veya direk FPGA farklı ise yani Spartan S3E Starter Kit değilse LOC değerinde değişiklik yapmanız gerekir. Eğer kitiniz Spartan S3E Starter Kit ise yine de dikkat etmeniz gerekir. İnsan hata yapabildiğinden UCF dosyası kod FPGA kitine yollanmadan bir daha kontrol edilmelidir. Aksi takdir çıkış ve girişler karışabilir ve hem FPGA’ya hem de çevre birimlerine kalıcı zarar verilebilir.

UCF dosyasını ve atamalarını kontrol etmenin bir yolu UCF dosyasını direk olarak kontrol etmektir. Diğer bir yolu ise Xilinx ISE’nin arayüzünden kod sentezlendikten ve gerçeklendikte sonra “Pinout Report” a bakmaktır. Programda anlık bir hata oluşabileceğini ve kod gerçeklenirken UCF dosyasının yanlış veya eksik okunabileceğini göz önünde bulundurarak her iki yöntem ile kontrol etmek akıllıca olacaktır. Eğer bir etiket için herhangi bir UCF kısıtı yok ise o zaman ISE gerçekleştiricisi otomatik olarak bir iğneyi o etikete atıyacaktır ve bu genelde istediğimiz iğne olmayacaktır.

D- Kod ve Proje Dosyaları (Xilinx ISE):

İndirmek için tıklayınız.

*Elinizdeki FPGA kitine göre kodda bazı değişiklikler yapmanız gerekebilir.

E- Vidyo:

Vidyo 1