學習筆記:FPGA之數字時鐘設計與實現

       數字時鐘我們分爲四個子模塊:一個是按鍵模塊(主要用來按鍵輸入和按鍵去抖動),一個計數器模塊(主要用於時分秒的計數),一個LED數碼管顯示模塊(主要用於時分秒數字顯示),一個蜂鳴器模塊(根據按鍵的不同,發出不同頻率的聲音)。

設計的RTL圖如下:

各模塊源碼如下:

//--	描述		:	用外設實現數字電子時鐘頂層文件

//---------------------------------------------------------------------------
module A4_Clock_Top
(
	//輸入端口
	CLK_50M,RST_N,KEY,LED,
	//輸出端口
	SEG_EN,SEG_DATA,BEEP
);

//---------------------------------------------------------------------------
//--	外部端口聲明
//---------------------------------------------------------------------------
input 				CLK_50M;					//時鐘端口
input 				RST_N;					//復位端口						
input	 	[ 7:0]	KEY;						//按鍵端口
output 				BEEP;						//蜂鳴器端口
output 	[ 7:0]	LED;						//LED端口
output 	[ 5:0]	SEG_EN;					//數碼管使能端口
output 	[ 7:0]	SEG_DATA;				//數碼管端口

//---------------------------------------------------------------------------
//--	內部端口聲明
//---------------------------------------------------------------------------
wire		[ 3:0] 	hours2_data;			//時鐘高4位數據
wire		[ 3:0] 	hours1_data;			//時鐘低4位數據
wire		[ 3:0] 	minutes2_data;			//分鐘高4位數據
wire		[ 3:0] 	minutes1_data;			//分鐘低4位數據
wire		[ 3:0] 	seconds2_data;			//秒鐘高4位數據
wire		[ 3:0] 	seconds1_data;			//秒鐘低4位數據
wire 		[ 7:0] 	key_out;					//消抖完畢輸出

//---------------------------------------------------------------------------
//--	邏輯功能實現	
//---------------------------------------------------------------------------
//例化時鐘計時模塊
Counter_Module		Counter_Init
(
	.CLK_50M			(CLK_50M			),		//時鐘端口
	.RST_N			(RST_N			),		//復位端口
	.LED				(LED				),		//按鍵端口
	.key_out			(key_out			),		//消抖完畢輸入
	.hours2_data	(hours2_data	),		//時鐘高4位數據
	.hours1_data	(hours1_data	),		//時鐘低4位數據
	.minutes2_data	(minutes2_data	),		//分鐘高4位數據
	.minutes1_data	(minutes1_data	),		//分鐘低4位數據
	.seconds2_data	(seconds2_data	),		//秒鐘高4位數據
	.seconds1_data	(seconds1_data	)		//秒鐘低4位數據
);

//---------------------------------------------------------------------------
//例化數碼管模塊
Segled_Module		Segled_Init
(
	.CLK_50M			(CLK_50M			),		//時鐘端口
	.RST_N			(RST_N			),		//復位端口
	.hours2_data	(hours2_data	),		//時鐘高4位數據
	.hours1_data	(hours1_data	),		//時鐘低4位數據
	.minutes2_data	(minutes2_data	),		//分鐘高4位數據
	.minutes1_data	(minutes1_data	),		//分鐘低4位數據
	.seconds2_data	(seconds2_data	),		//秒鐘高4位數據
	.seconds1_data	(seconds1_data	),		//秒鐘低4位數據
	.SEG_EN			(SEG_EN			),		//數碼管使能端口
	.SEG_DATA		(SEG_DATA		)		//數碼管端口
);

//---------------------------------------------------------------------------
//例化蜂鳴器模塊
Beep_Module			Beep_Init
(
	.CLK_50M			(CLK_50M			),		//時鐘端口
	.RST_N			(RST_N			),		//復位端口
	.BEEP				(BEEP				),		//蜂鳴器端口
	.KEY				(KEY				)		//沒有消抖輸入
);

//---------------------------------------------------------------------------
//例化按鍵消抖模塊
Key_Module			Key_Init
(
	.CLK_50M			(CLK_50M			),		//時鐘端口
	.RST_N			(RST_N			),		//復位端口
	.KEY				(KEY				),		//沒有消抖輸入
	.key_out			(key_out			)		//消抖完畢輸出
);
	
