Generics 达到计数时返回1的VHDL计时器
我正试图设计一个交通灯控制器,为此我需要一些不同的定时器。因此,我用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
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;