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