FPGA Verilog – Refleks Ölçer

Merhaba arkadaşlar, bu yazımızda sizlere Marmara Üniversitesi Digital Design dersinin dönem sonu projesi olarak geliştirdiğimiz refleks ölçer projesinden bahsedeceğiz ve gerekli kaynak kodları sağlayacağız.

Refleks Ölçer Nedir ve Nerelerde Kullanılır?

Refleks ölçerin çalışma mantığında belli bir süre geçmesinin ardından bir uyarıcının gösterilmesi yer alır. Bu bir ses veya görüntü olabilir. Kullanan kişi bu uyarıcı alır almaz bir düğmeye basmalı, bir hareket yapmalı veya bir şey söylemelidir. Bu araç sayesinde kullanan kişinin harekete geçme süresi ölçülebilir.

Refleks ölçerler ise özellikle maraton koşucuların da zil ile yarışa başlama sürelerini ölçmede ve kısaltmada, drag yarışlarında yeşil ışık yandıktan sonra gaza basılma süresini ölçmede ve kısaltmada ve bilimsel çalışmalarda kas ile beyin arasındaki iletişimin süresini ölçmede kullanılır.

Refleks Ölçer Tanıtım Videosu

Projenin Ana Çalışma Mantığı

Projemizde ana ekipman olarak 3 adet düğme, 3 adet LED, 7-Segment ve bir adet başlatıcı kapasitif sensör bulunuyor. Kapasitif sensöre dokunulduğunda yaklaşık olarak 3 saniye geçtikten sonra random olarak 3 LED’den birisi yanıyor. LED yandığı anda 0.1ms hassasiyetine sahip olan sayacımız devreye giriyor ve 7-Segment’de geçen süreyi gösteriyor. Siz LED’in karşılık geldiği düğmeye bastığınız anda ise sayaç duruyor ve sizin LED yanmasının ve düğmeye basmanızın ardından geçen süreyi gösteriyor. 

Projenin görsel çizimi / Quartus Prime 18.1

Kullanılan Malzemeler

  • FPGA Altera De2-115
  • 4 Adet 7-Segment LED /Kart üzerinde bulunuyor.
  • 3 Adet 10mm LED
  • 3 Adet Buton
  • TTP223B Dijital Dokunma Sensörü

Kod Algoritma Mantığı ve Kullanılan Program

Projeye başlarken ki amacımız olabildiğince verimli ve hassas çalışan bir refleks ölçer yapmak olmuştu. Bunun için FPGA kartı kullanarak kodlamanın da büyük bir kısmını kapı düzeyinde yazarak bu amacımıza ulaştık. Kodlamada 4 adet modül kullanıyoruz. Kodu yazmak ve gözlemlemek için kullandığımız program Quartus Prime 18.1

  • Random Number Module -> Bu modülün çalışma mantığı programı başlatır başlatmaz arka plan 1 ila 3 arasında bir sayı dönüyor. Kapasitif sensöre dokunulduğu anda ise o sıra arka planda hangi sayı varsa onu seçiyor ve ona göre bir LED yanıyor.  
  • 7- Segment Module -> Burada Clock sinyalinden gelen sinyali sayarak iç içe if yapıları kullanarak sayma işlemini gerçekleştiriyoruz. Clock sinyalini keserek saati durdurabiliyoruz.
  • Clock Module -> Bu kısım clock sinyalini üretiyor. Daha ayrıntılı anlatılacak.
  • Main Module -> Tüm modüllerin bağlandığı kısım reset gibi komutlar burada duruyor.

Clock Module Çalışma Mantığı

Bu kısım genelde kafa karıştıcı olduğu için daha ayrıntılı anlatalım dedik. Bizim kullandığımız Altera De2-115’in içerisindeki clock hızı 50MHz. Peki 50MHz neyi ifade ediyor? Bizim kare sinyalimiz 1 saniyede 50.000.000 kere yukarı çıkıp aşağı iniyor demek. Yani 1 saniyede 25.000.000 kere yukarı çıkıyor. Buna posedge deniyor. Bizde sayacımızda bu posedge’leri sayıyoruz. Eğer sayaç 25.000.000 olursa ms_clock 0 iken 1 oluyor. Yani kare sinyalimiz posedge oldu. Böylece 50Mhz clock’u 1Hz’e dönüştürmüş oluyor. Not: Aşağıda ms_clock yazıyor ama bu kod 1 saniyeye çevirmek için.

