ISE实现多功能数字钟设计.docx
《ISE实现多功能数字钟设计.docx》由会员分享,可在线阅读,更多相关《ISE实现多功能数字钟设计.docx(19页珍藏版)》请在冰豆网上搜索。
ISE实现多功能数字钟设计
一、任务要求
用FPGA器件和EDA技术实现多功能数字钟的设计。
基本功能要求:
能显示小时、分钟、秒钟(时、分用7段LED显示器,秒用LED灯)。
小时计数器为同步24进制;
要求手动校时、校分。
扩展功能要求:
任意时刻闹钟;
小时显示(12/24)切换电路
自动报整点时数。
二、建立工程
在ISE14,9软件中建立名为clock的工程文件。
芯片系列选择Spatan3E,具体芯片型号选择XC3S100E,封装类型选择CP132,速度信息选择—5。
三、原理设计
四、顶层模块设计
创建名为top_clock的文件,本设计中顶层模块用于调用各个子模块,以及将闹钟与整点报时模块综合在内,顶层源码如下:
moduletop_clock(
inputHchange,//24小时,12小时切换信号
inputChange,//用来进行时分和秒的显示切换
inputCLK_50,//50MHz时钟
inputnCR,EN,Clock_EN,
inputAdj_Min,Adj_Hour,Adj_Clock,//使能信号,小时分钟调时允许信号,闹钟使能信号(拨钮开关)
output[6:
0]HEX0,
outputregLed_Alarm,
outputreg[3:
0]HEX//共阳极数码管对应端
);
regAlarm;
wireENM_L,ENM_H,ENH;
wire[7:
0]Hour_24,TMinute,TSecond,CHour,CMinute;//中间变量声明,正常时钟变量和闹钟时钟变量
wire[7:
0]Hour_12,Display_HourT,Display_HourAdjust;
reg[3:
0]bcd=4’b0000;//记载数码管所要显示的数据
reg[7:
0]Display_Hour,Minute;
regLD_6_RADIO;
reg[7:
0]sum,counter;
supply1Vdd;
wireCP_1Hz;
//===========分频=============
Divider50MHzU0(。
CLK_50M(CLK_50),
。
nCLR(nCR),
。
CLK_1HzOut(CP_1Hz));//用以时钟计数的CP
defparamU0.N=25,
U0.CLK_Freq=50000000,
U0.OUT_Freq=1;
Divider50MHzU1(.CLK_50M(CLK_50),
。
nCLR(nCR),
。
CLK_1HzOut(CP_200Hz));//用以动态扫描的CP,供给数码管
defparamU1.N=18,
U1.CLK_Freq=50000000,
U1。
OUT_Freq=200;
//===========60进制秒计数器=========
Scounter10S0(TSecond[3:
0],nCR,EN,CP_1Hz);//秒:
个位
Scounter6S1(TSecond[7:
4],nCR,(TSecond[3:
0]==4'h9),CP_1Hz);//秒:
十位
//===========60进制分计数器=========
Mcounter10M0(TMinute[3:
0],nCR,ENM_L,EN,CP_1Hz);//分:
个位
Mcounter6M1(TMinute[7:
4],nCR,ENM_H,EN,CP_1Hz);//分:
十位
assignENM_L=Adj_Min?
Vdd:
(TSecond==8’h59);//分钟按书上CP调时
assignENM_H=(Adj_Min&&(TMinute[3:
0]==4’h9))||(TMinute[3:
0]==4'h9)&&(TSecond==8'h59);//24小时制
counter24H0(Hour_24[7:
4],Hour_24[3:
0],nCR,ENH,EN,CP_1Hz);
assignENH=Adj_Hour?
Vdd:
((TMinute==8'h59)&&(TSecond==8’h59));
//===========12小时与24小时进制切换控制==========
assignDisplay_HourAdjust=((Hour_24==8'h20)||(Hour_24==8'h21))?
(Hour_24—24):
(Hour_24—18);
assignHour_12=(Hour_24〈8'h13)?
Hour_24:
Display_HourAdjust;
assignDisplay_HourT=Hchange?
Hour_12:
Hour_24;
//===========闹钟============
//——-—-—-—-—时钟秒--——---—-
//counter60CCS(nCR,CP_1Hz,EN,CSecond[7:
4],CSecond[3:
0]);
//——--——--——时钟分—--—-—-——
counter60CCM(nCR,CP_1Hz,CMin_EN,CMinute[7:
4],CMinute[3:
0]);
//--产生分使能信号—-
assignCMin_EN=(!
EN&&Adj_Clock&&Adj_Min);
//-—-—-——--—时钟时—-—-—-———
Counter24CCCH(nCR,CP_1Hz,CHour_EN,CHour[7:
4],CHour[3:
0]);
//——产生时使能信号——
assignCHour_EN=(!
EN&&Adj_Clock&&Adj_Hour);
//-—闹钟响-—
always@(ENorClock_EN)//闹钟开关
begin
if(EN&&Clock_EN&&(CHour==Display_HourT)&&(CMinute==TMinute))Alarm<=1;
elseAlarm<=0;
end
always@(posedgeCLK_50ornegedgeENornegedgeAlarm)//表示闹钟的LED
begin
if(~EN)Led_Alarm<=0;
else
begin
if(~Alarm)Led_Alarm<=0;
elseLed_Alarm<=~Led_Alarm;
end
end
//alarm_clockAL0(Hour24,Minute,CP_1Hz,Set_Alarm,Close_clock,nCR,KeySet_Hour_ev,KeySet_Minute_ev,LD_7,Alarm_Hour,Alarm_Minute);
//===========数码显示=========
always@(Adj_Clock)//确定数码管显示闹钟还是正常时钟
begin
if(Adj_Clock)beginDisplay_Hour〈=CHour;Minute〈=CMinute;end
elsebeginDisplay_Hour<=Display_HourT;Minute〈=TMinute;end
end
always@(posedgeCP_200Hz)
begin
if(Change==1)//数码管进行时分显示
begin
case(HEX)
4’b1110:
beginHEX〈=4’b0111;bcd〈=Display_Hour[7:
4];end//第一根数码管显示小时十位
4’b0111:
beginHEX〈=4’b1011;bcd〈=Display_Hour[3:
0];end//第二根显示小时个位
4’b1011:
beginHEX<=4’b1101;bcd<=Minute[7:
4];end//第三根显示分钟十位
4'b1101:
beginHEX〈=4'b1110;bcd〈=Minute[3:
0];end//第四根显示分钟个位
default:
beginHEX<=0111;bcd<=Display_Hour[7:
4];end
endcase
end
else//数码管进行秒显示,change为低电平时显示秒
begin
case(HEX)
4'b1110:
beginHEX〈=4’b1101;bcd〈=TSecond[7:
4];end//第三根显示秒十位
4’b1101:
beginHEX<=4’b1110;bcd〈=TSecond[3:
0];end//第四根显示秒个位
default:
beginHEX<=1101;bcd〈=TSecond[7:
4];end
endcase
end
end
SEG7_LUTL0(HEX0,bcd);//调用数码管子函数
//======整点报时==========
assignLD_6=LD_6_RADIO;
always@(CP_1Hz)
begin
if((Minute[7:
0]==8’h00)&&(counter[7:
0]〈(Hour_24[7:
4]*10+Hour_24[3:
0])))
begin
LD_6_RADIO〈=CP_1Hz;
end
else
begin
LD_6_RADIO<=0;
end
end
always@(posedgeCP_1Hz)
if(Minute[7:
0]==8'h00)
begin
counter[7:
0]<=counter[7:
0]+1'b1;
end
else
begin
counter[7:
0]〈=8’h00;
end
endmodule
五、顶层模块设计图
六、子模块设计
1、50MHz分频器
moduleDivider50MHz(CLK_50M,nCLR,CLK_1HzOut);
parameterN=25;//位宽
parameterCLK_Freq=50000000;//50MHz时钟输入
parameterOUT_Freq=1;//1Hz时钟输出
inputnCLR,CLK_50M;//输入端口说明
outputregCLK_1HzOut;//输出端口说明
reg[N-1:
0]Count_DIV;//内部节点,存放计数器的输出值
always@(posedgeCLK_50MornegedgenCLR)
begin
if(!
nCLR)beginCLK_1HzOut〈=0;Count_DIV<=0;end
elsebegin
if(Count_DIV<(CLK_Freq/(2*OUT_Freq)—1))//计数器模
Count_DIV〈=Count_DIV+1'b1;//分频器计数加1
elsebegin
Count_DIV<=0;//分频器输出清零
CLK_1HzOut〈=~CLK_1HzOut;//输出信号取反
end
end
end
endmodule
2、秒模10计数器
moduleScounter10(Q,nCR,EN,CP);
inputCP,nCR,EN;
outputQ;
reg[3:
0]Q;
always@(posedgeCPornegedgenCR)
begin
if(~nCR)Q〈=4’b0000;//异步清零
elseif(~EN)Q〈=Q;//暂停计数
elseif(Q==4’b1001)Q<=4'b0000;
elseQ〈=Q+1’b1;
end
3、秒模6计数器
moduleScounter6(Q,nCR,EN,CP);
inputCP,nCR,EN;
outputQ;
reg[3:
0]Q;
always@(posedgeCPornegedgenCR)
begin
if(~nCR)Q〈=4’b0000;//异步清零
elseif(~EN)Q<=Q;//暂停计数
elseif(Q==4'b0101)Q<=4'b0000;
elseQ〈=Q+1'b1;
end
4、分模10计数器
moduleMcounter10(Q,nCR,EN1,EN2,CP);
inputCP,nCR,EN1,EN2;
outputQ;
reg[3:
0]Q;
always@(posedgeCPornegedgenCR)
begin
if(~nCR)Q〈=4’b0000;//异步清零
elseif(~EN1||!
EN2)Q<=Q;//暂停计数
elseif(Q==4'b1001)Q〈=4'b0000;
elseQ〈=Q+1'b1;
end
5、分模6计数器
moduleMcounter6(Q,nCR,EN1,EN2,CP);
inputCP,nCR,EN1,EN2;
outputQ;
reg[3:
0]Q;
always@(posedgeCPornegedgenCR)
begin
if(~nCR)Q〈=4'b0000;//异步清零
elseif(~EN1||~EN2)Q〈=Q;//暂停计数
elseif(Q==4'b0101)Q〈=4'b0000;
elseQ<=Q+1’b1;
end
6、模24计数器
modulecounter24(CntH,CntL,nCR,EN1,EN2,CP);
inputCP,nCR,EN1,EN2;
outputreg[3:
0]CntH,CntL;//小时的十位和个位输出
always@(posedgeCPornegedgenCR)
begin
if(~nCR){CntH,CntL}<=8'h00;//异步清零
elseif(~EN1||~EN2){CntH,CntL}〈={CntH,CntL};//暂停计数
elseif((CntH)>2||(CntL>9)||(CntH)==2&&(CntL)〉=3)
{CntH,CntL}<=8’h00;//对小时计数器出错时的处理
elseif((CntH)==2&&(CntL)〈3)//进行20~23计数
beginCntH〈=CntH;CntL〈=CntL+1’b1;end
elseif(CntL==9)//小时十位的计数
beginCntH<=CntH+1’b1;CntL<=4’b0000;end
else
beginCntH〈=CntH;CntL<=CntL+1'b1;end
end
endmodule
7、模60计数器
modulecounter60(nCLR,Clk,EN,CntH,CntL);
inputnCLR,Clk,EN;
outputreg[3:
0]CntH,CntL;
always@(posedgeClkornegedgenCLR)
begin
if(~nCLR)
{CntH,CntL}<=0;//异步清零
elseif(~EN)
{CntH,CntL}<={CntH,CntL};//暂停信号
elseif(((CntH>5)||(CntL>9))||((CntH==5)&&(CntL==9)))
{CntH,CntL}〈=8’h00;//异常处理
elseif(CntL==9)
beginCntH〈=CntH+1'b1;CntL〈=0;end//十位计数
else
beginCntH<=CntH;CntL〈=CntL+1'b1;end//个位计数
end
endmodule
8、数码管显示
moduleSEG7_LUT(oSEG,iDIG);
input[3:
0]iDIG;//二进制输入
outputreg[6:
0]oSEG;//7段码输出
always@(iDIG)
begin
case(iDIG)
4'h0:
oSEG=7'b000_0001;
4'h1:
oSEG=7'b100_1111;
4’h2:
oSEG=7’b001_0010;
4’h3:
oSEG=7’b000_0110;
4’h4:
oSEG=7'b100_1100;
4'h5:
oSEG=7'b010_0100;
4'h6:
oSEG=7'b010_0000;
4'h7:
oSEG=7'b000_1111;
4'h8:
oSEG=7’b000_0000;
4'h9:
oSEG=7’b000_0100;
default:
oSEG=7'b1111111;
endcase
end
endmodule
七、各模块仿真
1、模10计数器
测试代码:
//Inputs
regnCR;
regEN;
regCP;
//Outputs
wire[3:
0]Q;
//InstantiatetheUnitUnderTest(UUT)
counter10uut(
。
Q(Q),
。
nCR(nCR),
。
EN(EN),
。
CP(CP)
);
parameterPERIOD=40;//时钟信号周期设置为40ns
alwaysbegin
CP=1'b0;
#(PERIOD/2)CP=1’b1;
#(PERIOD/2);
end
initialbegin
//InitializeInputs
nCR=0;
EN=1;
CP=1;
//Wait100nsforglobalresettofinish
#100;
nCR=1;
//Addstimulushere
end
endmodule
2、模6计数器
测试代码:
//Inputs
regnCR;
regEN;
regCP;
//Outputs
wire[3:
0]Q;
//InstantiatetheUnitUnderTest(UUT)
counter6uut(
.Q(Q),
.nCR(nCR),
。
EN(EN),
.CP(CP)
);
parameterPERIOD=40;//时钟信号周期设置为40ns
alwaysbegin
CP=1’b0;
#(PERIOD/2)CP=1'b1;
#(PERIOD/2);
end
initialbegin
//InitializeInputs
nCR=0;
EN=1;
CP=1;
//Wait100nsforglobalresettofinish
#100;
nCR=1;
//Addstimulushere
end
endmodule
3、模24计数器
测试代码:
//Inputs
regnCR;
regEN;
regCP;
//Outputs
wire[3:
0]CntH;
wire[3:
0]CntL;
//InstantiatetheUnitUnderTest(UUT)
counter24uut(
。
CntH(CntH),
。
CntL(CntL),
。
nCR(nCR),
.EN(EN),
.CP(CP)
);
parameterPERIOD=40;//时钟信号周期设置为40ns
alwaysbegin
CP=1'b0;
#(PERIOD/2)CP=1’b1;
#(PERIOD/2);
end
initialbegin
//InitializeInputs
nCR=0;
EN=1;
CP=1;
//Wait100nsforglobalresettofinish
#100;
nCR=1;
//Addstimulushere
end
endmodule
4、模60计数器
测试代码:
//Inputs
regnCLR;
regClk;
regEN;
//Outputs
wire[3:
0]CntH;
wire[3:
0]CntL;
//InstantiatetheUnitUnderTest(UUT)
counter60uut(
。
nCLR(nCLR),
。
Clk(Clk),
。
EN(EN),
。
CntH(CntH),
。
CntL(CntL)
);
parameterPERIOD=40;//时钟信号周期设置为40ns
alwaysbegin
Clk=1'b0;
#(PERIOD/2)Clk=1'b1;
#(PERIOD/2);
end
initialbegin
//InitializeInputs
nCLR=0;
Clk=1;
EN=1;
//Wait100nsforglobalresettofinish
#100;
nCLR=1;
//Addstimulush