FPGA Günlükleri – Clock Division

Bir önceki yazılarda dijital temelleri hatırlarken artık zamanlama işlerine de girmem gerekiyor diye düşünüyordum. Artık vakit geldi. Olayın teorisi oldukça basitmiş. Bildiğiniz sayıcı tasarlıyoruz. Her arttırma 1 Clock’da yapılsın. Bunu yükselen kenar olarak yapalım. Her yükselen kenarda sayıcıyı 1 arttıralım. 50 MHz kristal için 50 milyona kadar saydığımızda 1 saniye geçmiş olacak. Bu sayma işlemlerini farklı sayaçlarda yaparak farklı zamanlama çıktıları elde edeceğiz. Hadi zamanı bükelim!

Öncelikle VHDL ortamında Toplama, Çıkarma, Büyük – Küçük Kontrol gibi işlemler için şu kütüphaneyi eklememiz gerekiyor.

USE IEEE.STD_LOGIC_UNSIGNED.all;

Yapacağımız zamanlama için referansımız Clock girişi olacak bunu entity kısmında şu şekilde belirtiyoruz.

entity Clock_Division is port
(
	CLK_IN	: in STD_LOGIC;
	LED1		: OUT STD_LOGIC
);
end Clock_Division;

Sayma işlemi için bir adet sayıcıya ve bir adet sabit değere ihtiyacımız var. Sabit değer üst limitimiz olacak. Son olarak uygulama için LED’i toggle edecek bir değişkene ihtiyacımız var.

Bu değişkenleri ve sabitleri VHDL ile tanımlamak normal yazılımlardan çok farklı gözüküyor diyebilirim. Örneğin bir sabit tanımlayalım.

constant COUNT_1HZ   		: natural 	:= 25000000;

Bu tanımlamada sabit olduğunu “constant” ifadesi ile belirtiyoruz. Sabitin ismi ise “COUNT_1HZ” olarak tanımlanıyor. Değeri ise “:= 25000000” bu şekilde atanıyor ve yazılımda olduğu gibi noktalı virgül ile satır son buluyor. Son olarak NATURAL ifadesi vardır ve bu da sabitin doğal sayılar kümesinde olduğunu belirtir. POSITIVE olsaydı sıfır dahil olmazdı.

Bunun dışında 2 adet “Signal” tanımlaması olacak.

signal 	VAL_TOGGLE_1HZ   	: std_logic := '0';
signal 	COUNTER_1HZ   		: natural 	range 0 to COUNT_1HZ;

İlk tanımlama LED durumunu tutan toggle değişkeni olacak. Bit ataması için tek tırnak kullanılıyormuş.

İkinci sinyal ise 0 dan “COUNT_1HZ” sabitine kadar sayacak olan değişken olacak ama bu signal olarak tanımlı. RTL çıktısında daha iyi anlaşılıyor. Gerisini temel MCU ve yazılımdan hatırlayacaksınız.

Algoritma ise şöyle olacak :

  1. Yükselen kenarı algıla.
  2. Sayac istenen değere ulaştı mı ?
  3. Evet ise sayacı sıfırla ve biti tersle.
  4. Hayır ise 1 arttır.
  5. LED çıkışına toggle bitini yükle. (VAL_TOGGLE_1HZ)
library IEEE;
use IEEE.STD_LOGIC_1164.all;
USE IEEE.STD_LOGIC_UNSIGNED.all;
 
entity Clock_Division is port
(
	CLK_IN	: in STD_LOGIC;
	LED1		: OUT STD_LOGIC
);
end Clock_Division;
 
architecture karakter of Clock_Division is

constant COUNT_1HZ   		: natural 	:= 25000000;
signal 	VAL_TOGGLE_1HZ   	: std_logic := '0';
signal 	COUNTER_1HZ   		: natural 	range 0 to COUNT_1HZ;

begin

	p_1_HZ : process (CLK_IN) is
	begin
		if rising_edge(CLK_IN) then
			if COUNTER_1HZ = COUNT_1HZ - 1 then
				VAL_TOGGLE_1HZ <= not VAL_TOGGLE_1HZ;
				COUNTER_1HZ    <= 0;
			else
				COUNTER_1HZ <= COUNTER_1HZ + 1;
			end if;
		end if;
	end process p_1_HZ;
	
	LED1 <= VAL_TOGGLE_1HZ;
 
end karakter;

RTL Çıktısı : 


Eğer birden çok zamanlama gerekirse şu şekilde yapılabilir.

library IEEE;
use IEEE.STD_LOGIC_1164.all;
USE IEEE.STD_LOGIC_UNSIGNED.all;
 
entity Clock_Division is port
(
	CLK_IN	: in STD_LOGIC;
	LED1		: OUT STD_LOGIC;
	LED2		: OUT STD_LOGIC
);
end Clock_Division;
 
architecture karakter of Clock_Division is

constant COUNT_1HZ   	: natural 	:= 25000000;
constant COUNT_2HZ   	: natural 	:= 12500000;

signal 	VAL_TOGGLE_1HZ   : std_logic := '0';
signal 	VAL_TOGGLE_2HZ   : std_logic := '0';

signal 	COUNTER_1HZ   	: natural 	range 0 to COUNT_1HZ;
signal 	COUNTER_2HZ   	: natural 	range 0 to COUNT_2HZ;

begin

	p_1_HZ : process (CLK_IN) is
	begin
		if rising_edge(CLK_IN) then
			if COUNTER_1HZ = COUNT_1HZ - 1 then
				VAL_TOGGLE_1HZ <= not VAL_TOGGLE_1HZ;
				COUNTER_1HZ    <= 0;
			else
				COUNTER_1HZ <= COUNTER_1HZ + 1;
			end if;
		end if;
	end process p_1_HZ;
	
	p_2_HZ : process (CLK_IN) is
	begin
		if rising_edge(CLK_IN) then
			if COUNTER_2HZ = COUNT_2HZ - 1 then
				VAL_TOGGLE_2HZ <= not VAL_TOGGLE_2HZ;
				COUNTER_2HZ    <= 0;
			else
				COUNTER_2HZ <= COUNTER_2HZ + 1;
			end if;
		end if;
	end process p_2_HZ;
	
	LED1 <= VAL_TOGGLE_1HZ;
	LED2 <= VAL_TOGGLE_2HZ;
 
end karakter;

RTL Çıktısı : 


Logic Analyzer Çıktısı :


Çıktılara bakacak olursak her şey yolunda gözüküyor. Şimdilik bu kadar.

Esen kalın.

You may also like...

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir