Generics 达到计数时返回1的VHDL计时器

Generics 达到计数时返回1的VHDL计时器,generics,timer,counter,vhdl,intel-fpga,Generics,Timer,Counter,Vhdl,Intel Fpga,我正试图设计一个交通灯控制器,为此我需要一些不同的定时器。因此,我用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 time

我正试图设计一个交通灯控制器,为此我需要一些不同的定时器。因此,我用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;
IEEE库;
使用IEEE.std_logic_1164.all、IEEE.numeric_std.all;
实体计时器为
一般(n:自然:=20);
端口(时钟,复位:在标准逻辑中;
计数:缓冲区标准(U逻辑);
结束实体计时器;
定时器的结构行为是
开始
o0:进程(clk、重置)正在运行
变量cnt:无符号(n-1到0);
开始
如果重置='0',则
cnt:=(其他=>'0');
elsif上升沿(clk)则
cnt:=cnt+1;
如果结束;
如果cnt=n-1,则

count其中
n
cnt
中的位数,这是:

    if cnt = n-1 then
        count <= '1';
这基本上使用了与
count
相同的
n
宽门输出,并使用一个反相器来提供和启用
cnt
计数器。它将仅通过
reset
cnt
的锁存触发值中取出

为什么
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;
ieee库;
使用ieee.std_logic_1164.all;
使用ieee.numeric_std.all;
实体计时器为
一般的(
触发:自然:=19
);
港口(
clk:标准逻辑中;
复位:在标准逻辑中;
计数:缓冲区标准逻辑
);
结束实体计时器;
定时器的结构行为是
开始
o0:进程(clk、重置)正在运行
变量cnt:自然范围0至触发_cnt;
开始
如果重置='0',则
cnt:=0;
如果上升沿(clk)和计数为'0',则
cnt:=cnt+1;
如果结束;
如果cnt=触发_cnt,则
钟伯爵,
重置=>重置,
计数=>计数
);
时钟:
过程
开始
等待20纳秒;
时钟360纳秒
等待
如果结束;
结束过程;
刺激:
过程
开始

重置如果按照David的建议进行修复,并按照上述建议映射到LED,则LED每2**n-1个时钟仅点亮1个时钟,并且您不太可能看到LED亮起。它将短暂开启,如果有的话,它的强度将非常低。@JimLewis谢谢,有没有办法让它保持在1的值上,直到它被重置?我真的需要计数器停止后,它已计数到指定的数字。谢谢。然而,“脉冲”的目的是在19个时钟之后出现,因为它需要在n个时钟滴答声之后触发交通灯控制器的变化。那么这是否意味着代码应该按原样工作呢?谢谢,我已经编写好了,稍后将对其进行测试:)。将其指定为“n”位值的原因是计时器需要计数到不同的大小(例如,在某一点上,它被初始化为“timer3:timer generic map(n=>3)端口映射(clk,reset3,count3);”),我假设这就是我如何将它计数的数字变为变量的方法?我建议使用算法(函数)将计数器(
cnt
)的大小与触发器值关联,并仅提供它,或提供两个泛型。当
(n-1到0)
为20位时,19的计数适合于5位计数器。一个函数可以向上移动2的幂,直到它超过触发器计数(不需要是2的幂),为
cnt
范围提供左值。谢谢,这样可以:)。我假设此方法比我的
(n-1到0)
分配更有效?使用无符号cnt实现使cnt足够大,它将更有效,而不是遍历不用于+1操作的位。它们在合成过程中自然会减少(产生警告)。使用自然(整数)cnt是最有效的。它不是循环遍历“位”的函数“+”,而是整数“+”的单个操作。当使用天然cnt时,范围告诉合成要使用多少位。
    elsif rising_edge(clk) and cnt /= n-1 then
        cnt := cnt + 1;
    end if;
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;