数电实验Verilog-数字钟

本文详细介绍了使用Verilog语言设计数字钟的过程,包括60进制和24进制计数模块,时间修改及数码管显示模块。在设计中,作者注意到60进制计数的进位问题以及修改时间时的闪烁效果,同时指出了设计中的不足,如缺少按键消抖和修改时间操作的不便。此外,还分享了分频模块的实现和在实际验证中遇到的挑战。
摘要由CSDN通过智能技术生成

数字钟

数字钟是数电实验最后一个用verilog写的实验,稍微有些难度,现在再回来看之前写的代码还是有很多不足和问题,但在当时并没有注意到。

计数模块

1.60进制计数
在计数模块中就考虑到修改时间时的计数修改,便于修改时间
60进制需要考虑到进位,为了能保证同时进位,需要在计数58时就将下一个计数器的计数使能开启,计数59时计数使能关闭

module count60(input clk,input jinwei,input changen,input reset,input [1:0]button,output reg [7:0]q,output reg s);
		
		reg [5:0]count;
		
		always@(posedge clk) begin
			
			if(reset==0||(count>(6'd59))) begin count<=0;s<=0; end

			else if(changen!=0)
				case(button)
					2'b10:begin count<=(count==6'd59)?0:(count+1);s<=s; end
					2'b01:begin count<=(count==0)?(6'd58):(count-1);s<=s; end
				endcase
			else if(jinwei==0) begin count<=count;s<=s; end
			
			else if(count==6'd58) begin count<=count+1;s<=1; end
			
			else if(count==6'd59) begin count<=0;s<=0; end
			
			else begin count<=count+1;s<=0; end
			
			q[3:0]<=count%(4'd10);
			q[7:4]<=count/(4'd10);
		end

endmodule

2.24进制计数模块
changen为修改计数使能,当其值不为0时,根据按键情况进行计数加减,每个时钟有效沿来时加减一次
输出为q[7:0],高4位为计数十位,低4位为计数个位

module count24(input clk,input jinwei,input changen,input reset,input [1:0]button,output reg [7:0]q);

		reg [4:0]count;
		
		always@(posedge clk) begin
			
			if(reset==0||(count>(5'd23))) count<=0;
			else if(changen!=0)
				case(button)
					2'b10:count<=(count==5'd23)?0:(count+1);
					2'b01:count<=(count==0)?(5'd23):(count-1);
				endcase
			else if(jinwei==0) count<=count;
			
			else if(count==5'd23) count<=0;
			
			else count<=count+1;
			q[3:0]<=count%(4'd10);
			q[7:4]<=count/(4'd10);
			
		end

endmodule

时钟修改模块

采用两个标志位chg1,chg2。五向按键中键进行修改使能与修改结束,chg1为其标志位。
再由左右按键选择需要修改的时钟

module timechange(input clk,input [2:0]button ,output reg[2:0]changen);
		
		reg chg1=0;
		reg chg2=0;
		always@(posedge button[2]) begin
			if (chg1==0)
				chg1<=1;
			else
				chg1<=0;
		end
		
		always@(posedge clk) begin
			if(chg1==1&&chg2==0) begin
				changen<=3'b100;
				chg2<=1;
			end
			else if(chg1==1&&chg2==1)
				case(button[1:0])
					2'b10:changen<={changen[1:0],changen[2]};
					2'b01:changen<={changen[0],changen[2:1]};
				endcase
			else if(chg1==0) begin
				changen<=3'b000;
				chg2<=0;
			end
		end

endmodule

数码管显示模块

这个模块挺折磨人的,分频没做好的话显示的就是一塌糊涂的东西,我当时搞了好久
当修改使能时,对应的计数器会闪烁。再由count_t轮流计数,分别亮灯显示各计数器的各位

module print(input clk,input [7:0]s,input [7:0]m,input [7:0]h,input [2:0]changen,output reg [5:0]led1,output reg [6:0]led2);
		reg [3:0] num;
		reg [26:0] temp;//分频率器的中间变量    
		reg [25:0] tempc=0;
      reg clk_t;
		reg [2:0]count_t=0;
		wire clk_tc;
		wire count;
		assign count=count_t;
		assign clk_tc=tempc[25];
		parameter S0=7'b0000001,S1=7'b1111001,S2=7'b0010010,S3=7'b0000110,S4=7'b1001100,
		S5=7'b0100100,S6=7'b0100000,S7=7'b0001111,S8=7'b0000000,S9=7'b0000100;
		
		always@(posedge clk)//时钟的分频模块
			begin
				if(temp<27'd1000)//clk_t频率100KHZ
					temp<=temp+1;
				else
					begin
						temp<=0;
						clk_t<=~clk_t;
					end
			end
		
		always@(posedge clk)//修改时间的闪烁模块
			begin
				if(tempc<26'd50000000)
					tempc<=tempc+1;
				else
					tempc<=0;
			end
		
		always@(posedge clk_t)
			begin 
				if(count_t==3'b101)
					count_t<=0;
				else
					count_t<=count_t+1;
			end 
			
		always@(count_t) begin
			case(count_t)
				3'b000:num<=s[3:0];
				3'b001:num<=s[7:4];
				3'b010:num<=m[3:0];
				3'b011:num<=m[7:4];
				3'b100:num<=h[3:0];
				3'b101:num<=h[7:4];
			endcase
		end
		
		always@(posedge clk_t) begin
				case(count_t) 
					3'b000:begin if(changen==(3'b001)&&clk_tc==1) led1<=6'b111111;else led1<=6'b111110; end
					3'b001:begin if(changen==(3'b001)&&clk_tc==1) led1<=6'b111111;else led1<=6'b111101; end
					3'b010:begin if(changen==(3'b010)&&clk_tc==1) led1<=6'b111111;else led1<=6'b111011; end
					3'b011:begin if(changen==(3'b010)&&clk_tc==1) led1<=6'b111111;else led1<=6'b110111; end
					3'b100:begin if(changen==(3'b100)&&clk_tc==1) led1<=6'b111111;else led1<=6'b101111; end
					3'b101:begin if(changen==(3'b100)&&clk_tc==1) led1<=6'b111111;else led1<=6'b011111; end
				endcase
				case(num) 
					5'd0:led2<=S0;
					5'd1:led2<=S1;
					5'd2:led2<=S2;
					5'd3:led2<=S3;
					5'd4:led2<=S4;
					5'd5:led2<=S5;
					5'd6:led2<=S6;
					5'd7:led2<=S7;
					5'd8:led2<=S8;
					5'd9:led2<=S9;
				endcase
			end

				
