赞
踩
首先明确试验任务, 利用小脚丫板子进行数字时钟的设计,实验要求:能够完整正常的走时功能,能够完成时钟的调节加或者减,并且能够设置闹钟和整点报时,指示分秒的变化。
首先是整体的设计思路clk时钟信号,rst清零信号,key四个按键,switch四个开关,利用不同的按键和开关进行时钟的控制。
使用说明如下:
优点,不需要按键消抖
缺点,在调节时分秒时是一秒调节一次,过一秒加一,或者过一秒减一。
关于实验结果是没问题的,三色闪烁灯闪烁分别指示秒针和分针,一列长的闪烁灯闪烁指示整点报时和闹钟。
下面是主文件的代码。管脚分配如图。
-
- module true5shuzishizhong(clk,rst,key,seg_led_1,seg_led_2,switch,led,rgb1,rgb2);
- input clk,rst; //时钟信号和清零信号
- input [2:0]key; //四个按键
- input [3:0]switch; //四个开关
- output reg [8:0] seg_led_1; //显示管1显示十位
- output reg [8:0] seg_led_2; //显示管2,显示个位
- output reg [7:0] led; //显示灯
- output reg [2:0] rgb1=3'b101; //三色灯
- output reg [2:0] rgb2=3'b010; //三色灯
- wire clk1;
- wire clk2;
- wire clk3;
- wire [2:0] key;
- reg [7:0] cntmiao;
- reg [7:0] cntfen;
- reg [7:0] cntxiaoshi;
- reg [8:0] seg [9:0];
- reg [7:0] setmiao;
- reg [7:0] setfen;
- reg [7:0] setxiaoshi;
- //此处产生秒分时的十位和个位
- //此处产生秒分时的调时闹钟
- divide1 #(.WIDTH(24),.N(12000000)) u1 ( //传递参数产生一秒钟
- .clk(clk), //例化的端口信号都连接到定义好的信号
- .rst(rst),
- .clkout(clk1)
- );
- divide1 #(.WIDTH(30),.N(720000000)) u2( //传递参数产生一分钟
- .clk(clk),//例化的端口信号都连接到定义好的信号
- .rst(rst),
- .clkout(clk2)
- );
- divide1 #(.WIDTH(6),.N(60)) u3 ( //传递参数产生一小时
- .clk(clk2), //例化的端口信号都
- .rst(rst),
- .clkout(clk3)
- );
- reg [7:0] cntmiao1;
- reg [7:0] cntfen1;
- reg [7:0] cntxiaoshi1;
- always @(posedge clk1 or negedge rst) //产生60进制计数器
- begin //数码管显示要按照十进制的方式显示
- if(!rst) begin
- cntmiao<=8'd0;
- setmiao<=8'd0;
- end
- else
- begin
- if(switch[0]==1)
- begin
- if(cntmiao[3:0] == 4'd9) //个位满九?
- begin
- cntmiao[3:0] <= 4'd0; //个位清零
- if(cntmiao[7:4] == 4'd5) //十位满五?
- cntmiao[7:4] <= 4'd0; //个位清零
- else
- cntmiao[7:4] <= cntmiao[7:4] + 1'b1; //十位加一
- end
- else cntmiao[3:0] <= cntmiao[3:0] + 1'b1; //个位加一
- end
- else if(switch[0]==0&&switch[1]==0&&switch[2]==0&&switch[3]==1 &&key[0]==0)//走时秒针加法
- begin
- if(cntmiao[3:0] == 4'd9) //个位满九?
- begin
- cntmiao[3:0] <= 4'd0; //个位清零
- if(cntmiao[7:4] == 4'd5 ) //十位满五?
- cntmiao[7:4] <= 4'd0; //个位清零
- else
- cntmiao[7:4] <= cntmiao[7:4] + 1'b1; //十位加一
- end
- else cntmiao[3:0] <= cntmiao[3:0] + 1'b1; //个位加一
- end
- else if(switch[0]==0&&switch[1]==1&&switch[2]==1&&switch[3]==1 &&key[0]==0)//闹钟秒针加法
- begin
- if(setmiao[3:0] == 4'd9) //个位满九?
- begin
- setmiao[3:0] <= 4'd0; //个位清零
- if(setmiao[7:4] == 4'd5 ) //十位满五?
- setmiao[7:4] <= 4'd0; //个位清零
- else
- setmiao[7:4] <= setmiao[7:4] + 1'b1; //十位加一
- end
- else setmiao[3:0] <= setmiao[3:0] + 1'b1; //个位加一
- end
- else if(switch[0]==0&&switch[1]==0&&switch[2]==1&&switch[3]==0 &&key[0]==0)//秒针减法
- begin
- if(cntmiao[3:0] == 4'd0) //个位满九?
- begin
- cntmiao[3:0] <= 4'd9; //个位清零
- if(cntmiao[7:4] == 4'd0 ) //十位满五?
- cntmiao[7:4] <= 4'd5; //个位清零
- else
- cntmiao[7:4] <= cntmiao[7:4] - 1'b1; //十位加一
- end
- else cntmiao[3:0] <= cntmiao[3:0] - 1'b1; //个位加一
- end
- else if(switch[0]==0&&switch[1]==1&&switch[2]==1&&switch[3]==0 &&key[0]==0)//闹钟秒针加法
- begin
- if(setmiao[3:0] == 4'd0) //个位满九?
- begin
- setmiao[3:0] <= 4'd9; //个位清零
- if(setmiao[7:4] == 4'd0 ) //十位满五?
- setmiao[7:4] <= 4'd5; //个位清零
- else
- setmiao[7:4] <= setmiao[7:4] - 1'b1; //十位加一
- end
- else setmiao[3:0] <= setmiao[3:0] - 1'b1; //个位加一
- end
- else begin
- cntmiao<=cntmiao;
- setmiao<=setmiao;
- end
- end
- end
- always @(posedge clk1 or negedge rst) //产生60进制计数器
- begin //数码管显示要按照十进制的方式显示
- if(!rst) begin
- cntfen<=8'd0;
- setfen<=8'd0;
- end
- else begin
- if(switch[0]==1&&cntmiao[3:0]==4'd9)
- begin
- if(cntmiao[7:4]==4'd5)
- if(cntfen[3:0] == 4'd9) //个位满九?
- begin
- cntfen[3:0] <= 4'd0; //个位清零
- if(cntfen[7:4] == 4'd5 ) //十位满五?
- cntfen[7:4] <= 4'd0; //个位清零
- else
- cntfen[7:4] <= cntfen[7:4] + 1'b1; //十位加一
- end
- else cntfen[3:0] <= cntfen[3:0] + 1'b1; //个位加一
- end
- else if(switch[0]==0&&switch[1]==0&&switch[2]==0&&switch[3]==1&&key[1]==0)//走时秒针加法
- begin
- if(cntfen[3:0] == 4'd9) //个位满九?
- begin
- cntfen[3:0] <= 4'd0; //个位清零
- if(cntfen[7:4] == 4'd5 ) //十位满五?
- cntfen[7:4] <= 4'd0; //个位清零
- else
- cntfen[7:4] <= cntfen[7:4] + 1'b1; //十位加一
- end
- else cntfen[3:0] <= cntfen[3:0] + 1'b1; //个位加一
- end
- else if(switch[0]==0&&switch[1]==1&&switch[2]==1&&switch[3]==1&&key[1]==0)//闹钟秒针加法
- begin
- if(setfen[3:0] == 4'd9) //个位满九?
- begin
- setfen[3:0] <= 4'd0; //个位清零
- if(setfen[7:4] == 4'd5 ) //十位满五?
- setfen[7:4] <= 4'd0; //个位清零
- else
- setfen[7:4] <= setfen[7:4] + 1'b1; //十位加一
- end
- else setfen[3:0] <= setfen[3:0] + 1'b1; //个位加一
- end
- else if(switch[0]==0&&switch[1]==0&&switch[2]==1&&switch[3]==0&&key[1]==0)//秒针减法
- begin
- if(cntfen[3:0] == 4'd0) //个位满九?
- begin
- cntfen[3:0] <= 4'd9; //个位清零
- if(cntfen[7:4] == 4'd0 ) //十位满五?
- cntfen[7:4] <= 4'd5; //个位清零
- else
- cntfen[7:4] <= cntfen[7:4] - 1'b1; //十位加一
- end
- else cntfen[3:0] <= cntfen[3:0] - 1'b1; //个位加一
- end
- else if(switch[0]==0&&switch[1]==1&&switch[2]==1&&switch[3]==0&&key[1]==0)//闹钟秒针加法
- begin
- if(setfen[3:0] == 4'd0) //个位满九?
- begin
- setfen[3:0] <= 4'd9; //个位清零
- if(setfen[7:4] == 4'd0 ) //十位满五?
- setfen[7:4] <= 4'd5; //个位清零
- else
- setfen[7:4] <= setfen[7:4] - 1'b1; //十位加一
- end
- else setfen[3:0] <= setfen[3:0] - 1'b1; //个位加一
- end
- else begin
- cntfen<=cntfen;
- setfen<=setfen;
- end
- end
- end
- always @(posedge clk1 or negedge rst) //产生60进制计数器
- begin //数码管显示要按照十进制的方式显示
- if(!rst) begin
- cntxiaoshi<=8'd0;
- setxiaoshi<=8'd0;
- end
- else begin
- if(switch[0]==1&& cntfen[3:0]==4'd9)
- begin
- if(cntfen[7:4]==4'd5 )
- if(cntmiao[7:4]==4'd5)
- if(cntmiao[3:0]==4'd9)
- if(cntxiaoshi[3:0] == 4'd9) //个位满九?
- begin
- cntxiaoshi[3:0] <= 4'd0; //个位清零
- if(cntxiaoshi[7:4] == 4'd5 ) //十位满五?
- cntxiaoshi[7:4] <= 4'd0; //个位清零
- else
- cntxiaoshi[7:4] <= cntxiaoshi[7:4] + 1'b1; //十位加一
- end
- else cntxiaoshi[3:0] <= cntxiaoshi[3:0] + 1'b1; //个位加一
- end
- else if(switch[0]==0&&switch[1]==0&&switch[2]==0&&switch[3]==1 && key[2]==0)//走时秒针加法
- begin
- if(cntxiaoshi[3:0] == 4'd9) //个位满九?
- begin
- cntxiaoshi[3:0] <= 4'd0; //个位清零
- if(cntxiaoshi[7:4] == 4'd5 ) //十位满五?
- cntxiaoshi[7:4] <= 4'd0; //个位清零
- else
- cntxiaoshi[7:4] <= cntxiaoshi[7:4] + 1'b1; //十位加一
- end
- else cntxiaoshi[3:0] <= cntxiaoshi[3:0] + 1'b1; //个位加一
- end
- else if(switch[0]==0&&switch[1]==1&&switch[2]==1&&switch[3]==1 && key[2]==0)//闹钟秒针加法
- begin
- if(setxiaoshi[3:0] == 4'd9) //个位满九?
- begin
- setxiaoshi[3:0] <= 4'd0; //个位清零
- if(setxiaoshi[7:4] == 4'd5 ) //十位满五?
- setxiaoshi[7:4] <= 4'd0; //个位清零
- else
- setxiaoshi[7:4] <= setxiaoshi[7:4] + 1'b1; //十位加一
- end
- else setxiaoshi[3:0] <= setxiaoshi[3:0] + 1'b1; //个位加一
- end
- else if(switch[0]==0&&switch[1]==0&&switch[2]==1&&switch[3]==0 && key[2]==0)//秒针减法
- begin
- if(cntxiaoshi[3:0] == 4'd0) //个位满九?
- begin
- cntxiaoshi[3:0] <= 4'd9; //个位清零
- if(cntxiaoshi[7:4] == 4'd0 ) //十位满五?
- cntxiaoshi[7:4] <= 4'd5; //个位清零
- else
- cntxiaoshi[7:4] <= cntxiaoshi[7:4] - 1'b1; //十位加一
- end
- else cntxiaoshi[3:0] <= cntxiaoshi[3:0] - 1'b1; //个位加一
- end
- else if(switch[0]==0&&switch[1]==1&&switch[2]==1&&switch[3]==0&&key[2]==0)//闹钟秒针加法
- begin
- if(setxiaoshi[3:0] == 4'd0) //个位满九?
- begin
- setxiaoshi[3:0] <= 4'd9; //个位清零
- if(setxiaoshi[7:4] == 4'd0 ) //十位满五?
- setxiaoshi[7:4] <= 4'd5; //个位清零
- else
- setxiaoshi[7:4] <= setxiaoshi[7:4] - 1'b1; //十位加一
- end
- else setxiaoshi[3:0] <= setxiaoshi[3:0] - 1'b1; //个位加一
- end
- else begin
- cntxiaoshi<=cntxiaoshi;
- setxiaoshi<=setxiaoshi;
- end
- end
- end
-
- initial //initial和always不同,其中语句只执行一次
- begin
- seg[0] = 9'h3f; //对存储器中第一个数赋值9'b00_0011_1111,相当于共阴极接地,DP点变低不亮,7段显示数字 0
- seg[1] = 9'h06; //7段显示数字 1
- seg[2] = 9'h5b; //7段显示数字 2
- seg[3] = 9'h4f; //7段显示数字 3
- seg[4] = 9'h66; //7段显示数字 4
- seg[5] = 9'h6d; //7段显示数字 5
- seg[6] = 9'h7d; //7段显示数字 6
- seg[7] = 9'h07; //7段显示数字 7
- seg[8] = 9'h7f; //7段显示数字 8
- seg[9] = 9'h6f; //7段显示数字 9
- end
- always @(posedge clk1)//显示模块分别对应着走时的秒分时和闹钟的秒分时
- begin
- if(switch[0]==1&&switch[1]==0&&switch[2]==1&&switch[3]==1)
- begin
- seg_led_1<=seg[cntmiao[7:4]];
- seg_led_2<=seg[cntmiao[3:0]];
- end
- else if(switch[0]==1&&switch[1]==1&&switch[2]==0&&switch[3]==0)
- begin
- seg_led_1<=seg[cntfen[7:4]];
- seg_led_2<=seg[cntfen[3:0]];
- end
- else if(switch[0]==1&&switch[1]==1&&switch[2]==0&&switch[3]==1)
- begin
- seg_led_1<=seg[cntxiaoshi[7:4]];
- seg_led_2<=seg[cntxiaoshi[3:0]];
- end
- else if(switch[0]==1&&switch[1]==0&&switch[2]==0&&switch[3]==0)
- begin
- seg_led_1<=seg[setmiao[7:4]];
- seg_led_2<=seg[setmiao[3:0]];
- end
- else if(switch[0]==1&&switch[1]==1&&switch[2]==1&&switch[3]==0)
- begin
- seg_led_1<=seg[setfen[7:4]];
- seg_led_2<=seg[setfen[3:0]];
- end
- else if(switch[0]==1&&switch[1]==1&&switch[2]==1&&switch[3]==1)
- begin
- seg_led_1<=seg[setxiaoshi[7:4]];
- seg_led_2<=seg[setxiaoshi[3:0]];
- end
- end
- always @(posedge clk1)//闹钟闪烁
- begin
- if(setfen == cntfen && setxiaoshi==cntxiaoshi)
- begin
-
- led<=~led;
- end
- else if(cntfen==8'd0)
- led<=~led;
- else
- begin
- led<=8'b 11111111;
- end
- end
- always @(posedge clk1)//三色灯闪烁显示秒的频率
- begin
- rgb1<=~rgb1;
- end
- always @(posedge clk2)//三色灯闪烁显示分的频率
- begin
- rgb2<=~rgb2;
- end
- endmodule
-

在主函数中提到的函数名如下,懒得自己写了用的小脚丫官网的代码。
- module divide1 #
- (
- parameter WIDTH = 24, //计数器的位数,计数的最大值为 2**(WIDTH-1)
- parameter N = 12_000_000 //分频系数,确保 N<2**(WIDTH-1)
- )
- (
- input clk,
- input rst,
- output clkout
- );
- reg [WIDTH-1:0] cnt_p,cnt_n; //cnt_p为上升沿触发时的计数器,cnt_n为下降沿触发时的计数器
- reg clk_p,clk_n; //clk_p为上升沿触发时分频时钟,clk_n为下降沿触发时分频时钟
-
- /**********上升沿触发部分**************************************/
- //上升沿触发时计数器的控制
- always @(posedge clk or negedge rst) begin
- if(!rst)
- cnt_p <= 1'b0;
- else if(cnt_p == (N-1))
- cnt_p <= 1'b0;
- else
- cnt_p <= cnt_p + 1'b1;
- end
- //上升沿触发的分频时钟输出
- always @(posedge clk or negedge rst)
- begin
- if(!rst)
- clk_p <= 1'b0;
- else if(cnt_p < (N>>1))
- clk_p <= 1'b0;
- else
- clk_p <= 1'b1;
- end
- /*****************下降沿触发部分**************************************/
- //下降沿触发时计数器的控制
- always @(negedge clk or negedge rst)
- begin
- if(!rst)
- cnt_n <= 1'b0;
- else if(cnt_n == (N-1))
- cnt_n <= 1'b0;
- else
- cnt_n <= cnt_n + 1'b1;
- end
- //下降沿触发的分频时钟输出,和clk_p相差半个clk时钟
- always @(negedge clk or negedge rst)
- begin
- if(!rst)
- clk_n <= 1'b0;
- else if(cnt_n < (N>>1))
- clk_n <= 1'b0;
- else
- clk_n <= 1'b1; //得到的分频时钟正周期比负周期多一个clk时钟
- end
- /*************************************************************************/
- wire clk1 = clk; //当N=1时,直接输出clk
- wire clk2 = clk_p; //当N为偶数也就是N的最低位为0,N[0]=0,输出clk_p
- wire clk3 = clk_p & clk_n; //当N为奇数也就是N最低位为1,N[0]=1,输出clk_p&clk_n。
-
- assign clkout = (N==1)? clk1:(N[0]? clk3:clk2);
- endmodule

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。