基于FPGA的秒表数码管显示
module time_clock(
clk,
reset_n,
start_key,
pause_key,
duan,
wei
);
input clk; //clk:50MHZ时钟输入;
input reset_n; //复位信号输入,低电平有效;
input start_key; //开始信号输入,低电平有效;
input pause_key; //暂停功能按键,进行秒表计时和倒计时时可以通过该按键进行暂停,‘1’暂停,‘0’继续
output [7:0] duan; //duan:数码管段码;
output [7:0] wei; //wei:数码管位码;
reg [7:0] duan; //duan:数码管段码;
reg [7:0] wei; //wei:数码管位码;
reg [24:0] count; //100HZ时钟计数器
reg [13:0] count2; //扫描时钟计数器
reg clk_2000hz; //100HZ时钟信号
reg clk_scan; //数码管扫描时钟
reg [1:0] select; //用于扫描时选择显示位码
// ****************************************************
//开始按键消抖模块
// ****************************************************
reg start_key_out;
parameter start_s0=3'b000,
start_s1=3'b001,
start_s2=3'b010,
start_s3=3'b011,
start_s4=3'b100,
start_s5=3'b101;
reg [2:0] start_state;
always @(posedge clk or negedge reset_n)
begin
if(reset_n == 1'b0)
begin
start_state <= start_s0;
start_key_out <= 1'b1;
end
else
begin
case (start_state)
start_s0:
begin
start_key_out <= 1'b1;
if(start_key == 1'b0)
start_state <= start_s1;
else
start_state <= start_s0;
end
start_s1:
begin
if(start_key == 1'b0)
start_state <= start_s2;
else
start_state <= start_s0;
end
start_s2:
begin
if(start_key == 1'b0)
start_state <= start_s3;
else
start_state <= start_s0;
end
start_s3:
begin
if(start_key == 1'b0)
start_state <= start_s4;
else
start_state <= start_s0;
end
start_s4:
begin
if(start_key == 1'b0)
start_state <= start_s5;
else
start_state <= start_s0;
end
start_s5:
begin
if(start_key == 1'b0)
begin
start_key_out <= 1'b0;
start_state <= start_s5;
end
else
begin
start_key_out <= 1'b0;
start_state <= start_s5;
end
end
default:
begin
start_state <= start_s0;
start_key_out <= 1'b1;
end
endcase
end
end
//****************************************************************************************************
// 模块名称:分频模块
// 功能描述:
//****************************************************************************************************
always @(posedge clk or negedge reset_n)//2000HZ时钟进程
begin
if(reset_n == 1'b0)
begin
count <= 25'd0;
clk_2000hz <= 1'b0;
end
else
if(count == 25'd12499)
begin
clk_2000hz <= ~clk_2000hz;
count <= 25'd0;
end
else
count <= count + 1'b1;
end
reg [17:0] counter_count;
reg clk_100hz;
always @(posedge clk or negedge reset_n)//100HZ时钟进程 clk_2000hz
begin
if(reset_n == 1'b0)
begin
counter_count <= 18'd0;
clk_100hz <= 1'b0;
end
else
if(~pause_key == 1'b0)//当暂停的时候不进行产生计数时钟信号
if(counter_count == 18'd1)//9
begin
clk_100hz <= ~clk_100hz;
counter_count <= 18'd0;
end
else
counter_count <= counter_count + 1'b1;
else
begin
clk_100hz <= 1'b0;
counter_count <= 18'd0;
end
end
//****************************************************************************************************
// 模块名称:秒表计时
// 功能描述:
//****************************************************************************************************
reg [3:0] counter_haomiao_ge; //秒表计时,毫秒个位数BCD码
reg [3:0] counter_haomiao_shi; //秒表计时,毫秒十位数BCD码
reg [3:0] counter_miao_ge; //秒表计时,秒个位数BCD码
reg [2:0] counter_miao_shi; //秒表计时,秒十位BCD二进制码
always @(posedge clk_100hz or negedge reset_n)
begin
if(reset_n == 1'b0)
begin
counter_haomiao_ge <= 4'd0;
counter_haomiao_shi <= 4'd0;
counter_miao_ge <= 4'd0;
counter_miao_shi <= 3'd0;
end
else
if(~start_key_out == 1'b1)//开始信号有效的时候进行计时
if(counter_haomiao_ge == 4'd9)
begin
counter_haomiao_ge <= 4'd0;
if(counter_haomiao_shi == 4'd9)
begin
counter_haomiao_shi <= 4'd0;
if(counter_miao_ge ==4'd9)
begin
counter_miao_ge <= 4'd0;
if(counter_miao_shi == 3'd5)
begin
counter_miao_shi <= 3'd0;
end
else
counter_miao_shi <= counter_miao_shi + 1'b1;
end
else
counter_miao_ge <= counter_miao_ge + 1'b1;
end
else
counter_haomiao_shi <= counter_haomiao_shi + 1'b1;
end
else
counter_haomiao_ge <= counter_haomiao_ge + 1'b1;
else
begin
counter_haomiao_ge <= 4'd0;
counter_haomiao_shi <= 4'd0;
counter_miao_ge <= 4'd0;
counter_miao_shi <= 3'd0;
end
end
//****************************************************************************************************
// 模块名称:毫秒、秒计数寄存模块
// 功能描述:
//****************************************************************************************************
reg [3:0] reg_haomiao_ge; //毫秒个位数BCD码
reg [3:0] reg_haomiao_shi; //毫秒十位数BCD码
reg [3:0] reg_miao_ge; //秒个位数BCD码
reg [2:0] reg_miao_shi; //秒十位BCD二进制码
always @(posedge clk or negedge reset_n)
begin
if(reset_n == 1'b0)
begin
reg_haomiao_ge <= 4'd9;
reg_haomiao_shi <= 4'd9;
reg_miao_ge <= 4'd9;
reg_miao_shi <= 3'd5;
end
else
begin
reg_haomiao_ge <= counter_haomiao_ge;
reg_haomiao_shi <= counter_haomiao_shi;
reg_miao_ge <= counter_miao_ge;
reg_miao_shi <= counter_miao_shi;
end
end
//****************************************************************************************************
// 模块名称:数码管位选择时钟产生模块
// 功能描述:
//****************************************************************************************************
always @(posedge clk or negedge reset_n)//数码管扫描时钟产生进程
begin
if(reset_n == 1'b0)
begin
count2 <= 14'd0;
clk_scan <= 1'b0;
end
else
if(count2 == 14'd10000)
begin
count2 <= 14'd0;
clk_scan <= ~clk_scan;//2500Hz的数码管扫描频率时钟信号
end
else
count2 <= count2 + 1'b1;
end
//****************************************************************************************************
// 模块名称:数码管位选择产生信号模块
// 功能描述:
//****************************************************************************************************
always @(posedge clk_scan or negedge reset_n)
begin
if(reset_n == 1'b0)
select <= 2'b00;
else
select <= select + 1'b1;//数码管位选择信号
end
//****************************************************************************************************
// 模块名称:译码电路
// 功能描述:
//****************************************************************************************************
always @(posedge clk or negedge reset_n)
begin
if(reset_n == 1'b0)
begin
wei <= 8'b11111111;
duan <= 8'hff;
end
else
begin
if(select == 2'd0)
begin
wei <= 8'b11101111;//毫秒个位数显示
case(reg_haomiao_ge)
4'b0000:duan <= 8'b1100_0000;//0
4'b0001:duan <= 8'b1111_1001;//1
4'b0010:duan <= 8'b1010_0100;//2
4'b0011:duan <= 8'b1011_0000;//3
4'b0100:duan <= 8'b1001_1001;//4
4'b0101:duan <= 8'b1001_0010;//5
4'b0110:duan <= 8'b1000_0010;//6
4'b0111:duan <= 8'b1111_1000;//7
4'b1000:duan <= 8'b1000_0000;//8
4'b1001:duan <= 8'b1001_0000;//9
default:duan <= 8'hff;
endcase
end
else if(select == 2'd1)
begin
wei <= 8'b11011111;//毫秒十位数显示
case(reg_haomiao_shi)
4'b0000:duan <= 8'b1100_0000;//0
4'b0001:duan <= 8'b1111_1001;//1
4'b0010:duan <= 8'b1010_0100;//2
4'b0011:duan <= 8'b1011_0000;//3
4'b0100:duan <= 8'b1001_1001;//4
4'b0101:duan <= 8'b1001_0010;//5
4'b0110:duan <= 8'b1000_0010;//6
4'b0111:duan <= 8'b1111_1000;//7
4'b1000:duan <= 8'b1000_0000;//8
4'b1001:duan <= 8'b1001_0000;//9
default:duan <= 8'hff;
endcase
end
else if(select == 2'd2)
begin
wei <= 8'b10111111;//秒个位数显示
case(reg_miao_ge)
4'b0000:duan <= 8'b0100_0000;//0
4'b0001:duan <= 8'b0111_1001;//1
4'b0010:duan <= 8'b0010_0100;//2
4'b0011:duan <= 8'b0011_0000;//3
4'b0100:duan <= 8'b0001_1001;//4
4'b0101:duan <= 8'b0001_0010;//5
4'b0110:duan <= 8'b0000_0010;//6
4'b0111:duan <= 8'b0111_1000;//7
4'b1000:duan <= 8'b0000_0000;//8
4'b1001:duan <= 8'b0001_0000;//9
default:duan <= 8'hff;
endcase
end
else if(select == 2'd3)
begin
wei <= 8'b01111111;//秒十位数显示
case(reg_miao_shi)
3'b000:duan <= 8'b1100_0000;
3'b001:duan <= 8'b1111_1001;
3'b010:duan <= 8'b1010_0100;
3'b011:duan <= 8'b1011_0000;
3'b100:duan <= 8'b1001_1001;
3'b101:duan <= 8'b1001_0010;
3'b110:duan <= 8'b1000_0010;
default:duan <= 8'hff;
endcase
end
else
begin
wei <= 8'b11111111;
duan <= 8'hff;
end
end
end
endmodule