endmodule

顶层模块

module topclock(input clk,input reset,input [4:0]button,output [7:0]led1,output [6:0]led2);
		
		reg [25:0]inclk;//1s分频
		reg inclklk;
		always @(posedge clk) begin
			if(inclk<26'd50000000)
				inclk <= inclk + 1;
			else begin
				inclk <=0;
				inclklk<=~inclklk;
			end
		end
		assign led1[1:0]=2'b11;
		wire [7:0]sec;//时钟计数和进位中间变量
		wire [7:0]min;
		wire [7:0]hour;

		wire sjin,mjin,hjin;
		
		wire [2:0]changen;//调时间使能和中间变量
		wire [2:0]changen1;
		wire [2:0]changen2;
		assign changen2=changen;
		assign changen1=changen;
		assign sjin=inclklk;
		
		//button[1:0]上下键调时间数字,button[3:2]左右键改数字位,button[4]确定和开始改时间
		timechange tc(clk,button[4:2],changen);
		count60 s(sjin,1,changen1[0],reset,button[1:0],sec,mjin);//时钟计数和进位
		count60 m(sjin,mjin,changen1[1],reset,button[1:0],min,hjin);
		count24 h(sjin,(hjin&&mjin),changen1[2],reset,button[1:0],hour);
		print tp(clk,sec,min,hour,changen2,led1[7:2],led2);

		
endmodule

引脚约束(ise可用)

由于五向按键中键同时是板子的一个时钟,所以需要在文件中额外加一句NET “button<4>” CLOCK_DEDICATED_ROUTE = FALSE;用来取消时钟的使用。

# PlanAhead Generated IO constraints 

NET "button[4]" IOSTANDARD = LVCMOS33;
NET "button[3]" IOSTANDARD = LVCMOS33;
NET "button[2]" IOSTANDARD = LVCMOS33;
NET "button[1]" IOSTANDARD = LVCMOS33;
NET "button[0]" IOSTANDARD = LVCMOS33;
NET "led1[7]" IOSTANDARD = LVCMOS33;
NET "led1[6]" IOSTANDARD = LVCMOS33;
NET "led1[5]" IOSTANDARD = LVCMOS33;
NET "led1[4]" IOSTANDARD = LVCMOS33;
NET "led1[3]" IOSTANDARD = LVCMOS33;
NET "led1[2]" IOSTANDARD = LVCMOS33;
NET "led1[1]" IOSTANDARD = LVCMOS33;
NET "led1[0]" IOSTANDARD = LVCMOS33;
NET "led2[6]" IOSTANDARD = LVCMOS33;
NET "led2[5]" IOSTANDARD = LVCMOS33;
NET "led2[4]" IOSTANDARD = LVCMOS33;
NET "led2[3]" IOSTANDARD = LVCMOS33;
NET "led2[2]" IOSTANDARD = LVCMOS33;
NET "led2[1]" IOSTANDARD = LVCMOS33;
NET "led2[0]" IOSTANDARD = LVCMOS33;

# PlanAhead Generated physical constraints 

NET "button[4]" LOC = E16;
NET "button[3]" LOC = T16;
NET "button[2]" LOC = R10;
NET "button[1]" LOC = F15;
NET "button[0]" LOC = V10;
NET "led1[7]" LOC = M1;
NET "led1[6]" LOC = L1;
NET "led1[5]" LOC = N4;
NET "led1[4]" LOC = N2;
NET "led1[3]" LOC = N5;
NET "led1[2]" LOC = M3;
NET "led1[1]" LOC = M6;
NET "led1[0]" LOC = N6;
NET "led2[6]" LOC = L3;
NET "led2[5]" LOC = N1;
NET "led2[4]" LOC = L5;
NET "led2[3]" LOC = L4;
NET "led2[2]" LOC = K3;
NET "led2[1]" LOC = M2;
NET "led2[0]" LOC = L6;

# PlanAhead Generated IO constraints 

NET "clk" IOSTANDARD = LVCMOS33;
NET "reset" IOSTANDARD = LVCMOS33;

# PlanAhead Generated physical constraints 

NET "clk" LOC = E3;
NET "reset" LOC = P3;
NET "button<4>" CLOCK_DEDICATED_ROUTE = FALSE;

最明显的不足之处就是没有按键消抖,当时还不会。。。。
修改时间的时候还得一直按着五向按键一秒钟变一次挺累的。。。
分频做的也不好搞得我自己当时都晕了,好不容易做出来赶紧给老师验收qwq
这个数字钟修改了三个大版本才最终成功到板子上,之前有点想放弃了找来一个人帮我看哪里出错了结果他找不出来qwq只能靠自己了
不保证这些模块写上去能直接用,因为有可能我在仿真的时候改了某些模块always@里面的东西,太久远了我自己也不记得了。。。
不过大部分是对的

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值