2Hz sinyalin 1Hz sinyaline dönüştürülmesi. Kırmızı yerler posedge’ler.
module s_clock(clock, ms_clock);

	input clock;
	output ms_clock;
	reg ms_clock;
	reg [0:27] count;
	
	//Generate 100 Hz clock from a 50 mHz clock input
	always @ (posedge clock)
		begin
			count <= count + 1;
			if (count == 25000000) //1000ms  -> 0.001
				begin
					ms_clock <= ~ms_clock;
					count <= 0;
				end
		end
endmodule

Tüm Kod

///RESPONSE TIME METER - 3LED 4BUTTON
//YUSUF SAVAŞ
//ALPER SARIÇAM


module SP(clk,button0,button1,button2,button3,reset_button,ledo0,ledo1,ledo2,ledo3,ledo4,ledo5,ledo6,HEX0, HEX1, HEX2, HEX3, HEX4, HEX5);

//Button0 -> Main-Start Button
//Button1,2,3 -> Red,Green,Blue Buttons
//Led0,1,2 -> Red,Green,Blue Leds,
//Led2,3,4,5,6 -> Debugging Leds /No need to connect.
//Hex4,5 -> For visual purpose. 

input clk,button0,button1,button2,button3,reset_button;
output ledo0,ledo1,ledo2,ledo3,ledo4,ledo5,ledo6;
output [0:6] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5;

wire [1:0] KEY;
wire wire1,wire2,wire3;
wire pause,stopwatch_start;

//Key[1] -> Reset
//Key[0] -> Pause

random_number rnd1(clk,button0,reset_button,ledo0,ledo1,ledo2,ledo3,ledo4,ledo5,ledo6);

and a1(wire1,ledo0,button1);
and a2(wire2,ledo1,button2);
and a3(wire3,ledo2,button3);
or or1(pause,wire1,wire2,wire3);

or(stopwatch_start,ledo0,ledo1,ledo2);

assign KEY[0] = ~pause;
assign KEY[1] = stopwatch_start;

segment_hex hex1(clk, KEY, HEX0, HEX1, HEX2, HEX3, HEX4, HEX5);

endmodule



////////////////////////////////////////////////////////////////////////////////
//////////////////////7SEGMENTHEX///////////////////////////////////////////////


module segment_hex(CLOCK_50, KEY, HEX0, HEX1, HEX2, HEX3, HEX4, HEX5);

//Binary_Coded_Decimal -> BCD
//Key[1] -> Reset
//Key[0] -> Pause /Pause is working by toggling.
//Clock_50 -> 50Mhz

	input CLOCK_50; //50Mhz Clock
	input [1:0] KEY;  //Key1 and Key2
	output [0:6] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5; //4 Hex for Digits 2 Hex for Alphabet
	
	wire ms_clk;    
	wire tenths_in, ones_in, tens_in;
	wire [3:0] hundredths_bcd, tenths_bcd, ones_bcd, tens_bcd;
	
	ms_clock ms_clock1(CLOCK_50, clk); //50Mhz to 1ms(clk)
	
	ms_clock_switched ms_clock_switched1(clk, KEY[0], ms_clk); //Key 0 stops the watch ->ms_clock is the new_clock
	
	bcd_counter bcd_counter_hundredths(ms_clk, KEY[1], hundredths_bcd[3:0], tenths_in); // xxx9 [3:0]-> Because 4 bit. 1001->9
	bcd_counter bcd_counter_tenths(tenths_in, KEY[1], tenths_bcd[3:0], ones_in); //xx9x
	bcd_counter bcd_counter_ones(ones_in, KEY[1], ones_bcd[3:0], tens_in); //x9xx
	bcd_counter bcd_counter_tens(tens_in, KEY[1], tens_bcd[3:0], );  //9xxx
	
	seven_segment_decoder seven_segment_decoder_hundredths(hundredths_bcd[3:0], HEX0[0:6]); //Hex0 Decoder
	seven_segment_decoder seven_segment_decoder_tenths(tenths_bcd[3:0], HEX1[0:6]);
	seven_segment_decoder seven_segment_decoder_ones(ones_bcd[3:0], HEX2[0:6]);
	seven_segment_decoder seven_segment_decoder_tens(tens_bcd[3:0], HEX3[0:6]);
	
	//Turn the unused displays off
	assign HEX4[0:6] = 7'b0100100;
	assign HEX5[0:6] = 7'b0110000;
	
