首页 > 其他分享 >基于FPGA的秒表计时系统设计--第一版--郝旭帅电子设计团队

基于FPGA的秒表计时系统设计--第一版--郝旭帅电子设计团队

时间:2024-07-20 16:59:30浏览次数:12  
标签:begin FPGA 记录 -- always clk b0 rst 电子设计

欢迎各位朋友关注“郝旭帅电子设计团队”,本篇为各位朋友介绍基于FPGA的秒表计时系统设计--第一版--郝旭帅电子设计团队。

 

功能说明:

 

  1. 利用六个数码管显示。

  2. 以10ms为精度显示

  3. 以秒为单位进行显示

  4. 记录最大为999.99

  5. 第一个数码管在运行时不显示

  6. 在翻看记录时,第一个数码管显示记录的次数

  7. 最多可以记录9次

  8. 使用说明:先按下启动,再按下记录(可以多次记录,此时秒依然运行),按下停止,按翻看即可。重复以上步骤

  

使用平台:本次设计应用Altera的平台设计(芯片:EP4CE10F17C8N)。

仿真平台:Modelsim。

作者QQ:746833924

说明:本篇设计中不涉及到IP和原语,代码在其他平台依然可以适用;当其他板卡电路不同时,会导致不同的现象出现,如有需要修改代码请联系作者;如需作者使用的板卡,请联系作者;

 

设计思想如下:


 

    

        key_ctrl模块负责将外部的按键信号进行消抖,并且产生对应边沿变化时的脉冲;sec_timer_ctrl模块负责根据脉冲信号和设计逻辑产生对应数字逻辑;seven_tube_drive(七段数码管驱动)模块负责将sec_timer_ctrl模块产生的数字逻辑显示到数码管上。

 

key_ctrl模块设计思想为:按键信号是由外部机械式按键产生,每次按下或者抬起时,会产生一定的抖动。如果直接对其进行边沿检测就会导致多次触发。故而需要设计按键消抖,进而对消抖之后的波形进行边沿检测。消抖原理为:外部按键信号发生改变后,如果能够持续20ms,没有新的改变,就认为此次改变不是抖动,而是真正的按下,然后进行采样即可。

 

// 记录任意边沿之后没有遇到新的边沿的时间长度是否达到20Ms 

//---------------------------------------------------------------------------------------  

