VHDL'de Variable Nerede Tanımlanıyor? Fpga

Başlatan vitruvius, 24 Şubat 2012, 16:01:07

vitruvius

Merhabalar, birkaç hafta ara verince bilgiler uçup gitmiş.  :(  Elimde Spartan 3E Starter Kit var. Yapmak istediğim şey şu: Bir i tam sayısı tanımlayayım. Butona her bastığımda i'nin değeri bir artsın. Ben bu i'ye bakarak butona kaç kere basılmışsa o sıradaki led'i yakayım. Switchlerde de ledleri ikili ikili yakmayı amaçlamıştım. Kodu kendimce yazdım ama bu i değişkenini tanımlama kısmında şu hatayı alıyorum:Line 54. parse error, unexpected VARIABLE

Yazdığım kod:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ornek1 is
    Port ( but1 : in  STD_LOGIC;
           sw1 : in  STD_LOGIC;
           sw2 : in  STD_LOGIC;
           sw3 : in  STD_LOGIC;
           sw4 : in  STD_LOGIC;
           led1 : out  STD_LOGIC;
           led2 : out  STD_LOGIC;
           led3 : out  STD_LOGIC;
           led4 : out  STD_LOGIC;
           led5 : out  STD_LOGIC;
           led6 : out  STD_LOGIC;
           led7 : out  STD_LOGIC;
           led8 : out  STD_LOGIC);
end ornek1;

architecture Behavioral of ornek1 is

begin

variable say:integer range 0 to 8;

if but1='1' then
	say:=say+1;
end if;

if say=1 then
	led1<='1';
		elsif say=2 then
		led1<='0';
		led2<='1';
			elsif say=3 then
			led2<='0';
			led3<='1';
				elsif say=4 then
				led3<='0';
				led4<='1';
					elsif say=5 then
					led4<='0';
					led5<='1';
						elsif say=6 then
						led5<='0';
						led6<='1';
							elsif say=7 then
							led6<='0';
							led7<='1';
								elsif say=8 then
								led7<='0';
								led8<='1';								
	else
	say:=0;
	led1<='0';
	led2<='0';
	led3<='0';
	led4<='0';
	led5<='0';
	led6<='0';
	led7<='0';
	led8<='0';
	
end if;

if sw1='1' then
	led1<='1';
	led2<='1';
		elsif sw2='1' then
		led1<='0';
		led2<='0';
		led3<='1';
		led4<='1';
			elsif sw3='1' then
			led3<='0';
			led4<='0';
			led5<='1';
			led6<='1';
				elsif sw4='1' then
				led5<='0';
				led6<='0';
				led7<='1';
				led8<='1';
	else
	led1<='0';
	led2<='0';
	led3<='0';
	led4<='0';
	led5<='0';
	led6<='0';
	led7<='0';
	led8<='0';
end if;
	
end Behavioral;


Teşekkürler.

kralsam

Hocam variable yerine
signal say std_logic_vector(3 downto 0):="0000";

kullanırsan sıkıntı yaşamazsın. İnteger sayılarla işlem yaparken taşmalar vs. sorun çıkarabiliyor.

vitruvius

Hocam bu sefer de Line 54. parse error, unexpected SIGNAL hatası alıyorum. Aslında çok basit bir hatam vardır muhtemelen ama ben çok acemi olduğumdan göremiyorum.

berat23

bu yazdığın kod,doğru çalışsa bile fpga mantığına ters.öncelkle normal sequential C de kod yazar gibi algoritma kurma.burada donanım tasarımı yapar gibi düşüneceksin.

bu yazdığın algoritmayı bir state machine ile gerçekleyebilirsin.butona her basışında bir sonraki state'e geçecek bir moore fsm tasarlayacaksın.switch içinde aynı mantığı kullanacaksın.birde bu kadar uzun kodlar yerine paralel prosesler yapmak daha doğru. bu arada kodu detaylı incelemedim ama bir mantık hatası var gibi çünkü hem buton hem de switch,aynı ledleri kontrol ediyor.


bu da buton için yazdığım örnek fsm
library ieee;
use ieee.std_logic_1164.all;

entity fsm is

	port(
		clk		 : in	std_logic;
		buton	 : in	std_logic;
		reset	 : in	std_logic;
		led	 : out	std_logic_vector(4 downto 0)
	);

end entity;

architecture rtl of fsm is

	type state_type is (s0, s1, s2, s3);
	signal state   : state_type;

begin

	process (clk, reset)
	begin
		if reset = '1' then
			state <= s0;
		elsif (rising_edge(clk)) then
			case state is
				when s0=>
					if buton = '1' then
						state <= s1;
					else
						state <= s0;
					end if;
				when s1=>
					if buton = '1' then
						state <= s2;
					else
						state <= s1;
					end if;
				when s2=>
					if buton = '1' then
						state <= s3;
					else
						state <= s2;
					end if;
				when s3 =>
					if buton = '1' then
						state <= s0;
					else
						state <= s3;
					end if;
			end case;
		end if;
	end process;

	process (state)
	begin
		case state is
			when s0 =>
				led <= "0001";
			when s1 =>
				led <= "0010";
			when s2 =>
				led <= "0100";
			when s3 =>
				led <= "1000";
		end case;
	end process;

end rtl;

kralsam

Hocam ben o hatayı yeni fark ettim. Kodda sadece o kısma bakmıştım. Arkadaşın dediği gibi işlemleri paralel processlere bölmelisin. Signal tanımladıktan sonra karşılaştığın hata çözümüde eşitliği atamayı ":=" şeklinde değilde "<=" şeklinde yapmalısın. Tahminimce hata budur...

Ama tasarımı berat23 hocamın bahsettiği şekilde yapmalısın..

vitruvius

Hocam daha yeni başladığım için donanım tasarlar gibi düşünemiyorum malesef, aklım hep C'ye gidiyor. Yani eğitimini almadım, internetten araştırdığım ve okuduğm e-booklar kadar bilgim var. Nasıl bir bakışla yaklaşmam gerekir kod yazmaya?

Hem switch hem butonla led kontrolünde mantık hatası var farkındayım ama deneme yaptığım için öyle yazdım kodu.

Birde yazdığınız kodun ufak bir izahını yapabilir misiniz acaba? Bu state machine ve more fsm terimlerini de bilemedim =/

Mesela;

elsif (rising_edge(clk)) then
            case state is
                when s0=>
                    if buton = '1' then
                        state <= s1;
                    else
                        state <= s0;
                    end if;


ve

process (state)
    begin
        case state is
            when s0 =>
                led <= "0001";


kısmı. Teşekkürler.

berat23

fpga ile birşeyler yapabilmek için önşart,iyi logic bilgisi ve matematik bilgisi.bunlar olmadan anlatımlar havada kalır.C veya mcu gibi kolay metodu yok malesef.

fsm için burada kabaca anlatımlar var.ben öğrenirken biryere takılınca genelde sözlüklere bakıyorum zira insan alatımı kitap cümlelerinden daha açık oluyor.
http://tr.wikipedia.org/wiki/Sonlu_durum_makinas%C4%B1
http://www.eksisozluk.com/show.asp?t=finite+state+machine


kabaca anlatmam gerekirse,senin değişken diye bahsettiğin şey,burada o anki içinde olduğumuz statedir,yani kabaca hafızamız diyelim.butondan giriş geldikçe durumumuzu yani değişkenimizi değiştiriyoruz.görüldüğü üzere 4 durum var.diğer process ise çıkış kısmı.burada da içinde olduğumuz duruma göre çıkış belirleniyor.yani ;
1.state-> 1.led
2.state-> 2.led
3.state-> 3.led
4.state-> 4.led
şeklinde.moore fsm ise çıkışın girişlere bağlı olmaması.yani her durumda çıkış sadece o anki duruma bağlı,girişe değil.

hiç logic bilmediğini varsayarak ancak bu kadar sade anlatabildim.yazdığım kodda ufak bir hata var,ledin 4 bit olması lazım.ben bu kodları hazır template kullanarak yaptım,sadece gereken kısımları düzenledim.quartusta var,mutlaka ise de de vardır.

kralsam

Arkadaşım birde yaygın olarak FPGA içine işlemci gömüp onun üzerine C ile program yazıp kullanıyorlar. Ben hiç kullanmadım. FPGA mantıpına ters geliyor ama çok kişi kullanıyor. Belki onun ile de çalışabilirsin. Aklında bulunsun. Örneğin Altera da Nios işlemci kullanılıyor. Xilinx in yaptığını hatırlayamadım.

vitruvius

Hocam o işe belki sonra girerim. Şu an temeli sağlam tutmak istiyorum. Berat23'ün verdiği kodun mantığını anladım ama bu elsif (rising_edge(clk)) then satırı ne işlem yapıyor? Bir de when komutu nasıl kullanılıyor onu anlayamadım.

kralsam

rising_edge yükselen kenarda tetiklendiği anlamına geliyor. when ise if else gibi koşul bloğu ama kombinasyonel. Eğer temelden devam edeceksen Morris Mono diye bir adamındı sanırım. Türkçe'ye çevrilmişide vardı sanırm, Sayısal tasarım diye. Ona bakmanı öneririm. Herşeyden önce lojik bilgin çok iyi olmalı.

berat23

Alıntı yapılan: vitruvius - 25 Şubat 2012, 14:03:04
Hocam o işe belki sonra girerim. Şu an temeli sağlam tutmak istiyorum. Berat23'ün verdiği kodun mantığını anladım ama bu elsif (rising_edge(clk)) then satırı ne işlem yapıyor? Bir de when komutu nasıl kullanılıyor onu anlayamadım.

when, bir nevi mux denilebilir.C deki karşılığı case gibi.

vitruvius

Hocam verdiğiniz örnek kodu bir kere okudum, mantığını anladım. Anladığım kadarıyla tekrar yazdım kodumu. Sonra sizinkiyle de karşılaştırdım son process hariç bir fark göremedim.

Program istediğim gibi çalışmıyor. Ledler sırayla yanmıyor. Resete bastığımda en başa dönüyor ama sonra yine kafasına göre devam ediyor. Bir de butona her bastığımda elimi çekene kadar 4 led kısık bir şekilde yanıyor. Sorun nerede acaba? İsterseniz video koyabilirim. Teşekkürler.

Vhdl kodum:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity butonveswitch is
    Port ( buton : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           led1 : out  STD_LOGIC;
			  led2 : out  STD_LOGIC;
			  led3 : out  STD_LOGIC;
			  led4 : out  STD_LOGIC;
           clk : in  STD_LOGIC);
end butonveswitch;

architecture Behavioral of butonveswitch is

type state_type is (s0,s1,s2,s3);
signal state : state_type;

begin

	process(clk,reset)
	begin
		if reset='1' then
		state <= s0;
			elsif (rising_edge(clk)) then
				case state is
					when s0 =>
						if buton='1' then
							state <= s1;
						else
							state <= s0;
						end if;
					when s1 =>
						if buton='1' then
							state <= s2;
						else
							state <= s1;
						end if;
					when s2 =>
						if buton='1' then
							state <= s3;
						else
							state <= s2;
						end if;
					when s3 =>
						if buton='1' then
							state <= s0;
						else
							state <= s3;
						end if;
				end case;
		end if;
	end process;
	
	process (state)
	begin
		case state is
			when s0 =>
				led1<='1';
				led2<='0';
				led3<='0';
				led4<='0';
			when s1 =>
				led1<='0';
				led2<='1';
				led3<='0';
				led4<='0';
			when s2 =>
				led1<='0';
				led2<='0';
				led3<='1';
				led4<='0';
			when s3 =>
				led1<='0';
				led2<='0';
				led3<='0';
				led4<='1';
		end case;
	end process;		

end Behavioral;


Bu da .ucf:

# PlanAhead Generated physical constraints 

NET "buton" LOC = D18;
NET "clk" LOC = C9;
NET "led1" LOC = F9;
NET "led2" LOC = E9;
NET "led3" LOC = D11;
NET "led4" LOC = C11;
NET "reset" LOC = H13;

# PlanAhead Generated IO constraints 

NET "buton" IOSTANDARD = LVTTL;
NET "clk" IOSTANDARD = LVCMOS33;
NET "led1" IOSTANDARD = LVTTL;
NET "led2" IOSTANDARD = LVTTL;
NET "led3" IOSTANDARD = LVTTL;
NET "led4" IOSTANDARD = LVTTL;
NET "reset" IOSTANDARD = LVTTL;
NET "buton" PULLDOWN;
NET "reset" PULLDOWN;
NET "clk"  period = 20 ns high 50 %;


Hocam bir de bir şey soracağım:

led <= "0100";
Bu satır ne demek oluyor? Yani led vektörünü 4 downto 0 tanımladınız. 3. led'in "1", diğerlerinin "0" olması durumunu mu belirtiyor? Yani benim şu satırlarımla aynı şey mi oluyor?

led1<='0';
led2<='0';
led3<='1';
led4<='0';


Teşekkür ederim.

yamak

Kodlarınız doğru sorun yaratan şey butonları debounce yapılmamış olması.Yani siz butona bir kere basıyosunuz fakat tasarladığınız devre onu 1 den fazla basılmış olarak algılıyo. Siz butona bastığınız aşağıdaki gibi bir sinyal oluşuyo yani.


Bu durumu önlemek için de ayrica bir debouncing devresi tasarlamanız gerekiyo. Bir de yapmaya çalıştığınız şeyi isterseniz
led<=led(2 downto 0)&'1' tarzı bi kod ile daha basit bir şekilde yapabilrsiniz.

vitruvius

Ah doğru hocam sizin bir başlığınızda okumuştum. Teşekkür ederim ona göre bir debounce devresi tasarlarım akşam.

pic365

Konu açıklığa kavuşmuş ama ben de variable ile ilgili birkaç ekleme yapayım. Process içinde variable tanımlandığı zaman sadece o process içinde kullanılabiliyor. Eğer birden fazla process'te kullanacaksanız, tanım process'in dışında (signal'ların tanımlandığı yerde) shared variable şeklinde yapılıyor. Diğer yandan RTL'de variable kullanmak benim pek tercih ettiğim bir şey değil, sadece testbench'te kullanıyorum. Çünkü yazımı kolaylaştırsa da hata olasılığını artırıyor.