基于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 = 19'd49_9999; //0.01s;
reg [18:0] cnt;
reg clk_en;
reg key_o_r;
always @(posedge clk or negedge rst_n) begin //control cnt value;
    if (~rst_n) begin
        cnt <= 0;
    end //if
    else begin
        cnt <= (cnt == CLK_MAX) ? 19'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 <= 1'b0;
    end //if
    else begin
        clk_en <= (cnt == CLK_MAX) ? 1'b1 : 1'b0;    
    end //else
end //always
reg [7:0] shift_val;
always @(posedge clk or negedge rst_n) begin //shift logic;
    if (~rst_n) begin
        shift_val <= 8'hff;
    end //if
    else begin
        shift_val <= (clk_en) ? {shift_val[6:0],key_i} : shift_val;    
    end //else
end //always
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        key_o_r <= 1'b0;
    end //if
    else begin
        if (shift_val == 8'b1000_0000 && clk_en) begin  //check key pressed negedge;
            key_o_r <= 1'b1;
        end    
        else begin
            key_o_r <= 1'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    [23:0]    din              ,  //data from sco model;
/*o*/   output   wire    [2:0]     sel              ,  //38 decoder;
        output   wire    [7:0]     seg                 //segement;      
);
parameter MS_MAX = 17'd4_9999; //1ms dynamic refresh;//4_9999;
reg          flag_1ms;
reg  [16:0]  cnt_1ms;
reg  [2:0]   sel_r;
reg  [6:0]   seg_r;
reg  [3:0]   seg_sel;
reg  [2:0]   cnt_sel;
wire         dp;  
always @(posedge clk or negedge rst_n) begin   //control cnt_1ms value;
    if (~rst_n) begin
        cnt_1ms <= 0;
    end //if
    else begin
        cnt_1ms <= (cnt_1ms == MS_MAX) ? 16'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 <= 1'b0;
    end //if
    else begin
        flag_1ms <= (cnt_1ms == MS_MAX) ? 1'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 <= 0;
    end //if
    else begin
        cnt_sel <= (cnt_sel == 3'd5 && flag_1ms) ? 3'd0 : (flag_1ms) ? cnt_sel + 1'b1 : cnt_sel;   
    end //else
end //always
always @(*) begin          //sel logic exchange;
        case (cnt_sel)
            3'd0: begin sel_r = 3'b101;seg_sel = din[3:0];   end
            3'd1: begin sel_r = 3'b100;seg_sel = din[7:4];   end
            3'd2: begin sel_r = 3'b011;seg_sel = din[11:8];  end
            3'd3: begin sel_r = 3'b010;seg_sel = din[15:12]; end
            3'd4: begin sel_r = 3'b001;seg_sel = din[19:16]; end
            3'd5: begin sel_r = 3'b000;seg_sel = din[23:20]; end
            default: begin sel_r = 3'b111;seg_sel = 4'd10;   end 
        endcase //case   
end //always
always @(*) begin         //display coder;
        case (seg_sel)
            4'd0: begin seg_r = 7'b100_0000;    end //0; 
            4'd1: begin seg_r = 7'b111_1001;    end //1; 
            4'd2: begin seg_r = 7'b010_0100;    end //2; 
            4'd3: begin seg_r = 7'b011_0000;    end //3; 
            4'd4: begin seg_r = 7'b001_1001;    end //4; 
            4'd5: begin seg_r = 7'b001_0010;    end //5; 
            4'd6: begin seg_r = 7'b000_0010;    end //6; 
            4'd7: begin seg_r = 7'b111_1000;    end //7; 
            4'd8: begin seg_r = 7'b000_0000;    end //8; 
            4'd9: begin seg_r = 7'b001_0000;    end //9; 
            default: begin seg_r = 7'b100_0000; end //x;
            endcase //case    
end //always

assign dp = !(cnt_sel == 3'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

再次感谢至芯科技公司以及李老师。

以上。

转载于:https://www.cnblogs.com/kingstacker/p/8001064.html

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本科生毕业论文(设计)开题报告书 题 目: 基于FPGA数字秒表设计 学生姓名: *********** 学 号: ********** 专业班级: 自动化******班 指导老师: ************ 2010年 3 月 20 日 论文(设计)题目 ISP技术及其应用研究 课题目的、意义及相关研究动态: 课题设计的主要目的:运用所学的数字电子技术的基本知识和数字电子电路的设计方法,将数字电子技术的基础知识与EDA技术有机地联系起来,EDA电子仿真软件的仿真功能强大,具有完备的文件库,具有选用元器件创建电路、仿真模拟运行电路的功能,并且在输入信号的加入、输出信号的显示上能完全模拟实际和调制过程中的各种波型和操作过程。此类设计需要在EDA仿真软件上仿真进行,并利用下载工具,下载到特定的硬件设备上,进行实时的运行与验证,来证明所设计的电路的正确性。这样把所学到的理论知识综合的运用到一些较复杂的数字逻辑电路系统中去,使我们在实践基本技能方面得到一次全面系统的锻炼;这样可以使我们了解和掌握现代复杂数字系统芯片的设计方法和所用到的EDA工具,为走上社会进入专业的电子技术公司后,能胜任各种电子产品集成化的实际设计工作打下了坚实的基础。 课题的意义:秒表是一种常见的计时工具,种类比较多。这里用EDA技术设计一种基于FPGA数字秒表。它可以为用户提供了传统的PLD技术无法达到的灵活性,带来了巨大的时间效益和经济效益,是可编程技术的实质性飞跃。FPGA还是有其具大的优势比如它的高速性。 相关研究动态:现在对EDA的概念或范畴用得很宽。包括在机械、电子、通信、航空航天、化工、矿产、生物、医学、军事等各个领域,都有EDA的应用。目前EDA 技术已在各大公司、企事业单位和科研教学部门广泛使用。例如在飞机制造过程中,从设计、性能测试及特性分析直到飞行模拟,都可能涉及到EDA技术。本文所指的EDA技术,主要针对电子电路设计、PCB设计和IC设计。EDA 设计可分为系统级、电路级和物理实现级。 课题的主要内容(观点)、创新之处: 课题设计的主要内容: 1. 设计任务: 设计一个采用六位LED数码管显示分、秒,0.1s,0.01s计时方式的数字秒表。使用按键开关可实现开始/结束计时操作,及复位清零操作。 2.设计要求: 要求:1、设计方案具有合理性、科学性; 2、系统工作稳定可靠; 3、系统抗干扰性能强; 4、系统硬件电路简单、程序结构明晰。 3.系统功能 1. 有启/停开关,用于开始/结束计时操作 2. 秒表计时长度为59.分59.99秒,超过计时长度,有溢出则报警,计时长度可手动设置。 3. 设置复位开关,在任何情况下只要按下复位开关,秒表都要无条件进行复位清0操作。 4. 用FPGA器件实现,用VHDL语言编程,并进行下载,仿真。 创新之处: 利用EDA技术中最为瞩目的在系统可编程技术进行电子系统的设计的创新之处:1、用软件的方式设计硬件;2、用软件方式设计的系统到硬件系统的转换是由有关的开发软件自动完成;3、设计过程中可用有关软件进行各种仿真;4、系统可现场编程,在线升级;5、整个系统可集成在一个芯片上,体积小、功耗低、可靠性高。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值