实验:实现电子时钟,显示时分秒,在六位数码管上分别显示时分秒
分析
在需要一个计数值来计时,单独出一个模块,根据逻辑写时分秒进位,和数码管的显示 作为一个模块,最后是一个顶层模块一共三个。
计数模块
module cnt(
input sys_clk, //系统输入
input sys_rst_n, //系统复位
output reg flag, //一秒输出高电平维持一个周期作为秒自加信号
output reg flag_div //0.016秒输出一个高电平作为 数码管位选位移信号,至少是1/6的flag时间
);
parameter cnt_max = 5000_0000 ; //自加最大值
//parameter cnt_max = 31'd50 ; //仿真是自加最大值
//parameter cnt_div_max = 4'd8; //方针是分配自加最大值
parameter cnt_div_max = 17'd80000; //分频自加最大值
reg [31:0] cnt; //
reg [16:0] cnt_div6; //
always @(posedge sys_clk or negedge sys_rst_n ) begin
if(!sys_rst_n) //复位
cnt <= 0 ; //cnt清零
else if(cnt < cnt_max - 1'b1 ) begin
cnt <= cnt + 1'b1 ; //当cnt未计到最大值时 一直自加
flag <= 1'b0; //秒自加信号一直是0
end
else begin
cnt <= 31'b0; //当cnt计到最大值时,cnt清空
flag <= 1'b1; //自加标志位 置1
end
end
always @(posedge sys_clk or negedge sys_rst_n ) begin
if(!sys_rst_n) //复位
cnt_div6 <= 0 ; //cnt清零
else if(cnt_div6 < cnt_div_max - 1'b1 ) begin
cnt_div6 <= cnt_div6 + 1'b1 ; //当cnt_div未计到最大值时 一直自加
flag_div <= 1'b0; //位选移位信号一直是0
end
else begin
cnt_div6 <= 31'b0; //当cnt_div计到最大值时 cnt_div6清空
flag_div <= 1'b1; //位选移位信号置1
end
end
endmodule
数码管显示模块
module tube(
input sys_clk , //系统输入
input sys_rst_n , //复位
input add_flag , //秒自加标志位
input add_div_flag , //位移标志位
output reg [5:0] dig_sel, //位选输出
output reg [7:0] dig_data //数码管段码输出
);
reg [5:0] num ;
reg [3:0] num_0 ;
reg [5:0] num_1 ;
reg [5:0] num_2 ;
//12 :36 :50
initial begin //初始化时分秒和数码管位选
dig_sel <= 6'b011111; //数码管位选
num_0 <= 4'd12; //时
num_1 <= 6'd36; //分
num_2 <= 6'd50; //秒
end
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
dig_sel <= 6'b011111;
end
else if (add_div_flag == 1'b1)begin //移位标志位
dig_sel[5:0] <= {dig_sel[0],dig_sel[5:1]}; //移位
end
else
dig_sel <= dig_sel ; //赋值给自己
end
/*
*时间显示
*/
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n) begin //复位,将时间恢复初始设定
num_0 <= 12;num_1 <= 36;num_2 <= 50; // 12.36.50
end
else if(add_flag == 1'b1) begin //当自加标志位为 1 时
num_2 <= num_2+ 1'b1 ; //秒上的值加1
if(num_2 == 6'd60 -1'b1) begin //因为这句判断语句和 上面那句是并行关系 秒为59时进位
num_2 <= 0; //进位后num_2 = 0
num_1 <= num_1+ 1'b1; //num_1 +1
if(num_1 == 6'd60 -1'b1) begin //因为这句判断语句和 上面那句是并行关系 分为59时进位
num_1 <= 0; //进位后num_1 = 0
num_0 <= num_0+ 1'b1; //num_0 +1
if(num_0 == 4'd24 -1'b1) begin //因为这句判断语句和 上面那句是并行关系 时为23时进位
num_0 <= 0; //进位后num_0 = 0
end
end
end
end
end
/*
*根据位选来给num赋值,就是对应的位上的值
*/
always@(posedge sys_clk or negedge sys_rst_n) begin
case(dig_sel)
6'b111110 : num <= num_2 % 4'd10;
6'b111101 : num <= num_2 / 4'd10;
6'b111011 : num <= num_1 % 4'd10;
6'b110111 : num <= num_1 / 4'd10;
6'b101111 : num <= num_0 % 4'd10;
6'b011111 : num <= num_0 / 4'd10;
default : num <= 0;
endcase
end
/*
*根据需要显示的值转换为数码管的段码
*/
always@(posedge sys_clk or negedge sys_rst_n) begin
case(num)
4'h0 : dig_data <= 8'b1100_0000;
4'h1 : dig_data <= 8'b1111_1001;
4'h2 : dig_data <= 8'b1010_0100;
4'h3 : dig_data <= 8'b1011_0000;
4'h4 : dig_data <= 8'b1001_1001;
4'h5 : dig_data <= 8'b1001_0010;
4'h6 : dig_data <= 8'b1000_0010;
4'h7 : dig_data <= 8'b1111_1000;
4'h8 : dig_data <= 8'b1000_0000;
4'h9 : dig_data <= 8'b1001_0000;
4'ha : dig_data <= 8'b1000_1000;
4'hb : dig_data <= 8'b1000_0011;
4'hc : dig_data <= 8'b1100_0110;
4'hd : dig_data <= 8'b1010_0001;
4'he : dig_data <= 8'b1000_0110;
4'hf : dig_data <= 8'b1000_1110;
default : dig_data <= 8'b1100_0000;
endcase
end
endmodule
/* 1.六个数码管统一从0显示到E
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
dig_sel <= 6'b111110;
end
else if (add_flag == 1'b1)begin
dig_sel[5:0] <= {dig_sel[0],dig_sel[5:1]};
end
else
dig_sel <= dig_sel ;
end
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
num <= 4'd0 ;
else if (num > 4'hf)
num <= 4'h0 ;
else if(add_flag == 1'b1) begin
num <= num + 1'b1 ;
end
else
num <= num ;
end
always@(posedge sys_clk or negedge sys_rst_n) begin
case(num)
4'h0 : dig_data <= 8'b1100_0000;
4'h1 : dig_data <= 8'b1111_1001;
4'h2 : dig_data <= 8'b1010_0100;
4'h3 : dig_data <= 8'b1011_0000;
4'h4 : dig_data <= 8'b1001_1001;
4'h5 : dig_data <= 8'b1001_0010;
4'h6 : dig_data <= 8'b1000_0010;
4'h7 : dig_data <= 8'b1111_1000;
4'h8 : dig_data <= 8'b1000_0000;
4'h9 : dig_data <= 8'b1001_0000;
4'ha : dig_data <= 8'b1000_1000;
4'hb : dig_data <= 8'b1000_0011;
4'hc : dig_data <= 8'b1100_0110;
4'hd : dig_data <= 8'b1010_0001;
4'he : dig_data <= 8'b1000_0110;
4'hf : dig_data <= 8'b1000_1110;
default : dig_data <= 8'b1100_0000;
endcase
end
*/
顶层模块
module tube_top(
input sys_clk, //系统输入
input sys_rst_n, //复位输入
output [5:0] dig_sel, //位选数据输出
output [7:0] dig_data //段选数据输出
);
wire flag ;
tube tube_inst(
.sys_clk (sys_clk), //系统输入
.sys_rst_n (sys_rst_n), //复位输入
.add_flag (flag), //秒自加标志位输入
.add_div_flag(flag_div), //位选位移标志位输入
.dig_sel (dig_sel), //位选数据输出
.dig_data (dig_data) //段选数据输出
);
cnt cnt_inst(
.sys_clk (sys_clk), //系统输入
.sys_rst_n (sys_rst_n), //复位输入
.flag (flag), //秒自加标志位输出
.flag_div (flag_div) //位选位移标志位输出
);
endmodule
仿真
编写测试平台
`timescale 1ns/1ns
module tb_tube();
reg sys_clk; //定义时钟
reg sys_rst_n; //定义复位信号
wire [7:0]dig_data; //定义输出段选信号
wire [5:0]dig_sel; //定义输出位选信号
always #10 sys_clk = ~ sys_clk; //模拟晶振
initial begin
sys_clk = 1'b1 ; //初始高电平
sys_rst_n <= 1'b0; //复位
#20 sys_rst_n <= 1'b1; //延时将复位信号拉高
end
tube_top tube_top_inst(
.sys_clk (sys_clk), //时钟输入
.sys_rst_n (sys_rst_n), //复位信号输入
.dig_sel (dig_sel), //输出位选信号
.dig_data (dig_data) //输出段选信号
);
endmodule
下载程序
下载到fpga
点击图圈位置
点击start下载
下载到配置芯片 EPCS64
.sof 转换成 .jic
点击 add file ,将生成的jic文件添加进来。
如果不删除.sof文件下载会出现如下问题
解决办法就是删除.sof文件后再下载。