Verilog数字钟

使用Verilog语言进行的数字钟的编写,FPGA开发板亲测正常

大学生一个,第一次自己做的东西,写出来分享在这里插入代码片一下,有不对的地方请大家批评指正。

这次的做的题是:设计一个数字钟,该数字钟能进行正常的时,分计时功能,且能对数字钟的时间进行调整。
该数字钟有3个按键,按键1为功能键,用于数字钟在“正常计时”,“时调整”,“分调整”这三个功能之间切换;按键2,3用于调整时间,仅当数字钟处于“时调整”或“分调整”时有效,分别对应加一和减一操作。

符号表示说明:时钟clk,模式切换键mode,加一键inc,减一键inc1,清零键clr,seg为译码器,hour为小时,min为分,sec为秒(十进制),hh为二进制中小时高位,hl为小时低位,mh为分高位,ml为分低位。inc_reg为inc的信号计数,inc1为inc的信号计数,state为状态表示。

源代码如下:
module clocka(seg0,clk,clr,mode,inc,inc1,seg1,seg2,seg3);
output[6:0] seg0,seg1,seg2,seg3;
input clk,mode,inc,clr,inc1;
reg[6:0]seg0,seg1,seg2,seg3;
reg[1:0]state;
reg[3:0]hh,hl,mh,ml,sh,sl;
reg clk1hz;
reg inc_reg;
reg inc1_reg;
reg[7:0]sec,min;
reg[7:0]hour;
parameter state0=2’b00,state1=2’b01,state2=2’b10;
reg[15:0]count1;
//1hz分频//
always@(posedge clk)
begin
if(count1=='d50000)
begin clk1hz<=~clk1hz;count1<=0;end
else
begin count1<=count1+1;end
end

//变换模式//
always@(posedge mode)
begin
if(clr)
begin state<=state0;end
else
begin state<=state+1;end
end
//状态控制//
always@(posedge clk1hz)
begin
if(clr)
begin hour<=0;min<=0;sec<=0;end
else begin
case(state)
state0:begin //正常计数
if(sec8’d59)
begin sec<='d0;
if(min
8’d59)
begin min<='d0;
if(hour8’d23)
begin hour<='d0;end
else begin hour=hour+1;end
end
else begin min<=min+1;end
end
else begin sec<=sec+1;end
end
state1:begin //设定小时时间
if(inc)
begin
if(!inc_reg)
begin inc_reg<=1;
if(hour
8’d23)
begin hour<=8’d0;end
else begin hour<=hour+1;end
end
end
else begin inc_reg<=0;end
if(inc1)
begin
if(!inc1_reg)
begin inc1_reg<=1;
if(hour8’d0)
begin hour<=8’d23;end
else begin hour<=hour-1;end
end
end
else begin inc1_reg<=0;end
end
state2:begin //设定分针
if(inc)
begin
if(!inc_reg)
begin inc_reg<=1;
if(min
8’d59)
begin min<=8’d0;end
else begin min<=min+1;end
end
end
else begin inc_reg<=0;end
if(inc1)
begin
if(!inc1_reg)
begin inc1_reg<=1;
if(min==8’d0)
begin min<=8’d59;end
else begin min<=min-1;end
end
end
else begin inc1_reg<=0;end
end
endcase
end
end
//分针十进制转BCD
always@(sec)
begin
case(min[7:0])
8’d0:begin mh[3:0]<='b0000;ml[3:0]<='b0000;end
8’d1:begin mh[3:0]<='b0000;ml[3:0]<='b0001;end
8’d2:begin mh[3:0]<='b0000;ml[3:0]<='b0010;end
8’d3:begin mh[3:0]<='b0000;ml[3:0]<='b0011;end
8’d4:begin mh[3:0]<='b0000;ml[3:0]<='b0100;end
8’d5:begin mh[3:0]<='b0000;ml[3:0]<='b0101;end
8’d6:begin mh[3:0]<='b0000;ml[3:0]<='b0110;end
8’d7:begin mh[3:0]<='b0000;ml[3:0]<='b0111;end
8’d8:begin mh[3:0]<='b0000;ml[3:0]<='b1000;end
8’d9:begin mh[3:0]<='b0000;ml[3:0]<='b1001;end
8’d10:begin mh[3:0]<='b0001;ml[3:0]<='b0000;end
8’d11:begin mh[3:0]<='b0001;ml[3:0]<='b0001;end
8’d12:begin mh[3:0]<='b0001;ml[3:0]<='b0010;end
8’d13:begin mh[3:0]<='b0001;ml[3:0]<='b0011;end
8’d14:begin mh[3:0]<='b0001;ml[3:0]<='b0100;end
8’d15:begin mh[3:0]<='b0001;ml[3:0]<='b0101;end
8’d16:begin mh[3:0]<='b0001;ml[3:0]<='b0110;end
8’d17:begin mh[3:0]<='b0001;ml[3:0]<='b0111;end
8’d18:begin mh[3:0]<='b0001;ml[3:0]<='b1000;end
8’d19:begin mh[3:0]<='b0001;ml[3:0]<='b1001;end
8’d20:begin mh[3:0]<='b0010;ml[3:0]<='b0000;end
8’d21:begin mh[3:0]<='b0010;ml[3:0]<='b0001;end
8’d22:begin mh[3:0]<='b0010;ml[3:0]<='b0010;end
8’d23:begin mh[3:0]<='b0010;ml[3:0]<='b0011;end
8’d24:begin mh[3:0]<='b0010;ml[3:0]<='b0100;end
8’d25:begin mh[3:0]<='b0010;ml[3:0]<='b0101;end
8’d26:begin mh[3:0]<='b0010;ml[3:0]<='b0110;end
8’d27:begin mh[3:0]<='b0010;ml[3:0]<='b0111;end
8’d28:begin mh[3:0]<='b0010;ml[3:0]<='b1000;end
8’d29:begin mh[3:0]<='b0010;ml[3:0]<='b1001;end
8’d30:begin mh[3:0]<='b0011;ml[3:0]<='b0000;end
8’d31:begin mh[3:0]<='b0011;ml[3:0]<='b0001;end
8’d32:begin mh[3:0]<='b0011;ml[3:0]<='b0010;end
8’d33:begin mh[3:0]<='b0011;ml[3:0]<='b0011;end
8’d34:begin mh[3:0]<='b0011;ml[3:0]<='b0100;end
8’d35:begin mh[3:0]<='b0011;ml[3:0]<='b0101;end
8’d36:begin mh[3:0]<='b0011;ml[3:0]<='b0110;end
8’d37:begin mh[3:0]<='b0011;ml[3:0]<='b0111;end
8’d38:begin mh[3:0]<='b0011;ml[3:0]<='b1000;end
8’d39:begin mh[3:0]<='b0011;ml[3:0]<='b1001;end
8’d40:begin mh[3:0]<='b0100;ml[3:0]<='b0000;end
8’d41:begin mh[3:0]<='b0100;ml[3:0]<='b0001;end
8’d42:begin mh[3:0]<='b0100;ml[3:0]<='b0010;end
8’d43:begin mh[3:0]<='b0100;ml[3:0]<='b0011;end
8’d44:begin mh[3:0]<='b0100;ml[3:0]<='b0100;end
8’d45:begin mh[3:0]<='b0100;ml[3:0]<='b0101;end
8’d46:begin mh[3:0]<='b0100;ml[3:0]<='b0110;end
8’d47:begin mh[3:0]<='b0100;ml[3:0]<='b0111;end
8’d48:begin mh[3:0]<='b0100;ml[3:0]<='b1000;end
8’d49:begin mh[3:0]<='b0100;ml[3:0]<='b1001;end
8’d50:begin mh[3:0]<='b0101;ml[3:0]<='b0000;end
8’d51:begin mh[3:0]<='b0101;ml[3:0]<='b0001;end
8’d52:begin mh[3:0]<='b0101;ml[3:0]<='b0010;end
8’d53:begin mh[3:0]<='b0101;ml[3:0]<='b0011;end
8’d54:begin mh[3:0]<='b0101;ml[3:0]<='b0100;end
8’d55:begin mh[3:0]<='b0101;ml[3:0]<='b0101;end
8’d56:begin mh[3:0]<='b0101;ml[3:0]<='b0110;end
8’d57:begin mh[3:0]<='b0101;ml[3:0]<='b0111;end
8’d58:begin mh[3:0]<='b0101;ml[3:0]<='b1000;end
8’d59:begin mh[3:0]<='b0101;ml[3:0]<='b1001;end
default:begin mh[3:0]<='bx;ml[3:0]<='bx;end
endcase
end

//时针十进制转BC
always@(sec)
begin
case(hour)
8’d0:begin hh[3:0]<='b0000;hl[3:0]<='b0000;end
8’d1:begin hh[3:0]<='b0000;hl[3:0]<='b0001;end
8’d2:begin hh[3:0]<='b0000;hl[3:0]<='b0010;end
8’d3:begin hh[3:0]<='b0000;hl[3:0]<='b0011;end
8’d4:begin hh[3:0]<='b0000;hl[3:0]<='b0100;end
8’d5:begin hh[3:0]<='b0000;hl[3:0]<='b0101;end
8’d6:begin hh[3:0]<='b0000;hl[3:0]<='b0110;end
8’d7:begin hh[3:0]<='b0000;hl[3:0]<='b0111;end
8’d8:begin hh[3:0]<='b0000;hl[3:0]<='b1000;end
8’d9:begin hh[3:0]<='b0000;hl[3:0]<='b1001;end
8’d10:begin hh[3:0]<='b0001;hl[3:0]<='b0000;end
8’d11:begin hh[3:0]<='b0001;hl[3:0]<='b0001;end
8’d12:begin hh[3:0]<='b0001;hl[3:0]<='b0010;end
8’d13:begin hh[3:0]<='b0001;hl[3:0]<='b0011;end
8’d14:begin hh[3:0]<='b0001;hl[3:0]<='b0100;end
8’d15:begin hh[3:0]<='b0001;hl[3:0]<='b0101;end
8’d16:begin hh[3:0]<='b0001;hl[3:0]<='b0110;end
8’d17:begin hh[3:0]<='b0001;hl[3:0]<='b0111;end
8’d18:begin hh[3:0]<='b0001;hl[3:0]<='b1000;end
8’d19:begin hh[3:0]<='b0001;hl[3:0]<='b1001;end
8’d20:begin hh[3:0]<='b0010;hl[3:0]<='b0000;end
8’d21:begin hh[3:0]<='b0010;hl[3:0]<='b0001;end
8’d22:begin hh[3:0]<='b0010;hl[3:0]<='b0010;end
8’d23:begin hh[3:0]<='b0010;hl[3:0]<='b0011;end
default:begin hh[3:0]<='bx;hl[3:0]<='bx;end
endcase
end

//七段译码
always@(sec)
begin
case(ml)
4’b0000:seg0[6:0]=7’b0000001;
4’b0001:seg0[6:0]=7’b1001111;
4’b0010:seg0[6:0]=7’b0010010;
4’b0011:seg0[6:0]=7’b0000110;
4’b0100:seg0[6:0]=7’b1001100;
4’b0101:seg0[6:0]=7’b0100100;
4’b0110:seg0[6:0]=7’b0100000;
4’b0111:seg0[6:0]=7’b0001111;
4’b1000:seg0[6:0]=7’b0000000;
4’b1001:seg0[6:0]=7’b0000100;
default:seg0[6:0]=7’b1111111;
endcase
end
always@(sec)
begin
case(mh)
4’b0000:seg1[6:0]=7’b0000001;
4’b0001:seg1[6:0]=7’b1001111;
4’b0010:seg1[6:0]=7’b0010010;
4’b0011:seg1[6:0]=7’b0000110;
4’b0100:seg1[6:0]=7’b1001100;
4’b0101:seg1[6:0]=7’b0100100;
4’b0110:seg1[6:0]=7’b0100000;
4’b0111:seg1[6:0]=7’b0001111;
4’b1000:seg1[6:0]=7’b0000000;
4’b1001:seg1[6:0]=7’b0000100;
default:seg1[6:0]=7’b1111111;
endcase
end
always@(sec)
begin
case(hl)
4’b0000:seg2[6:0]=7’b0000001;
4’b0001:seg2[6:0]=7’b1001111;
4’b0010:seg2[6:0]=7’b0010010;
4’b0011:seg2[6:0]=7’b0000110;
4’b0100:seg2[6:0]=7’b1001100;
4’b0101:seg2[6:0]=7’b0100100;
4’b0110:seg2[6:0]=7’b0100000;
4’b0111:seg2[6:0]=7’b0001111;
4’b1000:seg2[6:0]=7’b0000000;
4’b1001:seg2[6:0]=7’b0000100;
default:seg2[6:0]=7’b1111111;
endcase
end
always@(sec)
begin
case(hh)
4’b0000:seg3[6:0]=7’b0000001;
4’b0001:seg3[6:0]=7’b1001111;
4’b0010:seg3[6:0]=7’b0010010;
4’b0011:seg3[6:0]=7’b0000110;
4’b0100:seg3[6:0]=7’b1001100;
4’b0101:seg3[6:0]=7’b0100100;
4’b0110:seg3[6:0]=7’b0100000;
4’b0111:seg3[6:0]=7’b0001111;
4’b1000:seg3[6:0]=7’b0000000;
4’b1001:seg3[6:0]=7’b0000100;
default:seg3[6:0]=7’b1111111;
endcase
end
endmodule

重点代码解释
首先对于时钟分频问题,因为时钟clk原始频率过高,所以需分频,设置一个信号clk1hz,当时钟信号的上升沿来临,判断是否到所设置的数,如果不够则+1,如果够,则将信号clk1hz产生一个上升沿,将clk1hz作为一个时钟,就解决了分频的问题。
设置mode按键,并定义3个状态,分别为正常状态,调时状态,调分状态,初始状态为state0:正常状态,进行正常计时,主要考虑就是进位问题,使用if语句与begin语句结合使用可以编程,较为简单。
接着是调整时间的state1和state2状态比较难以解决,原因是因为时序的问题不好解决,无法控制加一和减一键的正确使用。
解决的方法就是使用inc_reg信号,以小时调整为例,在state1状态下,当按下按键加一键inc时,inc变为高电平,在inc_reg为0前提下,将inc_reg从0变为1,并接着进行小时加一的操作,完成此步后,因为clk1hz的时钟信号会来临很多次,inc也持续为高电平,但是因为不满足inc_reg为0的前提,不执行加一的操作,当inc变为低电平时,会将inc_reg变回0,那么下一次按下加一键时仍会执行一次的加一操作,真正使得一次按键执行一次加一操作变为可执行,解决时序问题。其他情况同理如此。
之后因为使用的是十进制所以需要将其转化为二进制BCD码,同时因为最后显示的是4个数码管,所以需分高低位。
转码完成后,进行数码管的译码操作,最后整个编程完毕。

你可能感兴趣的:(硬件开发)