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

VHDL电梯控制代码przybycie抵达信号晚1个时钟周期故障排查

VHDL电梯控制抵达信号时序异常问题
  • 开发场景:基于VHDL编写电梯控制代码,用于指示电梯抵达所选楼层的信号przybycie存在时序异常,拉高时机比预期晚1个时钟周期。
  • 预期逻辑:楼层计数器licznik_pieter计数到目标楼层值pietro时,przybycie信号立刻拉高。
  • 实际现象:przybycie在计数器值匹配目标楼层后,延迟1个时钟周期才输出高电平。

问题对应源代码

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
use IEEE.std_logic_unsigned.ALL;

entity winda is
    port (clk : in std_logic;
            pietro : in std_logic_vector(2 downto 0); -- 楼层按键输入
            alarm : in std_logic;
            numer_pietra : out std_logic_vector(2 downto 0);
            koniec : out std_logic);
end entity winda;

architecture winda_arch of winda is
type STANY is (otwarcie_drzwi,spoczynek, wybor_pietra, zamkniecie_drzwi, praca_windy, koniec_pracy);
signal stan, stan_nast: STANY;
signal licznik_pieter: std_logic_vector(2 downto 0) :="000";
signal drzwi: std_logic; -- 0=开门, 1=关门
signal przybycie: std_logic :='0'; -- 抵达所选楼层指示信号
signal otwarciozamkniecie: std_logic :='0'; -- 开关门动作指示信号
begin

    reg:process(clk, alarm)
        begin
            if (alarm = '1') then
                stan <= spoczynek;
            elsif rising_edge(clk) then
                stan <= stan_nast;
            end if;
        end process reg;
        
    komb:process(clk, alarm, stan)
        begin
            stan_nast <= stan;
            case stan is
            when otwarcie_drzwi =>
                    stan_nast <= spoczynek;
            when spoczynek => 
                    stan_nast <= wybor_pietra;
            when wybor_pietra =>
                if (pietro /= licznik_pieter) then
                        stan_nast <= zamkniecie_drzwi;
                        else
                            stan_nast <= wybor_pietra;
                        end if;
            when zamkniecie_drzwi =>
                    stan_nast <= praca_windy;
            when praca_windy =>
                if (pietro = licznik_pieter) then
                    stan_nast <= koniec_pracy;
                else
                    stan_nast <= praca_windy;
                end if;
            when koniec_pracy =>
                        stan_nast <= otwarcie_drzwi;
            when others =>
            stan_nast <= spoczynek;
            end case;
    end process komb;

drzwi<= '1' when stan = praca_windy or stan = zamkniecie_drzwi or stan = koniec_pracy else '0';
otwarciozamkniecie <= '1' when stan = zamkniecie_drzwi or stan = otwarcie_drzwi else '0';

licznik:process(clk,alarm,przybycie,pietro,otwarciozamkniecie)
    begin
        if (alarm = '1' or drzwi = '0' or otwarciozamkniecie = '1') then
            przybycie <= '0';
        elsif (rising_edge(clk)) then
            if (stan = praca_windy) then
                if (licznik_pieter = pietro) then
                przybycie <= '1';   
            elsif ( licznik_pieter > pietro ) then
                przybycie <= '0';
                licznik_pieter <= licznik_pieter - "01";
            else
                przybycie <= '0';
                licznik_pieter <= licznik_pieter + "01";
            end if;
            end if;
        end if;
end process licznik;
    
koniec <= '1' when stan = koniec_pracy or stan = spoczynek else '0';
numer_pietra <= licznik_pieter when drzwi = '0' else "000";

end architecture winda_arch;

核心逻辑错误说明

  1. przybycie被错误放在同步时序进程中赋值,天然存在时钟延迟
    当前przybycie的所有赋值逻辑都放在时钟沿触发的licznik进程内,只有时钟上升沿到来时才会判断条件、更新信号值,同步逻辑的输出必然比输入条件的变化晚1个时钟周期,不可能实现"计数到目标值立刻拉高"的即时响应效果。
    同时进程内判断顺序错误:时钟沿到来时,先判断当前计数值是否匹配目标楼层,不匹配才更新计数值。这意味着计数值更新到和目标值相等的那个时钟沿,不会触发przybycie拉高,必须等下一个时钟沿到来、再次判断匹配时才会拉高,正好对应观测到的1周期延迟。

  2. 组合进程敏感列表不完整,存在隐式延迟风险
    用于生成次态stan_nast的组合逻辑进程komb,敏感列表仅包含clk、alarm、stan三个信号,但进程内部读取了pietro和licznik_pieter信号。这两个信号变化时,组合逻辑不会立刻更新输出,会导致状态跳转滞后,进一步加剧时序异常。

修正方法

  • 将przybycie改为组合逻辑赋值,从同步时钟进程中移除:
    在架构的并行赋值区域新增语句,删除licznik进程中所有对przybycie的赋值:
    przybycie <= '1' when (stan = praca_windy and licznik_pieter = pietro) else '0';
    
    改完后只要电梯处于运行状态、计数值等于目标楼层,przybycie就会立刻拉高,不存在时钟延迟。
  • 补全组合进程敏感列表,将pietro、licznik_pieter加入komb进程的敏感列表;如果使用VHDL-2008及以上版本,可直接写process(all)自动补全敏感列表,避免漏写导致的逻辑错误。
  • 如果需要przybycie作为同步信号使用,可调整licznik进程内的判断顺序:时钟沿到来时先更新计数器值,再用更新后的值判断是否抵达目标楼层,可消除1周期的判断延迟,但输出仍然和计数器同步在时钟沿后更新,无法实现零延迟的即时响应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 23:09:31