【问题标题】:VHDL: signal cannot be synthesizedVHDL:无法合成信号
【发布时间】:2013-12-26 20:46:49
【问题描述】:

我对 VHDL 非常陌生,正在尝试为学校的一个项目编写代码。我想要的是使用 LED 充当球的一维乒乓球游戏。请注意,我对 VHDL 没有结构化的理解,我通过在 VHDL 中查找状态机设计来编写以下代码并尝试提出自己的。我有一个异步 RESET 和两个异步输入,对应于每个球员按下按钮以返回球。它们是异步的,因为我希望玩家即使在一个时钟周期内按下按钮的时间很短,也能够将球返回。

在 Xilinx 10.1 中,仿真以我想要的方式运行,但是当我尝试综合时,这是以下代码的错误:

ERROR:Xst:827 - "C:/Users/Emre/LED_pong/pong.vhd" line 49: Signal present_state cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.

当我删除包含 PAD1 和 PAD2 的 elsif 语句时,它会合成,但会失去其功能。

entity pong is
Port ( CLK : in  STD_LOGIC;
       RST : in  STD_LOGIC;
       PAD1 : in  STD_LOGIC;
       PAD2 : in  STD_LOGIC;
       LEDS : out  STD_LOGIC_VECTOR (7 downto 0));
end pong;

architecture Behavioral of pong is

type state is ( P1_SERVE, A1, A2, A3, A4, A5, A6, A7,
                     B0, B1, B2, B3, B4, B5, B6, P2_SERVE,
                     WAIT_FOR_P1, WAIT_FOR_P2, P1_HIT_EARLY, P2_HIT_EARLY,
               P1_SCORED, P2_SCORED );
signal present_state: state;
signal temp : STD_LOGIC_VECTOR (7 downto 0) := "00000000";

begin

process (CLK, RST, PAD1, PAD2) begin

    if (RST = '1') then
        temp <= "10000000";
        present_state <= P1_SERVE;

    elsif (rising_edge(CLK)) then
        case present_state is

            when P1_SERVE =>
                temp <= "10000000";
            when P2_SERVE =>
                temp <= "00000001";

            when P1_SCORED =>
                temp <= "00000000";
           present_state <= P2_SERVE;
            when P2_SCORED =>
           temp <= "00000000";
           present_state <= P1_SERVE;

            when A1 =>
                temp <= "01000000";
                present_state <= A2;
            when A2 =>
                temp <= "00100000";
                present_state <= A3;
            when A3 =>
                temp <= "00010000";
                present_state <= A4;
            when A4 =>
                temp <= "00001000";
                present_state <= A5;
            when A5 =>
                temp <= "00000100";
                present_state <= A6;
            when A6 =>
                temp <= "00000010";
           present_state <= A7;
            when A7 =>
                temp <= "00000001";
           present_state <= WAIT_FOR_P2;
        when WAIT_FOR_P2 =>
           temp <= "00000000";
           present_state <= P2_SERVE;

            when B6 =>
                temp <= "00000010";
                present_state <= B5;
            when B5 =>
                temp <= "00000100";
                present_state <= B4;
            when B4 =>
                temp <= "00001000";
                present_state <= B3;
            when B3 =>
                temp <= "00010000";
                present_state <= B2;
            when B2 =>
                temp <= "00100000";
                present_state <= B1;
            when B1 =>
                temp <= "01000000";
           present_state <=  B0;
            when B0 =>
                temp <= "10000000";
           present_state <= WAIT_FOR_P1;
        when WAIT_FOR_P1 =>
           temp <= "00000000";
           present_state <= P1_SERVE;

            when P1_HIT_EARLY =>
                temp <= "10000000";
                present_state <= P2_SCORED;
            when P2_HIT_EARLY =>
                temp <= "00000001";
                present_state <= P1_SCORED;

        when others =>
           null;
        end case;

  elsif (PAD1 = '1') then
     case present_state is 
        when P1_SERVE =>
           present_state <= A1;
        when B0 =>
           present_state <= P1_HIT_EARLY;
        when WAIT_FOR_P1 =>
           present_state <= A1;
        when others =>
           null;    
     end case;

    elsif (PAD2 = '1') then
        case present_state is
            when P2_SERVE =>
                present_state <= B6;
            when A7 =>
                present_state <= P2_HIT_EARLY;
            when WAIT_FOR_P2 =>
                present_state <= B6;
        when others =>
           null;
        end case;

    end if;
end process;

   LEDS <= temp;

end Behavioral;

【问题讨论】:

    标签: asynchronous vhdl


    【解决方案1】:

    除了 case 语句中的异步复位和时钟加载之外,您还尝试使用 PAD1 和 PAD2 作为为 present_state 启用的锁存器。

    您希望的行为的首选实现并不反映硬件。例如,当您使用 PAD1 和 PAD2 作为锁存器启用时,您在后两个 case 语句中查看 present_state,有效地组合时钟。

    您可能希望将 PAD1 和 PAD2 捕获为每个时钟都会清除的事件,类似于捕获中断边缘。根据您的时钟频率,您可能需要对它们进行脉冲过滤,问题是您是否可以从按钮中同时获得接通和断开反弹。还需要考虑时钟沿的设置时间,这意味着您可能希望在特定窗口期间进行采样,以确保设置时间。该模型是一个触发器,使用 PAD1 和 PAD2 作为时钟,后跟一个锁存器。

    通过事件捕获,您可以在rising_edge(CLK) 评估下将所有案例语句合并为一个。效果是在某些状态情况下根据 PAD1 或 PAD2(已存储)事件给出两种可能的输出状态。

    【讨论】:

      【解决方案2】:

      您的代码中存在概念问题(不是 VHDL 的错)。

      您正在尝试实现一个有限状态机,并且与任何 FSM 一样,必须注册当前状态(即,存储到触发器组中)。您在第一个 case 语句中执行此操作,因为对 present_state 的分配由时钟转换控制(即,它们在 ifrising_edge(clk) 语句下)。

      问题在于,在接下来的两个 case 语句(由 PAD1 和 PAD2 断言)中,您试图异步地修改 present_state 的值。回想一下,present_state 的值是已注册的,因此它是由触发器库产生的。由于触发器的输出值只能通过作用于其复位输入或修改其数据输入来修改,并且这些情况都与最后两个 case 语句中的情况相对应,因此您的代码根本无法翻译成硬件(正如 David 已经正确指出的那样)。

      我的建议:为你的 FSM 画一个详细的状态转换图(在任何 FSM 设计中都不要跳过这个阶段),这样可以清楚所有涉及的信号(包括 PAD1 和 PAD2)的作用。重写代码应该很简单。

      【讨论】:

        猜你喜欢
        • 2014-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多