目录

1.实验描述

2.系统模块框图

3.软件程序

3.1数据生成模块

3.2按键消抖模块

3.3二进制转BCD码模块

3.4数码驱动模块

3.5测设程序

1.实验描述

实现60s计数器的数码显示,当计数为60后回到1又循环,过程中可以通过按键控制暂停与继续。

key:按键控制计数开始或暂停

rst:清零

2.系统模块框图

系统模块主要包含四个模块:

1.数据生成模块:每过1s在原数据基础上加1,并且在等到按键按下的高电平控制数据的计数与暂停。

2.按键消抖模块:检测按键是否按下,按下则产生一个脉冲的高电平。

3.二进制转BCD码模块:将数据生成模块中的数据进行转换为BCD码,提供给数码驱动模块。

4.数码驱动模块:得到BCD码后,每过1ms驱动一个数码管位并显示内容。

3.软件程序

3.1数据生成模块

`timescale 1ns / 1ns   module top_seg
(input            sys_clk,          input            sys_rst_n,input            key      ,      output    [5:0]  sel,               //数码管位选信号output    [7:0]  seg                //数码管段选信号
);                         wire          [7:0]  data;                    //数码管显示的数值data_gen    data_gen_inst(              //数据产生模块,每过0.1s数据自加一     //@2seg_data_inst ?= u_seg_data .sys_clk        (sys_clk)       ,   .sys_rst_n      (sys_rst_n)     , .key            (key)           ,.data           (data)                  );seg_dynamic   seg_dynamic_inst(         //数码管动态显示模块.sys_clk       (sys_clk)       ,   .sys_rst_n     (sys_rst_n)     ,                           .data          (data)          , .sel           (sel)           ,   .seg           (seg)
);
endmodule

3.2按键消抖模块

`timescale  1ns/1nsmodule  key_filter
#(parameter CNT_MAX = 20'd999_999 //计数器计数最大值
)
(input   wire    sys_clk     ,   //系统时钟50Mhzinput   wire    sys_rst_n   ,   //全局复位input   wire    key_in      ,   //按键输入信号output  reg     key_flag        //key_flag为1时表示消抖后检测到按键被按下//key_flag为0时表示没有检测到按键被按下
);
//reg   define
reg     [19:0]  cnt_20ms    ;   //计数器//cnt_20ms:如果时钟的上升沿检测到外部按键输入的值为低电平时,计数器开始计数
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_20ms <= 20'b0;else    if(cnt_20ms == CNT_MAX && key_in == 1'b0)cnt_20ms <= cnt_20ms;else    if(key_in == 1'b1)      //按键没有按下,不计时cnt_20ms <= 20'b0;else   cnt_20ms <= cnt_20ms + 1'b1;//key_flag:当计数满20ms后产生按键有效标志位
//且key_flag在999_999时拉高,维持一个时钟的高电平
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)key_flag <= 1'b0;else    if(cnt_20ms == CNT_MAX - 1'b1)key_flag <= 1'b1;elsekey_flag <= 1'b0;endmodule

3.3二进制转BCD码模块

