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

基于分频时钟的Verilog 0-9计数FPGA实现问题咨询

Hey there! Let's get your Cyclone V 0-9 counter up and running smoothly. I’ll walk you through fixing the clock division, refining the counter logic, and handling those finicky mechanical buttons—since those are usually the culprits behind weird behavior.

First: Fixing the 50MHz to 1Hz Conversion

Instead of generating a new 1Hz clock (which can cause timing issues in FPGAs), we’ll create a 1Hz enable signal synchronized to the 50MHz core clock. This is way more reliable. Here’s how it works:

  • We need to count 50,000,000 cycles of 50MHz to make 1 second. So we’ll use a 26-bit counter (since 2^26 is ~67 million, which covers 50 million).
  • When the counter hits 49,999,999, we set the enable signal high for one cycle, then reset the counter to start over.

Next: Handling Button Debouncing

Mechanical buttons like KEY0 and KEY1 bounce when pressed/released—this means the signal flickers for 10-20ms before stabilizing. If we don’t fix this, your reset or run control might trigger multiple times accidentally. We’ll use:

  • Two sync registers to avoid metastability (since button inputs are asynchronous to the 50MHz clock).
  • A counter to wait for the button signal to stay stable for 20ms (1,000,000 cycles at 50MHz) before trusting it.

The Main Counter Logic

We’ll build a synchronous counter (all operations tied to the 50MHz clock edge) with these rules:

  1. Reset Priority: If KEY0 is pressed, the counter immediately resets to 0, no matter what else is happening.
  2. Run Control: Only when KEY1 is pressed and the 1Hz enable signal is active does the counter increment.
  3. Loop Back: When the counter hits 9, it wraps around to 0 instead of overflowing.

Full Verilog Example

module counter_0_9(
    input clk_50mhz,
    input key0, // Assuming active-low (common on Cyclone V boards)
    input key1, // Active-low run enable
    output reg [3:0] cnt // BCD output (0-9)
);

// 50MHz to 1Hz enable signal
reg [25:0] div_counter;
reg en_1hz;

always @(posedge clk_50mhz) begin
    if (div_counter == 49999999) begin
        div_counter <= 0;
        en_1hz <= 1'b1;
    end else begin
        div_counter <= div_counter + 1'b1;
        en_1hz <= 1'b0;
    end
end

// Debounce KEY0 (reset)
reg [1:0] key0_sync;
reg [19:0] key0_debounce_cnt;
reg key0_stable;

always @(posedge clk_50mhz) begin
    key0_sync <= {key0_sync[0], key0};
    if (key0_sync[1] != key0_sync[0]) begin
        key0_debounce_cnt <= 0;
    end else if (key0_debounce_cnt != 1000000) begin // 20ms wait
        key0_debounce_cnt <= key0_debounce_cnt + 1'b1;
    end else begin
        key0_stable <= key0_sync[1];
    end
end

// Debounce KEY1 (run)
reg [1:0] key1_sync;
reg [19:0] key1_debounce_cnt;
reg key1_stable;

always @(posedge clk_50mhz) begin
    key1_sync <= {key1_sync[0], key1};
    if (key1_sync[1] != key1_sync[0]) begin
        key1_debounce_cnt <= 0;
    end else if (key1_debounce_cnt != 1000000) begin
        key1_debounce_cnt <= key1_debounce_cnt + 1'b1;
    end else begin
        key1_stable <= key1_sync[1];
    end
end

// Main counter logic
always @(posedge clk_50mhz) begin
    // Reset takes top priority
    if (!key0_stable) begin
        cnt <= 4'd0;
    end else begin
        // Increment only if run is enabled and 1Hz tick hits
        if (!key1_stable && en_1hz) begin
            cnt <= (cnt == 4'd9) ? 4'd0 : cnt + 4'd1;
        end
        // Else, hold current value
    end
end

// Optional: Add BCD-to-7-segment decoder if using a display
// reg [6:0] seg_out;
// always @(*) begin
//     case(cnt)
//         4'd0: seg_out = 7'b1000000; // Adjust based on common anode/cathode
//         4'd1: seg_out = 7'b1111001;
//         4'd2: seg_out = 7'b0100100;
//         4'd3: seg_out = 7'b0110000;
//         4'd4: seg_out = 7'b0011001;
//         4'd5: seg_out = 7'b0010010;
//         4'd6: seg_out = 7'b0000010;
//         4'd7: seg_out = 7'b1111000;
//         4'd8: seg_out = 7'b0000000;
//         4'd9: seg_out = 7'b0010000;
//         default: seg_out = 7'b1111111;
//     endcase
// end

endmodule

Debugging Tips

  1. Test the Clock Divider: Use Intel’s SignalTap II to capture the en_1hz signal. It should pulse high once every second.
  2. Verify Button Debouncing: Check the key0_stable and key1_stable signals—they should only change after the button has been pressed/released for 20ms.
  3. Validate Counter Behavior: Make sure the counter resets to 0 when KEY0 is pressed, increments once per second when KEY1 is held, and loops back to 0 after 9.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:20:04