基于FPGA的数字钟 ——最终实现

我手里只有一块黑金的AX4010板子,板载的是Altera公司的Cyclone IV E系列 EP4CE10F17C8芯片。亲测成功,目前没发现bug

自己敲代码也不容易啊,虽说工程很简单,但所有代码都是自己分析后再敲出来的,学生创作不易。麻烦转载时注明出处啦,感谢!

功能:1.显示时间(s,min,h)
2.3个按键可以以加的形式更改时间
3.流水灯模块仅做装饰用,未写入

所有用到的代码如下:

时钟控制模块

//作者:杨成煜
//日期:2020/4/3
//==================defines=====================
module	clock3(
	//================System Signal================
	input				clk,
	input				rst_n,
	//================Interface====================
	input				key_s,
	input				key_min,
	input				key_h,
	output	reg[3:0]	s_shi,
	output	reg[3:0]	s_ge,
	output	reg[3:0]	min_shi,
	output	reg[3:0]	min_ge,
	output	reg[3:0]	h_shi,
	output	reg[3:0]	h_ge,
	output	wire		flag_ms//用于流水灯触发
);
	//================parameters===================
	`ifndef SIM
	localparam	CNT_MS_VAL = 16'd49999;
	`else
	localparam	CNT_MS_VAL = 499;
	`endif
	//================System regs==================
	reg[15:0]	cnt_ms;//用来计1ms
	reg[9:0]	cnt_div_ms;//用来计满1000ms
	wire flag_s;
	wire flag_min;
	wire flag_h;
	wire flag_key_s_trig;
	wire flag_key_min_trig;
	wire flag_key_h_trig;
	//================Main Codes===================
	//key
	reg key_s_t0;
	reg key_s_t1;
	reg key_min_t0;
	reg key_min_t1;
	reg key_h_t0;
	reg key_h_t1;
	//key_temp
	always	@(posedge clk)begin
		key_s_t0<=key_s;
		key_s_t1<=key_s_t0;
		key_min_t0<=key_min;
		key_min_t1<=key_min_t0;
		key_h_t0<=key_h;
		key_h_t1<=key_h_t0;
	end
	assign flag_key_s_trig = (key_s_t0==1'b1)&&(key_s_t1==1'b0);
	assign flag_key_min_trig = (key_min_t0==1'b1)&&(key_min_t1==1'b0);
	assign flag_key_h_trig = (key_h_t0==1'b1)&&(key_h_t1==1'b0);
	//cnt_ms
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			cnt_ms <= 'd0;
		else if(cnt_ms==CNT_MS_VAL)
			cnt_ms <= 'd0;
		else
			cnt_ms <= cnt_ms + 1'b1;
	end
	//cnt_div_ms
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			cnt_div_ms <= 'd0;
		else if(cnt_div_ms==10'd999&&cnt_ms==CNT_MS_VAL)
			cnt_div_ms <= 'd0;
		else if(cnt_ms==CNT_MS_VAL)
			cnt_div_ms <= cnt_div_ms + 1'b1;
	end
	
	assign flag_ms = (cnt_div_ms==10'd999&&cnt_ms==CNT_MS_VAL)?1'b1:1'b0;
	//s_ge
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			s_ge <= 'd0;
		else if(s_ge==4'd9&&flag_ms==1'b1)
			s_ge <= 'd0;
		else if(flag_key_s_trig==1'b1&&s_ge==4'd9)
			s_ge <= 'd0;
		else if(flag_key_s_trig==1'b1)
			s_ge <= s_ge + 1'b1;
		else if(flag_ms==1'b1)
			s_ge <= s_ge + 1'b1;
	end
	//s_shi
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			s_shi <= 'd0;
		else if(s_shi==4'd5&&s_ge==4'd9&&flag_ms==1'b1)
			s_shi <= 'd0;
		else if(flag_key_s_trig==1'b1&&s_ge==4'd9)
			s_shi <= s_shi + 1'b1;
		else if(s_ge==4'd9&&flag_ms==1'b1)
			s_shi <= s_shi + 1'b1;
	end
	assign flag_s = (s_shi==4'd5&&s_ge==4'd9&&flag_ms==1'b1)?1'b1:1'b0;
	//min_ge
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			min_ge <= 'd0;
		else if(min_ge==4'd9&&flag_s==1'b1)
			min_ge <= 'd0;
		else if(flag_key_min_trig==1'b1&&min_ge==4'd9)
			min_ge <= 'd0;
		else if(flag_key_min_trig==1'b1)
			min_ge <= min_ge + 1'b1;
		else if(flag_s==1'b1)
			min_ge <= min_ge + 1'b1;
	end
	//min_shi
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			min_shi <= 'd0;
		else if(min_ge==4'd9&&min_shi==4'd5&&flag_s==1'b1)
			min_shi <= 'd0;
		else if(flag_key_min_trig==1'b1&&min_ge==4'd9)
			min_shi <= min_shi + 1'b1;
		else if(min_ge==4'd9&&flag_s==1'b1)
			min_shi <= min_shi + 1'b1;
	end
	assign flag_min = (min_ge==4'd9&&min_shi==4'd5&&flag_s==1'b1);
	//h_ge
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			h_ge <= 'd0;
		else if(h_ge==4'd3&&h_shi==4'd2&&flag_min==1'b1)
			h_ge <= 'd0;
		else if(h_ge==4'd9&&flag_min==1'b1)
			h_ge <= 'd0;
		else if(flag_key_h_trig==1'b1&&h_ge==4'd3&&h_shi==4'd2)
			h_ge <= 'd0;
		else if(flag_key_h_trig==1'b1&&h_ge==4'd9)
			h_ge <= 'd0;
		else if(flag_key_h_trig==1'b1)
			h_ge <= h_ge + 1'b1;
		else if(flag_min==1'b1)
			h_ge <= h_ge + 1'b1;
	end
	//h_shi
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			h_shi <= 'd0;
		else if(h_ge==4'd3&&h_shi==4'd2&&flag_min==1'b1)
			h_shi <= 'd0;
		else if(flag_key_h_trig==1'b1&&h_ge==4'd9)
			h_shi <= h_shi + 1'b1;
		else if(h_ge==4'd9&&flag_min==1'b1)
			h_shi <= h_shi + 1'b1;
	end
	
endmodule

按键消抖模块

//作者:杨成煜
//日期:2020/4/3
//==================defines=====================
module	key_debounce(
	//================System Signal================
	input	clk,
	input	rst_n,
	//================Interface====================
	input	key_in,
	output	reg flag_key_down,
	output	reg flag_key_up
);
	//================parameters===================
	`ifndef SIM
	parameter	SAMPLE_CNT_VAL=499999;
	`else
	parameter	SAMPLE_CNT_VAL=499;
	`endif
	//state define
	localparam	S_UP = 4'b0001;
	localparam	S_SAMP_DOWN=4'b0010;
	localparam	S_DOWN=4'b0100;
	localparam	S_SAMP_UP=4'b1000;
	//================System regs==================
	reg[19:0] 	sample_cnt;
	wire		flag_trig_down;
	wire		flag_trig_up;
	reg 		flag_sample;
	reg 		key_in_t0;
	reg 		key_in_t1;
	reg[3:0]	state;
	//================Main Codes===================
	//state
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			state <= S_UP;
		else case(state)
			S_UP:begin
				if(flag_trig_down==1'b1)
					state <= S_SAMP_DOWN;
				else
					state <= S_UP;
			end
			S_SAMP_DOWN:begin
				if(sample_cnt==SAMPLE_CNT_VAL&&key_in_t0==1'b0)
					state <= S_DOWN;
				else if(sample_cnt==SAMPLE_CNT_VAL&&key_in_t0==1'b1)
					state <= S_UP;
				else
					state <= S_SAMP_DOWN;
			end
			S_DOWN:begin
				if(flag_trig_up==1'b1)
					state <= S_SAMP_UP;
				else
					state <= S_DOWN;
			end
			S_SAMP_UP:begin
				if(sample_cnt==SAMPLE_CNT_VAL&&key_in_t0==1'b1)
					state <= S_UP;
				else if(sample_cnt==SAMPLE_CNT_VAL&&key_in_t0==1'b0)
					state <= S_DOWN;
				else
					state <= S_SAMP_UP;
			end
		endcase
	end
	
	//key_temp
	always	@(posedge clk)begin
		key_in_t0 <= key_in;
		key_in_t1 <= key_in_t0;
	end
	//flag_trig
	assign flag_trig_down = (~key_in_t0)&(key_in_t1);
	assign flag_trig_up	  = (key_in_t0)&(~key_in_t1);
	//flag_key_down & up
	always	@(*)begin
		case(state)
			S_DOWN:flag_key_down = 1'b1;
			S_SAMP_UP:flag_key_down = 1'b1;
			default:flag_key_down = 1'b0;
		endcase
	end
	always	@(*)begin
		case(state)
			S_UP:flag_key_up = 1'b1;
			S_SAMP_DOWN:flag_key_up = 1'b1;
			default:flag_key_up = 1'b0;
		endcase
	end

	//flag_sample
	always	@(*)begin
		case(state)
			S_SAMP_DOWN:flag_sample = 1'b1;
			S_SAMP_UP:flag_sample = 1'b1;
			default:flag_sample = 1'b0;
		endcase
	end
	
	//sample_cnt
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			sample_cnt <= 'd0;
		else if(flag_sample==1'b1&&sample_cnt==SAMPLE_CNT_VAL)
			sample_cnt <= 'd0;
		else if(flag_sample==1'b1)
			sample_cnt <= sample_cnt + 1'b1;
		else
			sample_cnt <= 'd0;
	end
	
endmodule

数码管(板载)扫描模块

//作者:杨成煜
//日期:2020/4/3
//`define SIM
module	Seg_disp(
//system signal
	input	System_Clk,
	input	Rst_n,
//seg interface
	input	[3:0]		data_0,
	input	[3:0]		data_1,
	input	[3:0]		data_2,
	input	[3:0]		data_3,
	input	[3:0]		data_4,
	input	[3:0]		data_5,

	output	reg	[6:0]	Dig,
	output	reg			Dp,
	output	reg	[5:0]	Sel
//others
);
//Parameters and Defines
`ifndef SIM
	localparam	Sample_end = 49999;
`else
	localparam	Sample_end = 499;
`endif
//Regs
	reg	[3:0]	data_0_r;
	reg	[3:0]	data_1_r;
	reg	[3:0]	data_2_r;
	reg	[3:0]	data_3_r;
	reg	[3:0]	data_4_r;
	reg	[3:0]	data_5_r;
	reg	[3:0]	data_reg;
	reg	[2:0]	bit_cnt;
	reg			bit_flag;
	reg	[15:0]	sample_cnt;

//Main Code
	//data_0-5_reg
	always	@(posedge System_Clk or negedge	Rst_n)begin
		if(Rst_n == 1'b0)begin
			data_0_r <= 'd0;
			data_1_r <= 'd0;
			data_2_r <= 'd0;
			data_3_r <= 'd0;
			data_4_r <= 'd0;
			data_5_r <= 'd0;			
		end
		else if(bit_cnt==3'd0 && sample_cnt==16'd0)begin
			data_0_r <= data_0;//sample at bit0
			data_1_r <= data_1;
			data_2_r <= data_2;
			data_3_r <= data_3;
			data_4_r <= data_4;
			data_5_r <= data_5;	
		end
	end
	//bit_flag
	always	@(posedge System_Clk or negedge Rst_n)begin
		if(Rst_n==1'b0)
			bit_flag <= 1'b0;
		else if(sample_cnt==Sample_end)
			bit_flag <= 1'b1;
		else
			bit_flag <= 1'b0;
	end
	//bit_cnt
	always	@(posedge System_Clk or negedge Rst_n)begin
		if(Rst_n==1'b0)
			bit_cnt <= 'd0;
		else if(bit_cnt == 3'd5 && bit_flag==1'b1)
			bit_cnt <= 'd0;
		else if(bit_flag==1'b1)
			bit_cnt <= bit_cnt + 1'b1;
	end
	//data_reg
	always	@(*)begin
			case(bit_cnt)
				3'd0:data_reg = data_0_r;
				3'd1:data_reg = data_1_r;
				3'd2:data_reg = data_2_r;
				3'd3:data_reg = data_3_r;
				3'd4:data_reg = data_4_r;
				3'd5:data_reg = data_5_r;	
			default:data_reg = 4'd0;
			endcase
	end
	//sample_cnt
	always	@(posedge System_Clk or negedge Rst_n)begin
		if(Rst_n==1'b0)
			sample_cnt <= 'd0;
		else if(sample_cnt==Sample_end)
			sample_cnt <= 'd0;
		else
			sample_cnt <= sample_cnt + 1'b1;
	end
	//Dig
	always	@(*)begin
			case(data_reg)
				4'h0:{Dp,Dig} = 8'b11000000;
				4'h1:{Dp,Dig} = 8'b11111001;
				4'h2:{Dp,Dig} = 8'b10100100;
				4'h3:{Dp,Dig} = 8'b10110000;
				4'h4:{Dp,Dig} = 8'b10011001;
				4'h5:{Dp,Dig} = 8'b10010010;
				4'h6:{Dp,Dig} = 8'b10000010;
				4'h7:{Dp,Dig} = 8'b11111000;
				4'h8:{Dp,Dig} = 8'b10000000;
				4'h9:{Dp,Dig} = 8'b10010000;
				4'ha:{Dp,Dig} = 8'b10001000;
				4'hb:{Dp,Dig} = 8'b10000011;
				4'hc:{Dp,Dig} = 8'b11000110;
				4'hd:{Dp,Dig} = 8'b10100001;
				4'he:{Dp,Dig} = 8'b10000110;
				4'hf:{Dp,Dig} = 8'b10001110;
			endcase
	end
	//sel
	always	@(*)begin
			case(bit_cnt)
				3'd0:Sel = 6'b111110;//点亮右面第一个
				3'd1:Sel = 6'b111101;
				3'd2:Sel = 6'b111011;
				3'd3:Sel = 6'b110111;
				3'd4:Sel = 6'b101111;
				3'd5:Sel = 6'b011111;
				default:Sel = 6'b111111;
			endcase
	end
endmodule

顶层模块

//作者:杨成煜
//日期:2020/4/3
//==================defines=====================
module	top_clock3(
	//================System Signal================
	input	clk,
	input	rst_n,
	//================Interface====================

	//key interface
	input				key1,
	input				key2,
	input				key3,
	//seg interface
	output[6:0]			Dig,
	output				Dp,
	output[5:0]			Sel


);
	//================parameters===================
	`ifndef SIM
	
	`else
	
	`endif
	//================System regs==================
	wire[3:0]	s_shi;
	wire[3:0]	s_ge;
	wire[3:0]	min_shi;
	wire[3:0]	min_ge;
	wire[3:0]	h_shi;
	wire[3:0]	h_ge;
	wire		flag_ms;//用于流水灯触发
	wire		key_s;
	wire		key_min;
	wire		key_h;
	//================Main Codes===================
clock3 clock3_inst(
	//================System Signal================
	.clk		(clk),
	.rst_n		(rst_n),
	//================Interface====================
	.key_s		(key_s),
	.key_min	(key_min),
	.key_h		(key_h),
	.s_shi		(s_shi),
	.s_ge		(s_ge),
	.min_shi	(min_shi),
	.min_ge		(min_ge),
	.h_shi		(h_shi),
	.h_ge		(h_ge),
	.flag_ms	(flag_ms)//用于流水灯触发
);
Seg_disp Seg_disp_inst(
//system signal
	.System_Clk		(clk),
	.Rst_n			(rst_n),
//seg interface
	.data_0			(h_shi),
	.data_1			(h_ge),
	.data_2			(min_shi),
	.data_3			(min_ge),
	.data_4			(s_shi),
	.data_5			(s_ge),
	.Dig			(Dig),
	.Dp				(Dp),
	.Sel			(Sel)
//others
);
key_debounce key_debounce_s(
	//================System Signal================
	.clk			(clk),
	.rst_n			(rst_n),
	//================Interface====================
	.key_in			(key1),
	.flag_key_down	(key_s),
	.flag_key_up	()
);
key_debounce key_debounce_min(
	//================System Signal================
	.clk			(clk),
	.rst_n			(rst_n),
	//================Interface====================
	.key_in			(key2),
	.flag_key_down	(key_min),
	.flag_key_up	()
);
key_debounce key_debounce_h(
	//================System Signal================
	.clk			(clk),
	.rst_n			(rst_n),
	//================Interface====================
	.key_in			(key3),
	.flag_key_down	(key_h),
	.flag_key_up	()
);
endmodule

管脚约束

# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2013 Altera Corporation
# Your use of Altera Corporation's design tools, logic functions 
# and other software and tools, and its AMPP partner logic 
# functions, and any output files from any of the foregoing 
# (including device programming or simulation files), and any 
# associated documentation or information are expressly subject 
# to the terms and conditions of the Altera Program License 
# Subscription Agreement, Altera MegaCore Function License 
# Agreement, or other applicable license agreement, including, 
# without limitation, that your use is for the sole purpose of 
# programming logic devices manufactured by Altera and sold by 
# Altera or its authorized distributors.  Please refer to the 
# applicable agreement for further details.
#
# -------------------------------------------------------------------------- #
#
# Quartus II 64-Bit
# Version 13.1.0 Build 162 10/23/2013 SJ Full Version
# Date created = 20:16:33  April 03, 2020
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
#		clock_assignment_defaults.qdf
#    If this file doesn't exist, see file:
#		assignment_defaults.qdf
#
# 2) Altera recommends that you do not modify this file. This
#    file is updated automatically by the Quartus II software
#    and any changes you make may be lost or overwritten.
#
# -------------------------------------------------------------------------- #


set_global_assignment -name FAMILY "Cyclone IV E"
set_global_assignment -name DEVICE EP4CE10F17C8
set_global_assignment -name TOP_LEVEL_ENTITY top_clock3
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1
set_global_assignment -name PROJECT_CREATION_TIME_DATE "20:16:33  APRIL 03, 2020"
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
set_global_assignment -name VERILOG_FILE ../rtl/top_clock3.v
set_global_assignment -name VERILOG_FILE ../rtl/Seg_disp.v
set_global_assignment -name VERILOG_FILE ../rtl/key_debounce.v
set_global_assignment -name VERILOG_FILE ../rtl/clock3.v
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 256
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1
set_global_assignment -name NOMINAL_CORE_SUPPLY_VOLTAGE 1.2V
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top

#clock 50m
set_location_assignment PIN_E1 -to clk
#key 
set_location_assignment PIN_N13 -to rst_n
set_location_assignment PIN_M15 -to key1
set_location_assignment PIN_M16 -to key2
set_location_assignment PIN_E16 -to key3
#segment led
set_location_assignment PIN_R16 -to Dp
set_location_assignment PIN_N15 -to Dig[6]
set_location_assignment PIN_N12 -to Dig[5]
set_location_assignment PIN_P15 -to Dig[4]
set_location_assignment PIN_T15 -to Dig[3]
set_location_assignment PIN_P16 -to Dig[2]
set_location_assignment PIN_N16 -to Dig[1]
set_location_assignment PIN_R14 -to Dig[0]
set_location_assignment PIN_M11 -to Sel[5]
set_location_assignment PIN_P11 -to Sel[4]
set_location_assignment PIN_N11 -to Sel[3]
set_location_assignment PIN_M10 -to Sel[2]
set_location_assignment PIN_P9 -to Sel[1]
set_location_assignment PIN_N9 -to Sel[0]
#set_location_assignment PIN_D9 -to led[3]
#set_location_assignment PIN_C9 -to led[2]
#set_location_assignment PIN_F9 -to led[1]
#set_location_assignment PIN_E10 -to led[0]

set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "2.5 V"
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
发布了18 篇原创文章 · 获赞 25 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43650722/article/details/105301083