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

MOD10计数器异常:计数至9后复位至4的原因及解决方案

MOD10计数器复位到4而非0的问题分析与修复

问题原因分析

  • 异步复位的时序冲突:原代码采用异步复位(TFF的always @(posedge clr or negedge clk)),当计数器从9(1001)跳转到10(1010)时,复位信号w立刻拉高,将所有TFF清零为0000。但此时q1刚从0翻转为1,又被复位拉回0,这个q1的下降沿会触发tff3的时钟(tff3的时钟是q1,沿触发为negedge),导致tff3的输出q2翻转,从0变为1,最终计数器状态变成0100(4)。
  • 复位检测逻辑错误:原代码检测的是10(二进制1010,q[3]&q[1]),而MOD10计数器应在计数到9后直接复位到0,不需要进入10这个状态。进入10状态再复位会引入额外的信号翻转,触发后续TFF的误动作。
  • 异步计数器的固有风险:采用前级TFF输出作为后级时钟的异步计数器,在复位时容易因信号变化的时序问题产生非预期翻转。

修复后的代码

方案1:同步复位+正确状态检测(推荐)

将TFF改为同步复位,同时调整复位检测逻辑为检测9(1001),在时钟沿统一处理复位和计数:

module MOD10 (clk, clr, q);
    input clk, clr;
    output reg [3:0] q;
  
    // 检测计数到9(1001),同步复位条件
    wire reset_condition = (q == 4'b1001);
  
    always @(posedge clk or posedge clr) begin
        if (clr) begin
            q <= 4'b0000;
        end else if (reset_condition) begin
            q <= 4'b0000;
        end else begin
            q <= q + 1'b1;
        end
    end
endmodule

module MOD10_TB();
    reg clk, clr;
    wire [3:0] q;
  
    MOD10 uut (clk, clr, q);
  
    // 时钟生成(50% duty cycle)
    initial begin
        clk = 0;
        forever #5 clk = ~clk;  // Toggle clock every 5 time units
    end
  
    // Reset logic and test sequence
    initial begin
        clr = 1;  // Reset active
        #10 clr = 0;  // Deactivate reset after 10 time units
        #110 $finish;  // End simulation after 110 time units
    end
endmodule

方案2:修复原异步TFF架构的问题

如果坚持使用TFF搭建异步计数器,需要调整复位检测逻辑,并修改TFF的复位触发方式,避免复位后的误翻转:

module MOD10 (clk, clr, q);
    input clk, clr;
    output [3:0] q;
    
    wire w;
    // 检测计数到9(1001),提前触发复位,避免进入10状态
    assign w = clr | (q[3] & q[0]);
  
    TFF tff1(clk, w, 1'b1, q[0]);
    TFF tff2(q[0], w, 1'b1, q[1]);
    TFF tff3(q[1], w, ~(q[3] & q[0]), q[2]); // 当计数到9时,禁止tff3翻转
    TFF tff4(q[2], w, (q[1] & q[0]), q[3]); // 仅当q1和q0都为1时,tff4才翻转
endmodule

module TFF (clk, clr, t, q);
    input clk, clr, t;
    output reg q;
  
    // 改为同步复位,避免异步复位的时序冲突
    always @(negedge clk) begin
        if (clr)
            q <= 0;
        else begin
            if (t)
                q <= ~q;
            else
                q <= q;
        end
    end
endmodule

module MOD10_TB();
    reg clk, clr;
    wire [3:0] q;
  
    MOD10 uut (clk, clr, q);
  
    // 时钟生成(50% duty cycle)
    initial begin
        clk = 0;
        forever #5 clk = ~clk;  // Toggle clock every 5 time units
    end
  
    // Reset logic and test sequence
    initial begin
        clr = 1;  // Reset active
        #10 clr = 0;  // Deactivate reset after 10 time units
        #110 $finish;  // End simulation after 110 time units
    end
endmodule

修复代码解释

方案1解释

  • 同步复位:所有操作都在时钟上升沿完成,避免异步复位带来的时序冲突,保证复位和计数的动作同步执行。
  • 正确状态检测:直接检测计数器到达9(1001),在下一个时钟沿直接复位到0,跳过10这个状态,从根源上消除额外翻转的可能。
  • 简化架构:用组合逻辑+时序逻辑直接实现计数,比TFF级联更简洁,更易维护。

方案2解释

  • 调整复位检测条件:改为检测9(q[3]&q[0]),在到达9时就触发复位,避免进入10状态。
  • 同步复位:将TFF的复位改为同步(仅在时钟沿处理复位),避免复位信号变化触发的误翻转。
  • TFF使能控制:通过T端控制后级TFF的翻转,当计数到9时,禁止tff3翻转,确保计数器直接从9回到0,不会产生中间状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 00:12:08