Verilog数字钟

mac2024-03-06  33

使用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(min8’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(hour8’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(min8’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个数码管,所以需分高低位。 转码完成后,进行数码管的译码操作,最后整个编程完毕。

最新回复(0)