FPGA系统性学习笔记连载_Day13【简易计时器实验】之【Xilinx Spartan-6实现】篇
本系列为FPGA系统性学习学员学习笔记整理分享,如有学习或者购买开发板意向,可加交流群联系群主。
连载《叁芯智能fpga设计与研发-第13天》 【简易计时器实验】之【Xilinx Spartan-6实现】
原创作者:紫枫术河 转载请联系群主授权,否则追究责任
本实验记录一个简易计时器,要求时间分为 时、分、秒,增加2个按键,1个为启动计时、1个为停止计时。
数码管的驱动原理,网上有太多的例程,这里我先不赘述,请自行上网查询,后续到了数码管专题篇再给大家出对应的文章
一、一位数码管显示原理
二、四位数码管显示原理
三、我用的是6位数码管,原理和4位是一样的
我的实验要用6个数码管,位选用了一个38译码器,因为FPGA的引脚不够用了
四、整体设计框架
我分为digital_clock.v、seven_tube_driver.v、clock.v
seven_tube_driver.v是6个数码管的驱动文件
clock.v是计时器计数模块
digital_clock.v是顶层的设计模块,包含按键的检测和计数器的实例化
五、digital_clock.v代码实现
代码语言:javascript复制`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 15:42:30 12/01/2020
// Design Name:
// Module Name: digital_clock
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module digital_clock(
input clk,
input rst_n,
input on,
input off,
output [7:0] seg_out,
output [2:0] sel_out
);
reg flag_start_cnt; //启动计数标志
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
flag_start_cnt = 1'b0;
else if (on == 1'b0)
flag_start_cnt = 1'b1;
else if (off == 1'b0)
flag_start_cnt = 1'b0;
else
flag_start_cnt = flag_start_cnt;
end
clk clk_inst(
.clk (clk),
.rst_n (rst_n),
.start (flag_start_cnt),
.seg_out (seg_out),
.sel_out (sel_out)
);
endmodule
六、clock.v代码实现
代码语言:javascript复制module clk(
input clk,
input rst_n,
input start,
output [7:0] seg_out,
output [2:0] sel_out
);
wire [23:0] data;
//parameter T_1s = 50_000_000; //1s
parameter T_1s = 50_000_00; //100ms,看的数码管走的比较快
reg [25:0] cnt_clk;
reg [5:0] cnt_1s;
reg [5:0] cnt_1min;
reg [5:0] cnt_1h;
reg [5:0] cnt_1d;
reg flag_1s;
reg flag_1min;
reg flag_1h;
reg flag_1d;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
begin
cnt_clk <= 0;
flag_1s <= 0;
end
else if(cnt_clk == T_1s-1)
begin
cnt_clk <= 0;
flag_1s <= 1;
end
else
begin
flag_1s <= 0;
//判断是否启动计数
if(start)
cnt_clk <= cnt_clk 1'b1;
else
cnt_clk <= cnt_clk;
end
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
begin
cnt_1s <= 0;
flag_1min <= 0;
end
else if(flag_1s)
begin
if(cnt_1s == 59)
begin
cnt_1s <= 0;
flag_1min <= 1;
end
else
begin
cnt_1s <= cnt_1s 1'b1;
flag_1min <= 0;
end
end
else
begin
cnt_1s <= cnt_1s;
flag_1min <= 0;
end
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
begin
cnt_1min <= 0;
flag_1h <= 0;
end
else if(flag_1min)
if(cnt_1min == 59)
begin
cnt_1min <= 0;
flag_1h <= 1;
end
else
begin
cnt_1min <= cnt_1min 1'b1;
flag_1h <= 0;
end
else
begin
cnt_1min <= cnt_1min;
flag_1h <= 0;
end
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
begin
cnt_1h <= 0;
flag_1d <= 0;
end
else if(flag_1h)
if(flag_1h == 23)
begin
cnt_1h <= 0;
flag_1d <= 1;
end
else
begin
cnt_1h <= cnt_1h 1'b1;
flag_1d <= 0;
end
else
begin
cnt_1h <= cnt_1h;
flag_1d <= 0;
end
end
seven_tube_driver seven_tube_driver_inst(
.clk (clk),
.rst_n (rst_n),
.data (data),
.seg_out (seg_out),
.sel_out (sel_out)
);
assign data = cnt_1h*10000 cnt_1min * 100 cnt_1s;
endmodule
七、seven_tube_driver.v代码实现
代码语言:javascript复制`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 10:23:31 12/01/2020
// Design Name:
// Module Name: seven_tube_driver
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module seven_tube_driver(
input clk,
input rst_n,
input [23:0] data,
output reg [7:0] seg_out,
output reg [2:0] sel_out
);
parameter T_1K = 50_000;
parameter Sel_Total = 6;
reg flag_1k;
reg [15:0] cnt_1k;
reg [3:0] show_data;
reg [3:0] sel_38;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
begin
cnt_1k <= 16'b0;
flag_1k <= 1'b0;
end
else if(cnt_1k == T_1K-1)
begin
cnt_1k <= 16'b0;
flag_1k <= 1'b1;
end
else
begin
cnt_1k <= cnt_1k 1'b1;
flag_1k <= 1'b0;
end
end
//1KHz 的频率 ,同时切换显示的数据和数码管
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
sel_out <= 3'b0;
else if(flag_1k)
if(sel_out == Sel_Total-1)
sel_out <= 3'b0;
else
sel_out <= sel_out 1'b1;
else
sel_out <= sel_out;
end
always@(*)begin
case(sel_out)
3'b000 : show_data = data/100000;
3'b001 : show_data = data/10000;
3'b010 : show_data = data/1000;
3'b011 : show_data = data/100;
3'b100 : show_data = data/10;
3'b101 : show_data = data;
default:show_data = 0;
endcase
end
reg flag_dp; //显示小数点标志
always@(*)begin
case(sel_out)
3'b001 : flag_dp = 1;
3'b011 : flag_dp = 1;
default : flag_dp = 0;
endcase
end
always@(*)begin
case(show_data)
0:seg_out = 8'b11000000;
1:seg_out = 8'b11111001;
2:seg_out = 8'b10100100;
3:seg_out = 8'b10110000;
4:seg_out = 8'b10011001;
5:seg_out = 8'b10010010;
6:seg_out = 8'b10000010;
7:seg_out = 8'b11111000;
8:seg_out = 8'b10000000;
9:seg_out = 8'b10010000;
default:seg_out = 8'b11111111;
endcase
if(flag_dp)
seg_out = seg_out & 8'b01111111; //显示小数点,只需要将最高位写0即可
else
seg_out = seg_out;
end
endmodule
八、硬件原理图
九、硬件效果
【QQ交流群】
群号:173560979,进群暗语:FPGA技术江湖粉丝。
多年的FPGA企业开发经验,各种通俗易懂的学习资料以及学习方法,浓厚的交流学习氛围,QQ群目前已有1000多名志同道合的小伙伴,无广告纯净模式,给技术交流一片净土,从初学小白到行业精英业界大佬等,从军工领域到民用企业等,从通信、图像处理到人工智能等各个方向应有尽有。
【微信交流群】
现微信交流群已建立09群,人数已达数千人,欢迎关注“FPGA技术江湖”微信公众号,可获取进群方式。
完
后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。
江湖偌大,继续闯荡,愿大侠一切安好,有缘再见!