always@(posedgeclk)begin

   if(rst_n ==1'b0)

     cnt_20ms <=20'd0;

   else

     if(pulse_key_negedge ==1'b1||pulse_key_posedge ==1'b1)

       cnt_20ms <=20'd1;

     else

       if(cnt_20ms >20'd0&&cnt_20ms <T_20ms)

         cnt_20ms <=cnt_20ms +1'b1;

       else

           cnt_20ms <=20'd0;

 end

// --------------------------------------------------------------------------------------- 

// 任意边沿之后没有遇到新的边沿的时间长度达到20Ms,认为按键稳定,此时采样 

//--------------------------------------------------------------------------------------    

always@(posedgeclk)begin

   if(rst_n ==1'b0)

     key_wave <=1'b1;

   else

     if(cnt_20ms ==T_20ms)

       key_wave <=key_rr;

     else

       key_wave <=key_wave;

 end

//--------------------------------------------------------------------------------------

// 对消抖之后的按键信号进行边沿检测 

//---------------------------------------------------------------------------------------------

initialkey_wave_r =1'b1;

always@(posedgeclk)key_wave_r <=key_wave;

assignflag_neg =(key_wave_r ==1'b1&&key_wave ==1'b0)?1'b1:1'b0;

assignflag_pos =(key_wave_r ==1'b0&&key_wave ==1'b1)?1'b1:1'b0;

//--------------------------------------------------------------------------------------------  

 

 

sec_timer_ctrl模块的设计思想:首先根据外部的启动停止脉冲,确定运行的模式。

  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      state_run <= 1'b0;
    else
      if (flag_start_stop == 1'b1)
        state_run <= ~state_run;
      else
        state_run <= state_run;
  end

 

在运行模式下,启动10ms计时器。

 

  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      cnt_10ms <= 19'd0;
    else
      if (state_run == 1'b1)
        if (cnt_10ms < T_10ms - 1'b1)
          cnt_10ms <= cnt_10ms + 1'b1;
        else
          cnt_10ms <= 19'd0;
      else
        cnt_10ms <= 19'd0;
  end

 

在运行模式下,记录经过了多少个10ms。记录的信息要在下一次启动的时刻才可以清除,并不能停止就清除;因为还需要查看信息呢。

 

下一次的启动时刻:非运行状态下,启动停止按键被按下。

 

  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      counter <= 32'd0;
    else
      if (state_run == 1'b0 && flag_start_stop == 1'b1)
        counter <= 32'd0;
      else
        if (state_run == 1'b1 && cnt_10ms == T_10ms - 1'b1)
          if (counter < 99999)
            counter <= counter + 1'b1;
          else
            counter <= counter;
        else
          counter <= counter;
  end

 

利用移位寄存器的思想记录每一次数值(最多只能记录九次)。

 

  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      counter_buf <= 320'd0;
    else
      if (state_run == 1'b1 && flag_record == 1'b1 && record_num < 4'd9)
        counter_buf <= {counter_buf[287:32], counter, counter};
      else
        counter_buf <= counter_buf;
  end

 

统计记录的次数,同样也得需要下一次启动的时刻才可以清除。

 

  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      record_num <= 4'd0;
    else
      if (state_run == 1'b0 && flag_start_stop == 1'b1)
        record_num <= 4'd0;
      else
        if (state_run == 1'b1 && flag_record == 1'b1)
          if (record_num < 4'd9)
            record_num <= record_num + 1'b1;
          else
            record_num <= record_num;
        else
          record_num <= record_num;
  end

 

在停止状态下,根据外部按键,确认需要翻看的是那一次的记录。当然,如果下一次启动开始了,翻看的记录也需要归零。

 

  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      show_num <= 4'd0;
    else
      if (state_run == 1'b0 && flag_start_stop == 1'b1)
        show_num <= 4'd0;
      else
        if (state_run == 1'b0 && flag_show == 1'b1)
          if (show_num < record_num)
            show_num <= show_num + 1'b1;
          else
            show_num <= 4'd1;
        else
          show_num <= show_num;
  end

 

      在运行状态下,数码管显示正在跑的描述;在非运行状态中,如果没有记录或者翻看,一直显示停止记录的秒数,如果开始翻看,则开始显示记录的数值。

 

  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      show_data <= 32'd0;
    else
      if (state_run == 1'b1)
        show_data <= counter;
      else
        if (record_num == 4'd0 || show_num == 4'd0)
          show_data <= counter;
        else
          show_data <= (counter_buf >> {show_num, 5'd0});
  end

 

根据显示的方式,计算出每个位应该显示的内容。

  initial data[23:0] = 4'hf; 
  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      data[23:20] <= 4'hf;
    else
      if (state_run == 1'b1)
        data[23:20] <= 4'hf;
      else
        if (record_num == 4'd0 || show_num == 4'd0)
          data[23:20] <= 4'hf;
        else
          data[23:20] <= record_num + 1 - show_num;
  end
  
  always @ (posedge clk) begin
    if (rst_n == 1'b0)
      data[19:0] <= 20'd0;
    else begin
      data[3:0] <= show_data%10;
      data[7:4] <= show_data/10%10;
      data[11:8] <= show_data/100%10;
      data[15:12] <= show_data/1000%10;
      data[19:16] <= show_data/10000%10;
    end
  end

 

以上即为sec_timer_ctrl模块的设计思想;

 

七段数码管为普通六位一体的共阳极数码,采用动态驱动的方式,在此不再赘述。

 

    下板后,我们就可以看到秒表计时的运行情况。    
    当然我们也可以使用按键进行启动、记录、翻看等运行情况。

    

 

 

 

 

 


  下板后,演示视频(链接)如下:
https://www.bilibili.com/video/BV15z421B7iC/?spm_id_from=333.999.0.0&vd_source=b5405faeab8632f02533bcbfc5e52e55
     本设计所有内容(设计代码、设计工程)链接为:

     

链接:https://pan.baidu.com/s/19-14DaRzg_H0OLbZ77GWUg

提取码:vr1x

 

  本篇内容中有部分资源来源于网络,如有侵权,请联系作者。

 

  如果您觉得本公众号还不错的话,可以推给身边的朋友们,感谢并祝好!

标签:begin,FPGA,记录,--,always,clk,b0,rst,电子设计
From: https://www.cnblogs.com/fendoudexiaohai/p/18313343

相关文章

  • Deepin 20.9在GTX 1060显卡上安装Nvidia 550.100驱动
    1下载对应版本的显卡驱动下载地址:https://www.nvidia.com/Download/index.aspxhttps://www.nvidia.cn/geforce/drivers/https://www.nvidia.cn/drivers/lookup/https://developer.nvidia.cn/cuda-gpushttps://developer.nvidia.com/cudnnwgethttps://cn.download.nvidi......
  • 用marked预览markdown文档
    创建src/index.html:<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>Docu......
  • 什么是ToDesk虚拟屏?轻松实现设备灵活分屏,打造个性化工作空间
    很多人虽有使用或了解过能够随时随地解决跨设备、跨系统远程操作问题的ToDesk远程软件,却未必知道除基础的控制外,它的其他功能有哪些。其中,虚拟屏就是这样一项尤为适合各行各业打工人掌握的实用功能!通过巧用它,不仅能够灵活实现设备分屏处理任务,更能收获高级隐私屏,变身炫酷科技达......
  • 第三周
    本周学习了判断与循环以及数组;了解了java与c++语言的相通之处;并进行了相关例题训练:完成pta部分习题下周进行方法以及面向对象的学习;......
  • 线段树
    把给定的区间转换成如图所示的一棵二叉树每次把区间一分为2,左边是左儿子,右边是右儿子对于每个节点的信息,都可以由两个儿子的信息得到如何单点查询/修改可以发现,两个儿子处理的区间没有交集,所以每次只要判断是在左儿子还是在右儿子,不断的递归对于区间查询,每一......
  • 堆空间?栈区?不慌!看完就通透!!
    前言    在进行开发和学习的过程中,我们老是看到或听到“堆空间”,“栈区”,那么他们到底都是什么?有什么关联和区别呢?接下来我们一起看看。什么是堆空间    堆空间是内存管理中的一种区域,用于动态地分配内存给程序中的对象。堆空间允许程序在运行时根据需要分配......
  • python模块化设计
    在Python中,模块化是将代码分解为独立的功能块,并通过导入和使用这些功能块来实现代码复用和组织的一种方式。模块化的编程风格使得代码更易于维护、扩展和测试。以下是Python实现模块化的一些常用方法:使用import语句导入模块:可以使用import语句导入其他Python文件(.py文件)作为......
  • linux 内核功能编译为模块
    在内核配置过程中,makemenuconfig工具提供了一个用户友好的图形化界面,用于选择和配置内核功能。配置选项中的<M>意味着将该功能作为模块(module)来编译。内核配置选项解释在makemenuconfig中,有三种主要的选项来配置内核功能:[]excluded:表示功能被排除在内核之外,即不会被......
  • 5分钟解锁python多线程
    以下是一个使用Python多线程的简单示例代码:importthreadingdefprint_numbers():foriinrange(1,6):print(i)defprint_letters():forletterin['A','B','C','D','E']:print(letter)if__nam......
  • 工具箱
    \[\huge\texttt{Hello,AKer.}\]\(\large\texttt{官网OFFICIALWEBSITES}\)BackroomsWikiBackroomsFandomMinecraftWikiSCP基金会MC百科OIWikiTampermonkey\(\large\texttt{有用的网站USEFULWEBSIDES}\)检测你的密码强度\(\texttt{vscodeC/C++}\)配置洛谷......