HDLBits学习笔记——Count clock

计数器的最后一题。

题干:

Create a set of counters suitable for use as a 12-hour clock (with am/pm indicator). Your counters are clocked by a fast-running clk, with a pulse on ena whenever your clock should increment (i.e., once per second).

reset resets the clock to 12:00 AM. pm is 0 for AM and 1 for PM. hh, mm, and ss are two BCD (Binary-Coded Decimal) digits each for hours (01-12), minutes (00-59), and seconds (00-59). Reset has higher priority than enable, and can occur even when not enabled.

The following timing diagram shows the rollover behaviour from 11:59:59 AM to 12:00:00 PM and the synchronous reset and enable behaviour.

大意:设计一个钟表,可以显示时分秒以及上下午,当复位信号为高位时(同步复位,题目没有直接说明,但是从题目给出的参考图可以大概判断出来),将时间重置为12:00:00,PM=0(即AM)。

思路

拿到题目的时候想直接用一个always来解决,但是写下来发现逻辑很混乱,于是参考了别人的思路,把时分秒和上下午的判断分为4个部分来写。

由于每个部分的判断很类似,因此整个代码写起来比较流畅。

附上代码:

module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss); 
    //将时分秒以及PM分为四个部分
    //秒
    always@(posedge clk) begin
        if(reset)//复位,将秒置0
            ss <=0;
        else if(ena) begin //若使能为高电平,则开始计数
            if(ss==8'h59)//判断是否进位
                ss<=0;
            else begin
                if(ss[3:0]<4'h9)
                    ss[3:0] <= ss[3:0]+1;
                else begin
                    ss[7:4] <= ss[7:4]+1;
                    ss[3:0] <= 0;
                end
            end
        end
    end
    //分
    always@(posedge clk) begin
        if(reset)//复位,将分置0
            mm <=0;
        else if(ena) begin
            if(ss==8'h59)
                if(mm==8'h59)//59分且59秒时,进位
                	mm<=0;
            	else begin
                	if(mm[3:0]<4'h9)
                   		mm[3:0] <= mm[3:0]+1;
                	else begin
                    	mm[7:4] <= mm[7:4]+1;
                   		mm[3:0] <=0;
                	end
            	end
        	end
    	end
    //时
    always@(posedge clk) begin
        if(reset)//复位,将时置12
            hh<=8'h12;
        else if(ena) begin
            if(ss==8'h59&&mm==8'h59)
                if(hh==8'h12)
                	hh<=1;
            	else begin
                	if(hh[3:0]<4'h9)
                    	hh[3:0] <= hh[3:0]+1;
                	else begin
                    	hh[7:4] <=1;
                    	hh[3:0] <=0;
                	end
            	end
        	end
    	end
    //PM
    always@(posedge clk) begin
        if(reset) pm<=0;
        else if(hh==8'h11&&mm==8'h59&&ss==8'h59)//只有在11点59分59秒到12点0分0秒时昼夜切换,PM取反
            pm=~pm;
    end
endmodule

代码整体思路:

时分秒三个部分的区别在于,秒可以认为是独立工作的一个60进制计数器,根据题目给的条件,可以将一个8bits的数ss分为ss[7:4]和ss[3:0]两个部分,分别表示秒钟的十位数与个位数。因此在条件判断中只需要判断ss==8'h59,即是否进位,若不需要进位,则判断个位是否为ss[3:0]==4'h9,是否向十位进位。

一开始我在这个部分犯了个低级错误,BCD计数器本质是16进制的(4bits),而十进制是在设计时规定的,最先我进行ss[7:0]<h'59判断后,直接对整个ss进行+1运算,忽略了这个问题。

秒钟的计数部分设计完成后,分钟可以以此类推,不同的是,在考虑分钟是否进位时,不仅要判断分钟mm==8‘h59,还需要判断秒钟ss==8'h59,在ena==1时完成进位,将两者置0。

时钟与分钟类似,当秒钟与分钟满足条件时,时钟为hh==8'h12时进位,注意进位后hh<=1(复位时同理,置为12),本题的时钟不存在0时这个说法。、

上下午的判断,只需要考虑11点59分59秒时,AM与PM相互转化即可,即pm=~pm。

总结:

学习Verilog将近一周了,这题对于初学者来说难度还算中等,虽然整体代码较长,但是时分秒三个部分的设计较为雷同,可以依次类推得到。

计数器这部分题目里,最后几题的套路都一样。参考时分秒的进位方式,时需要同时判断分与秒,分需要同时判断秒,这与Countbcd和Exams/ece241 2014 q7b的解题思路如出一辙。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值