You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HDLBits 12小时时钟代码pm输出较标准答案少1小时,求排查

调试HDLBits 12小时时钟模块的问题

我在做HDLBits的12小时时钟题目时编写了代码,但平台仅提示存在测试用例不匹配,无法定位具体错误点,希望有人帮忙排查一下问题。

测试情况

平台返回的结果显示存在多处不匹配,但未给出具体错误场景,仅能确定代码逻辑存在问题。

我的代码

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] ssc, mmc, hhc;
    
    assign ssc[0] = ss[3]&ss[0];
    counter4buenld cssl(clk, ena, reset, ssc[0], 4'h0, ss[3:0]);
    assign ssc[1] = ss[4]&ss[6]&ssc[0];
    counter4buenld cssh(clk, ena&ssc[0], reset, ssc[1], 4'h0, ss[7:4]);
    
    assign mmc[0] = mm[3]&mm[0]&ssc[1];
    counter4buenld cmml(clk, ena&ssc[1], reset, mmc[0], 4'h0, mm[3:0]);
    assign mmc[1] = mm[4]&mm[6]&mmc[0];
    counter4buenld cmmh(clk, ena&mmc[0], reset, mmc[1], 4'h0, mm[7:4]);
    
    assign hhc[0] = hh[3]&hh[0]&mmc[1];
    assign hhc[1] = hh[4]&hh[1]&mmc[1];
    counter4buenld chhl(clk, ena&mmc[1], 1'b0, reset|hhc[0]|hhc[1], {2'b00, reset, ~reset}, hh[3:0]);
    counter4buenld chhh(clk, ena&hhc[0], 1'b0, reset|hhc[1], {3'b000, reset}, hh[7:4]);
    
    reg pml;
    assign pm = pml;
    always@(posedge clk) begin
        if(reset) begin
            pml <= 1'b0;
        end
        else begin
        if(hh[4]&hh[0]&mmc[1]) begin
            pml <= ~pml;
        end
        else begin
            pml <= pml;
        end
        end
    end
endmodule

module counter4buenld(
    input clk,
    input ena,
    input reset,
    input load,
    input [3:0] d,
    output reg [3:0] q
);
    always@(posedge clk) begin
        if(reset)
            q <= 4'h0;
        else
        if(load)
            q <= d;
        else
            q <= q + ena;
    end
endmodule

问题排查与修改建议

我梳理了代码逻辑,发现几个核心问题,下面给出具体分析和修改方案:

1. 小时计数器的复位与循环逻辑错误

12小时制时钟复位后应回到12:00:00 AM,但你的代码复位时小时会被置为00,不符合需求。同时,小时从12跳转时应该回到1,而不是0,原代码的加载值和进位条件逻辑混乱,导致计数循环错误。

2. PM信号切换条件不准确

原代码的PM切换条件是hh[4]&hh[0]&mmc[1],这个判断逻辑模糊,无法精准对应11:59:59到12:00:00的切换时刻(这才是AM/PM状态切换的正确节点)。

3. 信号可读性与逻辑严谨性不足

原代码用位运算判断计数器满值,容易出错,改成直接比较BCD码值会更清晰可靠。


修改后的完整代码

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] ssc, mmc;
    
    // 秒计数器逻辑
    assign ssc[0] = (ss[3:0] == 4'h9); // 秒低位到9,触发复位
    counter4buenld cssl(
        .clk(clk),
        .ena(ena),
        .reset(reset),
        .load(ssc[0]),
        .d(4'h0),
        .q(ss[3:0])
    );
    assign ssc[1] = (ss[7:4] == 4'h5) && ssc[0]; // 秒到59,触发分钟进位
    counter4buenld cssh(
        .clk(clk),
        .ena(ena & ssc[0]),
        .reset(reset),
        .load(ssc[1]),
        .d(4'h0),
        .q(ss[7:4])
    );
    
    // 分钟计数器逻辑
    assign mmc[0] = (mm[3:0] == 4'h9) && ssc[1]; // 分低位到9且秒满59,触发复位
    counter4buenld cmml(
        .clk(clk),
        .ena(ena & ssc[1]),
        .reset(reset),
        .load(mmc[0]),
        .d(4'h0),
        .q(mm[3:0])
    );
    assign mmc[1] = (mm[7:4] == 4'h5) && mmc[0]; // 分到59,触发小时进位
    counter4buenld cmmh(
        .clk(clk),
        .ena(ena & mmc[0]),
        .reset(reset),
        .load(mmc[1]),
        .d(4'h0),
        .q(mm[7:4])
    );
    
    // 小时计数器逻辑
    wire hour_inc = ena & mmc[1];
    wire hour_wrap = (hh[7:4] == 4'h1) && (hh[3:0] == 4'h2) && hour_inc; // 小时到12,循环回1
    wire hh_low_carry = (hh[3:0] == 4'h9) && hour_inc; // 小时低位到9,十位加1
    
    counter4buenld chhl(
        .clk(clk),
        .ena(hour_inc),
        .reset(reset),
        .load(reset || hour_wrap),
        .d(reset ? 4'h2 : 4'h1),
        .q(hh[3:0])
    );
    
    counter4buenld chhh(
        .clk(clk),
        .ena(hh_low_carry),
        .reset(reset),
        .load(reset || hour_wrap),
        .d(reset ? 4'h1 : 4'h0),
        .q(hh[7:4])
    );
    
    // PM信号逻辑
    reg pml;
    assign pm = pml;
    always@(posedge clk) begin
        if(reset) begin
            pml <= 1'b0; // 复位初始为AM
        end
        else if(hour_inc && (hh[7:4] == 4'h1) && (hh[3:0] == 4'h1)) begin
            // 小时从11跳转到12时,切换AM/PM状态
            pml <= ~pml;
        end
        else begin
            pml <= pml;
        end
    end
endmodule

module counter4buenld(
    input clk,
    input ena,
    input reset,
    input load,
    input [3:0] d,
    output reg [3:0] q
);
    always@(posedge clk) begin
        if(reset)
            q <= 4'h0;
        else if(load)
            q <= d;
        else
            q <= q + ena;
    end
endmodule

修改点说明

  1. 小时逻辑修正:复位时直接加载12的BCD码(十位1,个位2),当小时到12时自动循环到1,符合12小时制的计数规则。
  2. PM信号修正:仅在小时从11跳转到12时切换状态,精准对应AM/PM的切换节点。
  3. 可读性优化:把位运算判断改成直接比较BCD码值,逻辑更直观,降低出错概率。

你可以把修改后的代码放到HDLBits上测试,应该能解决大部分不匹配问题。如果还有异常,可以进一步检查时钟信号同步性或复位状态的细节。

内容的提问来源于stack exchange,提问作者Lyxikun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 10:31:14