基于FPGA的数字秒表(数码管显示模块和按键消抖)实现
本文主要是学习按键消抖和数码管动态显示,秒表显示什么的,个人认为,拿FPGA做秒表真是嫌钱多。
感谢
感谢学校和至芯科技,笔者专业最近去北京至芯科技培训交流了一周。老师的经验还是可以的,优化了自己的代码也学习了新的知识。北京是个好地方,故宫没有想象中的那么大,但人真是多到密集恐惧症。至芯科技的最小开发板设计的一般般。。。
言归正传,本次主要实现数字数码管的主要功能,按键触发:秒表开始,暂停,记录,回显。一共四个按键,第一个按键控制全局复位,第二个按键控制秒表的开始与暂停,第三个按键控制秒表在运行中按下记录,第四个按键控制秒表在暂停的时候,记录的数据可以按一下则顺序回显一个数据,一共三个数据。
秒表可以从00:00:00 -- 59:59:99 , 6位数码管。
设计功能分解
至芯的板子数码管那位选采用了三八译码器,由于一般不用数码管,二进制转bcd的方法就不在这里阐述(不用也不会,至芯科技直接用了除号等不符合设计规范的编码实现)。直接采用到9则进1的方式,由于采用单时钟域,时序对齐还是需要特别注意的。

