EDA课程设计多功能数字钟设计程序清单数字系统设计与verilogHDL第四版王金明.docx
《EDA课程设计多功能数字钟设计程序清单数字系统设计与verilogHDL第四版王金明.docx》由会员分享,可在线阅读,更多相关《EDA课程设计多功能数字钟设计程序清单数字系统设计与verilogHDL第四版王金明.docx(14页珍藏版)》请在冰豆网上搜索。
![EDA课程设计多功能数字钟设计程序清单数字系统设计与verilogHDL第四版王金明.docx](https://file1.bdocx.com/fileroot1/2023-1/27/5c265477-159d-4b92-a0ff-d3ac14563818/5c265477-159d-4b92-a0ff-d3ac145638181.gif)
EDA课程设计多功能数字钟设计程序清单数字系统设计与verilogHDL第四版王金明
EDA课程设计
多功能数字钟设计程序清单
数字系统设计与verilogHDL(第四版)王金明
/*引脚锁定基于DE2一70,芯片为EP2C70F896,信号定义如下:
Clk50m:
50MHz时钟输,
mode:
模式选择0:
计时模式1:
设置闹钟模式
mcheck:
手动调整时间
turn:
手动调整时间,在时、分之间选择
change:
对选中的数据调整
ledhourl,led_hour0,led_minul,led_minu0,led_secl,ledsec0;
alert:
闹钟输出
ld_alert:
是否设置了闹钟
ld_hour,id_min,ld_sec:
在调整时,指示选中了时,分还是秒*/
moduleclock(clk50m,mode,turn,change,mreset,led_hour1,led_hour0,led_minu1,led_minu0,led_sec1,led_sec0,alert,ld_alert,ld_check,ld_hour,ld_min,ld_sec);
inputclk50m;
inputmode;//key0键
inputturn;//keyl键
inputchange;//key2键
inputmreset;//switch0复位,低电平有效
outputalert;//gpioO->IOAO
outputld_alert;//ledgO-led19
outputld_check;//ledgl-led22
outputld_hour;//ledr3-led13
outputld_min;//ledr9-led9
outputld_sec;//ledr7-led7
output[6:
0]led_hour1;
output[6:
0]led_hour0;
output[6:
0]led_minu1;
output[6:
0]led_minu0;
output[6:
0]led_sec1;
output[6:
0]led_sec0;
reg[1:
0]modestate;
//00:
计时模式10:
闹钟模式;01:
手动调整模式;11:
非法模式
wirenowmode;//记录当前模式,0:
计时模式;1:
设置闹钟模式
wireischecking;//是否在手动调整时间
assign{nowmode,ischecking}=modestate;
always@(negedgemode)//两个按钮都是低电平有效
begin
case(modestate)
2'b00:
modestate<=2'b10;//设置闹钟模式优先
2'b10:
modestate<=2'b01;//手动调整模式
2'b01:
modestate<=2'b00;
default:
modestate<=2'b00;
endcase
end
wirereset,clk_1hz;
switch#(8)rmjitter(clk50m,mresetr,reset);
clk50mtolgenlhz(clk50m,clk_1hz);//生成1Hz的时钟
wire[2:
0]selcode;//对turn信号在不同模式
bitselseldecoder(nowmode,ischecking,turn,selcode,reset);
wire[3:
0]clocktime0,clocktimel,clocktime2,clocktime3,clocktime4,clockthre5;
//计时输出的时钟数值
wireclockalarmon;//整点报时的闹钟输出
wire[2:
0]counterselcode;
assigncounterselcode=(modestate==2'b01)?
selcode:
3'b000;
counter_timeclock_time(clk_1hz,counterselcode,~change,clocktime5,clocktime4,clocktime3,clocktime2,clocktime1,clocktime0,clockalarmon,reset);
wire[3:
0]alarmtime0,alarmtime1,alarmtime2,alarmtime3;
wirealarmon;
alarm_timealarm_time(clk_1hz,nowmode,selcode[2:
1],change,
{clocktime5,clocktime4,clocktime3,clocktime2,clocktime1},
{alarmtime3,alarmtime2,alarmtime1,alarmtime0},alarmon,reset);
wirevoiceout;
alarmalarmvoice(clk50m,{clockalarmon,alarmon},voiceout,raset);
//显示输出部分
assign{ld_hour,ld_min,ld_sec}=(ischecking||nowmode)?
selcode:
3'b000;
assignalert=voiceout;
reg[3:
0]showout2,showout3,showout4,showout5;
ledled5(showout5,led_hour1);//led译码显示
ledled4(showout4,led_hour0);
ledled3(showout3,led_minu1);
ledled2(showout2,led_minu0);
ledled1(clocktime1,led_sec1);
ledled0(clocktime0,led_sec0);
always
beginif(nowmode)
beginshowout5=alarmtime3;showout4=alarmtime2;
showout3=alarmtime1;showout2=alarmtime0;end
elsebegin
showout5=clocktime5;showout4=clocktime4;
showout3=clocktime3;showout2=clocktime2;end
end
assignld_alert=nowmode;assignld_check=ischecking;
endmodule
/*alarm.V:
闹铃模块
Clk50m:
50MHz输入时钟
alarmon:
闹铃是否打开,2'b00:
不打开:
2'b01:
闹钟;2'b10:
整点报时
alarmoUt:
闹铃声音输出*/
modulealarm(clk50m,alarmon,alarmout,reset);
input[1:
0]alarmon;
inputclk50m,reset;
outputregalarmout;
reg[15:
0]counter_1k;
wireclk_1k;
assignclk_1k=counter_1k[4];
always@(posedgeclk50m)
beginif(counter_1k==20)counter_1k<=0;
elsecounter_1k<=counter_1k+1'b1;end
wireddd_du_out,ddd_out;
sound_ddd_duddd_du(clk_1k,alarmon[1],ddd_du_out);
sound_dddddd(clk_1k,alarmon[0],ddd_out);
always
beginif(!
reset)
beginif(alarmon[0]==1'b1)//ddd,闹钟的响铃优先级更高
alarmout=ddd_out;
elseif(alarmon==2'b10)alarmout=ddd_du_out;
elsealarmout=0;
endelsealarmout=0;
end
endmodule
/*alarm_time.V:
闹钟时间设定模块
enable:
使能信号
Sel:
在时、分之间切换选择10:
时;01:
分
inc:
对选中的信号自增
basetime:
基准时钟*/
modulealarm_time(clk_1hz,enable,sel,inc,basetime,alarmouttime,alarm_on,reset);
inputclk_1hz,enable,inc,reset;
input[1:
0]sel;
input[4*5-1:
0]basetime;
outputregalarm_on;
output[4*4-1:
0]alarmouttime;
reg[3:
0]hour1,hour0,minu1,minu0;//存储的设定时间
always@(posedgeincorposedgereset)
beginif(reset)//reset=1时复位
begin{hour1,hour0,minu1,minu0}<=16'h0;end
elsebegin
if(enable)begin
if(sel==2'b10)//设置时
beginif({hour1,hour0}==8'h23){hour1,hour0}<=8'h00;
elseif(hour0==9)
beginhour0<=0;hour1<=hour1+1'b1;end
elsehour0<=hour0+1'b1;
end
elseif(sel===2'b01)//设置分
beginif({minu1,minu0}==8'h59){minu1,minu0}<=8'h00;
elseif(minu0==4'h9)
beginminu0<=4'h0;minu1<=minu1+4'h1;end
elseminu0<=minu0+4'h1;end
else{hour1,hour0,minu1,minu0}<=16'h0;
endend
end
always//闹钟开始条件
begin
if(({hour1,hour0,minu1,minu0}==basetime[(4*5-1):
4])&&(basetime[3:
0]<2))
alarm_on=1'b1;
elsealarm_on=1'b0;end
assignalarmouttime={hour1,hour0,minu1,minu0};
endmodule
/*countertime,v:
计时模块,并留有调整接;
check:
调整信号,3位,分别调整时、分、秒,调整方法:
将计数输出给加法器,把调整信息
转换成异步置数信息,将加法器的输出作为置数值;
hour1,hour0,minul,minu0,sec1,sec0:
输出的计时时钟;
alarmout:
整点报时输出*/
modulecounter_time(clk_1hz,check,inc,hour1,hour0,minu1,minu0,sec1,sec0,alarmout,reset);
inputclk_1hz,inc,reset;
input[2:
0]check;
output[3:
0]hour1,hour0,minu1,minu0,sec1,sec0;
outputregalarmout;
regclk_1hz_md;
wire[6:
0]carryclk;
reg[5:
0]incplus;//自增脉冲
wire[5:
0]carry;//进位时钟
wire[3:
0]adderout0,adderout1,adderout2,adderout3,adderout4,adderout5;
wire[3:
0]timerout0,timerout1,timerout2,timerout3,timerout4,timerout5;
hexcountercounter_sec0(carryclk[0],reset,4'd9,4'b0,timerout0,carry[0]);
hexcountercounter_sec1(carryclk[1],reset,4'd5,4'b0,timerout1,carry[1]);
hexcountercounter_minu0(carryclk[2],reset,4'd9,4'b0,timerout2,carry[2]);
hexcountercounter_minu1(carryclk[3],reset,4'd5,4'b0,timerout3,carry[3]);
wire[3:
0]hour0max;
assignhour0max=(timerout5==4'h2)?
(4'h3):
(4'h9);
hexcountercounter_hour0(carryclk[4],reset,hour0max,4'b0,timerout4,carry[4]);
hexcountercounter_hour1(carryclk[5],reset,4'd2,4'b0,timerout5,carry[5]);
//每个计时器的时钟,由前级进位和自堦脉冲相加得到
assigncarryclk[0]=(check==4'h0)?
clk_1hz_md:
incplus[0];
assigncarryclk[1]=carry[0]|incplus[1];
assigncarryclk[2]=(check==4'h0)?
carry[1]:
incplus[2];
assigncarryclk[3]=carry[2]|incplus[3];
assigncarryclk[4]=(check==4'h0)?
carry[3]:
incplus[4];
assigncarryclk[5]=carry[4]|incplus[5];
always//对异步置位信号进行解码
begincase(check)
3'b001:
beginclk_1hz_md=0;
incplus={5'b00000,inc};end
3'b010:
beginclk_1hz_md=0;
incplus={3'b000,inc,2'b00};end
3'b100:
begin//在正常的调节状态中
clk_1hz_md=0;
incplus={1'b0,inc,4'b000};end
default:
beginincplus=6'b000000;
clk_1hz_md=clk_1hz;
end
endcase
end
alwaysbeginif(((reset|check)==0)&&(timerout3==0)&&(timerout2==0)&&(timerout1<2))alarmout=1;
//时间小于20秒的时间内
elsealarmout=0;end
assignhour1=timerout5;
assignhour0=timerout4;
assignminu1=timerout3;
assignminu0=timerout2;
assignsec1=timerout1;
assignsec0=timerout0;
endmodule
/*Clk50mtol.v:
50mhz时钟分频到lhz*/
moduleclk50mtol(clk50m,clk1hz);
inputclk50m;
outputclk1hz;
reg[25:
0]counter_1hz;//从50mhz分频到lhz的计数器
assignclk1hz=counter_1hz[14];//assignclk1hz=counter_1hz[25];
always@(posedgeclk50m)
begin
if(counter_1hz==20000)counter_1hz<=0;
elsecounter_1hz<=counter_1hz+1'b1;
end
endmodule
/*led.v:
7段数码管(led)译码显示模块
datain:
4位,10进制数输入
ledout:
7位,数码管的7段*/
moduleled(datain,ledout);
parameterINWIDTH=4;
parameterOUTWIDTH=7;
input[INWIDTH-1:
0]datain;
output[OUTWIDTH-1:
0]ledout;
reg[OUTWIDTH-1:
0]dataout;
assignledout=dataout;
alwaysbegin
case(datain)
0:
dataout<=7'b1000000;
1:
dataout<=7'b1111001;
2:
dataout<=7'b0100100;
3:
dataout<=7'b0110000;
4:
dataout<=7'b0011001;
5:
dataout<=7'b0010010;
6:
dataout<=7'b0000010;
7:
dataout<=7'b1111000;
8:
dataout<=7'b0000000;
9:
dataout<=7'b0010000;
default:
dataout<=7'b1000000;
endcase
end
endmodule
/*switch-v:
对按键开关的消抖电路,采用一个频率较低的时钟,
对输入进行采样,消除抖动*/
moduleswitch(clk,keyin,keyout);
parameterCOUNTWIDTH=8;
inputclk,keyin;
outputregkeyout;
reg[COUNTWIDTH-1:
0]counter;
wireclk_use;//频率较低的时钟
assignclk_use=counter[COUNTWIDTH-1];
always@(posedgeclk)
counter<=counter+1'b1;
always@(posedgeclk_use)
keyout<=keyin;
endmodule
/*bitsel-v:
将输出解码成对时、分、秒的选择(并且分闹钟设置模式还是计时模式)
Alarmmode:
是否是在设置闹钟模式
checkmode:
是否是在调整时间模式*/
modulebitsel(alarmmode,checkmode,sel,selcode,reset);
inputalarmmode,checkmode,sel,reset;
outputreg[2:
0]selcode;
reg[2:
0]check_code;
reg[1:
0]alarm_code;
always@(negedgeselorposedgereset)
beginif(reset)check_code<=3'b000;//reset=1复位
elsebegin
case(check_code)
3'b000:
check_code<=3'b001;
3'b001:
check_code<=3'b010;
3'b010:
check_code<=3'b100;
3'b100:
check_code<=3'b001;
default:
check_code<=3'b000;
endcase
end
end
always@(negedgeselorposedgereset)
beginif(reset)alarm_code<=2'b00;//低电平复位
elsebegin
case(alarm_code)
2'b00:
alarm_code<=2'b01;
2'b01:
alarm_code<=2'b10;
2'b10:
alarm_code<=2'b01;
default:
alarm_code<=2'b00;
endcase
end
end
always
beginif(alarmmode^checkmode)//两个当中只有1个为1
beginif(checkmode)selcode=check_code;
elseselcode={alarm_code,1'b0};end
elseselcode=3'b000;
end
endmodule
/*adder.v:
加法器*/
moduleadder(in1,in2,out);
parameterin1width=8;
parameterin2width=8;
parameteroutwidth=8;
input[in1width-1:
0]in1;
input[in2width-1:
0]in2;
output[outwidth-1:
0]out;
assignout=in1+in2;
endmodule
/*excounter-v:
16进制计数的一个计数器*/
modulehexcounter(clk,set,max,setdata,dataout,carryout);
inputclk,set;
input[3:
0]max,setdata;
outputcarryout;
output[3:
0]dataout;
reg[3:
0]counter;
regcarrybit;
assigncarryout=carrybit;
assigndataout=counter;
always@(posedgeclkorposedgeset)
beginif(set)//set是高电平有效
begincounter<=setdata;
carrybit<=0;