0

我正在尝试设计一个交通灯控制器,为此我需要许多不同的计时器。因此,我用 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 对此进行了测试),因此我的控制器中的状态没有进展。我不知道为什么会这样?

4

1 回答 1

1

n中的位数在哪里cnt,这是:

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

应该:

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

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

这是上面的校正并n设置为3使其适合短波形显示:

输入 n 等于 3 的计时器

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

使计数变得粘稠

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

假设n-1是 的触发值count

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

这基本上使用与反相器相同的n宽栅极输出count来提供和启用cnt计数器。它只会超出cntby的锁存触发值reset

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

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

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

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

于 2014-04-01T03:34:51.150 回答