一、数码管
Cyclone IV开发板上的数码管一共有6个,我们每次只能选择其中一个显示,怎么解决电子时钟时、分、秒同时显示呢?要实现电子时钟首先要了解什么是余晖效应。
余晖效应一般指视觉暂留。 视觉暂留现象即视觉暂停现象(Persistence of vision,Visual staying phenomenon,duration of vision)又称“余晖效应”。只要数码管位选信号切换得足够快,数码管由亮到灭这一过程是需要一段时间的,由于时间很短,我们的眼睛是没有办法分清此时此刻数码管的状态,给人的感觉就是数码管是一直亮的。以此来达到欺骗人眼的效果,这样就可以实现同时显示时、分、秒。
二、CyloneⅣ 数码管原理图
三、代码实现
本项目是为了实现类似于23:59:59的时钟显示,由于八段式数码管仅包含小数点无冒号,因此本项目为了简化忽略冒号
所用芯片为:EP4CE6F17C8
本项目设计了两个模块,分别为:counter、reg_driver;分别用于设计计数器和数码管驱动,另有dig_clock作为顶层文件
counter模块代码分析:
- 首先,博主在本模块中设计了一个总计时为24×60×60=86400s的计数器
- 对于如何从86400s中取出相应的值作为小时,分钟,秒的数据可以参考下列公式:
hour = cnt_day / 12’d3600 ;
min = (cnt_day % 12’d3600) / 6’d60 ;
sec = (cnt_day % 12’d3600) % 6’d60 ;
module counter (
input wire clk ,
input wire rst_n ,
output reg [4:0] hour ,
output reg [5:0] min ,
output reg [5:0] sec
);
parameter MAX1S = 26'd50_000_000;
parameter MAXDAY = 17'd86400;
reg [25:0] cnt1s ;
reg [16:0] cnt_day ;
//1s计数器
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt1s <= 1'b0;
end
else if(cnt1s == MAX1S - 1'b1) begin
cnt1s <= 1'b0;
end
else begin
cnt1s <= cnt1s + 1'b1;
end
end
//一天计数器
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt_day <= 1'b0;
end
else if(cnt_day == MAXDAY - 1'b1 && cnt1s == MAX1S - 1'b1) begin
cnt_day <= 1'b0;
end
else if(cnt1s == MAX1S - 1'b1) begin
cnt_day <= cnt_day + 1'b1;
end
else begin
cnt_day <= cnt_day;
end
end
always @(*) begin
hour = cnt_day / 12'd3600 ;
min = (cnt_day % 12'd3600) / 6'd60 ;
sec = (cnt_day % 12'd3600) % 6'd60 ;
end
endmodule
seg_driver模块代码分析:
- 本模块需要一个八位的seg寄存器作为八段式数码管的段选信号以及一个六位的sel寄存器作为位选信号
- 本模块设计了一个20微秒计数器,确保数码管依次显示时能够产生余晖效应,使人在视觉上能够同时感觉到是六个数码管同时显示
- 此外,设计了一个4位寄存器number用于保存小时位、分钟位、秒位的高位与地位,由于时钟中最大数字为9,因此4位即可满足数值保存条件
- 本模块中数码管每隔20微秒移动一位,移动后根据位选信号的值选择number寄存器应该保存时分秒的哪一位,随后立即将值赋给段选信号seg(所有always块都是并发运行的)
module seg_driver(
input wire clk ,
input wire rst_n ,
input wire [4:0] hour ,
input wire [5:0] min ,
input wire [5:0] sec ,
output wire [7:0] seg ,
output wire [5:0] sel
);
parameter MAX20US = 10'd1000;
parameter ZERO = 8'b1100_0000,
ONE = 8'b1111_1001,
TWO = 8'b1010_0100,
THREE = 8'b1011_0000,
FOUR = 8'b1001_1001,
FIVE = 8'b1001_0010,
SIX = 8'b1000_0010,
SEVEN = 8'b1111_1000,
EIGHT = 8'b1000_0000,
NINE = 8'b1001_0000;
reg [9:0] cnt_20us ;
reg [5:0] sel_r ;
reg [3:0] number ;
reg [7:0] seg_r ;
//20微秒计数器
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt_20us <= 1'b0;
end
else if(cnt_20us == MAX20US - 1'b1) begin
cnt_20us <= 1'b0;
end
else begin
cnt_20us <= cnt_20us + 1'b1;
end
end
//位选信号约束
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
sel_r <= 6'b111_110;
end
else if(cnt_20us == MAX20US - 1'b1)begin
sel_r <= {sel_r[4:0],sel_r[5]};
end
else begin
sel_r <= sel_r;
end
end
assign sel = sel_r;
//得到各位数字
always @(*)begin
case(sel_r)
6'b111_110 : number = hour /10;
6'b111_101 : number = hour %10;
6'b111_011 : number = min / 10;
6'b110_111 : number = min % 10;
6'b101_111 : number = sec / 10;
6'b011_111 : number = sec % 10;
default : number = 4'd0;
endcase
end
//通过数字number解析出seg_r值
always @(*)begin
case(number)
4'd0 : seg_r <= ZERO ;
4'd1 : seg_r <= ONE ;
4'd2 : seg_r <= TWO ;
4'd3 : seg_r <= THREE;
4'd4 : seg_r <= FOUR ;
4'd5 : seg_r <= FIVE ;
4'd6 : seg_r <= SIX ;
4'd7 : seg_r <= SEVEN;
4'd8 : seg_r <= EIGHT;
4'd9 : seg_r <= NINE ;
default: seg_r <= ZERO;
endcase
end
assign seg = seg_r;
endmodule
顶层文件
module clock_top(
input wire clk ,
input wire rst_n ,
output wire [7:0] seg ,
output wire [5:0] sel
);
wire [4:0] hour ;
wire [5:0] min ;
wire [5:0] sec ;
counter u_counter (
.clk (clk ),
.rst_n (rst_n),
.hour (hour),
.min (min ),
.sec (sec )
);
seg_driver u_seg_driver(
.clk ( clk ),
.rst_n ( rst_n),
.hour (hour ),
.min (min ),
.sec (sec ),
.seg (seg),
.sel (sel)
);
endmodule
TCL引脚绑定代码
# Copyright (C) 2018 Intel Corporation. All rights reserved.
# Your use of Intel Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Intel Program License
# Subscription Agreement, the Intel Quartus Prime License Agreement,
# the Intel FPGA IP License Agreement, or other applicable license
# agreement, including, without limitation, that your use is for
# the sole purpose of programming logic devices manufactured by
# Intel and sold by Intel or its authorized distributors. Please
# refer to the applicable agreement for further details.
# Quartus Prime Version 18.1.0 Build 625 09/12/2018 SJ Standard Edition
# File: D:\intelFPGA\core\seg_led_static\tcl\seg_led_static_top.tcl
# Generated on: Wed Apr 26 09:36:22 2023
package require ::quartus::project
set_location_assignment PIN_A4 -to sel[0]
set_location_assignment PIN_B4 -to sel[1]
set_location_assignment PIN_A3 -to sel[2]
set_location_assignment PIN_B3 -to sel[3]
set_location_assignment PIN_A2 -to sel[4]
set_location_assignment PIN_B1 -to sel[5]
set_location_assignment PIN_B7 -to seg[0]
set_location_assignment PIN_A8 -to seg[1]
set_location_assignment PIN_E1 -to clk
set_location_assignment PIN_E15 -to rst_n
set_location_assignment PIN_A5 -to seg[7]
set_location_assignment PIN_B8 -to seg[6]
set_location_assignment PIN_A7 -to seg[5]
set_location_assignment PIN_B6 -to seg[4]
set_location_assignment PIN_B5 -to seg[3]
set_location_assignment PIN_A6 -to seg[2]
四、实现效果
如果还有不会创建项目,下载驱动,绑定引脚,请参考博主过往博文。
五、参考资料
https://blog.csdn.net/weixin_43828944/article/details/122699533文章来源:https://www.toymoban.com/news/detail-485317.html
六、电子时钟新编
博主于正式学习FPGA后所写的新版电子时钟博客文章来源地址https://www.toymoban.com/news/detail-485317.html
到了这里,关于FPGA学习——FPGA实现电子时钟的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!