我的FPGA中有一个25MHz的时钟,我想制作一个计时器,当它计数60秒时返回'1'。但我有两个问题:
以下是我的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;
以及testbench文件:
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;
感谢您的支持。
答案 0 :(得分:2)
除了我对您的语法无效的评论,即有一个混淆,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
是信号时输入,则此循环为无限循环,如果为count_sortie <= '0'
,则该循环将解析为单个语句q
是一个变量。
你的循环没有任何等待声明。如果q
是一个信号,它将永远不会更新为新值,因为当一个进程结束或遇到一个等待语句时会发生这种情况,然后你会得到一个无限循环。
如果q
是变量,则循环展开,只有最后一个赋值有效。请注意,如果q < 25000000
退出循环,则永远不会执行else
语句。
最后,请注意,如果这是您的最终目标,这种结构将无法合成。
答案 1 :(得分:1)
实际上没有人回答你的问题:
- 我不明白为什么我的输出信号&#34; count_sortie&#34;当我模拟它时,在Vivado中是未定义的。
- 要强制定义我的信号count_sortie,我添加&#34;:= 0&#34;在testbench文件中模拟但是&#34; count_sortie&#34;等于&#39; 0&#39;延迟60秒后。
使用变量赋值:=
编写时,您的设计描述不是有效的VHDL。
可能值得重新审视警告信息,那里发生的事情应该是显而易见的。标记为count
的实例化uut
在测试平台tbcount
中未绑定,并且其输出信号未被驱动。就测试平台而言,没有count
的实例化。
至于未提出的问题&#39;如何使其发挥作用&#39;
正如乔纳森所指出的那样,你的代码在任何情况下都无法做到你想要的。 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
以重新启动定时器,那么count_sortie
转到&#39; 0&之前会有一个时钟延迟。 #39;
如果这可能是有害的,你可以将比较恢复到25000000,并将if语句的赋值移动到count_sortie
超出if语句边界的范围,评估clk
的上升沿,甚至制作它是一个并发的条件信号赋值语句。
在过程中保留作业可能更节俭,它在合成中与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)。