endmodule
//--	描述		:	按鍵消抖模塊

//---------------------------------------------------------------------------
module Key_Module
(
	//輸入端口
	CLK_50M,RST_N,KEY,
	//輸出端口
	key_out
);  
 
//---------------------------------------------------------------------------
//--	外部端口聲明
//---------------------------------------------------------------------------
input					CLK_50M;				//時鐘的端口,開發板用的50MHz晶振
input					RST_N;				//復位的端口,低電平復位
input		[ 7:0]	KEY;					//對應開發板上的KEY
output	[ 7:0]	key_out;				//對應開發板上的LED

//---------------------------------------------------------------------------
//--	內部端口聲明
//---------------------------------------------------------------------------
reg		[19:0]	time_cnt;			//用來計數按鍵延遲的定時計數器
reg		[19:0]	time_cnt_n;			//time_cnt的下一個狀態
reg		[ 7:0]	key_reg;				//用來接收按鍵信號的寄存器
reg		[ 7:0]	key_reg_n;			//key_reg的下一個狀態
reg		[ 7:0]	led_reg;				//用來控制LED亮滅的顯示寄存器			
reg		[ 7:0]	led_reg_n;			//led_reg的下一個狀態
wire		[ 7:0]	key_out;				//消抖完成輸出按鍵

//設置定時器的時間爲20ms,計算方法爲  (20*10^6)ns / (1/50)ns  50MHz爲開發板晶振
parameter SET_TIME_20MS = 27'd1_000_000;	

//---------------------------------------------------------------------------
//--	邏輯功能實現	
//---------------------------------------------------------------------------
//時序電路,用來給time_cnt寄存器賦值
always @ (posedge CLK_50M, negedge RST_N)
begin
	if(!RST_N)								//判斷復位
		time_cnt <= 20'h0;				//初始化time_cnt值
	else
		time_cnt <= time_cnt_n;			//用來給time_cnt賦值
end

//組合電路,實現20ms的定時計數器
always @ (*)
begin
	if(time_cnt == SET_TIME_20MS)		//判斷20ms時間
		time_cnt_n = 20'h0;				//如果到達20ms,定時計數器將會被清零
	else
		time_cnt_n <= time_cnt + 1'b1;//如果未到20ms,定時計數器將會繼續累加
end

//時序電路,用來key_reg寄存器賦值
always @ (posedge CLK_50M, negedge RST_N)
begin
	if(!RST_N)								//判斷復位
		key_reg <= 8'h11;					//初始化key_reg值
	else
		key_reg <= key_reg_n;			//用來給time_cnt賦值
end

//組合電路,每20ms接收一次按鍵的值
always @ (*)
begin
	if(time_cnt == SET_TIME_20MS)		//判斷20ms時間
		key_reg_n <= KEY;					//如果到達20ms,接收一次按鍵的值
	else
		key_reg_n <= key_reg;			//如果未到20ms,保持原狀態不變
end

assign key_out = key_reg & (~key_reg_n);	//判斷按鍵有沒有按下

	 
endmodule
//--	描述		:	時鐘計時模塊

//---------------------------------------------------------------------------
module Counter_Module
( 
	//輸入端口
	CLK_50M,RST_N,key_out,LED,
	//輸出端口
	hours2_data,hours1_data,minutes2_data,minutes1_data,seconds2_data,
	seconds1_data
);

//---------------------------------------------------------------------------
//--	外部端口聲明
//---------------------------------------------------------------------------
input 				CLK_50M;							//時鐘的端口,開發板用的50MHz晶振
input 				RST_N;							//復位的端口,低電平復位
input		[ 7:0]	key_out;							//按鍵端口
output	[ 7:0]	LED;								//LED端口
output 				hours2_data;					//時鐘高4位數據
output 				hours1_data;					//時鐘低4位數據
output 				minutes2_data;					//分鐘高4位數據
output 				minutes1_data;					//分鐘低4位數據
output 				seconds2_data;					//秒鐘高4位數據
output 				seconds1_data;					//秒鐘低4位數據

