【问题标题】:VHDL timer that returns 1 when it has reached its countVHDL 定时器,当它达到它的计数时返回 1
【发布时间】:2014-04-01 01:51:30
【问题描述】:

我正在尝试设计一个交通信号灯控制器,为此我需要许多不同的计时器。因此,我用 VHDL 设计了这个通用计时器:

library IEEE;
use IEEE.std_logic_1164.all, IEEE.numeric_std.all;

entity timer is
generic (n: NATURAL :=20);
    port (clk, reset : in std_logic;
            count : buffer std_logic);
end entity timer;


architecture behavioural of timer is
begin
    o0: process (clk, reset) IS
    variable cnt : unsigned (n-1 downto 0);
    begin
        if reset = '0' then
            cnt := (others => '0');
        elsif rising_edge(clk) then
            cnt := cnt + 1;
        end if;
        if cnt = n-1 then
            count <= '1';
        else
            count <= '0';
        end if;
    end process;
end architecture behavioural;

但是,当我运行定时器时,它输出 0 并且永远不会改变(我通过将计数映射到 Altera MAX II EMP240T100C5 上的 LED 对此进行了测试),因此我的控制器中的状态没有进展。我不知道为什么会这样?

【问题讨论】:

  • 如果您按照 David 的建议修复此问题并按照您上面的建议映射到 LED,那么 LED 将仅每 2**n-1 个时钟点亮 1 个时钟,您不太可能会看到带领。它会如此短暂地开启,如果有的话,它的强度将非常低。
  • @JimLewis 谢谢,有没有办法让它在 1 的值上直到它被重置?我真的需要在计数到指定的数字后才能停止。

标签: generics timer counter vhdl intel-fpga


【解决方案1】:

其中ncnt 中的位数,这是:

    if cnt = n-1 then
        count <= '1';

应该是:

    if cnt = 2**n-1 then
        count <= '1';

count 只有一个时钟的“1”。你有没有眨眼并错过它?您没有指定时钟频率。为了演示计数器,我将 clk 设置为 25 MHz。

这是上面的修正,n 设置为3,所以它适合短波形显示:

如果没有上述更正,count 'pulse' 将在 19 个时钟后发生。为什么您的红绿灯控制器没有响应是另一个问题。

使计数具有粘性

在您发表评论说您想将计时器用作 19 时钟延迟后,您问 Jim 如何锁定计数。

假设n-1count的触发值:

    elsif rising_edge(clk) and cnt /= n-1 then
        cnt := cnt + 1;
    end if;

这实质上使用与count 相同的n 宽门输出和反相器来提供和启用cnt 计数器。它只会超出cnt 的锁定触发值reset

为什么cnt 在它的声明中指定为n 位值,而在这种情况下它只需要 5 位长?

您是否打算单独提供触发器计数来概括您的计时器?在这种情况下,我怀疑同步重置会按顺序进行。

最简单的整体解决方案可能是 -

制作cnt和整数类型:

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

entity timer is
    generic (
        trigger_cnt:    natural := 19
    );
    port (
        clk:        in      std_logic;
        reset:      in      std_logic;
        count:      buffer  std_logic
    );
end entity timer;


architecture behavioural of timer is

begin
o0: process (clk, reset) IS
    variable cnt : natural range 0 to trigger_cnt;
    begin
        if reset = '0' then
            cnt := 0;
        elsif rising_edge(clk) and count = '0' then
            cnt := cnt + 1;
        end if;
        if cnt = trigger_cnt then
            count <= '1';
        else
            count <= '0';
        end if;
    end process;

end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity tb_timer is
end entity;

architecture foo of tb_timer is
    signal clk:     std_logic := '0';
    signal reset:   std_logic;
    signal count:   std_logic;
begin 

DUT:  
    entity work.timer
    generic map (
        trigger_cnt =>  7
    )
    port map (
    clk => clk,
    reset => reset,
    count => count
    );

CLOCK:
    process

    begin
        wait for 20 ns;
        clk <= not clk;
        if Now > 360 ns then
            wait;
        end if;
    end process;

STIMULUS:
    process 
    begin
        reset <= '0';
        wait for 40 ns;
        reset <= '1';
        wait;
    end process;
end architecture;

注意这里有粘性count

不是n 作为泛型,而是将值trigger_cnt(与整数类型兼容)呈现为泛型。

在此过程中,trigger_cnt 用于限制cnt 的范围,这将为您提供正确位数的合成计数器。

因为计数器在重置前停止,所以不会出现任何基于整数类型 cnt 超出其范围的讨厌错误。

这仅适用于 VHDL 实现的整数范围内的触发计数(此处显示的自然范围,subtype NATURAL is INTEGER range 0 to INTEGER'HIGH; 其中 INTEGER'HIGH 是实现定义的,并且至少为 2**31-1(+2147483647,请参阅预定义整数类型,IEEE Std 1076)。

【讨论】:

  • 谢谢。然而,目的是让“脉冲”在 19 个时钟后发生,因为它需要在 n 个时钟节拍后触发交通灯控制器的变化。那么这是否意味着代码应该按原样工作?
  • 谢谢,我已经写好了,我会尽快测试它:)。将其指定为 'n' 位值的原因是因为计时器需要计数到不同的大小(例如,在某一时刻它被初始化为 'timer3 : timer generic map (n => 3) port map(clk,reset3,count3); ') 并且我认为这就是我如何将它计数为可变的数字?
  • 我建议通过算法(一个函数)将计数器 (cnt) 的大小与触发值相关联并提供它,或者提供两个泛型。 19 的计数适合 5 位计数器,而 (n-1 downto 0) 是 20 位。一个函数可以增加 2 的幂,直到超过触发计数(不需要是 2 的幂),为cnt 的范围提供左值。
  • 谢谢,这行得通:)。我认为这种方法比我的(n-1 downto 0) 分配更有效?
  • 使用无符号的 cnt 实现使 cnt 足够大,它会更有效,而不是遍历您不用于 + 1 操作的位。它们在合成过程中自然会被削减(产生警告)。使用自然(整数)cnt 是最有效的。它不是带有遍历“位”的循环的函数“+”,而是整数“+”的单个操作。当使用自然 cnt 时,范围告诉合成要使用多少位。
猜你喜欢
  • 1970-01-01
  • 2015-07-09
  • 1970-01-01
  • 1970-01-01
  • 2017-07-29
  • 2016-02-01
  • 1970-01-01
  • 2021-07-13
  • 2012-08-04
相关资源
最近更新 更多