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

使用JK触发器的Mod-6计数器输出始终未知,求代码错误排查

问题描述

尝试改造Mod-8计数器实现Mod-6计数器,但仿真波形不符合预期。以下是设计代码和测试平台代码:

原设计代码

module mod_six_counter(clk,rst,q,qbar);
  input clk;
  input wire rst;
  output wire  [2:0]q;
  output [2:0]qbar;
  assign rst = ~((~q[0])&q[1]&(q[2]));
  jkff ff1(1'b1,1'b1,clk,rst,q[0],qbar[0]);
  jkff ff2(1'b1,1'b1,q[0],rst,q[1],qbar[1]);
  jkff ff3(1'b1,1'b1,q[1],rst,q[2],qbar[2]);
endmodule

module jkff(j,k,clk,rst,q,qbar);
  input j,k,clk,rst;
  output reg q;
  output qbar;
  always@(posedge clk or negedge rst)
  begin
        if (!rst)       q <= 1'b0;
  else begin
    case({j,k})
      2'b00 : q<=q;
      2'b01 : q<=1'b0;
      2'b10 : q<=1'b1;
      2'b11 : q<=~q;
      endcase
    end
  end
     assign  qbar = ~q;
endmodule

原测试平台代码

module tbmod_sixcounter;
  reg clk,rst;
  wire[2:0] q,qbar;

  mod_six_counter DUT(.clk(clk),.rst(rst),.q(q),.qbar(qbar));

  always #10 clk=~clk;

  initial 
  begin
    clk<=0;
    rst<=0;
    #7 rst<=1;
  end
endmodule

错误分析

  • 复位端口双重驱动:mod_six_counter模块中,rst被定义为输入端口,同时又通过assign语句内部赋值,这会导致信号冲突,属于Verilog语法错误,直接引发仿真或综合异常。
  • 复位逻辑混淆:原代码试图复用输入复位端口实现计数清零,未区分外部全局复位和内部计数清零逻辑,导致外部复位信号被覆盖,无法正常发挥作用。
  • 毛刺风险:直接用组合逻辑生成复位信号,若计数信号存在毛刺,可能误触发清零,导致计数异常。

修正方案

  1. 拆分复位信号:将输入的外部全局复位与内部计数清零逻辑分离,避免端口驱动冲突。
  2. 实现正确的Mod-6计数逻辑:Mod-6计数器需覆盖0~5共6个状态,当计数到6(3'b110)时,异步清零回到0。
  3. 保留外部复位功能:确保外部复位可以强制将计数器置0。

修正后的设计代码

module mod_six_counter(clk, ext_rst_n, q, qbar);
  input clk;
  input ext_rst_n;  // 外部低有效复位
  output wire [2:0] q;
  output [2:0] qbar;

  // 内部复位信号:外部复位有效 或 计数到6(3'b110)时,触发清零(低有效)
  wire internal_rst_n = ext_rst_n & ~((~q[0]) & q[1] & q[2]);

  // JK触发器连接,使用内部复位信号
  jkff ff1(1'b1, 1'b1, clk, internal_rst_n, q[0], qbar[0]);
  jkff ff2(1'b1, 1'b1, q[0], internal_rst_n, q[1], qbar[1]);
  jkff ff3(1'b1, 1'b1, q[1], internal_rst_n, q[2], qbar[2]);
endmodule

module jkff(j, k, clk, rst_n, q, qbar);
  input j, k, clk, rst_n;
  output reg q;
  output qbar;

  always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      q <= 1'b0;
    end else begin
      case({j, k})
        2'b00 : q <= q;
        2'b01 : q <= 1'b0;
        2'b10 : q <= 1'b1;
        2'b11 : q <= ~q;
      endcase
    end
  end

  assign qbar = ~q;
endmodule

修正后的测试平台代码

module tbmod_sixcounter;
  reg clk, ext_rst_n;
  wire[2:0] q, qbar;

  mod_six_counter DUT(.clk(clk), .ext_rst_n(ext_rst_n), .q(q), .qbar(qbar));

  // 生成10ns周期时钟
  always #10 clk = ~clk;

  initial begin
    clk       <= 0;
    ext_rst_n <= 0;  // 初始复位
    #7 ext_rst_n <= 1;  // 释放复位,开始计数
    
    // 仿真足够长时间,观察计数循环
    #200 $finish;
  end
endmodule

说明

修正后的代码将外部复位命名为ext_rst_n(低有效),内部生成internal_rst_n结合外部复位和计数到6时的清零逻辑,确保计数器在0~5之间稳定循环。测试平台增加了$finish语句避免仿真无限运行,同时保留初始复位逻辑验证计数器启动行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 05:47:08