//---------------------------------------------------------------------------
//--	內部端口聲明
//---------------------------------------------------------------------------
reg		[26:0] 	time_seconds;					//秒鐘低位計數器
reg		[26:0] 	time_seconds_n;				//time_seconds的下一個狀態
reg		[ 3:0] 	seconds1_data;					//秒鐘低位數據寄存器1
reg		[ 3:0] 	seconds1_data_n;				//seconds1_data的下一個狀態
reg		[ 3:0] 	seconds2_data;					//秒鐘高位數據寄存器2
reg		[ 3:0] 	seconds2_data_n;				//seconds2_data的下一個狀態
reg		[ 3:0] 	minutes1_data;					//分鐘低位數據寄存器
reg		[ 3:0] 	minutes1_data_n;				//minutes1_data的下一個狀態
reg		[ 3:0] 	minutes2_data;					//分鐘高位數據寄存器
reg		[ 3:0] 	minutes2_data_n;				//minutes1_data的下一個狀態
reg		[ 3:0] 	hours1_data;					//時鐘低位數據寄存器
reg		[ 3:0] 	hours1_data_n;					//hours1_data一個狀態
reg		[ 3:0] 	hours2_data;					//時鐘高位數據寄存器
reg		[ 3:0] 	hours2_data_n;					//hours2_data一個狀態
reg					stop_reg;						//控制時鐘的開始和暫停
reg					stop_reg_n;						//stop_reg的下一個狀態

//設置定時器的時間爲1s,計算方法爲  (1*10^9) / (1/50)  50MHZ爲開發板晶振
parameter SEC_TIME_1S  = 27'd50_000_000;		

//---------------------------------------------------------------------------
//--	邏輯功能實現	
//---------------------------------------------------------------------------
//時序電路,用來給stop_reg寄存器賦值
always @ (posedge CLK_50M or negedge RST_N)
begin
	if(!RST_N)											//判斷復位
		stop_reg <= 1'b0;								//初始化stop_reg值
	else
		stop_reg <= stop_reg_n;						//用來給stop_reg賦值
end

//組合電路,用於控制數字時鐘的暫停與開始
always @ (*)
begin
	if(key_out[7])										//判斷KEY8有沒有按下
		stop_reg_n = ~stop_reg;						//當按鍵按下時,改變stop_reg寄存器的狀態
	else
		stop_reg_n = stop_reg;						//當按鍵沒有按下時,stop_reg保持原狀態不變
end
//---------------------------------------------------------------------------
//時序電路,用來給time_seconds寄存器賦值
always @ (posedge CLK_50M or negedge RST_N)
begin
	if(!RST_N)											//判斷復位
		time_seconds <= 1'b0;						//初始化time_seconds值
	else
		time_seconds <= time_seconds_n;			//用來給time_seconds賦值
end

//組合電路,實現1s的定時計數器
always @ (*)
begin
	if(time_seconds == SEC_TIME_1S)				//判斷1s時間
		time_seconds_n = 1'b0;						//如果到達1s,定時計數器將會被清零
	else if(stop_reg)									//判斷有沒有按下暫停
		time_seconds_n = time_seconds + 1'b1;	//如果沒有暫停,定時計數器將會繼續累加
	else
		time_seconds_n = time_seconds;			//否則,定時計數器將會保持不變
end	
//---------------------------------------------------------------------------
//時序電路,用來給seconds1_data寄存器賦值
always @ (posedge CLK_50M or negedge RST_N)
begin
	if(!RST_N)											//判斷復位
		seconds1_data <= 1'b0;						//初始化seconds1_data值
	else
		seconds1_data <= seconds1_data_n;		//用來給seconds1_data賦值
end

