VHDL 我的定时器不工作
VHDL My timer does not work
我的 FPGA 中有一个 25MHz 的时钟,我想制作一个定时器,当它计数 60 秒时 returns '1'。但是我有两个问题:
- 我不明白为什么我的输出信号 "count_sortie" 在 Vivado 中仿真时未定义。
- 为了强制定义我的信号 count_sortie,我在测试台文件中添加“:= 0”进行模拟,但 "count_sortie" 在 60 秒延迟后保持等于“0”。
这是我的 VHDL 文件:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity count is
Port ( clk : in STD_LOGIC;
count_entree : in STD_LOGIC;
count_sortie : out STD_LOGIC
);
end count;
architecture Behavioral of count is
signal q : integer range 0 to 30000000 :=0;
begin
process(clk)
begin
if (clk'event and clk='1')
then
while ((count_entree = '1') and (q < 25000000)) loop
if (q < 25000000) then
q := q + 1;
count_sortie <= '0';
else
count_sortie <= '1';
end if;
end loop;
end if;
end process;
end Behavioral;
和测试台文件:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY tbcount IS
END tbcount;
ARCHITECTURE behavior OF tbcount IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT count
PORT(
clk : in STD_LOGIC;
count_entree : in STD_LOGIC;
count_sortie : out STD_LOGIC
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal count_entree : std_logic;
--Outputs
signal count_sortie : std_logic;
--Clock
constant clk_period : time := 40 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: count PORT MAP (
clk => clk,
count_entree => count_entree,
count_sortie => count_sortie
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
count_entree <= '1';
wait;
end process;
END;
感谢您的支持。
除了我对您的语法无效的评论之外,即存在混淆 q
是信号还是变量,以下代码不会执行您期望的操作:
while ((count_entree = '1') and (q < 25000000)) loop
if (q < 25000000) then
q := q + 1;
count_sortie <= '0';
else
count_sortie <= '1';
end if;
end loop;
如果在 count_entree = '1'
和 q
是信号时进入此循环,则该循环是无限循环,或者如果 q
是信号,则解析为单个语句 count_sortie <= '0'
变量。
您的循环没有任何等待语句。如果 q
是一个信号,它将永远不会更新为新值,因为当进程结束或遇到等待语句时会发生这种情况,然后您将进入无限循环。
如果q
是变量,循环展开,只有最后一次赋值有效。请注意,由于如果 q < 25000000
退出循环,因此永远不会执行 else
语句。
最后,请注意,如果这是您的最终目标,这种结构将无法合成。
没有人实际回答您的问题:
- I don't understand why my outpout signal "count_sortie" is undefined in Vivado when I simulate it.
- To force to define my signal count_sortie, I add ":= 0" in the testbench file to simulate but "count_sortie" stays equal to '0' after the 60 seconds delay.
正如变量赋值 :=
所写,您的设计描述不是有效的 VHDL。
可能值得重新审视警告消息,那里发生的事情应该很明显。标记为 uut
的实例化 count
在测试平台 tbcount
中未绑定,并且其输出信号未被驱动。就测试台而言,没有 count
.
的实例化
至于未问的问题'how to get it work'
并且正如 Jonathan 所指出的那样,您的代码在任何情况下都无法执行您希望它执行的操作。 Jonathan 对 while 循环所做的解释基本上是正确的,即使 uut
被实例化,您的过程也不会按预期工作。
基本思路是一直计数到q
达到25,000,000,然后设置输出count_sortie
。请注意,评估 25000000 实际上会向 count_sortie
.
添加额外的时钟延迟
if clk'event and clk = '1' then
if q /= 24999999 and count_entree = '1' then
q <= q + 1;
end if;
if q = 24999999 then
count_sortie <= '1';
else
count_sortie <= '0';
end if;
end if;
这将计数到 24999999 并停止计数。一个时钟后 count_sortie
将被设置 (1
)。
它具有 属性,如果您要清除或加载 q
回到 0 以重新触发计时器,在 count_sortie
进入 ' 0'.
如果这可能是有害的,您可以将比较恢复到 25000000,并将赋值给 count_sortie
的 if 语句移到评估 clk
上升沿的 if 语句的边界之外,或者甚至使它成为并发条件信号赋值语句。
在过程中保留赋值可能更节俭,它在合成中与count
共享相同的比较,保证。
上面这个答案中的代码看起来像这样:
if clk'event and clk = '1' then
if q /= 25000000 and count_entree = '1' then
q <= q + 1;
end if;
end if;
if q = 25000000 then
count_sortie <= '1';
else
count_sortie <= '0';
end if;
并且q
应该在敏感列表中。还要注意整数的范围 q
只需要从最左边的值扩展到最右边的赋值。
为了演示这一点,我将所有计数值除以 100,000(出于演示目的,数字文字 250 可以在所有三个地方设置为 25000000):
architecture behavioral of count is
signal q: integer range 0 to 250 ;
begin
timer:
process (clk,q)
begin
if clk'event and clk = '1' then
if q /= 250 and count_entree = '1' then
q <= q + 1;
end if;
end if;
if q = 250 then
count_sortie <= '1';
else
count_sortie <= '0';
end if;
end process;
end architecture;
缩放 q 是为了不必要地等待所有这些时钟
演示 count_sortie
与您的测试平台一起工作:
(可点击)
现在我们不仅直接回答了您的问题,还展示了如何使其正常工作。
如果您打算使用 count_sortie
作为时钟,您会希望使用第一种方法(使用 24999999)。
我的 FPGA 中有一个 25MHz 的时钟,我想制作一个定时器,当它计数 60 秒时 returns '1'。但是我有两个问题:
- 我不明白为什么我的输出信号 "count_sortie" 在 Vivado 中仿真时未定义。
- 为了强制定义我的信号 count_sortie,我在测试台文件中添加“:= 0”进行模拟,但 "count_sortie" 在 60 秒延迟后保持等于“0”。
这是我的 VHDL 文件:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity count is
Port ( clk : in STD_LOGIC;
count_entree : in STD_LOGIC;
count_sortie : out STD_LOGIC
);
end count;
architecture Behavioral of count is
signal q : integer range 0 to 30000000 :=0;
begin
process(clk)
begin
if (clk'event and clk='1')
then
while ((count_entree = '1') and (q < 25000000)) loop
if (q < 25000000) then
q := q + 1;
count_sortie <= '0';
else
count_sortie <= '1';
end if;
end loop;
end if;
end process;
end Behavioral;
和测试台文件:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY tbcount IS
END tbcount;
ARCHITECTURE behavior OF tbcount IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT count
PORT(
clk : in STD_LOGIC;
count_entree : in STD_LOGIC;
count_sortie : out STD_LOGIC
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal count_entree : std_logic;
--Outputs
signal count_sortie : std_logic;
--Clock
constant clk_period : time := 40 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: count PORT MAP (
clk => clk,
count_entree => count_entree,
count_sortie => count_sortie
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
count_entree <= '1';
wait;
end process;
END;
感谢您的支持。
除了我对您的语法无效的评论之外,即存在混淆 q
是信号还是变量,以下代码不会执行您期望的操作:
while ((count_entree = '1') and (q < 25000000)) loop
if (q < 25000000) then
q := q + 1;
count_sortie <= '0';
else
count_sortie <= '1';
end if;
end loop;
如果在 count_entree = '1'
和 q
是信号时进入此循环,则该循环是无限循环,或者如果 q
是信号,则解析为单个语句 count_sortie <= '0'
变量。
您的循环没有任何等待语句。如果 q
是一个信号,它将永远不会更新为新值,因为当进程结束或遇到等待语句时会发生这种情况,然后您将进入无限循环。
如果q
是变量,循环展开,只有最后一次赋值有效。请注意,由于如果 q < 25000000
退出循环,因此永远不会执行 else
语句。
最后,请注意,如果这是您的最终目标,这种结构将无法合成。
没有人实际回答您的问题:
- I don't understand why my outpout signal "count_sortie" is undefined in Vivado when I simulate it.
- To force to define my signal count_sortie, I add ":= 0" in the testbench file to simulate but "count_sortie" stays equal to '0' after the 60 seconds delay.
正如变量赋值 :=
所写,您的设计描述不是有效的 VHDL。
可能值得重新审视警告消息,那里发生的事情应该很明显。标记为 uut
的实例化 count
在测试平台 tbcount
中未绑定,并且其输出信号未被驱动。就测试台而言,没有 count
.
至于未问的问题'how to get it work'
并且正如 Jonathan 所指出的那样,您的代码在任何情况下都无法执行您希望它执行的操作。 Jonathan 对 while 循环所做的解释基本上是正确的,即使 uut
被实例化,您的过程也不会按预期工作。
基本思路是一直计数到q
达到25,000,000,然后设置输出count_sortie
。请注意,评估 25000000 实际上会向 count_sortie
.
if clk'event and clk = '1' then
if q /= 24999999 and count_entree = '1' then
q <= q + 1;
end if;
if q = 24999999 then
count_sortie <= '1';
else
count_sortie <= '0';
end if;
end if;
这将计数到 24999999 并停止计数。一个时钟后 count_sortie
将被设置 (1
)。
它具有 属性,如果您要清除或加载 q
回到 0 以重新触发计时器,在 count_sortie
进入 ' 0'.
如果这可能是有害的,您可以将比较恢复到 25000000,并将赋值给 count_sortie
的 if 语句移到评估 clk
上升沿的 if 语句的边界之外,或者甚至使它成为并发条件信号赋值语句。
在过程中保留赋值可能更节俭,它在合成中与count
共享相同的比较,保证。
上面这个答案中的代码看起来像这样:
if clk'event and clk = '1' then
if q /= 25000000 and count_entree = '1' then
q <= q + 1;
end if;
end if;
if q = 25000000 then
count_sortie <= '1';
else
count_sortie <= '0';
end if;
并且q
应该在敏感列表中。还要注意整数的范围 q
只需要从最左边的值扩展到最右边的赋值。
为了演示这一点,我将所有计数值除以 100,000(出于演示目的,数字文字 250 可以在所有三个地方设置为 25000000):
architecture behavioral of count is
signal q: integer range 0 to 250 ;
begin
timer:
process (clk,q)
begin
if clk'event and clk = '1' then
if q /= 250 and count_entree = '1' then
q <= q + 1;
end if;
end if;
if q = 250 then
count_sortie <= '1';
else
count_sortie <= '0';
end if;
end process;
end architecture;
缩放 q 是为了不必要地等待所有这些时钟
演示 count_sortie
与您的测试平台一起工作:
现在我们不仅直接回答了您的问题,还展示了如何使其正常工作。
如果您打算使用 count_sortie
作为时钟,您会希望使用第一种方法(使用 24999999)。