按键消抖模块设计
系统时钟50MHZ,采用时钟使能的方式10ms采样一个值,用一个8bit的移位寄存器实现消抖并只检测下降沿(按键按下为低电平),当按键按下产生1个系统时钟周期的高电平。
代码仅供学习使用:
//************************************************
// Filename : debounce.v
// Author : kingstacker
// Company : School
// Email : kingstacker_work@163.com
// Device : Altera cyclone4 ep4ce6f17c8
// Description : when the key is pressed ,porduce 1 period clk high;
//************************************************
module debounce ( //use shift reg logic;
/*i*/ input wire clk ,
input wire rst_n ,
input wire key_i ,
/*o*/ output wire key_o
);
parameter CLK_MAX = 'd49_9999; //0.01s;
reg [:] cnt;
reg clk_en;
reg key_o_r;
always @(posedge clk or negedge rst_n) begin //control cnt value;
if (~rst_n) begin
cnt <= ;
end //if
else begin
cnt <= (cnt == CLK_MAX) ? 'd0 : cnt + 1'b1;
end //else
end //always
always @(posedge clk or negedge rst_n) begin //produce clk_en;
if (~rst_n) begin
clk_en <= 'b0;
end //if
else begin
clk_en <= (cnt == CLK_MAX) ? 'b1 : 1'b0;
end //else
end //always
reg [:] shift_val;
always @(posedge clk or negedge rst_n) begin //shift logic;
if (~rst_n) begin
shift_val <= 'hff;
end //if
else begin
shift_val <= (clk_en) ? {shift_val[:],key_i} : shift_val;
end //else
end //always
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
key_o_r <= 'b0;
end //if
else begin
if (shift_val == 'b1000_0000 && clk_en) begin //check key pressed negedge;
key_o_r <= 'b1;
end
else begin
key_o_r <= 'b0;
end
end //else
end //always
assign key_o = key_o_r; endmodule
6位数码管动态显示模块设计
数码管由于dp位需要控制,本模块中dp位逻辑单独了出来,动态显示1ms刷新数码管,6个管需要6ms,注意间隔不要太大,否则会闪烁,太紧也没有必要,保证数据对齐,采用组合逻辑实现:
//************************************************
// Filename : led_display.v
// Author : kingstacker
// Company : School
// Email : kingstacker_work@163.com
// Device : Altera cyclone4 ep4ce6f17c8
// Description :on board ok; one clk domain;input din is bcd ;
//************************************************
module led_display (
/*i*/ input wire clk ,
input wire rst_n ,
input wire [:] din , //data from sco model;
/*o*/ output wire [:] sel , //38 decoder;
output wire [:] seg //segement;
);
parameter MS_MAX = 'd4_9999; //1ms dynamic refresh;//4_9999;
reg flag_1ms;
reg [:] cnt_1ms;
reg [:] sel_r;
reg [:] seg_r;
reg [:] seg_sel;
reg [:] cnt_sel;
wire dp;
always @(posedge clk or negedge rst_n) begin //control cnt_1ms value;
if (~rst_n) begin
cnt_1ms <= ;
end //if
else begin
cnt_1ms <= (cnt_1ms == MS_MAX) ? 'd0 : cnt_1ms + 1'b1;
end //else
end //always
always @(posedge clk or negedge rst_n) begin //produce the flag_1ms high level;
if (~rst_n) begin
flag_1ms <= 'b0;
end //if
else begin
flag_1ms <= (cnt_1ms == MS_MAX) ? 'b1 : 1'b0;
end //else
end //always
always @(posedge clk or negedge rst_n) begin //cnt sel value control;
if (~rst_n) begin
cnt_sel <= ;
end //if
else begin
cnt_sel <= (cnt_sel == 'd5 && flag_1ms) ? 3'd0 : (flag_1ms) ? cnt_sel + 'b1 : cnt_sel;
end //else
end //always
always @(*) begin //sel logic exchange;
case (cnt_sel)
'd0: begin sel_r = 3'b101;seg_sel = din[:]; end
'd1: begin sel_r = 3'b100;seg_sel = din[:]; end
'd2: begin sel_r = 3'b011;seg_sel = din[:]; end
'd3: begin sel_r = 3'b010;seg_sel = din[:]; end
'd4: begin sel_r = 3'b001;seg_sel = din[:]; end
'd5: begin sel_r = 3'b000;seg_sel = din[:]; end
default: begin sel_r = 'b111;seg_sel = 4'd10; end
endcase //case
end //always
always @(*) begin //display coder;
case (seg_sel)
'd0: begin seg_r = 7'b100_0000; end //0;
'd1: begin seg_r = 7'b111_1001; end //1;
'd2: begin seg_r = 7'b010_0100; end //2;
'd3: begin seg_r = 7'b011_0000; end //3;
'd4: begin seg_r = 7'b001_1001; end //4;
'd5: begin seg_r = 7'b001_0010; end //5;
'd6: begin seg_r = 7'b000_0010; end //6;
'd7: begin seg_r = 7'b111_1000; end //7;
'd8: begin seg_r = 7'b000_0000; end //8;
'd9: begin seg_r = 7'b001_0000; end //9;
default: begin seg_r = 'b100_0000; end //x;
endcase //case
end //always assign dp = !(cnt_sel == 'd2 || cnt_sel == 3'd4); //dp produce logic;
assign seg = {dp,seg_r};
assign sel = sel_r; endmodule
sco模块就没啥意思了,本文主要讲述按键消抖的实现方式以及数码管动态显示的问题。
如果需要整体源码,请上github查看:git@github.com:kingstacker/second_counter.git
再次感谢至芯科技公司以及李老师。
以上。
基于FPGA的数字秒表(数码管显示模块和按键消抖)实现的更多相关文章
- 基于FPGA的数字识别的实现
欢迎大家关注我的微信公众号:FPGA开源工作室 基于FPGA的数字识别的实现二 作者:lee神 1 背景知识 1.1基于FPGA的数字识别的方法 通常,针对印刷体数字识别使用的算法有:基于模版 ...
- 基于FPGA的LCD+CMOS视频采集显示使用小结
基于FPGA的LCD+CMOS视频采集显示 液晶显示器采用扫描模式,RGB888 电源采用:+5V供电 usb供电有时候会出现供电不足的问题 显示器接口有两种选择:16bit或24bit 分别对应 ...
- 09B-独立按键消抖实验02——小梅哥FPGA设计思想与验证方法视频教程配套文档
芯航线--普利斯队长精心奉献 实验目的: 1.复习按键的设计 2.用模块化设计的方式实现每次按下按键0,4个LED显示状态以二进制加法格式加1,每次按下按键1,4个LED显示状态以二进制加法格式减 ...
- FPGA学习笔记(八)—— 状态机设计实例之独立按键消抖
###### [该随笔中部分内容转载自小梅哥] ######### 独立按键消抖自古以来在单片机和FPGA中都是个不可避免的问题,首先,解释一下什么叫做按键抖动,如图,按键在按下和松开的那个瞬间存在大 ...
- 我的 FPGA 学习历程(11)—— 实验:按键消抖
按键是一个输入设备,在理论上可以归为开关一类,理想的按键波形如下: 然而由于按键的机械特性,断开和闭合动作是不可能在一瞬间完成的,实际的波形如下: 抖动期间电平处于临界值,由于晶振的频率相当的高,数字 ...
- 09A-独立按键消抖实验01——小梅哥FPGA设计思想与验证方法视频教程配套文档
芯航线--普利斯队长精心奉献 实验目的: 1.复习状态机的设计思想并以此为基础实现按键消抖 2.单bit异步信号同步化以及边沿检测 3.在激励文件中学会使用随机数发生函数$random 4.仿真模 ...
- FPGA经典:Verilog传奇与基于FPGA的数字图像处理原理及应用
一 简述 最近恶补基础知识,借了<<Verilog传奇>>,<基于FPGA的嵌入式图像处理系统设计>和<<基千FPGA的数字图像处理原理及应用>& ...
- 基于FPGA的key button等开关消抖,按键消抖电路设计
最近要用上一个key消抖的功能.于是找到了之前写的并放入博客的程序,发现居然全部有问题.http://www.cnblogs.com/sepeng/p/3477215.html —— 有问题,包括很多 ...
- fpga Verilog hdl 按键消抖 部分程序讲解
module debounce(clk_in,rst_in,key_in,key_pulse,key_state); input clk_in;//system clock input rst_in; ...
随机推荐
- Sparse Principal Component Analysis via Rotation and Truncation
目录 对以往一些SPCA算法复杂度的总结 Notation 论文概述 原始问题 问题的变种 算法 固定\(X\),计算\(R\) 固定\(R\),求解\(X\) (\(Z =VR^{\mathrm{T ...
- Python_内置函数之max
源码: def max(*args, key=None): # known special case of max """ max(iterable, *[, defau ...
- python中类方法,实例方法,静态方法的作用和区别
Python中至少有三种比较常见的方法类型,即实例方法,类方法.静态方法.它们是如何定义的呢?如何调用的呢?它们又有何区别和作用呢?且看下文. 首先,这三种方法都定义在类中.下面我先简单说一下怎么 ...
- 福州大学软件工程1816 | W班 第5次作业成绩排名
写在前面 汇总成绩排名链接 1.作业链接 第五次作业--项目选题报告(团队) 2.评分准则 本次作业映射总分为100分+贡献度得分,由以下部分组成: 选题报告内容(10分) 本组评审表设计(5分) 现 ...
- Zk搭建(Zookeeper)
第一步: 上传----解压 tar -zxvf zookeeper-3.4.5.tar.gz---- 配置zk的环境变量 ----------配置源码 vim ...
- Ubuntu Linux Recovery Mode
在安全模式/修復模式有以下的選項︰resume Resume normal boot繼續正常啟動作業,供不小心誤入此選單的使用者開機使用.(继续以正常模式启动) clean Try to make f ...
- javascript中的 return false和return true
关于javascript中的 return false和return true,return 是javascript里函数返回值的关键字,一个函数内处理的结果可以使用return 返回,这样在调用函数 ...
- oninput事件和onchange事件区别
onchange事件 触发条件:在域内容更改时触发,也可用于单选框和复选框改变后触发 作用对象:select.input.textarea oninput事件 触发条件:在域内容更改时触发(严格说在用 ...
- 利用js给datalist或select动态添加option选项
<!DOCTYPE html> <html> <head> <title>鼠标点击时加载</title> <script type=& ...
- springboot+ELK+logback日志分析系统demo
之前写的有点乱,这篇整理了一下搭建了一个简单的ELK日志系统 借鉴此博客完成:https://blog.csdn.net/qq_22211217/article/details/80764568 设置 ...