在 VHDL 中保持动作
Posted
技术标签:
【中文标题】在 VHDL 中保持动作【英文标题】:Holding an action in VHDL 【发布时间】:2012-11-15 18:18:58 【问题描述】:我想用 Quartus II 创建一个项目,它的功能是根据代码启用三个不同的 LED。当您输入代码时,第一个 LED 将亮起。根据输入的代码,第二个或第三个将打开。我的问题是,当代码正确时,我希望第二个 LED 亮 3 秒,如果不正确,第三个 LED 将在 2 秒内亮。如果你能帮助我,那就太好了。
谢谢!
注意:led 被声明为逻辑向量,代码的编号被声明为从 0 到 7 的中断。
代码:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY programa IS
PORT
(
interrup : in Std_Logic_Vector (7 downto 0);
clk, rst: in Std_Logic;
led : out Std_Logic_Vector (2 downto 0)
);
END programa;
ARCHITECTURE arch_programa OF programa IS
type state is (zero, one, two, three, four, five, six);
signal pr_state, nx_state : state;
signal A : Std_Logic_Vector (3 downto 0);
BEGIN
process(interrup, pr_state)
begin
case pr_state is
when zero =>
led <= "100";
A(0) <= interrup(7);
nx_state <= one;
when one =>
led <= "100";
A(1) <= interrup(6);
nx_state <= two;
when two =>
led <= "100";
A(2) <= interrup(5);
nx_state <= three;
when three =>
led <= "100";
A(3) <= interrup(3);
nx_state <= four;
when four =>
led <= "100";
if(A = "1111") then nx_state <= five;
else nx_state <= six;
end if;
when five =>
led <= "010";
nx_state <=zero;
when six =>
led <= "001";
nx_state <=zero;
end case;
end process;
process(rst,clk)
begin
if(rst='1') then
pr_state <= zero;
elsif (clk'event and clk = '1') then
pr_state <= nx_state;
end if;
end process;
end arch_programa;
【问题讨论】:
@BrianDrummond 我想知道如何让 LED 亮起 3 或 2 秒,以及程序如何等到有人按下按钮而不是时钟为“1”时。 【参考方案1】:至于第一个问题,您需要计算 3 或 2 秒的时钟脉冲,因此您需要知道时钟频率。 例如,当您打开 LED 时启动计数器,当您计算出正确的脉冲数时关闭 LED 和计数器。从该值开始倒数并在计数器达到零时停止通常更容易。
至于第二个,按钮必须通过输入端口连接,您可以将其用作进程之一的输入。
【讨论】:
感谢您的回答。第一个问题似乎很好添加一个计数器,但在第二个答案中,我需要以时钟频率的速度按下一个按钮(而且我还没有那么快),那么我的程序如何等到我按下它?我正在考虑添加一个 ENABLE,但我不知道它是否会起作用。 你开始思考正确的路线。找到例如的例子应该不难。带在线启用的计数器,或随 Quartus 提供 请注意,VHDL不是C,没有程序,你用VHDL写的东西是综合成硬件的。您在 VHDL 中编写的所有内容都是同时“执行”的,因此 VHDL 中没有“等待”,您可以使用不同的组合来控制逻辑,就像它正在“等待”一样。 vhdl 中的等待大多是不可合成的。您可以使用等待;但这会阻止循环进一步发展。等待不用于创建一些时间延迟,它只是等待某个事件或永远等待。 等到rising_edge(clk);肯定是可以综合的!但是等1个我们; (这确实会产生时间延迟,并且在模拟中很常见)是不可综合的。【参考方案2】:可能有很多方法可以解决这个问题,但在不更改代码的情况下,这里有一个(注意,未完全测试)。
为每个状态提供一个取决于时钟速率的计数输出。 建立一个足以容纳最大计数的计数器寄存器。 减少每个时钟的计数,当它为零时重新加载。 重载值来自新状态。 在零之前的最后一个计数上切换状态。library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY programa IS
PORT
(
interrup : in Std_Logic_Vector (7 downto 0);
clk, rst: in Std_Logic;
led : out Std_Logic_Vector (2 downto 0)
);
END programa;
ARCHITECTURE arch_programa OF programa IS
type state is (zero, one, two, three, four, five, six);
signal pr_state, nx_state : state;
signal A : Std_Logic_Vector (3 downto 0);
signal count,pr_count:integer; --NOTE: Synthisizing integers is very unpredictable, should use unsigned
BEGIN
assign_counts:process(pr_state)
begin
--no idea what states need what delay, this is just an example
case pr_state is
when zero | one | two =>
pr_count<=10;
when four =>
pr_count<=20;
when others =>
pr_count<=50;
end case;
end process;
process(interrup, pr_state)
begin
case pr_state is
when zero =>
led <= "100";
A(0) <= interrup(7);
nx_state <= one;
when one =>
led <= "100";
A(1) <= interrup(6);
nx_state <= two;
when two =>
led <= "100";
A(2) <= interrup(5);
nx_state <= three;
when three =>
led <= "100";
A(3) <= interrup(3);
nx_state <= four;
when four =>
led <= "100";
if(A = "1111") then nx_state <= five;
else nx_state <= six;
end if;
when five =>
led <= "010";
nx_state <=zero;
when six =>
led <= "001";
nx_state <=zero;
end case;
end process;
process(rst,clk)
begin
if(rst='1') then
pr_state <= zero;
count<=pr_count;
elsif (clk'event and clk = '1') then
if count=0 then
count<=pr_count;
elsif count=1 then
pr_state <= nx_state;
count<=count-1;
else
count<=count-1;
end if;
end if;
end process;
end architecture;
--Test bench
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity bench is
end bench;
architecture bench of bench is
component programa IS
PORT (
interrup : in Std_Logic_Vector (7 downto 0);
clk, rst: in Std_Logic;
led : out Std_Logic_Vector (2 downto 0));
END component;
signal clk:std_logic:='1';
signal interrup:std_logic_vector (7 downto 0);
signal rst:std_logic;
constant freq:real:=1.0e6;
begin
do_reset:process
begin
rst<='1';
wait for 10 us;
rst<='0';
wait;
end process;
clk<=not clk after 0.5 sec / freq;
UUT:programa port map (
interrup => interrup,
clk => clk,
rst => rst);
end architecture;
【讨论】:
整数合成工作得很好。但是对它们进行子类型化或至少设置一个范围来控制结果的大小!例如信号计数:整数范围 0 到 99;以上是关于在 VHDL 中保持动作的主要内容,如果未能解决你的问题,请参考以下文章