`timescale  1ns/1nsmodule  bcd_8421
(input   wire            sys_clk     ,   input   wire            sys_rst_n   ,   input   wire    [7:0]  data        ,   //输入需要转换的数据output  reg     [3:0]   unit        ,   //个位BCD码output  reg     [3:0]   ten         ,   //十位BCD码output  reg     [3:0]   hun         ,   //百位BCD码output  reg     [3:0]   tho         ,   //千位BCD码output  reg     [3:0]   t_tho       ,   //万位BCD码output  reg     [3:0]   h_hun           //十万位BCD码
);
reg     [4:0]   cnt_shift   ;            //移位判断计数器  移动次数由十转为二进制的位数决定
reg     [43:0]  data_shift  ;            //移位判断数据 寄存器  存放BCD码与二进制码
reg             shift_flag  ;            //移位判断标志信号   用于控制移位判断的先后顺序//cnt_shift:从0到21循环计数(当计为20时进行判断移位,21时则是取BCD码数据)
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_shift   <=  5'd0;else    if((cnt_shift == 5'd21) && (shift_flag == 1'b1))    cnt_shift   <=  5'd0;else    if(shift_flag == 1'b1)cnt_shift   <=  cnt_shift + 1'b1;elsecnt_shift   <=  cnt_shift;//data_shift:计数器为0时赋初值,计数器为1~20时进行移位判断操作
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)data_shift  <=  44'b0;else    if(cnt_shift == 5'd0)   //计数器为0时赋初值data_shift  <=  {24'b0,data};else    if((cnt_shift <= 20) && (shift_flag == 1'b0))     //<=为小于等于,先判断再移位 begin data_shift[23:20]   <=  (data_shift[23:20] > 4) ? (data_shift[23:20] + 2'd3) : (data_shift[23:20]);data_shift[27:24]   <=  (data_shift[27:24] > 4) ? (data_shift[27:24] + 2'd3) : (data_shift[27:24]);data_shift[31:28]   <=  (data_shift[31:28] > 4) ? (data_shift[31:28] + 2'd3) : (data_shift[31:28]);data_shift[35:32]   <=  (data_shift[35:32] > 4) ? (data_shift[35:32] + 2'd3) : (data_shift[35:32]);data_shift[39:36]   <=  (data_shift[39:36] > 4) ? (data_shift[39:36] + 2'd3) : (data_shift[39:36]);data_shift[43:40]   <=  (data_shift[43:40] > 4) ? (data_shift[43:40] + 2'd3) : (data_shift[43:40]);endelse    if((cnt_shift <= 20) && (shift_flag == 1'b1))data_shift  <=  data_shift << 1;elsedata_shift  <=  data_shift;
//shift_flag:移位判断标志信号,低电平判断   高电平移位
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)shift_flag  <=  1'b0;elseshift_flag  <=  ~shift_flag;
//当计数器等于20时,移位判断操作完成,对各个位数的BCD码进行赋值
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)beginunit    <=  4'b0;ten     <=  4'b0;hun     <=  4'b0;tho     <=  4'b0;t_tho   <=  4'b0;h_hun   <=  4'b0;endelse    if(cnt_shift == 5'd21)beginunit    <=  data_shift[23:20];ten     <=  data_shift[27:24];hun     <=  data_shift[31:28];tho     <=  data_shift[35:32];t_tho   <=  data_shift[39:36];h_hun   <=  data_shift[43:40];end
endmodule

3.4数码驱动模块

`timescale  1ns/1nsmodule  seg_dynamic
#(parameter   CNT_MAX =   16'd49_999  //数码管刷新 时间计数最大值 1ms
)
(input   wire            sys_rst_n   , input   wire            sys_clk     , input   wire    [7:0]   data        , //数码管要显示的值output  reg     [5:0]   sel         , //数码管位选信号output  reg     [7:0]   seg           //数码管段选信号
);
//wire  define
wire    [3:0]   unit        ;   //个位数
wire    [3:0]   ten         ;   //十位数
wire    [3:0]   hun         ;   //百位数
wire    [3:0]   tho         ;   //千位数
wire    [3:0]   t_tho       ;   //万位数
wire    [3:0]   h_hun       ;   //十万位数
//reg   define
reg     [23:0]  data_reg    ;   //待显示数据 寄存器
reg     [15:0]  cnt_1ms     ;   //1ms计数器
reg             flag_1ms    ;   //1ms标志信号
reg     [2:0]   cnt_sel     ;   //数码管位选计数器
reg     [5:0]   sel_reg     ;   //位选信号
reg     [3:0]   data_disp   ;   //当前数码管显示的数据//cnt_1ms:1ms计数器
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_1ms <=  16'd0;else    if(cnt_1ms == CNT_MAX)cnt_1ms <=  16'd0;elsecnt_1ms <=  cnt_1ms + 1'b1;
//flag_1ms:1ms标志信号
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)flag_1ms    <=  1'b0;else    if(cnt_1ms == CNT_MAX - 1'b1)flag_1ms    <=  1'b1;                                                  // unit  为BCD码,可以总效果4'bXXXXelse                                                                       // ten   为BCD码,可以总效果4'bXXXXflag_1ms    <=  1'b0;                                                  // hun   为BCD码,可以总效果4'bXXXX// tho   为BCD码,可以总效果4'bXXXX
//data_reg:控制数码管显示数据                                                 // t_tho 为BCD码,可以总效果4'bXXXXalways@(posedge sys_clk or  negedge sys_rst_n)                                // h_hun 为BCD码,可以总效果4'bXXXXif(sys_rst_n == 1'b0)                                                      data_reg    <=  24'b0;
//若显示的十进制数的 十万 位为非零数据则六个数码管全显示                       else    if(h_hun)    //h_hun非空即数据有六位                               data_reg    <=  {h_hun,t_tho,tho,hun,ten,unit};
//若显示的十进制数的 万 位为非零数据则值显示在5个数码管上else    if(t_tho)data_reg <= {4'd11,t_tho,tho,hun,ten,unit}; //4'd11(第六位)我们定义为不显示
//若显示的十进制数的 千 位为非零数据则值显示4个数码管else    if(tho)data_reg <= {4'd11,4'd11,tho,hun,ten,unit};
//若显示的十进制数的 百 位为非零数据则值显示3个数码管else    if(hun)data_reg <= {4'd11,4'd11,4'd11,hun,ten,unit};
//若显示的十进制数的 十 位为非零数据则值显示2个数码管else    if(ten)data_reg <= {4'd11,4'd11,4'd11,4'd11,ten,unit};
//若上面都不满足都只显示 个 位数码管elsedata_reg <= {4'd11,4'd11,4'd11,4'd11,4'd11,unit};//cnt_sel:标记0-5ms所对应显示的BCD码
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_sel <=  3'd0;else    if((cnt_sel == 3'd5) && (flag_1ms == 1'b1))cnt_sel <=  3'd0;else    if(flag_1ms == 1'b1)cnt_sel <=  cnt_sel + 1'b1;elsecnt_sel <=  cnt_sel;//数码管位选信号寄存器
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)sel_reg <=  6'b000_000;else    if((cnt_sel == 3'd0) && (flag_1ms == 1'b1))sel_reg <=  6'b000_001;else    if(flag_1ms == 1'b1)sel_reg <=  sel_reg << 1;elsesel_reg <=  sel_reg;//控制数码管的位选信号,使六个数码管轮流显示
always@(posedge sys_clk or  negedge sys_rst_n)if(sys_rst_n == 1'b0)data_disp    <=  4'b0;else    if(flag_1ms == 1'b1)case(cnt_sel)3'd0:   data_disp    <=  data_reg[3:0]  ;  //给第1个数码管赋个位值3'd1:   data_disp    <=  data_reg[7:4]  ;  //给第2个数码管赋十位值3'd2:   data_disp    <=  data_reg[11:8] ;  //给第3个数码管赋百位值3'd3:   data_disp    <=  data_reg[15:12];  //给第4个数码管赋千位值3'd4:   data_disp    <=  data_reg[19:16];  //给第5个数码管赋万位值3'd5:   data_disp    <=  data_reg[23:20];  //给第6个数码管赋十万位值default:data_disp    <=  4'b0        ;endcaseelsedata_disp   <=  data_disp;//控制数码管段选信号,显示数字
always@(posedge sys_clk or  negedge sys_rst_n)if(sys_rst_n == 1'b0)seg <=  8'b1111_1111;else    case(data_disp)4'd0  : seg  <=  8'b1100_0000;    //显示数字04'd1  : seg  <=  8'b1111_1001;    //显示数字14'd2  : seg  <=  8'b1010_0100;    //显示数字24'd3  : seg  <=  8'b1011_0000;    //显示数字34'd4  : seg  <=  8'b1001_1001;    //显示数字44'd5  : seg  <=  8'b1001_0010;    //显示数字54'd6  : seg  <=  8'b1000_0010;    //显示数字64'd7  : seg  <=  8'b1111_1000;    //显示数字74'd8  : seg  <=  8'b1000_0000;    //显示数字84'd9  : seg  <=  8'b1001_0000;    //显示数字9default:seg  <=  8'b1111_1111;endcase//sel:数码管位选信号赋值
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)sel <=  6'b000_000;elsesel <=  sel_reg;bcd_8421    bcd_8421_inst
(.sys_clk     (sys_clk  ),   //系统时钟,频率50MHz.sys_rst_n   (sys_rst_n),   //复位信号,低电平有效.data        (data     ),   //输入需要转换的数据.unit        (unit     ),   //个位BCD码.ten         (ten      ),   //十位BCD码.hun         (hun      ),   //百位BCD码.tho         (tho      ),   //千位BCD码.t_tho       (t_tho    ),   //万位BCD码.h_hun       (h_hun    )    //十万位BCD码
);
endmodule

3.5测试程序

`timescale  1ns/1ns
module  tb_top_seg();reg           sys_clk   ;  reg           sys_rst_n ;  reg           key       ;  wire    [5:0]       sel       ;        wire    [7:0]       seg       ;initialbegin                                      sys_clk = 1'b0;sys_rst_n <= 1'b0;key  <= 1'b1;#20;sys_rst_n <= 1'b1;#60;key  <= 1'b0;          //按键第一次拉低#500;key  <= 1'b1;#80000key  <= 1'b0;          //按键第二次拉低#500;key  <= 1'b1;end    always #10 sys_clk = ~sys_clk;defparam  top_seg_inst.data_gen_inst.KEY_CNT =  20'd11;
defparam  top_seg_inst.data_gen_inst.CNT_MAX_1S    = 26'd49;
defparam  top_seg_inst.seg_dynamic_inst.CNT_MAX   = 16'd20;top_seg     top_seg_inst
(.sys_clk    (sys_clk   ) ,.sys_rst_n  (sys_rst_n ) ,.key        (key       ) ,.sel        (sel      ) , .seg        (seg       )
);
endmodule

烧入板子后可以成功实现相关功能,欢迎评论区讨论!

FPGA动态数码管应用——60S计数相关推荐

  1. FPGA 动态数码管显示实验

    参考:正点原子开拓者 FPGA 开发指南 一.数码管动态显示简介 由于一般的静态驱动操作虽然方便,但占用的I/0口较多,例如要驱动6位8段数码管,以静态驱动方式让数码管各个位显示不同的数值,如&quo ...

  2. 基于FPGA的两位按键控制LED数码管加减计数实验

    两位按键控制LED数码管加减计数实验 这是一篇拖了一个多月的文章,主要是基于FPGA利用按键消抖原理与动态数码管驱动原理相结合,来实现一个利用两位按键来控制数码管实现0-99的加法计数或者减法计数功能 ...

  3. FPGA之动态数码管显示实验

    1.试验任务 完成6位数码管以动态方式从0开始计数,没100ms计数值增加1,当计数值从0增加到999999后重新从0开始计数. 2.硬件原理图 3.程序框图 程序设计思想: FPGA顶层(top_s ...

  4. FPGA实战篇——【6】动态数码管

    FPGA实战--动态数码管 rtl文件 模块设计: 计数模块,产生数码管的数据 数码管显示驱动模块 时钟分频 数字转码(二进制->BCD码) 位选信号切换 调试warning: ucf文件 ** ...

  5. 实验三 基于FPGA的数码管动态扫描电路设计 quartus/数码管/电路模块设计

    实验三 基于FPGA的数码管动态扫描电路设计 源文件的链接放在最后啦 实验目的: (1) 熟悉7段数码管显示译码电路的设计. (2) 掌握数码管显示原理及静态.动态扫描电路的设计. 实验任务: (1) ...

  6. 数字IC-1.8 子模块组建整模块-动态数码管设计代码实例

    感谢野火开源教程的支持!EmbedFire – 东莞野火电子技术有限公司 本实验采用阳极6位数码管,其中段选是共用的. 一.实验目标 让六位数码管显示从十进制数 0 开始计数,每 0.1s 加 1,一 ...

  7. 动态数码管verilog模块功能分析

    学习正点原子FPGA开发板关于动态数码管章节: 实验任务是使用FPGA 开发板上的 6 位数码管以动态方式从 0 开始计数,每 100 ms 计数值增加 一,当计数值从 0 增加到 999999 后重 ...

  8. 74HC595工作原理及FPGA实现数码管驱动方法

    74HC595,移位寄存器,串行输入,8位并行输出,一般用于数码管电路以减少使用的IO口数量. 管脚介绍: Q0~Q7 :八位并行输出位 Q7'       :  级联位,若输入位数大于8位,先进入的 ...

  9. 黑金AX301开发板学习(3)——动态数码管的时钟实验

    开发板的使用是AX301,学习资料可以在我的另一篇文章中找到.链接在如下:https://blog.csdn.net/qq_24213087/article/details/108238682 一.动 ...

最新文章

  1. 话里话外:信息资源整合失败之痛(二)
  2. 查找内存泄漏的一个思路
  3. java replaceall lt_static lt;Tgt; boolean replaceAll(Listlt;Tgt; list, T oldVal, T newVal)_Java...
  4. PHP7新增的主要特性
  5. 系统架构师-基础到企业应用架构-业务逻辑层
  6. java day55【 Mybatis 连接池与事务深入 、 Mybatis 的动态 SQL 语句、 Mybatis 多表查询之一对多 、 Mybatis 多表查询之多对多】...
  7. 德国Java工程师_1886年,德国工程师。
  8. gtest的介绍和使用
  9. 【系统分析师之路】系统分析师历年真题大汇总
  10. 省市区三级数据-MySQL
  11. ptc转4-20mA热电阻变送器NI1000 NTC转0-10ma输出PWM
  12. Thymeleaf介绍和基操(附截图和代码)
  13. C# dataGridView上下移动选中行
  14. centos7安装otrs
  15. 计算机为什么不读500g硬盘,为什么我的500g硬盘的实际容量只有46 5. 1G
  16. jmeter断言(自动判断实际和预期结果是否相符的jmeter组件)
  17. java update 8_java 8 update 77可以删除吗
  18. 三阶魔方有多少种状态
  19. apache http server 停止工作_(二)http协议的网站装ssl升级成https
  20. java如何读取word文档内容并修改指定内容文本颜色

热门文章

  1. Task 03 python自动化之word操作
  2. pte模拟考试_PTE考试题型详解
  3. EEE407 Electrical Energy Utilization (学习整理 Week 1)
  4. modelsim-win64-10.4-se.exe安装
  5. [Java]用面向对象的知识来做一个简易版植物大战僵尸
  6. OpenRPG横版格斗RPG(Demo)
  7. fifo 详细讲解实例
  8. 合并HEX文件的一种方法
  9. DIY一把属于自己的机械键盘(二)
  10. Ubuntu20安装deepin-wine版本的QQ、微信等