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

VHDL状态机COUNT_OUT输出始终为0,仿真观测异常求助

正交编码器计数器FSM的问题分析与解决

一、COUNT_OUT始终为0的根本原因

你的代码存在两个核心问题,直接导致count信号无法正常更新,进而COUNT_OUT输出始终为0:

1. 多进程驱动同一个信号(非法操作)

信号count被两个进程同时赋值:

  • SYNC_PROC时序进程(时钟上升沿触发)中,当z='1'时会给count赋0;
  • NEXT_STATE_DECODE组合逻辑进程(敏感列表触发)中,在各个状态分支里对count做赋值/增减操作。

VHDL中,非resolved类型的信号不允许被多个进程驱动,unsigned属于非resolved类型,这种冲突会导致信号值异常,仿真中通常会保持初始值(0),综合时会直接报错。

2. 计数逻辑的时序设计错误

正交编码器的计数更新必须是同步时序逻辑,你现在把count的增减放在组合逻辑进程里,不仅会引发多驱动问题,还会引入亚稳态、毛刺等风险,不符合FPGA同步设计的基本原则。

二、代码修正方案

重构代码,将count的更新完全移到同步进程中,组合逻辑进程只负责生成状态转移和计数控制信号:

修正后的核心代码示例

-- 新增计数控制信号,用于组合逻辑给时序进程传递计数指令
signal en_count : std_logic;
signal up_down  : std_logic;

SYNC_PROC: process(CLK)
begin
    if rising_edge(CLK) then
        if (z='1') then
            state <= S00;
            count <= (others=>'0');
        else
            state <= next_state;
            -- 同步更新count,仅在计数使能有效时操作
            if en_count = '1' then
                if up_down = '1' then
                    count <= count + 1;
                else
                    count <= count - 1;
                end if;
            end if;
        end if;
    end if;
end process;

NEXT_STATE_DECODE: process(state, A, B)
begin
    -- 给所有输出信号加默认赋值,避免组合逻辑锁存
    next_state <= state;
    en_count   <= '0';
    up_down    <= '0';
    
    case state is
        when S00 => 
            if(A = '0' and B = '1') then
                next_state <= S01;
            elsif(A = '1' and B = '0') then
                next_state <= S10;
            end if;
         when S01 => 
            if(A = '1' and B = '1') then
                next_state <= S11;
            elsif(A = '0' and B = '0') then
                next_state <= S00;
            end if;
         when S11 => 
            if(A = '1' and B = '0') then
                en_count   <= '1';
                up_down    <= '0'; -- 计数减1
                next_state <= S10;
            elsif(A = '0' and B = '1') then
                en_count   <= '1';
                up_down    <= '1'; -- 计数加1
                next_state <= S01;
            end if;
         when S10 => 
            if(A = '0' and B = '0') then
                en_count   <= '1';
                up_down    <= '0'; -- 计数减1
                next_state <= S00;
            elsif(A = '1' and B = '1') then
                en_count   <= '1';
                up_down    <= '1'; -- 计数加1
                next_state <= S11;
            end if;
    end case;
end process;

-- COUNT_OUT直接同步输出count
COUNT_OUT <= count;

修正要点说明

  • 将count的更新完全移到SYNC_PROC时序进程中,彻底解决多驱动问题;
  • 组合逻辑进程仅负责生成状态转移指令和计数控制信号(en_count控制是否计数,up_down控制加减方向);
  • 组合逻辑进程中给所有输出信号添加默认赋值,避免出现组合逻辑锁存(FPGA设计的基本规范);
  • 移除原组合进程中对count的所有赋值,确保信号驱动唯一。

三、仿真无法观测内部信号的解决方法

针对state、next_state、count无法在仿真中观测的问题,按以下步骤处理:

  1. 使用行为级仿真(前仿真)
    不要使用综合后仿真(门级仿真),因为综合工具会优化掉未被直接输出的内部信号。行为级仿真直接基于VHDL代码,能完整保留所有内部信号。

  2. 手动添加信号到波形窗口
    以Vivado仿真为例:

    • 运行仿真后,在左侧Scope窗口找到GPIO_demo模块,展开后即可看到state、next_state、count等内部信号;
    • 选中目标信号,右键选择Add to Waveform,即可在波形窗口观测。
  3. 添加属性强制保留信号
    如果行为级仿真中仍看不到信号,可以在信号定义时添加keep属性,强制工具保留信号:

    type state_type is (S00, S01, S10, S11);
    signal state, next_state: state_type;
    attribute keep : boolean;
    attribute keep of state : signal is true;
    attribute keep of next_state : signal is true;
    
    signal count: unsigned(11 downto 0) := (others=>'0');
    attribute keep of count : signal is true;
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 10:25:15