VHDL 我的定时器不工作

VHDL My timer does not work

我的 FPGA 中有一个 25MHz 的时钟,我想制作一个定时器,当它计数 60 秒时 returns '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;

和测试台文件:

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)。