HDLBits练习-12小时时钟

前言

        最近在用HDLBits开始学习verilog,做了一百道出头的题了,遇到这个12小时时钟的题比较有意思,题目地址是https://hdlbits.01xz.net/wiki/Count_clock。看了好几个答案,没有用层次化思维写的,都是一个模块大量的分支语句和always块直接堆完,菜鸡如我看答案都费劲,于是贴一个自己写的。比较高大上地用了层次化建模的思想,这样思路梳理起来个人觉得比较方便。

分析

        分和秒的计数用的是同一个模块,0-59的六十进制的计数器,不过需要注意题目要求用一个8bit数的高4位表示十位,低4位表示个位。

        小时单独写一个模块,1-12的十二进制计数器,需要考虑复位、进位、循环的问题。

        顶层模块的部分就很简单了,例化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 [1:0] ena_t;
        
        mod_c60 mod_ss(clk, reset, ena, ss, ena_t[0]);
        mod_c60 mod_mm(clk, reset, ena_t[0], mm, ena_t[1]);
        mod_c12 mod_hh(clk, reset, ena_t[1], hh, pm);

endmodule

//六十进制的计数器模块
module mod_c60 (
    input clk,
    input reset,        // Synchronous active-high reset
        input en,
    output [7:0] q,
        output cout
);
        wire d_temp; 
        
        assign d_temp = (q[3:0] == 4'd9) && en;
        assign cout = (q == 8'h59) && d_temp;
        
        //十进制,0-9
        always @ (posedge clk)begin
                if(reset)
                        q[3:0] <= '0;
                else if(en)begin
                        if(q[3:0] < 4'd9)
                                q[3:0] <= q[3:0] + 1'd1;
                        else
                                q[3:0] <= '0;
                end
        end

        //六进制,0-5
        always @ (posedge clk)begin
                if(reset)
                        q[7:4] <= '0;
                else if(d_temp)begin
                        if(q[7:4] < 4'd5)
                                q[7:4] <= q[7:4] + 1'b1;
                        else
                                q[7:4] <= '0;
                end
        end
endmodule

//十二进制的计数器模块
module mod_c12 (
    input clk,
    input reset,        // Synchronous active-high reset
        input en,
    output [7:0] q,
        output cout
);

        wire d_temp; 
        assign d_temp = ((q[3:0] == 4'd9) || (q == 8'h12)) && en;

        //十进制,0-9,且当q=12时再加为1,复位为2
        always @ (posedge clk)begin
                if(reset)begin
                        q[3:0] <= 4'd2;
                        cout <= 1'b0;
                end
                else if(en)begin
                        if(q[3:0] < 4'd9)begin
                                if(q==8'h12)
                                        q[3:0] <=  4'd1;       //12再加变1
                                else begin
                                        q[3:0] <= q[3:0] + 1'd1;
                                        //11再加am与pm变换
                                        cout <= (q==8'h11) ? ~cout : cout;
                                end
                        end
                        else
                                q[3:0] <= '0;
                end
        end

        //二进制,0-1,复位为1
        always @(posedge clk)begin
                if(reset)
                        q[7:4] <= 4'd1;
                else if(d_temp)begin
                        if(q[7:4] == '0)
                                q[7:4] <= 4'd1;
                        else
                                q[7:4] <= '0;
                end
        end
endmodule

总共一百行代码,可读性不敢保证,但是长度比我找到的其他答案要短。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值