Vhdl'de case ve when kullanımı

Başlatan vitruvius, 01 Nisan 2012, 02:02:14

vitruvius

Circuit Designs with VHDL kitabında case ve when konularını okuduktan sonra bu ikisiyle bir yürüyen ışık yapayım dedim ama olmadı. Programı çalıştırdığımda bütün ledler yanıyor. Sorun nedir acaba? Teşekkürler.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;


entity deneme1 is
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
           led : out  STD_LOGIC_VECTOR (7 downto 0));
end deneme1;

architecture Behavioral of deneme1 is

begin

process (clk,rst)
	variable say:integer;
	begin		
		if (rst='1') then
			led <= "00000000";
		elsif(clk'event and clk='1') then
			say := say+1;
				case say is
					when 1000=>led<="00000001";
					when 2000=>led<="00000010";
					when 3000=>led<="00000100";
					when 4000=>led<="00001000";
					when 5000=>led<="00010000";
					when 6000=>led<="00100000";
					when 7000=>led<="01000000";
					when 8000=>led<="10000000";
					when 9000=> say:=0;
					when others => null;
				end case;
		end if;
			
end process;

end Behavioral;

yamak

Çünkü süreyi çok kısa tutuyosun yani o 1000 2000 3000 ... i 20000000,3000000,4000000 civarında yaparsan olması lazım

vitruvius

Tamamdır hocam bir an için 50MHz'i unutmuşum. Süreyi uzatınca çalıştı.

vitruvius

Hocam iki process 4+4 led ile oynayayım dedim. Aslında hedefim lcd'ye geçmek de şu clock olayını bir oturtmadan lcd'ye geçmek istemiyorum. say:=say+1 kısmını nereye koyacağımı çözemedim. Sorun orada da olmayabilir de...

if(start1='1') then satırından sonra koymayı denemiştim ilk. Start'a bastığımda saymaya başlasın ve olaylar devam etsin diye. O şekilde yapınca butona her bastığımda ışıklar yürüyor. İstediğim gibi olmuyor.

elsif (clk'event and clk='1') then satırından sonra koymak da mantıklı geliyor ama o zaman ben start'a 10 sn sonra basarsam say değişkeni alır başını gider gibi geliyor. O şekilde yaptığımda butonlara bastığımda ledlerde yanma olmuyor.

Basit şeyler ama can sıkıyor işte. =/ Teşekkür ederim.


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;


entity deneme2 is
    Port ( clk : in  STD_LOGIC;
           start1 : in  STD_LOGIC;
           start2 : in  STD_LOGIC;
           rst1 : in  STD_LOGIC;
           rst2 : in  STD_LOGIC;
           led1 : out  STD_LOGIC_VECTOR (3 downto 0);
           led2 : out  STD_LOGIC_VECTOR (3 downto 0));
end deneme2;

architecture Behavioral of deneme2 is

begin

U1: process(clk,rst1)
		variable say1:integer;		
			begin
				if(rst1='1') then
				led1 <= "0000";
				say1:=0;
					elsif (clk'event and clk='1') then					
						if(start1='1') then
						say1:=say1+1;
							case say1 is
								when 25000000  =>led1<="0001";
								when 50000000  =>led1<="0010";
								when 75000000  =>led1<="0100";
								when 100000000 =>led1<="1000";	
								when 125000000 =>say1:=0;
								when others => null;
							end case;
						end if;
				end if;
			end process U1;
			
	U2: process(clk,rst2)
		variable say2:integer;
			begin
				if(rst2='1') then
				led2 <= "0000";
				say2:=0;
					elsif (clk'event and clk='1') then					
						if(start2='1') then	
						say2:=say2+1;
							case say2 is
								when 25000000  =>led2<="1000";
								when 50000000  =>led2<="0100";
								when 75000000  =>led2<="0010";
								when 100000000 =>led2<="0001";	
								when 125000000 =>say2:=0;
								when others => null;
							end case;
						end if;
				end if;
			end process U2;


end Behavioral;

yamak

when others=>null satırını sil. Çünkü öyle yaparsan ledler sadece say değişkenin belli değerlerinde yanacak gerisinde yanmayacak.Bir de start sinyali butona mı bağlı switch e mi?

vitruvius

O satırı silince şu hatayı alıyorum hocam: 'others' is missing in case with 'integer' selector. O hatayı önlemek için koymuştum o satırı zaten. Startlar da butona bağlı.

yamak

O zaman şöyle yap when others=>led1<=led1;

vitruvius

Hocam o zaman da Object led1 of mode OUT can not be read hatasını alıyorum.

yamak

Oyle derken direk çıkışlarla işlem yapmanı kastetmemiştim. İlk olarak led_in1,led_in2 diye iki signal tanımla. process in içinde bunları kullan process in dışında da led1<=led_in1;
led2<=led_in2;
ataması yap.

vitruvius

Hocam galiba istediğiniz gibi yazamadım kodu çünkü niye böyle bir yönteme başvurduğumuzu ve bu yöntemin ilk verdiğim koddan farkını anlayamadım. Sonuç da yine aynı oldu. Others kısmına ne yazacağız ayrıca?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;


entity deneme2 is
    Port ( clk : in  STD_LOGIC;
           start1 : in  STD_LOGIC;
           start2 : in  STD_LOGIC;
           rst1 : in  STD_LOGIC;
           rst2 : in  STD_LOGIC;
           led1 : out  STD_LOGIC_VECTOR (3 downto 0);
           led2 : out  STD_LOGIC_VECTOR (3 downto 0));
end deneme2;

architecture Behavioral of deneme2 is
signal led_in1:std_logic_vector(3 downto 0);
signal led_in2:std_logic_vector(3 downto 0);
begin

U1: process(clk,rst1)
		variable say1:integer;		
			begin
				if(rst1='1') then
				led_in1 <= "0000";
				say1:=0;
					elsif (clk'event and clk='1') then					
						if(start1='1') then
						say1:=say1+1;
							case say1 is
								when 25000000  =>led_in1<="0001";
								when 50000000  =>led_in1<="0010";
								when 75000000  =>led_in1<="0100";
								when 100000000 =>led_in1<="1000";	
								when 125000000 =>say1:=0;
								when others =>
							end case;
						end if;
				end if;
			end process U1;
		led1<=led_in1;
			
	U2: process(clk,rst2)
		variable say2:integer;
			begin
				if(rst2='1') then
				led_in2 <= "0000";
				say2:=0;
					elsif (clk'event and clk='1') then					
						if(start2='1') then	
						say2:=say2+1;
							case say2 is
								when 25000000  =>led_in2<="1000";
								when 50000000  =>led_in2<="0100";
								when 75000000  =>led_in2<="0010";
								when 100000000 =>led_in2<="0001";	
								when 125000000 =>say2:=0;
								when others =>
							end case;
						end if;
				end if;
			end process U2;
		led2<=led_in2;


end Behavioral;

speak48

start girişinin ne? önemli olan bu burdaki tasarım start sürekli birse çalışır bu yüzden start girişlerini bir siwitch e bağlaman gerekekir.
eğer sen bunu button ile kotnrol etmek istiyorssan bir tanede başladığını belirten bir değişken tanımlamalısın ve durma özelliğinide belirmen gerekir.
tek butonla start stop özelliğide olabilir.

vitruvius

Doğru dediniz hocam düşünememişim o kısmı. Ama şimdi çözümü bulamadım yine aynı şey olacak benim aklımdakilere göre. Mesela bir değişken tanımlayıp start '1' ise buna 5 gibi bir değer atayayım. Aşağıda if(x=5) satırıyla kontrol edip olaylar döngüsünü başlatmak geldi aklıma. Ama böyle yapsam da yine aynı hatayı yapmış olmayacak mıyım? O değer sadece butona bastığım anda 5 olacaktır, bunu nasıl genelleyebilirim?

speak48

verilogla  yazdım tek butonla start stop özelliği ekledim ,ledleri ayrı değilde bütün yaptım .
burada programlama  dili mantığıyla dünürsek herzaman ufak sandığımız hatalar çıkacaktır çözümü donanım tanımlama diliyle yazdığımızı unutmamaktır.
bunu söylerken bende 1 yıl boyunca hatalar aradıktan sonra promlemi kökünden mantığı kurarak kaldırabildim.

module led( 
   // Port Declarations
   input   wire      clk, 
   input   wire      rst, 
   input   wire      ss, 
   output  reg  [7:0]   led1   
);

reg ssi;
reg sso;
reg basladi;
reg [32:0] zmnsay;
reg [1:0] drmsay;

always@(posedge clk or posedge rst)
begin
	if(rst) 
		begin
			basladi<=0;
			ssi<=0;
			sso<=0;
			zmnsay<=0;
			drmsay<=0;
		end
	else
		begin
			if(ss)
				ssi<=1;
			else
				ssi<=0;
				
			sso<=ssi;
			
			if(sso&~ssi)
				basladi<=~basladi;
			else
				basladi<=basladi;
			
			if(basladi)
				begin
					zmnsay<=zmnsay+1;
					
					if(zmnsay==25000000)
						begin
							drmsay<=drmsay+1;
							zmnsay<=0;
						end
	
					case(drmsay)
						0: led1<=8'b10000001;
						1: led1<=8'b01000010;
						2: led1<=8'b00100100;
						3: led1<=8'b00011000;
						default: ;
					endcase
		
				end

		end
	
end
endmodule // led