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

为何我的8位计数器卡在0或255?Verilog代码故障排查

Cyclone 4 FPGA上下计数器异常问题排查

我在Cyclone 4 FPGA上练习Verilog代码开发,原本的8位计数器在板载50MHz时钟下运行速度过快,LED变化无法肉眼观测,于是编写了如下分频模块:

module enableCounter(
    input clock_5,
    input reset,
    output reg enable_out);

    reg [3:0] counter;

    always @(posedge clock_5) begin
        if (reset) begin
            counter <= 4'b0000;
        end 
        else begin
            counter <= counter + 1;
            if (counter == 4'b0000)
                enable_out <= 1;
            else
                enable_out <= 0;
        end
    end

endmodule

理论上该模块可让enable_out仅在clock_5的1/16周期内为高电平。之后我编写了上下计数器模块:

module updown_counter(
    input up_down,
    input clk,
    input enable,
    input reset,

    output reg [7:0] count_out);
    
    always @ (posedge clk) begin
        if (up_down == 0) begin                 // 向上计数
            if (reset)
                count_out <= 8'b0000_0000;
            else if (enable && count_out == 8'b1111_1111)
                count_out <= 8'b0000_0000;
            else if (enable && count_out != 8'b1111_1111)
                count_out <= count_out + 8'b0000_0001;
            else
                count_out <= count_out;
        end
        
        else if (up_down == 1) begin            // 向下计数
            if (reset)
                count_out <= 8'b1111_1111;
            else if (enable && count_out == 8'b0000_0000)
                count_out <= 8'b1111_1111;
            else if (enable && count_out != 8'b0000_0000)
                count_out <= count_out - 8'b0000_0001;
            else
                count_out <= count_out;
        end
    end            
endmodule

代码无编译错误,但连接count_out的8个LED始终全灭,按下复位按钮时全亮;切换up_down方向后现象相反,推测代码存在bug。

补充说明:在Quartus中通过BDF文件连接板载时钟到PLL模块,再接入上述两个模块,连接示意图如下:
Quartus模块连接示意图


问题分析与修复方案

1. 核心问题:分频系数过小

当前16分频后,计数器更新频率为50MHz/16≈3.125MHz,远高于人眼可分辨的20Hz以下阈值,LED高速闪烁会被肉眼识别为常亮/常灭,导致看不到计数变化。

2. 代码逻辑优化与修复

(1)增大分频系数

将分频模块的计数器位数提升至24位,使enable_out频率降至约2.98Hz,肉眼可清晰观测LED变化:

module enableCounter(
    input clock_5,
    input reset,
    output reg enable_out);

    reg [23:0] counter; // 改为24位计数器,实现约50MHz/2^24≈2.98Hz的分频

    always @(posedge clock_5) begin
        if (reset) begin
            counter <= 24'd0;
            enable_out <= 1'b0;
        end 
        else begin
            counter <= counter + 1'b1;
            // 取计数器最高位作为使能信号,获得50%占空比的低频信号
            enable_out <= counter[23];
        end
    end

endmodule
(2)简化上下计数器逻辑

去除冗余代码,避免逻辑分支混乱:

module updown_counter(
    input up_down,
    input clk,
    input enable,
    input reset,
    output reg [7:0] count_out);
    
    always @ (posedge clk) begin
        if (reset) begin
            // 复位时根据计数方向设置初始值
            count_out <= up_down ? 8'hFF : 8'h00;
        end else if (enable) begin
            if (!up_down) begin // 向上计数
                count_out <= (count_out == 8'hFF) ? 8'h00 : count_out + 1'b1;
            end else begin // 向下计数
                count_out <= (count_out == 8'h00) ? 8'hFF : count_out - 1'b1;
            end
        end
        // 未使能时保持原值,无需额外赋值
    end            
endmodule

3. 硬件连接验证

  • 确认PLL输出时钟已正确连接到两个模块的时钟引脚;
  • 检查复位信号极性:若板载复位为低电平有效,需将代码中if (reset)改为if (!reset);
  • 确认LED连接方式:共阳LED需低电平点亮,共阴LED需高电平点亮,根据实际情况调整代码或硬件接线。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 19:15:01