【记录】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.

 写一下在做这道题的时候出现的一些问题和debug的过程。

问题1:计时器部分是很简单的多位计数器,只需要把握好进位和重置的条件就可以,分钟进位要受到秒针的影响,在59秒进位,在9分59秒进位;时钟进位要受到秒针和分钟影响,59分59秒进位,9时59分59秒进位,清零也是一样的条件。

问题2:时钟部分需要注意,测试用例默认reset后为12:00:00,所以初始化的时钟个位和十位分别为2和1,并且个位存在达到9进位清零的情况,也存在和十位一起达到12后归1的情况,要分开讨论。

问题3:pm跳变是其中的一个难点,pm不能响应时钟变化(不能always块加posedge clk也不能加*),也不能在reset后12:00:00显示为1(此时是午夜0时)。在这个地方真是卡了很久!最后采用了计数方式,也就是计数12点出现的次数,这里为了同步时钟,改成了11:59:59的计数,计数达到偶数次时,则将pm置为1。

(代码里看起来很像是偶数次置0?reset后为1,在零点后遇到第一个12点,变为2,此时判断问句结果为0,应该置0?但实际上,非阻塞赋值同时进行,hh_count的+1操作和取余操作是同时的,所以会置1)。

问题4:其实是ena的使用,因为ena使能实际在每一级都有体现,控制每一级进位和清零的,除了上一级数值还有ena的允许。

最终代码如下:(csdn为什么没有verilog的代码解析器真是令人失望)

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] ss_one,ss_ten,mm_one,mm_ten,hh_one,hh_ten;
    reg [5:0] in;
    reg [3:0] hh_count;

    always@(posedge clk)begin
        if(reset||(ena&&ss_one==9))begin
            ss_one<=0;end
        else if(ena)begin
            ss_one<=ss_one+1;end
        else begin
            ss_one<=ss_one;end
    end
    assign in[0]=(ena&&ss_one==9)?1:0;
    always@(posedge clk)begin
        if(reset||(ena&&ss_one==9&&ss_ten===5))begin
            ss_ten<=0;end
        else if(in[0])begin
            ss_ten<=ss_ten+1;end
        else begin
            ss_ten<=ss_ten;end
    end                  //second complete
    assign in[1]=(ena&&ss_one==9&&ss_ten==5)?1:0;
    always@(posedge clk)begin
        if(reset||(ena&&mm_one==9&&ss_one==9&&ss_ten==5))begin
            mm_one<=0;end
        else if(in[1])begin
            mm_one<=mm_one+1;end
        else begin
            mm_one<=mm_one;end
    end
    assign in[2]=(ena&&mm_one==9&&ss_one==9&&ss_ten==5)?1:0;
    always@(posedge clk)begin
        if(reset||(ena&&mm_one==9&&ss_one==9&&ss_ten==5&&mm_ten===5))begin
            mm_ten<=0;end
        else if(in[2])begin
            mm_ten<=mm_ten+1;end
        else begin
            mm_ten<=mm_ten;end
    end
    assign in[3]=(ena&&mm_one==9&&ss_one==9&&ss_ten==5&&mm_ten===5)?1:0;
    always@(posedge clk)begin
        if(reset)begin
            hh_one<=8'd2;end
        else if(mm_one==9&&ss_one==9&&ss_ten==5&&mm_ten===5&&hh_one==9)begin
            hh_one<=0;end
        else if(mm_one==9&&ss_one==9&&ss_ten==5&&mm_ten===5&&hh_one==2&&hh_ten==1)begin
            hh_one<=1;end
        else if(in[3])begin
            hh_one<=hh_one+1;end
        else begin
            hh_one<=hh_one;end      
    end
    assign in[4]=(ena&&mm_one==9&&ss_one==9&&ss_ten==5&&mm_ten===5&&hh_one==9)?1:0;
    always@(posedge clk)begin
        if(reset)begin
            hh_ten<=8'd1;end
        else if(mm_one==9&&ss_one==9&&ss_ten==5&&mm_ten===5&&hh_one==2&&hh_ten==1)begin
            hh_ten<=0;end
        else if(in[4])begin
            hh_ten<=hh_ten+1;end
        else begin
            hh_ten<=hh_ten;end
    end
    assign in[5]=(ena&&mm_one==9&&ss_one==9&&ss_ten==5&&mm_ten===5&&hh_one==1&&hh_ten==1)?1:0;  
//判断11:59:59
  
    always@(posedge clk)begin
        if(reset)begin
            hh_count<=1;end
        else if(in[5])begin
            hh_count<=hh_count+1;pm<=(hh_count%2)?1:0;end  //偶数次pm置为1(非阻塞赋值同时进行)
        else begin
            hh_count<=hh_count;
            end
    end
              
            
    assign hh={hh_ten,hh_one};
    assign mm={mm_ten,mm_one};
    assign ss={ss_ten,ss_one};

endmodule

收获颇多! 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值