verilog1 HDLbits:12 hour clock(12小时计时器)

这篇具有很好参考价值的文章主要介绍了verilog1 HDLbits:12 hour clock(12小时计时器)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

本文主要介绍我在解决12小时计时器问题时的思路,代码以及总结,用于自己复习记录,希望也能帮助到其他人。

一.题目

verilog1 HDLbits:12 hour clock(12小时计时器),verilog,学习,fpga开发
HDL bit -12 hour clock题目地址
翻译:创建一组适合用作 12 小时制的计数器。计数器由一个快速运行的 clk 计时,每当时钟增加(即每秒一次)时,ena 就会有一个脉冲。
reset 将时钟重置为凌晨 12:00。pm 为 0 表示 AM,1 表示 PM。 hh、mm 和 ss 是两个 BCD(二进制编码十进制)数字,分别表示小时(01-12)、分钟 (00-59) 和秒(00-59)。
重置的优先级高于启用,即使未启用也可能发生。时序图显示了从上午 11:59:59 到下午 12:00:00 的翻转行为以及同步复位和启用行为。

二.方法1

1.完整代码:

module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss); 
    
    
	reg [3:0] s0; //秒针的个位
    reg [3:0] s1; //秒针的十位
    
    //秒计数
    always @(posedge clk) begin
        if(reset)	begin
            s0<=4'h0;
        end 
        else if(ena)	begin
                if (s0==4'h9)	begin
                s0<=4'h0;
                end 
                else begin
                s0<=s0+1'b1;
                end
            end
    end
    
    always @(posedge clk)	begin
        if(reset) begin
            s1<=4'h0	;
        end 
        else if (ena&&s0==4'h9) begin
            if (s1==4'h5) begin
                s1<=4'h0;
            end 
            else begin
            s1<=s1+1'b1;
            end
        end
    end
    //分计数
    reg [3:0] m0; //分针的个位
    reg [3:0] m1; //分针的十位
    
    always @(posedge clk) begin
        if(reset) begin
            m0<=4'd0;
        end 
        else if(ena&&s0==4'h9&&s1==4'h5) begin//当秒计时到59时,就需要考虑分计时
            if(m0==4'h9)	begin   //此时为 x9分59秒 此时显然m0需要置零
                m0<=4'h0;
            end 
            else begin
                m0<=m0+1'b1 ;      //当m0未满9时,继续计数
            end
        end
    end
    
    always @(posedge clk) begin
        if(reset) begin
            m1<=4'h0;
        end 
        else if(ena&&s0==4'd9&&s1==4'd5&&m0==4'd9) begin
            if(m1==4'h5)	begin
                m1<=4'h0;
            end 
            else begin
                m1<=m1+1'b1 ;
            end
        end
    end
    //时计数
    reg[3:0]h0; //时的个位
    reg[3:0]h1; //时的十位  只能取0,1;

    always @(posedge clk) begin
        if(reset) begin
        h0<= 4'd2;
        end 
        else if(ena&&s0==4'h9&&s1==4'h5&&m0==4'h9&&m1==4'h5&h0==4'h2&&h1==4'h1) begin 
        h0<=4'h1;   //12:59:59 下一时刻为01:00:00
        end 
        else if(ena&&s0==4'h9&&s1==4'h5&&m0==4'h9&&m1==4'h5) begin    //此时为xx:59:59
            if(h0==4'h9) begin
            h0<=4'h0;//满9置零
            end 
            else begin
            h0<=h0+1'b1;  //当h0未满9时,继续计数
            end
        end
    end
    
    always @(posedge clk) begin
        if(reset) begin
            h1<=4'h1;
        end
        else if(ena==1'b1&&s0==4'h9&&s1==4'h5&&m0==4'h9&&m1==4'h5&h0==4'h2&&h1==4'h1) begin //此时为12:59:59
                h1<=4'h0;//01:00:00
        end 
        else if(ena==1'b1&&s0==4'h9&&s1==4'h5&&m0==4'h9&&m1==4'h5&h0==4'h9) begin   //x9:59:59 当h0未满9时h1不会改变
            h1<=h1+1'b1;
        end
        else  h1<=h1;
    end
    
    reg	r_pm;
    
    //am or pm
    always @(posedge clk)	begin
        if (reset) r_pm<=1'b0;
        else if (ena&&s0==4'h9&&s1==4'h5&&m0==4'h9&&m1==4'h5&&h0==4'h1&&h1==4'h1) begin
        r_pm<=~r_pm;   //pm每十二个小时翻转一次,即满足11:59:59下一状态pm翻转
        end
    end
    //赋值
    assign hh={h1,h0};	
    assign mm={m1,m0};
    assign ss={s1,s0};
    assign pm=r_pm;
    
endmodule

2.详解介绍
由于分秒简单、两者类似且都有注释,故取稍微复杂的时钟的第2个always块进行介绍,按原理逻辑上推即可。

    always @(posedge clk) begin
        if(reset) begin
            h1<=4'h1;
        end
        else if(ena==1'b1&&s0==4'h9&&s1==4'h5&&m0==4'h9&&m1==4'h5&h0==4'h2&&h1==4'h1) begin //此时为12:59:59
                h1<=4'h0;//01:00:00
        end 
        else if(ena==1'b1&&s0==4'h9&&s1==4'h5&&m0==4'h9&&m1==4'h5&h0==4'h9) begin   //x9:59:59 当h0未满9时h1不会改变
            h1<=h1+1'b1;
        end
        else  h1<=h1;
    end
    

hh的十位只能取0,1。
if 语句:表示reset为1时,进行复位操作将时钟的十位复位为1,题目要求时钟重置为凌晨12:00:00。
第一个else if语句:当时间为12:59:59,下个时间需要跳到01:00:00,则十位置0。
第二个else if语句:当时间为x9:59:59,下一时刻十位需要发生改变,而其他时间不满足这个时间段时,h1不变。

二.方法2

此种方法学习于此
1.完整代码:

module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss); 
    
    wire [6:1] enable;
    wire [7:0] hh_r;
    
    assign enable[1] = ena && (ss[3:0]==4'h9);
    assign enable[2] = enable[1] && (ss[7:4]==4'h5);
    assign enable[3] = enable[2] && (mm[3:0]==4'h9); 
    assign enable[4] = enable[3] && (mm[7:4]==4'h5);
    assign enable[5] = enable[4] && (hh_r[3:0]==4'hb); //b=11
    assign enable[6] = enable[5] && (hh_r[7:4]==4'h1);
    //模块例化
    BCD_count #(.START(4'h0),.END_r(4'h9)) ss9 (clk, reset, ena, ss[3:0]);
    BCD_count #(.START(4'h0),.END_r(4'h5)) ss5 (clk, reset, enable[1], ss[7:4]);
    BCD_count #(.START(4'h0),.END_r(4'h9)) mm9 (clk, reset, enable[2], mm[3:0]);
    BCD_count #(.START(4'h0),.END_r(4'h5)) mm5 (clk, reset, enable[3], mm[7:4]);
    BCD_count #(.START(4'h0),.END_r(4'hb)) hhb (clk, reset, enable[4], hh_r[3:0]);
    BCD_count #(.START(4'h0),.END_r(4'h1)) hh1 (clk, reset, enable[5], hh_r[7:4]);
    
    assign pm=(hh_r[7:4]==4'h1);
    assign hh=(hh_r[3:0]==4'h0)?8'h12:((hh_r[3:0]>4'h9)?{4'h1,hh_r[3:0]-4'ha}:{4'h0,hh_r[3:0]});// a=10
    
endmodule
//BCD计数器模块
module BCD_count(
    input clk,
    input reset,
    input ena,
    output reg[3:0] q
);
    parameter START=4'h0,END_r=4'h9; 
    always @(posedge clk) begin
        if(reset)             q<=START;
        else if(!reset&&ena)  q<=(q==END_r)?START:q+4'h1;
        else if(!reset&&!ena) q<=q;
    end 
endmodule

2.介绍
这种方法是通过编写的一个BCD计数器模块,来对其进行例化,推荐采用这种方法,看起来更清晰。
声明的中间变量,[6:1]enable其中6个元素代表秒分时的进位信号,若为1,即重置对应的时间计数。
paramter参数可自行搜索学习,parameter在模块中声明后,后续编译时还可以被重新声明的值所覆盖。重新声明格式如下代码举例:

BCD_count #(.START(4'h0),.END_r(4'h9)) ss9 (clk, reset, ena, ss[3:0]);

详情参考下面学习:
paramter参数详解介绍文章来源地址https://www.toymoban.com/news/detail-827894.html

到了这里,关于verilog1 HDLbits:12 hour clock(12小时计时器)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 51单片机通过计时器实现倒计时

    软件 : Keil5+Proteus7 元件 : AT89C51 * 1,7SEG-MPX2-CA * 1

    2024年02月16日
    浏览(70)
  • qt学习:QTimer定时器+重复计时+单次计时

    在指定的间隔时间会发送出一个timeout信号,关联对应的槽函数 #includeQTimer

    2024年01月19日
    浏览(62)
  • WPF计时器功能

    本文实现WPF的计时器功能是通过system.timers.timer这个组件实现的。现在网上相关的资料有很多,我只是在自己的工作中刚好遇到要实现这个功能,中间也走了很多的弯路,不停的参考网上现有的资源,终于实现了基本的定时功能。希望本文可以帮助到您,让您花更少的时间来完

    2024年02月05日
    浏览(52)
  • 555计时器原理

    以Multisim上的555计时器为例: 图0.0 555计时器包含八个引脚 分别为: RST - Reset 复位引脚(低电平有效) DIS - Discharge 三极管集电极Collector输入引脚 THR - Threshold 上阈值电压引脚 TRI - Trigger 触发引脚 CON - Control voltage 1 电压控制引脚 OUT - Output 信号输出引脚 VCC GND 555定时器内部功能图

    2024年02月05日
    浏览(45)
  • Qt实现计时器

    一、样图 二、代码 mainwidow.h mainwindow.cpp main.cpp ui_mainwindow.h

    2024年02月07日
    浏览(37)
  • java计时器

      在 Java中,我们有一个重要的概念:同步和异步。同步就是 Java中的线程安全,异步就是 Java中的线程非安全。 在使用 JVM时,我们一般都是用 start ()方法启动一个线程,然后设置时间,比如定时器,定时器是在某个指定的时间执行相应的任务。但是,在实际应用中,我们

    2023年04月18日
    浏览(60)
  • 24秒计时器

    方案一:采用计数器(74LS192)作为核心部分。同时选择(74LS47)作为BCD码译码器来对7段数码显示管进行译码驱动,两个七段共阳数码显示管进行显示。采用计时器(NE555)制成的多谐振荡器,进行秒脉冲的输入。因为我们需要对其进行暂停、清零、报警和自动清零等控制,所

    2024年02月06日
    浏览(44)
  • RIP四大计时器

    RIP 计时器(以下均以华为 ensp 中信息为参考) 希望有需要的小伙伴可以参考参考,如有误解、请指正! 一、实验原理 1. 更新计时器( Update Timer ) Update time(更新时间):指运行RIP协议的路由器向其连接口广播自己的路由信息的时间间隔(用于更新RIP路由表信息),控制

    2024年02月03日
    浏览(45)
  • FPGA 课程综合实验——倒计时(简易计时器闹钟)基于STEP MAX10 FPGA

    组合使用STEP MAX10 FPGA核心板和STEP BaseBoard扩展底板,编写程序,完成一个倒计时定时 器的设计。 功能要求: 使用扩展底板上相邻的4位数码管显示计时时间,显示数值单位为“秒”。(2分) 定时器最大定时时间为99秒,时间显示分辨力为1/100秒。(2分) 倒计时结束时,扩展

    2024年02月03日
    浏览(48)
  • STM32屏幕计时器

    显示屏显示计时时间,格式为 00:00:00 ,依次为 时:分:秒 ,程序运行之后自动计时,当按下按键,计时清零,按下按键采用外部中断。 调用lcd驱动代码让屏幕显示时间信息, 屏幕为SPI协议的128x128的LCD屏幕,查看原理图,找到对应接口 在STM32CubeMX中进行引脚配置 由于所调用的

    2024年02月09日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包