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

Verilog中同一端口的双if分支是否冲突?按键控制功能异常排查

问题根源与解决方案

首先明确:同一端口sw_i[0]的两个if分支不存在冲突,问题出在你的时钟生成逻辑上,导致sw_i[0]关闭时,第二个always块根本没机会执行清零代码。

具体原因分析

  1. 你的clk_29由count[div_para]生成,而count的更新完全受sw_i[0]控制:

    always@(posedge clk or negedge rstn) begin
        if(!rstn) count <= 0;
        else if(!sw_i[0]) count <= 0; // sw_i[0]关闭时,count被持续置0
        else if(sw_i[0]) count <= count + 1;
    end
    

    当sw_i[0]关闭时,count始终为0,clk_29也就一直是0,没有上升沿。

  2. 第二个always块的触发条件是@(posedge clk_29 or negedge rstn),只有clk_29出现上升沿或rstn下降时才会执行。sw_i[0]关闭后,clk_29停在0,没有上升沿,rstn又未变化的话,这个always块就完全停止运行,自然不会执行if(!sw_i[0])的清零分支,cnt和tmp就停留在最后一次的状态。

  3. 换成sw_i[1]时,sw_i[0]仍处于开启状态,count持续自增,clk_29有正常的上升沿,第二个always块能正常触发,所以能检测到sw_i[1]的状态变化并执行对应分支,功能恢复正常。

修正方案

方案1:改用原始clk触发第二个always块(推荐)

把第二个always块的触发时钟换成原始输入clk,同时在内部检测clk_29的上升沿来保持原来的计数速度,这样不管sw_i[0]状态如何,always块都能持续运行,及时响应sw_i[0]的变化。同时注意时序always块必须用非阻塞赋值<=(你原来用的阻塞赋值=会导致仿真与硬件行为不一致):

always@(posedge clk or negedge rstn) begin
    reg clk_29_dly;
    if(!rstn) begin
        cnt <= 4'd0;
        tmp <= 7'b0000000;
        clk_29_dly <= 1'b0;
    end
    else if(!sw_i[0]) begin
        tmp <= 7'b0000000;
        cnt <= 4'd0;
        clk_29_dly <= 1'b0;
    end
    else begin
        clk_29_dly <= clk_29;
        // 检测clk_29的上升沿,保持原有的计数频率
        if(clk_29 && !clk_29_dly) begin
            case(cnt)
                4'b0000:tmp<=7'b0111111;
                4'b0001:tmp<=7'b0000110;
                4'b0010:tmp<=7'b1011011;
                4'b0011:tmp<=7'b1001111;
                4'b0100:tmp<=7'b1100110;
                4'b0101:tmp<=7'b1101101;
                4'b0110:tmp<=7'b1111101;
                4'b0111:tmp<=7'b0000111;
            endcase
            cnt <= cnt + 1;
            if(cnt >= 4'b0111) cnt <= 4'b0000;
        end
    end
end

方案2:修改时钟生成逻辑(不推荐)

如果一定要用clk_29触发,需要保证sw_i[0]关闭时clk_29仍有上升沿,但这种方式会让时钟受输入信号控制,容易产生毛刺和时序问题,不建议在FPGA/ASIC设计中使用。

额外注意点

  • 时序always块(由时钟沿触发的always块)中,必须使用非阻塞赋值<=,阻塞赋值=仅用于组合逻辑always块(@(*)),否则会出现仿真结果和实际硬件行为不符的情况。
  • 你的两个if分支else if(!sw_i[0])和else if(sw_i[0])是互斥的,语法和逻辑上完全合法,不会出现冲突,这次的问题和分支本身无关。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 22:53:18