endmodule




module bcd_counter(clock, reset, bcd, next);

	input clock, reset;
	output bcd, next;
	reg [3:0] bcd;
	reg next;
	wire not_reset;
	not(not_reset, reset);
	
	always @(posedge clock or posedge not_reset)
		begin
			if (not_reset == 1)
				bcd <= 0;
			else
			begin
				bcd <= bcd + 1;
				next <= 0;
				if (bcd > 8)
					begin
						bcd <= 0;
						next <= 1; //if xxx9 --> xx10
					end
			end
		end
endmodule

//CLOCK MODULE 1-Miliseconds Delay
module ms_clock(clock, ms_clock);

	input clock;
	output ms_clock;
	reg ms_clock;
	reg [0:17] count;
	
	//Generate 100 Hz clock from a 50 mHz clock input
	always @ (posedge clock)
		begin
			count <= count + 1;
			if (count == 25000) //1ms 
				begin
					ms_clock <= ~ms_clock;
					count <= 0;
				end
		end
endmodule

module ms_clock_switched(ms_clock, control, ms_clock_switched);

	input ms_clock, control;
	output ms_clock_switched;
	reg ms_clock_switched;
	reg state; //0 paused, 1 active
	
	//Basic state machine for toggleing the clock
	always @ (negedge control)
		state <= ~state;
	
	always @ (ms_clock)
		begin
			if (state == 0)
				ms_clock_switched <= 0;
			else
				ms_clock_switched <= ms_clock;
		end
endmodule

module seven_segment_decoder(bcd[3:0], HEX[0:6]);

//Binary Number to 7-Segment Number.

	input [3:0] bcd;
	output [0:6] HEX;
	reg [0:6] HEX;
	
	always @ (bcd)
		case(bcd)
			4'b0000:HEX[0:6] = 7'b0000001; //0
			4'b0001:HEX[0:6] = 7'b1001111; //1
			4'b0010:HEX[0:6] = 7'b0010010; //2
			4'b0011:HEX[0:6] = 7'b0000110; //3
			4'b0100:HEX[0:6] = 7'b1001100; //4
			4'b0101:HEX[0:6] = 7'b0100100; //5
			4'b0110:HEX[0:6] = 7'b0100000; //6
			4'b0111:HEX[0:6] = 7'b0001111; //7
			4'b1000:HEX[0:6] = 7'b0000000; //8
			4'b1001:HEX[0:6] = 7'b0001100; //9
			default: HEX[0:6] = 7'b1111111; //Empty
		endcase
endmodule


///////////////////////7SEGMENTHEX///////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////




/////////////////////////////////////////////////////////////////////////////////
/////////////////////////RANDOM_NUMBER////////////////////////////////////////////


module random_number(input clk,button_input,button_input2,output ledo0,ledo1,ledo2,ledo3,ledo4,ledo5,ledo6);
reg led0,led1,led2,led3,led4,led5,led6;
reg button1;
//assign button = button_input;
reg selectedpin;
reg selectedpin_assign;
reg[1:0] selectedled;
reg[1:0] randcounter;
wire resetor;

// initial 
//     begin 
//      button <= 1'b0;
//		led0 <= 1'b0;
//		led1 <= 1'b0;
//		led2 <= 1'b0;
//		randcounter <= 2'b00;
//     end


wire new_clock;
or or1(resetor,~selectedpin,button_input2);
and a1(new_clock,clk,resetor); //if selectedpin is 1 stop the controlling(clock)


always @ (posedge new_clock)
begin


////////////////////////////////////////RESET

