基于FPGA的数字跑表设计

基于FPGA的数字跑表设计

本设计中数字跑表的主要功能有:1、具有显示分、秒以及百分秒的秒表功能,2、具有暂停和复位功能
结构示意图
一、设计准备
输入端口:
1)复位信号CLR,当CLR=1时输出全部置0,当CLR=0时系统正常工作。
2)暂停信号PAUSE,当PAUSE=1时暂停计数,当PAUSE=0时正常计数。
3)系统时钟CLK,CLK=50MHz
输出端口:
数码管驱动—-DATA[13:0](位宽14位),其中DATA[7:0](后八位)是数码管显示值,DATA[13:8](前六位)是数码管控制端口
分模块
按照自顶向下设计,应该分为以下模块:
分频1—-将下载板上50MHz时钟分频为100Hz(周期0.01s)的时钟,提供给百分计数
分频2—-将下载板上50MHz时钟分频为10KHz的时钟,提供给动态扫描
计数1—-100进制计数器,输入100Hz的时钟,计数满100进位
计数2—-60进制计数器,输入百分位,或者秒位的进位,计数满60向高位进位
数码管显示控制—-驱动数码管数据,显示控制端口。
二、分频模块
分频模块的输入为50MHz的系统时钟clk50m,输出为分频后的100Hz时钟信号clk100和10KHz时钟信号clk10k,定义了两个计数寄存器cout1[18:0](19位)和cout2[15:0](16位)。系统时钟为50MHz,百分秒计数需要100Hz(周期0.01s)的时钟信号,因此对50MHz进行(50×10^6)/100=500,000次分频,定义计数器cout1对50MHZ方波上升沿进行计数,从0到499,999循环计数,每满499,999后cout1就置0重新计数,并且当cout1=499,999时clk100置1。至于再分频一个10KHz时钟的原因是动态扫描在100Hz时有明显闪烁,而在50MHz时闪烁频率过快导致根本看不清数码管上的数字。
分频
三、计时模块
计时模块的输入为分频后的100Hz时钟信号clk100,输出为分位、秒位、百分位的个位和百分位的十位[3:0]:ML、SL、MSL、MSH和分位、秒位的十位[2:0]:MH、SH,定义了两个进位信号cn1和cn2。每个clk100的上升沿到来代表时间过了0.01s,每个cn1的上升沿到来代表时间过了1s,每个cn2的上升沿到来代表时间过了60s。
四、数码管显示模块
显示模块的输入为分频后的10KHz时钟信号clk10k,输出为带有数码管控制端口和数码管显示值的DATA[12:0],定义了一个位选寄存器dig[2:0]。因为不需要数码管上的小数点亮所以数码管显示值设为7位,而数码管控制端口只用6只所以是6位,数码管分共阴极和共阳极两种,共阴极的1表示亮,共阳极的0表示亮,我是当共阴极来设计的;四位一体数码管用动态扫描控制,每个clk10k的上升沿到来dig在0到5之间循环,dig的值等于几显示控制函数就往那支数码管里送与之对应的数据。
四位一体数码管
共阴极
真值表
`timescale 1ns / 1ps
module timer(clk50m,clr,pause,data);
input clk50m; //输入50MHz的时钟信号
input clr; //清零开关
input pause; //暂停开关
output reg[12:0]data;
reg [2:0]dig; //数码管位选
reg [3:0] ML,SL,MSL,MSH; //分位,秒位,百分位的个位和百分位的十位
reg [2:0] MH,SH; //分位,秒位的十位
reg [18:0] cout1; //定义计数寄存器
reg [15:0] cout2; //定义计数寄存器
reg clk100; //定义分频得到的100Hz时钟信号
reg clk10k; //频率10KHz的时钟信号
reg cn1; //百分位向秒位的进位
reg cn2; //秒位向分位的进位

//——————-分频得到100Hz的时钟信号clk100——————–
always@(posedge clk50m or posedge clr)
if(clr) cout1<=0;
else if(cout1 == 19″h7a11f) cout1<=0;
else cout1<=cout1+1″b1;
always@(posedge clk50m or posedge clr)
if(clr) clk100<=0;
else if(cout1 == 19″h7a11f) clk100<=1″b1;
else clk100<=0;
//——————-分频得到10KHz的时钟信号clk10k——————-
always@(posedge clk50m or posedge clr)
if(clr) cout2<=0;
else if(cout2 == 19″hc34f) cout2<=0;
else cout2<=cout2+1″b1;
always@(posedge clk50m or posedge clr)
if(clr) clk10k<=0;
else if(cout2 == 19″hc34f) clk10k<=1″b1;
else clk10k<=0;
//———————–计时模块——————–
//—————-百分位计时—————
always@(posedge clk100 or posedge clr)
if(clr) begin {MSH,MSL}<=8″h00;cn1<=0;end //异步复位
else if(!pause) //PAUSE为0时正常计数
begin
if(MSL == 4″b1001)
begin MSL<=0;
if(MSH == 4″b1001) begin MSH<=0; cn1<=1; end
else begin MSH<=MSH+1″b1;cn1<=0; end
end
else begin MSL<=MSL+1″b1; cn1<=0; end
end
//—————-秒位计时—————–
always@(posedge cn1 or posedge clr)
if(clr) begin {SH,SL}<=8″h00;cn2<=0; end
else if(SL == 4″b1001)
begin SL<=0;
if(SH == 5) begin SH<=0; cn2<=1; end
else begin SH<=SH+1″b1;cn2<=0; end
end
else begin SL<=SL+1″b1;cn2<=0; end
//—————分位计时——————
always@(posedge cn2 or posedge clr)
if(clr) begin {MH,ML}<=8″h00; end
else if(ML == 4″b1001)
begin ML<=0;
if(MH == 3″b101) begin MH<=0; end
else begin MH<=MH+1″b1; end
end
else begin ML<=ML+1″b1; end
//——————-数码管显示模块——————–
always@(posedge clk10k or posedge clr)
if(clr) data<=13″b1111111111110;
else case(dig)
3″b000:data<={6″b000001,Xrom(MSL)};
3″b001:data<={6″b000010,Xrom(MSH)};
3″b010:data<={6″b000100,Xrom(SL)};
3″b011:data<={6″b001000,Xrom(SH)};
3″b100:data<={6″b010000,Xrom(ML)};
3″b101:data<={6″b100000,Xrom(MH)};
default:data<=13″h1fff;
endcase
//——————-动态扫描——————-
always@(posedge clk10k or posedge clr)
if(clr) dig<=0;
else begin
if(clk10k == 0) begin
if(dig==5) dig<=0;
else dig<=dig+1″b1; end
else dig<=dig;
end
//————–数码管显示控制函数—————
function[6:0] Xrom;
input [3:0] sum;
case(sum)
4″d0:Xrom=7″h7e;
4″d1:Xrom=7″h30;
4″d2:Xrom=7″h6d;
4″d3:Xrom=7″h79;
4″d4:Xrom=7″h33;
4″d5:Xrom=7″h5b;
4″d6:Xrom=7″h5f;
4″d7:Xrom=7″h70;
4″d8:Xrom=7″h7f;
4″d9:Xrom=7″h7b;
default:Xrom=7″h00;
endcase
endfunction
endmodule

hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » 基于FPGA的数字跑表设计