//組合電路,用來控制秒數個位的進位和清零
always @ (*)
begin
	if(time_seconds == SEC_TIME_1S | key_out[6] == 1'b1)	//判斷按鍵KEY7和判斷1s時間
		seconds1_data_n = seconds1_data + 1'b1;//如果按鍵按下或者到達1s,seconds1_data將會加1
	else if(seconds1_data == 4'd10)				//判斷seconds1_data有沒有達到10s
		seconds1_data_n = 1'b0;						//如果seconds1_data到達10s,seconds1_data將會被清零
	else			
	seconds1_data_n = seconds1_data;				//否則seconds1_data將會保持不變
end
//---------------------------------------------------------------------------
//時序電路,用來給seconds2_data寄存器賦值
always @ (posedge CLK_50M or negedge RST_N)
begin	
	if(!RST_N)											//判斷復位
		seconds2_data <= 4'd0;						//初始化seconds2_data值
	else
		seconds2_data <= seconds2_data_n;		//用來給seconds2_data賦值
end

//組合電路,用來控制秒數十位的進位和清零
always @ (*)
begin
	if(seconds1_data == 4'd10)						//判斷seconds1_data有沒有達到10s
		seconds2_data_n = seconds2_data + 1'b1;//如果seconds1_data到達10s,seconds2_data將會加1
	else if(seconds2_data == 4'd6)				//判斷seconds2_data有沒有達到60s
		seconds2_data_n = 1'b0;						//如果seconds2_data到達60s,seconds2_data將會被清零
	else
		seconds2_data_n = seconds2_data;			//否則seconds2_data將會保持不變
end
//---------------------------------------------------------------------------
//時序電路,用來給minutes1_data寄存器賦值
always @ (posedge CLK_50M or negedge RST_N)
begin
	if(!RST_N)											//判斷復位
		minutes1_data <= 4'd0;						//初始化minutes1_data值
	else
		minutes1_data <= minutes1_data_n;		//用來給minutes1_data賦值
end

//組合電路,用來控制分數個位的進位和清零
always @ (*)
begin
	if(seconds2_data == 4'd6 | key_out[5] == 1'b1)	//判斷按鍵KEY6和判斷1m時間
		minutes1_data_n = minutes1_data + 1'b1;//如果按鍵按下或者到達1m,minutes1_data將會加1
	else if(minutes1_data == 4'd10)				//判斷minutes1_data有沒有達到10m
		minutes1_data_n = 1'b0;						//如果minutes1_data達到10m,minutes1_data將會被清零
	else
		minutes1_data_n = minutes1_data;			//否則minutes1_data將會保持不變
end
//---------------------------------------------------------------------------
//時序電路,用來給minutes2_data寄存器賦值
always @ (posedge CLK_50M or negedge RST_N)
begin
	if(!RST_N)											//判斷復位
		minutes2_data <= 4'd0;						//初始化minutes2_data值
	else
		minutes2_data <= minutes2_data_n;		//用來給minutes2_data賦值
end

//組合電路,用來控制分數十位的進位和清零
always @ (*)
begin
	if(minutes1_data == 4'd10)						//判斷minutes1_data有沒有達到10m
		minutes2_data_n = minutes2_data + 1'b1;//如果minutes1_data達到10m,minutes2_data將會加1
	else if(minutes2_data == 4'd6)				//判斷minutes2_data有沒有達到60m
		minutes2_data_n = 1'b0;						//如果minutes2_data達到10m,minutes2_data將會被清零
	else
		minutes2_data_n = minutes2_data;			//否則minutes2_data將會保持不變
end
//---------------------------------------------------------------------------
//時序電路,用來給hours1_data寄存器賦值
always @ (posedge CLK_50M or negedge RST_N)
begin	
	if(!RST_N)											//判斷復位
		hours1_data <= 4'd2;							//初始化hours1_data值
	else
		hours1_data <= hours1_data_n;				//用來給hours1_data賦值
end

//組合電路,用來控制時數個位的進位和清零
always @ (*)
begin
	if(minutes2_data == 4'd6 | key_out[4] == 1'b1)	//判斷按鍵KEY5和判斷1h時間
		hours1_data_n = hours1_data + 1'b1;		//如果按鍵按下或者到達1h,hours1_data將會加1	
	else if((hours2_data == 4'd0 || hours2_data == 4'd1) && hours1_data == 4'd10 || (hours2_data == 4'd2 && hours1_data == 4'd4))
		hours1_data_n = 1'b0;						//如果hours2_data等於0,且hours1_data等於10,hours1_data將會被清零
															//如果hours2_data等於1,且hours1_data等於10,hours1_data將會被清零
															//如果hours2_data等於2,且hours1_data等於 4,hours1_data將會被清零
	else
		hours1_data_n = hours1_data;				//否則hours1_data將會保持不變
end
//---------------------------------------------------------------------------
//時序電路,用來給hours2_data寄存器賦值
always @ (posedge CLK_50M or negedge RST_N)
begin
	if(!RST_N)											//判斷復位
		hours2_data <= 1'b1;							//初始化hours2_data值
	else
		hours2_data <= hours2_data_n;				//用來給hours2_data賦值
end

//組合電路,用來控制時數十位的進位和清零
always @ (*)
begin
	if((hours2_data == 4'd0 || hours2_data == 4'd1) && hours1_data == 4'd10 || (hours2_data == 4'd2 && hours1_data == 4'd4))
		hours2_data_n = hours2_data + 1'b1;		//如果hours2_data等於0,且hours1_data等於10,hours1_data將會被清零
															//如果hours2_data等於1,且hours1_data等於10,hours1_data將會被清零
															//如果hours2_data等於2,且hours1_data等於 4,hours1_data將會被清零
	else if(hours2_data == 4'd3)							
		hours2_data_n = 1'b0;						//如果hours2_data等於3,hours2_data將會被清零
	else
		hours2_data_n = hours2_data;				//否則hours2_data將會保持不變
end
//---------------------------------------------------------------------------
assign LED = {seconds2_data,seconds1_data};	//將秒鐘低4位數據和秒鐘高4位數據賦值給LED端口

endmodule
//--	描述		:	蜂鳴器發聲模塊

//---------------------------------------------------------------------------
module Beep_Module
(
	//輸入端口
	CLK_50M,RST_N,KEY,
	//輸出端口
	BEEP
);

//---------------------------------------------------------------------------
//--	外部端口聲明
//---------------------------------------------------------------------------
input					CLK_50M;					//時鐘的端口,開發板用的50MHz晶振
input					RST_N;					//復位的端口,低電平復位
input 	[ 7:0]	KEY;						//按鍵端口
output				BEEP;						//蜂鳴器端口

//---------------------------------------------------------------------------
//--	內部端口聲明
//---------------------------------------------------------------------------
reg		[19:0]	time_cnt;				//用來控制蜂鳴器發聲頻率的定時計數器
reg		[19:0]	time_cnt_n;				//time_cnt的下一個狀態
reg		[15:0]	freq;						//各種音調的分頻值
reg					beep_reg;				//用來控制蜂鳴器發聲的寄存器
reg					beep_reg_n;				//beep_reg的下一個狀態

//---------------------------------------------------------------------------
//--	邏輯功能實現	
//---------------------------------------------------------------------------
//時序電路,用來給time_cnt寄存器賦值
always @ (posedge CLK_50M or negedge RST_N)
begin
	if(!RST_N)									//判斷復位
		time_cnt <= 1'b0;						//初始化time_cnt值
	else
		time_cnt <= time_cnt_n;				//用來給time_cnt賦值
end

//組合電路,判斷頻率,讓定時器累加 
always @ (*)
begin
	if(time_cnt < freq)						//判斷分頻值
		time_cnt_n = time_cnt + 1'b1;		//定時器累加操作
	else
		time_cnt_n = 1'b0;					//定時器清零操作
end

//時序電路,用來給beep_reg寄存器賦值
always @ (posedge CLK_50M or negedge RST_N)
begin
	if(!RST_N)									//判斷復位
		beep_reg <= 1'b0;						//初始化beep_reg值
	else
		beep_reg <= beep_reg_n;				//用來給beep_reg賦值
end

//組合電路,判斷頻率,使蜂鳴器發聲
always @ (*)
begin
	if(time_cnt < freq)						//判斷分頻值
		beep_reg_n = beep_reg;				//蜂鳴器的狀態保持不變
	else
		beep_reg_n = ~beep_reg;				//改變蜂鳴器的狀態
end

//組合電路,按鍵選擇分頻值來實現蜂鳴器發出不同聲音
//中音do的頻率爲523.3hz,freq = 50 * 10^6 / (523 * 2) = 47774
always@(KEY)
begin
	case(KEY)
		8'b00000001: freq<=16'd47774; 	//中音1的頻率值523.3Hz
		8'b00000010: freq<=16'd42568; 	//中音2的頻率值587.3Hz
		8'b00000100: freq<=16'd37919; 	//中音3的頻率值659.3Hz
		8'b00001000: freq<=16'd35791; 	//中音4的頻率值698.5Hz
		8'b00010000: freq<=16'd31888; 	//中音5的頻率值784Hz
		8'b00100000: freq<=16'd28409; 	//中音6的頻率值880Hz
		8'b01000000: freq<=16'd25309; 	//中音7的頻率值987.8Hz
		8'b10000000: freq<=16'd23889; 	//高音1的頻率值1046.5Hz
		default	  : freq<=16'd0;
	endcase
end

assign BEEP = beep_reg;		//最後,將寄存器的值賦值給端口BEEP

endmodule



//--	描述		:	數碼管顯示模塊

//---------------------------------------------------------------------------
module Segled_Module
(	
	//輸入端口 
	CLK_50M,RST_N,seconds2_data,seconds1_data,minutes1_data,minutes2_data,
	hours1_data,hours2_data,
	//輸出端口
	SEG_DATA,SEG_EN
);
	
//---------------------------------------------------------------------------
//--	外部端口聲明
//---------------------------------------------------------------------------
input 						CLK_50M;					//時鐘端口
input							RST_N;					//復位端口
input	 		[ 3:0]		hours2_data;			//時鐘高4位數據
input	 		[ 3:0]		hours1_data;			//時鐘低4位數據
input	 		[ 3:0]		minutes2_data;			//分鐘高4位數據
input	 		[ 3:0]		minutes1_data;			//分鐘低4位數據
input	 		[ 3:0]		seconds2_data;			//秒鐘高4位數據
input	 		[ 3:0]		seconds1_data;			//秒鐘低4位數據
output reg 	[ 5:0] 		SEG_EN;					//數碼管使能端口
output reg 	[ 7:0] 		SEG_DATA;				//數碼管端口

//---------------------------------------------------------------------------
//--	內部端口聲明
//---------------------------------------------------------------------------
reg			[26:0]		time_cnt;				//用來控制數碼管閃爍頻率的定時計數器
reg			[26:0]		time_cnt_n;				//time_cnt的下一個狀態
reg			[ 2:0]		led_cnt;					//用來控制數碼管亮滅及顯示數據的顯示計數器
reg			[ 2:0]		led_cnt_n;				//led_cnt的下一個狀態
reg 			[ 3:0]		led_data;				//數據轉換寄存器

//設置定時器的時間爲10ms,計算方法爲  (1*10^6) / (1/50)  50MHz爲開發板晶振
parameter SEC_TIME = 16'd50_000;	

//---------------------------------------------------------------------------
//--	邏輯功能實現	
//---------------------------------------------------------------------------
//時序電路,用來給time_cnt寄存器賦值
always @ (posedge CLK_50M or negedge RST_N)  
begin
	if(!RST_N)											//判斷復位
		time_cnt <= 27'h0;							//初始化time_cnt值
	else
		time_cnt <= time_cnt_n;						//用來給time_cnt賦值
end

//組合電路,實現10ms的定時計數器
always @ (*)  
begin
	if(time_cnt == SEC_TIME )						//判斷10ms時間
		time_cnt_n = 27'h0;							//如果到達10ms,定時計數器將會被清零
	else
		time_cnt_n = time_cnt + 27'h1;			//如果未到10ms,定時計數器將會繼續累加
end

//時序電路,用來給led_cnt寄存器賦值
always @ (posedge CLK_50M or negedge RST_N)  
begin
	if(!RST_N)											//判斷復位
		led_cnt <= 3'b000;							//初始化led_cnt值
	else
		led_cnt <= led_cnt_n;						//用來給led_cnt賦值
end

//組合電路,判斷時間,實現控制顯示計數器累加
always @ (*)  
begin
	if(time_cnt == SEC_TIME )						//判斷10ms時間		
		led_cnt_n = led_cnt + 1'b1;				//如果到達10ms,計數器進行累加
	else
		led_cnt_n = led_cnt;							//如果未到10ms,計數器保持不變
end

//組合電路,實現數碼管的數字顯示,將時鐘中的數據轉換成顯示數據
always @ (*)
begin
	case(led_cnt)
		0 : led_data = hours2_data;				//時鐘高4位顯示
		1 : led_data = hours1_data;				//時鐘低4位顯示
		2 : led_data = minutes2_data;				//分鐘高4位顯示
		3 : led_data = minutes1_data;				//分鐘低4位顯示
		4 : led_data = seconds2_data;				//秒鐘高4位顯示
		5 : led_data = seconds1_data;				//秒鐘低4位顯示
		default: led_data = 4'hF;					//給數碼管賦值爲F
	endcase
end

//組合電路,控制數碼管的亮滅
always @ (*)
begin
	case (led_cnt)  
		0 : SEG_EN = 6'b111110; 					//當計數器爲0時,數碼管SEG1顯示
		1 : SEG_EN = 6'b111101;  					//當計數器爲1時,數碼管SEG2顯示
		2 : SEG_EN = 6'b111011; 					//當計數器爲2時,數碼管SEG3顯示
		3 : SEG_EN = 6'b110111; 					//當計數器爲3時,數碼管SEG4顯示
		4 : SEG_EN = 6'b101111;						//當計數器爲4時,數碼管SEG5顯示
		5 : SEG_EN = 6'b011111;						//當計數器爲5時,數碼管SEG6顯示
		default : SEG_EN = 6'b111111;				//熄滅所有數碼管	
	endcase 	
end

//組合電路,控制數碼管小數點的亮滅
always @ (*)
begin
	case (led_cnt)  
		0 : SEG_DATA[7] = 1'b0;  					//熄滅數碼管SEG1的小數點
		1 : SEG_DATA[7] = 1'b1;	  					//點亮數碼管SEG2的小數點
		2 : SEG_DATA[7] = 1'b0; 					//熄滅數碼管SEG3的小數點
		3 : SEG_DATA[7] = 1'b1;  					//點亮數碼管SEG4的小數點
		4 : SEG_DATA[7] = 1'b0; 					//熄滅數碼管SEG5的小數點
		5 : SEG_DATA[7] = 1'b0; 					//熄滅數碼管SEG6的小數點
		default : SEG_DATA[7] = 1'b0;				//熄滅所有數碼管的小數點
	endcase 	
end

//組合電路,實現數碼管的顯示
always @ (*)
begin
  case(led_data)
		0  : SEG_DATA[6:0] = 7'b0111111;   		//顯示數字 "0"
		1  : SEG_DATA[6:0] = 7'b0000110;  		//顯示數字 "1"
		2  : SEG_DATA[6:0] = 7'b1011011;   		//顯示數字 "2"
		3  : SEG_DATA[6:0] = 7'b1001111;   		//顯示數字 "3"
		4  : SEG_DATA[6:0] = 7'b1100110;  		//顯示數字 "4"
		5  : SEG_DATA[6:0] = 7'b1101101;   		//顯示數字 "5"
		6  : SEG_DATA[6:0] = 7'b1111101;   		//顯示數字 "6"
		7  : SEG_DATA[6:0] = 7'b0000111;   		//顯示數字 "7"
		8  : SEG_DATA[6:0] = 7'b1111111;   		//顯示數字 "8"
		9  : SEG_DATA[6:0] = 7'b1101111;  		//顯示數字 "9"
		10 : SEG_DATA[6:0] = 7'b1110111;   		//顯示數字 "A"
		11 : SEG_DATA[6:0] = 7'b1111100;   		//顯示數字 "B"
		12 : SEG_DATA[6:0] = 7'b1011000;   		//顯示數字 "C"
		13 : SEG_DATA[6:0] = 7'b1011110;   		//顯示數字 "D"
		14 : SEG_DATA[6:0] = 7'b1111001;   		//顯示數字 "E"
		15 : SEG_DATA[6:0] = 7'b1110001;   		//顯示數字 "F"
		default :SEG_DATA[6:0] = 7'b0111111;	//顯示數字 "0"
  endcase
end

endmodule

在按鍵去抖動模塊裏面用到了脈衝邊沿檢測法,原理不是很清楚,後面再寫一下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章