if (button_input2 == 1'b1) //Reset İf
 begin
  selectedpin <= 1'b0;
//  selectedled <= randcounter; 
  led6 <= 1'b1; //led6 Debugg
//  delay_count <= 4'b0000;
//  delay_completed <= 1'b0;
//  
 end 
else
begin
led6 <= 1'b0; 
end

////////////////////////////////////////RESET



button1 <= button_input;

if (randcounter == 2'b11)
begin
randcounter <= 2'b00;
end
else
begin
randcounter <= randcounter + 1'b1;
end


if (button_input == 1'b1)
 begin
  selectedpin <= 1'b1;
  selectedled <= randcounter; 
  led5 <= 1'b1; //led5 Debugg
 end 
else 
begin 
  selectedpin <= 1'b0; //1 kalmalı yoksa buton mantıgı olmuyor.
  selectedled <= 2'b11; 
  led5 <= 1'b0; //led5 Debugg
 end

end

s_clock clocke1(clk,ms_clock); //Uptade the clock


reg[3:0] delay_count;
reg delay_completed;



//LED SELECT Always
always @ (posedge ms_clock)
begin
led4 <= 1'b1;
//delay_count <= delay_count +1;


////////////////////////////////////////RESET

if (button_input2 == 1'b1) //Reset İf
 begin
  //selectedpin <= 1'b0;
//  selectedled <= randcounter; 
//  led6 <= 1'b1; //led6 Debugg
delay_count <= 4'b0000;
delay_completed <= 1'b0;
//  
 end 
else
begin
//led6 <= 1'b0; 
end

////////////////////////////////////////RESET


if (selectedpin == 1'b1) //Eger dugmeye basıldıysa delay_count artsın
begin 
 delay_count <= delay_count + 1'b1;
  if (delay_count == 4'b0100) //4second is passed
       begin  delay_completed <= 1'b1;
		  led3 <= 1'b1; //debug_led
		 end 
	else if(delay_count > 4'b1010) //8second is passed delay->0
	begin
	//delay_completed <= 1'b0;
	led3 <= 1'b0; //debu_led
    end
end
else 
begin
//Kodgelecek
end
	 
	 
	 
if( delay_completed == 1'b1 & selectedpin == 1'b1 &  (selectedled == 2'b00 | selectedled == 2'b11)) //led0
begin
   led0 <= 1'b1;
	led1 <= 1'b0;
   led2 <= 1'b0;
   
end
else if ( delay_completed == 1'b1 & selectedpin == 1'b1 &  selectedled == 2'b01 ) //led1
begin
  led1 <= 1'b1;
  led0 <= 1'b0;
  led2 <= 1'b0;
  
end
else if ( delay_completed == 1'b1 & selectedpin == 1'b1 &  selectedled == 2'b10 ) //led2
begin
   led2 <= 1'b1;
	led0 <= 1'b0;
   led1 <= 1'b0;
end
else
begin 
led0 <= 1'b0;
led1 <= 1'b0;
led2 <= 1'b0;
led4 <= 1'b1; //debugg
end 


end

    assign ledo0=led0;
	 assign ledo1=led1;
	 assign ledo2=led2;
    assign ledo3=led3;
	 assign ledo4=led4;
	 assign ledo5=led5;
    assign ledo6=led6;
	 endmodule

	 	 
//CLOCK MODULE 1-Seconds delay
module s_clock(clock, ms_clock);

	input clock;
	output ms_clock;
	reg ms_clock;
	reg [0:27] count;
	
	//Generate 100 Hz clock from a 50 mHz clock input
	always @ (posedge clock)
		begin
			count <= count + 1;
			if (count == 25000000) //1000ms  -> 0.001
				begin
					ms_clock <= ~ms_clock;
					count <= 0;
				end
		end
endmodule


//////////////////////////RANDOM_NUMBER/////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Tools -> Netlist -> RTL Viewer

Aşağıdaki dropbox linkinden tüm projeyi, proje dosyasını ve kodlarının yanı sıra tüm Digital Design dersinde yapmış olduğumuz projeleri, ödevleri, araştırmaları ve vize notlarını indirebilirsiniz.


Projenin sonuna gelmiş bulunuyoruz eğer herhangi bir sorunuz varsa Hakkımda bölümünden veya aşağıya cevap yazarak bana ulaşabilirsiniz. Bir sonraki projede görüşmek üzere.

Etiket(ler): , , .Yer işareti koy Kalıcı Bağlantı.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir