HDLBits_Counters最后一题12—hour clolk思路和代码

题目

创建一组适合用作12小时时钟的计数器(带有上午/下午指示器)。你的计数器由一个快速运行的clk计时,每当你的时钟增加时(即每秒一次),ena上就会有一个脉冲。

reset将时钟重置为12:00 AM。AM的pm为0,pm为1。hh、mm和ss是两个BCD(二进制编码的十进制)数字,分别表示小时(01-12)、分钟(00-59)和秒(00-59。重置的优先级高于启用,即使未启用也可能发生重置。

以下时序图显示了从上午11:59:59到下午12:00:00的翻转行为以及同步重置和启用行为。

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.

思路

创建十进制和六进制模块

创建十进制和六进制模块,来计算mm和ss的个位和十位,hh的计算放在顶部模块里

module bcdcnt_l(
    input clk,
    input reset,
    input ena,
    output [3:0]q);
    always @(posedge clk)
        begin
            if(reset) q= 4'h0;
            else if (ena)
                q <= (q == 4'h9) ? 4'h0 : q + 1;
            else q <= q;
        end
endmodule

module bcdcnt_h(
    input clk,
    input reset,
    input ena,
    output [3:0]q);
    always @(posedge clk)
        begin
            if(reset) q = 4'h0;
            else if (ena)
                q <= (q == 4'h5) ? 4'h0 : q + 1;
            else q <= q;
        end
endmodule

assign语句,计算模块的使能位

    wire ena_sh,ena_ml,ena_mh,ena_hl,ena_hh,am_pm_c;//定义导线
    assign ena_sh = ena && (ss[3:0] == 4'h9);//秒个位使能位
    assign ena_ml = ena && (ss[7:0] == 8'h59);//秒十位使能位
    assign ena_mh = ena_ml && (mm[3:0] == 4'h9);//分钟个位使能位
    assign ena_hl = ena_ml && (mm[7:0] == 8'h59);//分钟十位使能位
    assign ena_hh = ena_hl && (hh[3:0] == 4'h9);//小时个位使能位
    assign am_pm_c = ena_hl &&(hh[7:0] == 8'h11);//am,pm转换位,这个不知道为什么12点就变为下午了

子模块实例化

分别计算分、秒的个位和十位

    bcdcnt_l s_cnt_l(clk, reset, ena, ss[3:0]);
    bcdcnt_h s_cnt_h(clk, reset, ena_sh, ss[7:4]);
    bcdcnt_l m_cnt_l(clk, reset, ena_ml, mm[3:0]);
    bcdcnt_h m_cnt_h(clk, reset, ena_mh, mm[7:4]);

always块处理最复杂的小时位

always @(posedge clk)
        begin
            if(reset) begin
                hh[7:0] <= 8'h12;
            	pm <= 0;
            end
            else if(ena_hl &&(hh[7:0] == 8'h12))
                begin
                	hh[7:0] <= 8'h01; 
            	end
            else if(ena_hh) hh[7:0] <= 8'h10;
            else if(ena_hl) hh <= hh + 1;
            else hh <= hh;
            if(am_pm_c)pm <= ~pm;
        end

总的代码

module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss);
    
    wire ena_sh,ena_ml,ena_mh,ena_hl,ena_hh,am_pm_c;
    assign ena_sh = ena && (ss[3:0] == 4'h9);
    assign ena_ml = ena && (ss[7:0] == 8'h59);
    assign ena_mh = ena_ml && (mm[3:0] == 4'h9);
    assign ena_hl = ena_ml && (mm[7:0] == 8'h59);
    assign ena_hh = ena_hl && (hh[3:0] == 4'h9);
    assign am_pm_c = ena_hl &&(hh[7:0] == 8'h11);
    
    bcdcnt_l s_cnt_l(clk, reset, ena, ss[3:0]);
    bcdcnt_h s_cnt_h(clk, reset, ena_sh, ss[7:4]);
    bcdcnt_l m_cnt_l(clk, reset, ena_ml, mm[3:0]);
    bcdcnt_h m_cnt_h(clk, reset, ena_mh, mm[7:4]);
    always @(posedge clk)
        begin
            if(reset) begin
                hh[7:0] <= 8'h12;
            	pm <= 0;
            end
            else if(ena_hl &&(hh[7:0] == 8'h12))
                begin
                	hh[7:0] <= 8'h01; 
            	end
            else if(ena_hh) hh[7:0] <= 8'h10;
            else if(ena_hl) hh <= hh + 1;
            else hh <= hh;
            if(am_pm_c)pm <= ~pm;
        end
endmodule

module bcdcnt_l(
    input clk,
    input reset,
    input ena,
    output [3:0]q);
    always @(posedge clk)
        begin
            if(reset) q= 4'h0;
            else if (ena)
                q <= (q == 4'h9) ? 4'h0 : q + 1;
            else q <= q;
        end
endmodule

module bcdcnt_h(
    input clk,
    input reset,
    input ena,
    output [3:0]q);
    always @(posedge clk)
        begin
            if(reset) q = 4'h0;
            else if (ena)
                q <= (q == 4'h5) ? 4'h0 : q + 1;
            else q <= q;
        end
endmodule

反思即错误总结

刚开始写的时候出来了重复赋值的错误提示,看了下确实我给hh向量赋值了很多次导致冲突。

改正方法是将这些给hh向量复制的语句放在always块下的一个if语句下面,根据优先级来给hh向量赋值。

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值