📄 duogongnengzhong.txt
字号:
//多功数字钟
//功能描述
//多功数字钟共有5种功能:功能1为数字钟;功
//能2为数字跑表;功能3为调时;功能4为闹钟设置;功
//能5为日期设置。除调时功能以外,电子表处于其他功
//能状态下时并不影响数字钟的运行。使用数字钟功能
//时,还可以通过按键快速查看当前的闹钟设置时间和
//当前日期。该多功数字钟利用EDA实验平台的扬声器整点
//报时和定时报时,设置3个按键分别作为功能键和调整键。
//Verilog-HDL程序
module clock(clk_1Hz, clk_1kHz, func_key, key1, key2,
mode, hour, minute, second, alarm);
input clk_1Hz ; //1Hz时钟,供数字钟使用
input clk_1kHz ;
//1 kHz时钟, 分成500 Hz供闹钟和整点报时使用, 分频100Hz供跑表使用
input func_key ;
//功能键, 1表示数字钟, 2表示跑表, 3表示调时, 4表示设置闹钟,5表示日期设置
input key1 ; //功能1时显示闹钟时间, 功能2时暂停, 功能3、4时调小时, 功能5时调月份
input key2 ; //功能1时显示日期, 功能2时清零, 功能3、4时调分, 功能5时调日
output [3:0] mode; //功能号指示
output [7:0] hour ; //功能1、3和4时显示小时, 功能2时显示分钟, 功能5时显示月份
output [7:0] minute; //功能1、3和4时显示分钟, 功能2时显示秒, 功能5时显示日期
output [7:0] second; //功能1时显示秒, 功能2时显示1/100秒, 其余时固定显示0
output alarm ; //连至扬声器, 整点报时及闹钟
reg[3:0] mode; //功能号指示(1~5)
reg[7:0] hour,minute,second;
reg[2:0] divide; //1 kHz信号10分频得100 Hz, 先5分频,再2分频
reg clk_100Hz; //100 Hz供跑表用
reg clk_500Hz; //500 Hz供准点报时时用
reg temp1,temp2,temp3;
wire funckey,adjust_key1,adjust_key2;
always@(posedge clk_1kHz)
begin
clk_500Hz=~clk_500Hz; //2分频
//由1 kHz分频得500 Hz时钟信号,整点报时使用
temp1=func_key;
temp2=key1;
temp3=key2;
if(divide==3'b101) // 5 分频
//由1 kHz分频得到100 Hz信号,用作跑表的时钟
begin
divide=0;clk_100Hz=~clk_100Hz;
end
else divide=divide+1;
end
assign funckey=func_key^temp1;
//将func_key(乒乓开关)转换为琴键开关开关,即每按动一次,相应引脚上的电平就翻转一 次。
//这里需将其变为琴键开关,即每按动一次将产生一个上跳脉冲,从而启动进程的运行
assign adjust_key1=key1^temp2; //将key1(乒乓开关)转换为琴键开关
assign adjust_key2=key2^temp3; //将key2(乒乓开关)转换为琴键开关
always@(posedge funckey)
begin
if(mode[2]&mode[0]) mode[2]=0; /// 101-->001
//功能号在1~5之间变化
else mode=mode+1;
end
//功能1与功能3:数字钟及时间设置, 功能3以外其他功能将不影响数字钟的运行
reg[5:0] h1; //功能1(数字钟)的时、分、秒
reg[6:0] m1,s1;
wire clk_1;
//数字钟时为1Hz时钟, 时间设置时为按调整键产生的脉冲
//即当不处于功能3时为1HZ时钟信号,处于功能3时为adjust-key1 or adjust_key2脉冲信号。
//这样,当将电子表调整到数字钟功能外的其他功能时将不会影响数字钟 的运行。
assign clk_1=(clk_1Hz&&mode!=3)||(mode==3&&(adjust_key1||adjust_key2));
always@(posedge clk_1)
begin
if(mode!=3) //数字钟
begin //23:59:59'时变为00:00:00 注意此处是BCD码
if(h1[5]&h1[1]&h1[0]&m1[6]&m1[4]&m1[3]&m1[0]&s1[6]&s1[4]&s1[3]&s1[0])
{h1,m1,s1}=0;
else
if(h1[3]&h1[0]&m1[6]&m1[4]&m1[3]&m1[0]&s1[6]&s1[4]&s1[3]&s1[0])
begin //*9:59:59'时小时加7,分、秒变为0为了数码管显示
h1=h1+7;m1=0;s1=0;
end
else
if(m1[6]&m1[4]&m1[3]&m1[0]&s1[6]&s1[4]&s1[3]&s1[0])
begin //59:59' 时分、秒为0,小时加1
h1=h1+1;m1=0;s1=0;
end
else if(m1[3]&m1[0]&s1[6]&s1[4]&s1[3]&s1[0])
begin //*9:59'时秒为0,分加7
m1=m1+7; s1=0;
end
else if(s1[6]&s1[4]&s1[3]&s1[0])
begin //59秒时秒为0,分加1
m1=m1+1;s1=0;
end
else if(s1[3]&s1[0]) s1=s1+7;//*9秒时秒加7
else s1=s1+1; //秒加1
end
else if(adjust_key1)//调时
begin
if(h1[5]&h1[1]&h1[0]) h1=0; //10_0011=23
else if(h1[3]&h1[0]) h1=h1+7; // 9
else h1=h1+1;
end
else if(adjust_key2)//调分
begin
if(m1[6]&m1[4]&m1[3]&m1[0]) m1=0;//调分
else if(m1[3]&m1[0]) m1=m1+7;
else m1=m1+1;
end
end
//功能2:跑表,key1作为暂停键,key2作为清零键
reg[6:0] h2,m2; /// 7 bit
//功能2(数字跑表)时的时、分、秒
reg[7:0] s2;
wire clk_2;
assign clk_2=clk_100Hz&&mode==2&&!key1;
//跑表的100 Hz时钟,key1此时为暂停键
always@(posedge clk_2)
begin
if(key2||(h2[6]&h2[4]&h2[3]&h2[0]&m2[6]&m2[4]&m2[3]&m2[0]&s2[7]&s2[4]&s2[3]&s2[0]))
{h2,m2,s2}=0;
//跑表时key2清零,59:59'99"时清零
else
if(h2[3]&h2[0]&m2[6]&m2[4]&m2[3]&m2[0]&s2[7]&s2[4]&s2[3]&s2[0])
begin /// 9:59'99"时
h2=h2+7;m2=0;s2=0; // 分转换成BCD
end
else
if(m2[6]&m2[4]&m2[3]&m2[0]&s2[7]&s2[4]&s2[3]&s2[0])
begin /// 59'99"时
h2=h2+1;m2=0;s2=0; // 够1分,其它清零
end
else if(m2[3]&m2[0]&s2[7]&s2[4]&s2[3]&s2[0])
begin /// 9'99"时
m2=m2+7; s2=0;
end
else if(s2[7]&s2[4]&s2[3]&s2[0])
begin // 99"时
m2=m2+1;s2=0;
end
else if(s2[3]&s2[0])// 9"时
s2=s2+7;
else s2=s2+1;
end
//功能4:闹钟设置,key1和key2分别用来调时和调分
reg[5:0] h4; //功能4(闹钟设置)时的时和分
reg[6:0] m4;
wire clk_key1,clk_key2;
assign clk_key1=adjust_key1 && mode==4;
//功能4时key1作为调时键
assign clk_key2=adjust_key2 && mode==4;
//功能4时key2作为调分键
always@(posedge clk_key1) //最大24小时
begin
if(h4[5]&h4[1]&h4[0]) h4=0; //23
else if(h4[3]&h4[0]) h4=h4+7; //*9
else h4=h4+1;
end
always@(posedge clk_key2) //最大60分
begin
if(m4[6]&m4[4]&m4[3]&m4[0]) m4=0;//60
else if(m4[3]&m4[0]) m4=m4+7; //*9
else m4=m4+1;
end
//功能5:调日期,key1和key2分别调月和调日
reg[4:0] month;
reg[5:0] day;
wire clk_key3,clk_key4;
assign clk_key3=adjust_key1 && mode==5;
//功能5时key1作为调月键
assign clk_key4=adjust_key2 && mode==5;
//功能5时key2作为调日键
always@(posedge clk_key3) //最大12个月
begin
if(month[4]&month[1]) month=1;
else if(month[3]&month[0]) month=month+7;
else month=month+1;
end
always@(posedge clk_key4) //每月按30天算
begin
if(day[5]&day[4]) day=1; //30
else if(day[3]&day[0]) day=day+7; //*9
else day=day+1;
end
//显示模块:在各功能号下分别显示相应的值
always@(h1 or m1 or s1 or h2 or m2 or s2 or h4 or m4 or
month or day or mode or key1 or key2)
begin
if(mode[2]|(mode[1]&mode[0])|(mode==1&(key1|key2)))
second=0; //功能3,4,5时固定显示0,功能1时显示闹钟时间 或者日期时显示为0
else if(mode==1) second=s1;//功能1时显示秒数
else second=s2; //功能2时显示1%秒,
if((mode==1 & !key1 &!key2) | mode==3) /// 数字钟模式下或者调时模式
begin
hour=h1;minute=m1;
end
else if(mode==2) /// 跑表
begin
hour=h2;minute=m2; //
end
else if(mode==4 | ((mode==1) & key1)) // 4表示设置闹钟,或者显示闹钟时间时
begin
hour=h4;minute=m4;
end
else
begin
hour=month;minute=day;//5表示日期设置时,显示月 和 天
end
end
//发声单元:整点报时和定点闹时
wire spk,temp4,temp5;
assign
temp4=m1[6]&m1[4]&m1[3]&m1[0]&s1[6]&s1[4]&!s1[0];
//59:50', 52', 54', 56', 58'时
assign
temp5=({m1,s1}==0)||((h1==h4)&&(m1==m4)&&!s1[0]);
//定时到时每隔1秒及整点时
assign spk=(temp4&&clk_500Hz)||(temp5&&clk_1kHz);
//整点及闹时送到扬声器的不同频率
assign alarm=(temp4||temp5)?spk:0;
//扬声器在整点及闹钟时间发出声响,, 其余时间为低
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -