Vhdl Can';t解析多个常量驱动程序-两个触发器必须更改相同的向量

Vhdl Can';t解析多个常量驱动程序-两个触发器必须更改相同的向量,vhdl,fpga,intel-fpga,quartus,Vhdl,Fpga,Intel Fpga,Quartus,我知道错误是什么意思,为什么它不好,但我不知道如何用其他方式来做 无法在snake\u驱动程序处解析网络“snake[17]”的多个常量驱动程序 (其他与此相同) 我们的任务是在std_逻辑_向量中有一条“移动的蛇”,它是端到端的,当你按下一个按钮(切换信号)时,蛇会改变它的长度(2,3,4,5,6,2,…) 显然,snake向量必须通过监听toggle的进程和监听clock的进程来改变。当我把两者放在同一个过程中,我得到一个错误,两个边缘检测不能在同一个过程中 /\____ +-----

我知道错误是什么意思,为什么它不好,但我不知道如何用其他方式来做

无法在snake\u驱动程序处解析网络“snake[17]”的多个常量驱动程序

(其他与此相同)

我们的任务是在std_逻辑_向量中有一条“移动的蛇”,它是端到端的,当你按下一个按钮(切换信号)时,蛇会改变它的长度(2,3,4,5,6,2,…)

显然,snake向量必须通过监听toggle的进程和监听clock的进程来改变。当我把两者放在同一个过程中,我得到一个错误,两个边缘检测不能在同一个过程中

/\____    +--------------------+
toggle ---->  change length    |
          |          v         |
          |  [snake register] =====> snake 17 downto 0
\/\/\/    |          ^         |
clock  ---->  move one step    |
          +--------------------+
欢迎任何意见

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity snake_driver is
    generic
    (
        LEN : integer := 18;
        MAX_SNAKE_LEN : integer := 6
    );

    port
    (
        clk : in std_logic;
        change : in std_logic;
        output : out std_logic_vector(LEN-1 downto 0)
    );
end snake_driver;

architecture Anaconda of snake_driver is
signal snake : std_logic_vector(LEN-1 downto 0) := (0 => '1', 1 => '1', others => '0'); -- two snake pieces
signal dir_right : boolean := FALSE; -- start left
begin


    process(change)

        variable data : std_logic_vector(LEN-1 downto 0); -- two snake pieces

        variable snake_len : integer := 2; -- snake 2 long
    begin

        if rising_edge(change) then -- change snake length
            -- add snake piece based on direction

            data := snake; -- <-- here I tried to avoid the problem
                           -- by caching snake data. To no avail.

            if snake_len = MAX_SNAKE_LEN then

                snake_len := 2;

                -- shorten to 2 len

                if dir_right then
                    -- moving right, remove from left
                    data := std_logic_vector(unsigned(data) and shift_right(unsigned(data), MAX_SNAKE_LEN-2));
                else
                    -- moving left, remove from right
                    data := std_logic_vector(unsigned(data) and shift_left(unsigned(data), MAX_SNAKE_LEN-2));
                end if;
            else

                -- add one at the end
                if dir_right then
                    -- moving right, add on left
                    data := std_logic_vector(unsigned(data) or shift_left(unsigned(data), 1));
                else
                    -- moving left, add on right
                    data := std_logic_vector(unsigned(data) or shift_right(unsigned(data), 1));
                end if;

            end if;


            snake <= data;
        end if;

    end process;




    -- move snake on clock
    process(clk)
        -- variables in the process
        variable data : std_logic_vector(LEN-1 downto 0);

    begin
        -- shift the snake
        if rising_edge(clk) then

            data := snake;

            if dir_right then
                -- right move
                data(LEN-2 downto 0) := data(LEN-1 downto 1);

                if data(0) = '1' then
                    dir_right <= FALSE; -- change direction
                end if;             
            else
                -- left move
                data(LEN-1 downto 1) := data(LEN-2 downto 0);

                if data(LEN-1) = '1' then
                    dir_right <= TRUE; -- change direction
                end if;

            end if;

            snake <= data;

        end if;

    end process;


    -- send changed data to output
    output <= snake;    

end Anaconda;
ieee库;
使用ieee.std_logic_1164.all;
使用ieee.numeric_std.all;
实体snake_驱动程序是
通用的
(
LEN:整数:=18;
最大长度:整数:=6
);
港口
(
clk:标准逻辑中;
变更:在std_逻辑中;
输出:输出标准逻辑向量(LEN-1向下至0)
);
终端驱动程序;
snake_驱动程序的架构Anaconda是
信号蛇:标准逻辑向量(LEN-1到0):=(0=>'1',1=>'1',其他=>'0');--两条蛇
信号方向右:布尔:=FALSE;——左起
开始
过程(变更)
变量数据:标准逻辑向量(LEN-1向下至0);--两条蛇
变量snake_len:整数:=2;--蛇2长
开始
如果上升沿(改变),那么——改变蛇的长度
--根据方向添加蛇形块

数据:=snake;-- 你的钟有多快?通常,FPGA中的时钟非常快(50MHz或更高)。如果它很快,您通常会在每个时钟边缘上使用延迟元素对“切换”信号进行采样,以检测边缘。可以使用此边缘检测来增加蛇的长度。如果你需要移动蛇的速度慢到足以让人检测到它,你通常只需要每隔x个时钟边缘移动一步(使用计数器生成时钟启用)。这一切都可以在一个进程中完成,该进程只依赖于您的高速时钟边缘

但是,如果切换信号来自物理开关,则可能需要注意开关反弹的物理现象。通过在检测到负边缘后忽略一定数量的正边缘计数,可以避免大多数反弹问题。这样,当按下开关时,只有第一条正边计数,释放开关时不使用任何(反弹)正边

如果我上面说的任何一句话没有意义,我可以更详细地讲

下面是我上面所说的一条蛇的例子,它总是向右旋转,开始宽度为2位,最大尺寸没有限制(警告:未测试):

snake的架构行为是 信号时钟:标准逻辑--实际上是一个输入。50MHz 信号切换:标准逻辑:='0'--实际上是一个输入,而不是一个内部信号 信号切换_d:std_逻辑:='0'; 信号蛇向量:标准逻辑向量(17到0):=“0000000000000000 11”; 信号禁用_计数:无符号(20到0):=(其他=>“0”)--在全量程内循环约50毫秒 信号步进计数:无符号(24到0):=(其他=>“0”)--约0.7秒,在整个范围内循环 开始 过程(clk) 如果(clk='1'和clk'事件),则
我不确定。但是在以前的项目中,我们只在
clk
上使用
rising\u edge()。在另一个异步信号上,我们只使用了
change='1'
。我知道这很简单,但也许能奏效?请注意,当我从正负“边缘”触发动作时,我并没有真正使用
切换信号中的边缘触发逻辑。我只是在读取时钟正边缘上的注册样本,以告诉大致的时间间隔,在此期间,慢得多的信号(
切换
)的正边缘或负边缘出现。蛇需要以大约4 Hz的频率移动,尽管这个频率确实是从50米时钟获得的(snake放慢了速度,因为项目的另一部分是一个可切换的预调谐器,而其他东西共享相同的频率).去抖动不是问题,该套件附带了一些输入净化功能。我曾想过在收到拨动开关时设置一些信号,然后清除并在时钟边缘使用它,但我收到一个投诉,说两个进程不能写入相同的信号,或者类似的。真的检查拨动开关是否是唯一可行的方法?你知道吗您可以在4 Hz时钟上使用相同的采样技术,但您必须按住按钮至少1/4秒,以确保检测到事件。或者,您可以检测50 MHz时钟上的切换事件,然后使用锁存寄存器存储指示,直到在4 Hz时钟上读取为止。这通常在物理上是不可能的在FPGA中,从两个不同的时钟域写入同一触发器(信号)。请参阅我的编辑,其中有一个高速域上的锁存示例。您也可以使用低速域中设置的确认信号(每次扩展snake时,1个时钟)要在高速域中取消断言
extend\u event
,以避免同步(
divide\u event
)时钟分频器的输出,但这限制了你最多只能每隔一个低速周期延长一次。谢谢,但现在已经很晚了,所以我明天就试试。我希望quartus不会再做它的特技。从我开始,它就不断地以新的错误取悦我……顺便说一句,知道一些关于这方面的好书或教程吗?我的编码是到目前为止大部分都是命中或未命中。
architecture behav of snake is

signal clk       : std_logic; --actually an input. 50MHz
signal toggle    : std_logic := '0'; --actually an input, not an internal signal
signal toggle_d  : std_logic := '0';
signal snake_vec : std_logic_vector(17 downto 0) := "000000000000000011";
signal disable_count : unsigned(20 downto 0):=(others => '0'); --about 50ms to cycle through full range
signal step_count    : unsigned(24 downto 0):=(others => '0'); --about 0.7s to cycle through full range

begin
  process(clk)
    if (clk = '1' and clk'event) then
      toggle_d <= toggle; --store previous value of toggle
      if (toggle_d = '1' and toggle = '0') then --trigger blocking counter on negative edges of toggle
        disable_count <= (others => '1');
      elsif (disable_count /= 0) then --count down if blocking counter is enabled
        disable_count <= disable_count-1;
      end if;

      if (toggle_d = '0' and toggle = '1' and disable_count = 0) then --extend on allowed rising edges of toggle
        snake_vec <= snake_vec or (snake_vec(0) & snake_vec(17 downto 1); --extend the snake by 1
      else
        step_count <= step_count-1; --this could be + or -
        if (step_count = 0) then --functions as a clock enable every 1 in 33.5 million cycles
          snake_vec <= snake_vec(0) & snake_vec(17 downto 0); --rotate snake
        end if;
      end if;      
    end if;
  end process;
end behav;
architecture behav of snake is

signal clk       : std_logic; --50MHz
signal divide_event : std_logic; --on the 50MHz domain, single clock wide pulse every rising edge of 4Hz clock, sourced from clock divider
signal clk_slow  : std_logic; --4Hz
signal toggle    : std_logic := '0'; --actually an input, not an internal signal
signal toggle_d  : std_logic := '0';
signal snake_vec : std_logic_vector(17 downto 0) := "000000000000000011";

begin
  process(clk)
    if (clk = '1' and clk'event) then
      toggle_d <= toggle; --store previous value of toggle
      if (toggle_d = '0' and toggle = '1') then
        extend_event <= '1';
      elsif divide_event = '1' then
        extend_event <= '0';
      end if;
  end process;

  process(clk_slow)
    if (clk_slow = '1' and clk_slow'event) then
      if (extend_event = '1') then
        snake_vec <= snake_vec or (snake_vec(0) & snake_vec(17 downto 1); --extend the snake by 1
      else
        snake_vec <= snake_vec(0) & snake_vec(17 downto 0); --rotate snake
      end if;
    end if;  
  end process
end behav;