数字钟
数字钟是数电实验最后一个用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@里面的东西,太久远了我自己也不记得了。。。
不过大部分是对的