[Verilog] 实现数字钟(自动计时+手动校准+倒计时+设置闹钟)附完整源代码 |
您所在的位置:网站首页 › 桌面数字时钟闹钟怎么设置 › [Verilog] 实现数字钟(自动计时+手动校准+倒计时+设置闹钟)附完整源代码 |
数字钟 是大二小学期数字电路课程设计的题目 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 |