程序是实现一个数字钟,有进位、清零、校时与校分功能。数字钟的分钟和小时是用数码管显示,秒信号是用LED显示8421BCD码。
下面是采用8421BCD码计数,并在一个模块中实现时钟功能的Verilog程序。由主时钟分频(50MHz)得到秒信号,计秒到60分加1,秒清零。计分到60时,分清零。同时,可以通过按键进行校分与校时。
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 16:20:22 11/19/2013
// Design Name:
// Module Name: DigitalClk
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module DigitalClk(
input clk,
input clr,
input setm,//设定分钟
input seth,//设定小时
output reg[3:0]secondL,//秒数的低位
output reg[3:0]secondH,//秒数的高位
output reg[6:0]atog,
output reg[3:0]an
);
reg [3:0]minuteL;//分钟数的低位
reg [3:0]minuteH;//分钟数的高位
reg [3:0]hourL;//小时数的低位
reg [3:0]hourH;//小时数的高位
reg [1:0]s; //四个数码管轮流使能信号
reg [3:0]digit; //使能数码管中的数字
reg [26:0] counter;
reg [7:0]minute;//记录分钟数
reg [7:0]hour;//记录小时数
reg [7:0]sec;//记录秒数
integer i;
integer j;
integer k;
always@(posedge clk or posedge clr)
begin
if(clr==1) //清零键按下时将所有数据置零
begin
counter<=0;
secondL<=0;
secondH<=0;
minuteL<=0;
minuteH<=0;
hourH<=0;
hourL<=0;
minute<=0;
hour<=0;
sec<=0;
end
else if(counter==50000000)//时间达到一秒
begin
counter<=0;
if(setm==1)//如果设置分钟建按下(长按一秒才会起作用)
begin
if(minute==59)
begin
minute<=0;
if(hour==23)//23:59进位变为00:00
begin
hour<=0;
end
else
begin
hour<=hour+1;
end
end
else
begin
minute<=minute+1;
end
end
if(seth==1)//如果设置小时建按下(长按一秒才会起作用)
begin
if(hour==23)
begin
hour<=0;
minute<=0;
minuteH<=0;
minuteL<=0;
end
else
begin
hour<=hour+1;
end
end
//一般情况
if(sec==59)//秒针进位
begin
sec<=0;
if(minute==59)
begin
minute<=0;
if(hour==23)//23:59进位后变成00:00
begin
hour<=0;
end
else if(hour<23)
begin
hour<=hour+1;
end
end
else if(minute<59)//分钟数进位
begin
minute<=minute+1;
end
end
else if(seth==0&&setm==0)//在调时,调分键没有按下的情况下,秒钟计数
begin
sec<=sec+1;
end
for(i=0;i<6;i=i+1)//分离出秒钟数的个位和十位
begin
if(sec[7:0]-i*10<10)
begin
secondH<=i;
secondL<=sec[7:0]-i*10;
i=6;
end
end
for(j=0;j<6;j=j+1)//分离出分钟数的个位和十位
begin
if(minute[7:0]-j*10<10)
begin
minuteH<=j;
minuteL<=minute[7:0]-j*10;
j=6;
end
end
for(k=0;k<3;k=k+1)//分离出十钟数的个位和十位
begin
if(hour[7:0]-k*10<10)
begin
hourH<=k;
hourL<=hour[7:0]-k*10;
k=3;
end
end
end
else
begin
counter<=counter+1;
end
end
//数码管动态显示
always@(*)
begin
an=4'b1111;
s<=counter[14:13];
an[s]=0;
case(s)
0:digit<=minuteL[3:0];
1:digit<=minuteH[3:0];
2:digit<=hourL[3:0];
3:digit<=hourH[3:0];
default:digit<=hourH[3:0];
endcase
case(digit)
0:atog=7'b0000001;
1:atog=7'b1001111;
2:atog=7'b0010010;
3:atog=7'b0000110;
4:atog=7'b1001100;
5:atog=7'b0100100;
6:atog=7'b0100000;
7:atog=7'b0001111;
8:atog=7'b0000000;
9:atog=7'b0000100;
default:atog=7'b0000001;
endcase
end
endmodule
NET "clk" LOC="B8";
//NET "clr" LOC="P11";
NET "clr" LOC="A7";
NET "secondL[0]" LOC="M5";
NET "secondL[1]" LOC="M11";
NET "secondL[2]" LOC="P7";
NET "secondL[3]" LOC="P6";
NET "secondH[0]" LOC="N5";
NET "secondH[1]" LOC="N4";
NET "secondH[2]" LOC="P4";
NET "secondH[3]" LOC="G1";
NET"atog[0]"LOC=M12;
NET"atog[1]"LOC=L13;
NET"atog[2]"LOC=P12;
NET"atog[3]"LOC=N11;
NET"atog[4]"LOC=N14;
NET"atog[5]"LOC=H12;
NET"atog[6]"LOC=L14;
NET"an[3]"LOC=K14;
NET"an[2]"LOC=M13;
NET"an[1]"LOC=J12;
NET"an[0]"LOC=F12;
NET"setm"LOC=G12;
NET"seth"LOC=M4;