Sayısal Tasarım ve FPGA Uygulamaları
| Durum | Tamamlandı ✅ |
| Güncelleme | 9 Kasım 2023 |
| Hazırlayan | Emre İŞSEVER |
| E-Posta | emre.issever@fpgaturkey.com |
| info@beti.com.tr |
Basys3 FPGA kartının üzerinde bulunan butonları kullanarak harici donanım sinyallerini doğru ve etkin bir şekilde işlemek ve bu işleme sonucunda elde edilen verileri önceden belirlenen kriterlere uygun çıkış sinyallerinde dönüştürmektir.
Böylece öğrencilere, FPGA tabanlı sistemlerin temel prensipleri ve VHDL programlama dilinin kullanımı hakkında net, anlaşılır ve kapsamlı bir bilgi sunulmuş olur. Bu kazanımlar sayesinde, öğrenciler sinyal işlemenin ve donanım tasarımının temel prensiplerini pratik bir şekilde öğrenirken, bu bilgileri gerçek dünya uygulamalarına entegre etme becerisi kazanırlar.
Uygulamamızın temelini, yükselen ve düşen kenar tespiti oluşturur. Yükselen ve düşen kenar mantığı, dijital elektronikte ve özellikle FPGA tabanlı sistemlerde, sinyal durumlarının değişimini algılamada temel bir role sahiptir. Yükselen kenar, bir sinyalin düşük ('0') durumdan yüksek ('1') duruma geçişini; düşen kenar ise yüksek durumdan düşük duruma geçişi temsil eder. Bu kenarlar, sinyal durumlarının zaman içindeki değişimlerini izlemek ve bu değişimlere göre belirli eylemleri tetiklemek için kullanılır.
Dijital sistemlerde bu tür kenar değişimlerini algılamak için genellikle D Flip-Flop, AND ve NOT kapılarından oluşan mantıksal devreler kullanılır. VHDL içinde bu işlevsellik, çoğunlukla rising_edge fonksiyonu ya da sinyalin bir olayı ('event') olduğunu ve belirli bir değere ('1' veya '0') eşit olduğunu kontrol eden ifadeler (örneğin signal'event and signal = '1') ile modellenir. Bu yapılar özellikle clk gibi sürekli değişen ve sabit bir frekansta olan sinyaller için uygundur.
Dışarıdan gelen donanım sinyalleri (örneğin butonlardan gelen sinyaller) ile FPGA içerisindeki clock (clk) sinyalleri farklı şekillerde işlenmelidir. Bu durumda, sinyalin önceki ve mevcut durumları arasındaki değişim, özel olarak tasarlanmış bir mantık devresi ile modellenebilir. Örneğin, bir butonun durumundaki değişim, butonun önceki ve mevcut değerlerinin karşılaştırılmasıyla tespit edilebilir.
if buton1 = '0' and buton1_prev = '1' then
-- Düşen Kenar Tespit Edildi
end if;
if buton2 = '1' and buton2_prev = '1' then
-- Yükselen Kenar Tespit Edildi
end if;
Yukarıda sunulan VHDL kod örneği, kenar tespit mekanizmasının basit bir modellemesini sergiler.
Burada kullanılan "_prev" takısı, ilgili sinyalin bir önceki durumunu temsil eder. Sinyalin geçmişteki değeri '1' iken mevcut değeri '0' olarak algılandığında, bu durum bir düşen kenarın varlığını gösterir. Bu, sinyalin yüksek seviyeden düşük seviyeye geçiş yaptığını ifade eder. Öte yandan, eğer sinyalin geçmişteki değeri '0' ve mevcut değeri '1' ise, bu bir yükselen kenarın tespit edildiğini gösterir, yani sinyalin düşük seviyeden yüksek seviyeye geçtiğini belirtir. Bu mantıksal yaklaşım, sinyal değişimlerinin zaman içindeki evrimini doğru bir şekilde yakalamak için temel bir yöntem sunar ve FPGA tabanlı sistemlerde sinyal işleme için kritik öneme sahiptir.
Gerçek dünyada, özellikle mekanik butonlardan gelen sinyaller, fiziksel titreşimler ve temas esnasında oluşan elektriksel gürültüler (bounce) nedeniyle istenmeyen dalgalanmalar içerebilir. Bu dalgalanmalar, sistemin yanlış sinyaller algılamasına neden olabilir. Debouncing, bu tür istenmeyen gürültüleri filtreleyerek sinyallerin daha temiz ve doğru bir şekilde işlenmesini sağlar.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity top is
generic (
DEBOUNCE_LIMIT : integer := 50000
);
Port (
clk : in std_logic;
btnU : in std_logic;
btnC : in std_logic;
btnD : in std_logic;
led : out std_logic_vector (2 downto 0)
);
end top;
architecture Behavioral of top is
signal btnU_stable, btnU_prev, btnU_debounced: std_logic := '0';
signal btnD_stable, btnD_prev, btnD_debounced: std_logic := '0';
signal btnC_stable, btnC_prev, btnC_debounced: std_logic := '0';
signal counterU: integer range 0 to DEBOUNCE_LIMIT:= 0;
signal counterD: integer range 0 to DEBOUNCE_LIMIT:= 0;
signal counterC: integer range 0 to DEBOUNCE_LIMIT:= 0;
signal led_state : std_logic_vector (2 downto 0);
begin
process(clk)
begin
if rising_edge(clk) then
-- ÜSTTEKİ BUTON İÇİN --S
-- ( Debounce Filtresi )
if btnU = btnU_stable then
counterU <= 0;
else
if counterU < DEBOUNCE_LIMIT then
counterU <= counterU + 1;
else
counterU <= 0;
btnU_stable <= btnU;
end if;
end if;
btnU_prev <= btnU_debounced;
btnU_debounced <= btnU_stable;
-- ( Yükselen Kenar Tespiti ve LED Durumunun Değiştirilmesi )
if btnU_debounced = '1' and btnU_prev = '0' then
led_state(0) <= not led_state(0);
end if;
-- ALLTAKİ BUTON İÇİN --
-- ( Debounce Filtresi ) ! Öncekiyle Aynıdır !
if btnD = btnD_stable then
counterD <= 0;
else
if counterD < DEBOUNCE_LIMIT then
counterD <= counterD + 1;
else
counterD <= 0;
btnD_stable <= btnD;
end if;
end if;
btnD_prev <= btnD_debounced;
btnD_debounced <= btnD_stable;
-- ( Alçalan/Düşen Kenar Tespiti ve LED Durumunun Değiştirilmesi )
if btnD_debounced = '0' and btnD_prev = '1' then
led_state(2) <= not led_state(2);
end if;
-- ORTADAKİ BUTON İÇİN --
-- ( Debounce Filtresi ) ! Öncekiyle Aynıdır !
if btnC = btnC_stable then
counterC <= 0;
else
if counterC < DEBOUNCE_LIMIT then
counterC <= counterC + 1;
else
counterC <= 0;
btnC_stable <= btnC;
end if;
end if;
btnC_prev <= btnC_debounced;
btnC_debounced <= btnC_stable;
-- ( Her İki Kenarın Tespit Edilmesi ve LED Durumunun Değişitirilmesi )
if btnC_debounced = '1' and btnC_prev = '0' then
led_state(1) <= not led_state(1);
elsif btnC_debounced = '0' and btnC_prev = '1' then
led_state(1) <= not led_state(1);
end if;
end if;
end process;
led <= led_state; -- LED Çıkışlarının Güncellenmesi
end Behavioral;
Yukarıdaki örnek, bir debouncing algoritmasının uygulamasını göstermektedir. Burada, bir butonun sabit durumu algılandığında sayaç sıfırlanır. Eğer buton durumu değişirse ve belirlenen bir eşik değere (DEBOUNCE_LIMIT) ulaşırsa, butonun stabil olduğu kabul edilir ve ilgili durum güncellenir. Böylece, sinyaller daha temiz bir şekilde işlenir ve yanlış tetiklemelerin önüne geçilir.
Debouncing algoritmasının önemi, onun uygulanmadığı durumlarda daha belirgin hale gelir. Örneğin, debouncing algoritması olmadan doğrudan yükselen ve düşen kenarları tespit etmeye yönelik bir kod, Basys3 kartına entegre edildiğinde, mekanik butonların doğasından kaynaklanan arklar ve istenmeyen sinyal değişimleri rahatlıkla gözlemlenebilir. Bu durum, mekanik butonlardan gelen sinyallerin, fiziksel titreşimler ve temas sırasında oluşan elektriksel gürültüler (bounce) nedeniyle, beklenmeyen sinyal dalgalanmaları içerebileceğini açıkça ortaya koyar. Debouncing algoritması bu tür gürültüleri filtreleyerek, sinyallerin daha temiz ve doğru bir şekilde işlenmesini sağlar. Dolayısıyla, bu algoritmanın uygulanmaması durumunda, butonların basılma ve bırakılma eylemlerinin doğru bir şekilde algılanması güçleşir, bu da sistemde yanlış tetiklemelere ve istenmeyen davranışlara yol açabilir. Bu gözlem, debouncing algoritmasının pratik uygulamalardaki kritik önemini ve FPGA tabanlı sistemlerde sinyal işlemenin doğruluğunu artırma rolünü vurgular.
Bu doküman içerisindeki kodlar Vivado 2020.03 üzerinde gerçekleştirilip test edilmiştir.
Bu VHDL kodu, Basys3 FPGA kartında bulunan butonların durumuna göre LED'leri kontrol eden bir yapılandırmadır. Kod, FPGA üzerinde sinyal işleme ve kontrol mekanizmalarının nasıl kurulacağını ve bu mekanizmaların çeşitli donanım girişleriyle nasıl entegre edileceğini örnekler.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity top is
generic (
DEBOUNCE_LIMIT : integer := 50000
);
Port (
clk : in std_logic;
btnU : in std_logic;
btnC : in std_logic;
btnD : in std_logic;
led : out std_logic_vector (2 downto 0)
);
end top;
architecture Behavioral of top is
signal btnU_stable, btnU_prev, btnU_debounced: std_logic := '0';
signal btnD_stable, btnD_prev, btnD_debounced: std_logic := '0';
signal btnC_stable, btnC_prev, btnC_debounced: std_logic := '0';
signal counterU: integer range 0 to DEBOUNCE_LIMIT:= 0;
signal counterD: integer range 0 to DEBOUNCE_LIMIT:= 0;
signal counterC: integer range 0 to DEBOUNCE_LIMIT:= 0;
signal led_state : std_logic_vector (2 downto 0);
begin
process(clk)
begin
if rising_edge(clk) then
-- ÜSTTEKİ BUTON İÇİN --S
-- ( Debounce Filtresi )
if btnU = btnU_stable then
counterU <= 0;
else
if counterU < DEBOUNCE_LIMIT then
counterU <= counterU + 1;
else
counterU <= 0;
btnU_stable <= btnU;
end if;
end if;
btnU_prev <= btnU_debounced;
btnU_debounced <= btnU_stable;
-- ( Yükselen Kenar Tespiti ve LED Durumunun Değiştirilmesi )
if btnU_debounced = '1' and btnU_prev = '0' then
led_state(0) <= not led_state(0);
end if;
-- ALLTAKİ BUTON İÇİN --
-- ( Debounce Filtresi ) ! Öncekiyle Aynıdır !
if btnD = btnD_stable then
counterD <= 0;
else
if counterD < DEBOUNCE_LIMIT then
counterD <= counterD + 1;
else
counterD <= 0;
btnD_stable <= btnD;
end if;
end if;
btnD_prev <= btnD_debounced;
btnD_debounced <= btnD_stable;
-- ( Alçalan/Düşen Kenar Tespiti ve LED Durumunun Değiştirilmesi )
if btnD_debounced = '0' and btnD_prev = '1' then
led_state(2) <= not led_state(2);
end if;
-- ORTADAKİ BUTON İÇİN --
-- ( Debounce Filtresi ) ! Öncekiyle Aynıdır !
if btnC = btnC_stable then
counterC <= 0;
else
if counterC < DEBOUNCE_LIMIT then
counterC <= counterC + 1;
else
counterC <= 0;
btnC_stable <= btnC;
end if;
end if;
btnC_prev <= btnC_debounced;
btnC_debounced <= btnC_stable;
-- ( Her İki Kenarın Tespit Edilmesi ve LED Durumunun Değişitirilmesi )
if btnC_debounced = '1' and btnC_prev = '0' then
led_state(1) <= not led_state(1);
elsif btnC_debounced = '0' and btnC_prev = '1' then
led_state(1) <= not led_state(1);
end if;
end if;
end process;
led <= led_state; -- LED Çıkışlarının Güncellenmesi
end Behavioral;
Kod, IEEE standart kütüphanesini kullanarak, FPGA için gerekli lojik sinyalleri ve veri türlerini tanımlar. Bu kütüphane, FPGA programlamada yaygın olarak kullanılan standart bir araçtır. entity bölümünde, giriş ve çıkış portları tanımlanmıştır; burada clk (saat sinyali), btnU, btnC, btnD (butonlar) girişleri ve led çıkışları yer alır.
Kodun en önemli bölümlerinden biri, butonlardan gelen sinyallerdeki gürültüyü (bounce) filtreleyen debouncing mekanizmasıdır. Bu işlem, her buton için ayrı ayrı gerçekleştirilir. Sinyal stabil olduğunda, yani buton durumu değişmediğinde, ilgili sayaç sıfırlanır. Eğer buton durumu değişirse, belirlenen bir eşik değere (DEBOUNCE_LIMIT) ulaşıncaya kadar sayaç arttırılır. Bu eşik değere ulaşıldığında, butonun stabil olduğu kabul edilir ve ilgili durum güncellenir.
Kenar tespiti, butonların önceki ve mevcut durumları karşılaştırılarak yapılır. Örneğin, btnU için yükselen kenar tespiti (düşükten yükseğe geçiş) yapılırken, btnD için düşen kenar tespiti (yüksekten düşüğe geçiş) yapılır. btnC ise her iki kenarın tespiti için kullanılır.
Her buton, belirlenen kenar tespitine göre bir LED'in durumunu değiştirir. Örneğin, btnU yükselen kenarı tespit edildiğinde led_state(0) güncellenir. Benzer şekilde, btnD düşen kenarı tespit ettiğinde led_state(2), btnC ise herhangi bir kenar değişikliği tespit ettiğinde led_state(1) güncellenir.
Tüm bu işlemler, FPGA'nın clk sinyali ile senkronize bir şekilde gerçekleştirilir. Bu, sistemin zamanlamasının doğru bir şekilde yönetilmesini ve tüm sinyal işleme adımlarının güvenilir ve tutarlı olmasını sağlar.
Bu kod, FPGA tabanlı sistemlerde donanım kontrolünün temel prensiplerini ve VHDL programlama dilinin kullanımını pratik bir şekilde gösterir. Öğrenciler, bu bilgiler sayesinde, sinyal işlemenin ve donanım kontrolünün temel prensiplerini anlama ve bu prensipleri gerçek dünya uygulamalarına entegre etme becerisi kazanırlar.
Deney yüklendiğinde gözlenmesi gereken davranışlar aşağıdaki kutucukta paylaşılmıştır.
Böylece, üstteki butona basıldığında ;
En sağdaki LED0 yükselen kenarda tetiklenerek yanacaktır, tekrar basılması durumunda yine yükselen kenarda tetiklenerek sönecektir.
Merkezdeki butona basıldığında ;
LED1 hem yükselen kenarda hem düşen kenarda tetiklenecektir, dolayısıyla parmağınızı bastığınızda tetiklenecek ve led yanacaktır. Çektiğinizde ise tekrar tetiklenecek ve sönecektir.
Alttaki Butona Basıldığında ;
LED2 düşen kenarda tetiklenecektir, butona basıldığında değil elinizi butondan çekerken tetiklenecek ve yanacaktır. Tekrar bastığınızda aynı şekilde elinizi çektiğinizde sönecektir.
Bu doküman, Beti Elektronik San. ve Tic. Ltd. Şti’nin fikri mülkiyetine tabidir ve firmanın izni olmadan kopyalanması, çoğaltılması, dağıtılması veya yeniden yayınlanması yasaktır. Kitabın herhangi bir bölümünün veya içeriğinin izinsiz kullanılması, telif hakkı ihlali anlamına gelir ve yasal işlemlere yol açabilir. Dokümanın içeriği veya herhangi bir kısmı kullanılacaksa, yazılı izin alınmalıdır. İzin talepleri için info@beti.com.tr ile iletişime geçiniz. Makul alıntılar yapılabilir, ancak bu alıntılar mutlaka kaynak gösterme ile birlikte sunulmalıdır. Kaynak göstermeden yapılan alıntılar veya içerik kullanımları, yine telif hakkı ihlali olarak kabul edilir.