[Verilog] 实现数字钟(自动计时+手动校准+倒计时+设置闹钟)附完整源代码

您所在的位置:网站首页 桌面数字时钟闹钟怎么设置 [Verilog] 实现数字钟(自动计时+手动校准+倒计时+设置闹钟)附完整源代码

[Verilog] 实现数字钟(自动计时+手动校准+倒计时+设置闹钟)附完整源代码

2024-07-15 09:29| 来源: 网络整理| 查看: 265

数字钟 是大二小学期数字电路课程设计的题目

update20220318:全部源代码及完整报告请订阅后查看文章底部

文章目录 update20220318:全部源代码及完整报告请订阅后查看文章底部写在前面的话2020.07.02 Verilog的重要知识点模块1:分频模块模块2:自动计时模块自动计时继承手动计时 模块3:手动模块3.1 模式设定模块3.2 手动调整模块3.1模式设定模块和3.2手动调整模块放到一起再讲点事情模块3 手动模块 整体源代码: 模块4:计时输出模块模块5:整点报时模块模块6:倒计时模块+配套的数码管的可视化模块6.1:倒计时模块6.2:倒计时的数码管输出模块 模块7:闹钟设定模块和闹钟触发模块7.1:闹钟设定模块模块7.2:闹钟触发模块模块7整体源代码 模块8:可视化数码管模块源代码

写在前面的话 2020.07.02

本代码在对应开发板和环境下验证无误,详细见开头的资源。

此外,我还想声明的是,如果能直接用到其他环境最好,但这个源代码只是作为无偿的分享,来提供思路。

课设的东西还是要自己做的,希望大家在评论区能多讨论一下跟知识本身有关的事情。

Thanks!

Verilog的重要知识点

首先要说的是,在Verilog中的always模块是并行的,即always模块执行的次序与其在module中的位置无关。

那么就引来了一个问题,我怎么确定要执行哪一个模块?

答案是:

对于并行:通过引入flag(标志)和if判断来确定执行哪一个模块。对于串行:引入中间变量(always中为reg类型),后执行的模块对先执行的模块的输出敏感。

简单来说:

小的always模块通过输出和敏感条件相连接,组成逻辑上串行的大模块大的always模块的敏感条件为主时钟(或其替代),通过if实现大模块的并行

也就是说,我们可以通过敏感变量的设置和flag的设置来控制数字系统的结构。

理解上面这些是理解下面代码的基础!!!

针对这个数字钟系统,整个系统具有三种模式(互为并行关系),其相应的flag要求如下:

自动计时:set_mod==1手动计时:set_mod==0 且 set_alarm==0手动设置闹钟:set_mod==0 且 set_alarm==1

接下来我会按模块讲解,当然整个源码会放到最后。

模块1:分频模块

功能: 对开发板的50MHz时钟信号,取50M分频,得到频率为1s的时钟信号

模块用到的输入:

input clk

模块的敏感条件:

posedge clk

模块的输出:

clk_div(reg类型,中间变量)

模块框图: 在这里插入图片描述

模块代码:

//---------------------分频开始----------------------- parameter m=49999999; integer div_cnt=0; reg clk_div; always@(posedge clk) begin if(div_cnt==m) begin clk_div 23:59:59 的循环的时间计时

模块用到的输入:

clk_div:分频后的时钟信号,频率1Hz(周期 T=1s)。set_mod:区分自动计时(set_mod==1)和手动计时(set_mod==0)。set_alarm:区分设定闹钟(set_alarm==1)和手动计时(set_alarm==0)

再结合我之前提到的:并行的模块由flag和if来控制。 大家对并行模块的控制的理解应该更直观和深刻了。

模块的敏感条件:

posedge clk_div

模块的输出:

[3:0] secL_1(秒的个位,reg类型,中间变量)[3:0] secH_1(秒的十位,reg类型,中间变量)[3:0] minL_1(分的个位,reg类型,中间变量)[3:0] minH_1(分的十位,reg类型,中间变量)[3:0] hourL_1(时的个位,reg类型,中间变量)[3:0] hourH_1(时的十位,reg类型,中间变量)

至于为什么要把secL_1、secH_1、minL_1、minH_1、hourL_1、hourH_1都定义为reg(寄存器类型,中间变量)而不定义为直接的输出output,原因会在 模块4:计时输出模块 解释。

模块框图: 在这里插入图片描述

自动计时

对flag的要求: set_mod==1

末状态清零: 当时间为 23:59:59 时,在下一秒时(clk_div的posedge触发该模块)对secL_1、secH_1、minL_1、minH_1、hourL_1、hourH_1进行清零操作,重置为 00:00:00

考虑进位关系: 自动计时模块中,我们考虑 秒、分、时 之间的 进位关系 (这是与手动计时的重大区别)。 嵌套的if-else的作用是:当该位需要接收进位时,判断该位是否达到其上限(比如秒的低位最大为9,秒的高位最大为5)。 如果达到上限,则该位清零并向上进位;如果未达到上限,则该位+1。

继承手动计时

对 flag的要求: set_mod==0 && set_alarm==0 至于为什么不加,其实加不加都行。

为什么要继承手动计时的结果: 手动计时可以视为对数字钟的 校准。 也就是说当自动计时出现误差的时候,可以用手动校时来消除误差。 手动校时的输出为准确结果,应当作为自动计时模块的新的初值。

模块代码:

//------------------自动计数开始---------------------- reg [3:0]secL_1; reg [3:0]secH_1; reg [3:0]minL_1; reg [3:0]minH_1; reg [3:0]hourL_1; reg [3:0]hourH_1; always@(posedge clk_div) begin if(set_mod==1) begin //末状态清零 if(hourH_1==4'b0010 && hourL_1==4'b0011 && minH_1==4'b0101 && minL_1==4'b1001 && secH_1==4'b0101 && secL_1==4'b1001) begin secL_1


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3