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

Verilog(Vivado环境)下橄榄球计分板寄存器加不同分值故障问题

问题根因分析
  1. 违规将普通按键输入作为寄存器时钟源
    FPGA中仅专用时钟网络输入的信号适合作为时钟,你当前把4个按键的上升沿直接加入always块的敏感列表,相当于把普通IO当成了时钟源。这类信号时延不稳定,极易受到毛刺、机械抖动的干扰,每次电平跳变产生的上升沿都会触发加法操作,直接导致分值连续累加。
  2. if-else分支顺序导致加6功能巧合正常
    你将加6的逻辑放在分支最末尾,仅当其余3个按键均为低电平时才会触发。测试时按下达阵按键恰好没有其他按键干扰,所以看起来功能正常,本质是巧合而非逻辑正确。
  3. 缺失按键消抖与单脉冲触发逻辑
    物理开关拨动时会产生5~20ms的机械抖动,这段时间内电平会反复跳变产生多个上升沿。没有消抖和单脉冲转换逻辑的情况下,每次跳变都会触发一次加法,就是你看到的分值快速跳变的直接原因。
修复方案

1. 引入全局同步时钟

所有逻辑统一使用开发板的板载全局时钟(通常为50MHz/100MHz)作为唯一触发时钟,禁止将按键IO作为时钟源使用。

2. 实现按键消抖模块

过滤按键抖动期间的无效电平跳变,输出稳定的按键电平信号:

module key_debounce(
    input        clk,
    input        rst_n, // 低电平复位,可根据你的实际需求改为高电平
    input        key_in,
    output reg   key_out
);
reg [19:0] cnt; // 50MHz时钟下20位计数器可计数约20ms,覆盖常规按键抖动时长
reg key_sync;

// 按键输入先打两拍同步到时钟域,避免亚稳态
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) key_sync <= 1'b1; // 默认按键高电平,按下为低,可根据硬件调整
    else key_sync <= key_in;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        cnt <= 20'd0;
        key_out <= 1'b1;
    end
    else begin
        if(key_sync != key_out) begin
            cnt <= cnt + 1'b1;
            if(cnt == 20'd999_999) begin // 计数满20ms更新输出
                key_out <= key_sync;
                cnt <= 20'd0;
            end
        end
        else cnt <= 20'd0;
    end
end
endmodule

3. 实现上升沿检测模块

对消抖后的按键信号做边沿检测,仅在按键按下的上升沿产生一个时钟周期的高电平使能信号,保证每次按键仅触发一次加法:

module edge_detect(
    input        clk,
    input        rst_n,
    input        signal_in,
    output       pos_edge
);
reg signal_dly;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) signal_dly <= 1'b0;
    else signal_dly <= signal_in;
end
assign pos_edge = signal_in & ~signal_dly;
endmodule

4. 重写得分寄存器逻辑

使用全局时钟触发,通过使能信号控制加法操作,同时增加得分上限99的溢出判断:

module teamAPoints(
    input        clk,
    input        masterReset,
    input        td_en,      // 达阵使能,单脉冲信号
    input        fg_en,      // 射门使能,单脉冲信号
    input        two_pt_en,  // 两分转换使能,单脉冲信号
    input        extra_en,   // 附加分使能,单脉冲信号
    output reg [6:0] teamAScore
);

always @(posedge clk or posedge masterReset) begin
    if (masterReset) begin
        teamAScore <= 7'd0;
    end
    else begin
        if(td_en && (teamAScore + 7'd6 <= 7'd99)) 
            teamAScore <= teamAScore + 7'd6;
        else if(fg_en && (teamAScore + 7'd3 <= 7'd99)) 
            teamAScore <= teamAScore + 7'd3;
        else if(two_pt_en && (teamAScore + 7'd2 <= 7'd99)) 
            teamAScore <= teamAScore + 7'd2;
        else if(extra_en && (teamAScore + 7'd1 <= 7'd99)) 
            teamAScore <= teamAScore + 7'd1;
        else 
            teamAScore <= teamAScore;
    end
end
endmodule

5. 顶层模块连线

在顶层模块中对每个按键依次实例化消抖模块和边沿检测模块,将输出的单脉冲使能信号接到得分模块的对应输入即可。

注意:上述代码中的复位极性、按键默认电平需要根据你使用的开发板硬件实际情况调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 22:15:07