我正在使用webPack ISE v 13使用以下代码对Nexys 3板进行编程,并通过在if elsif语句中交换语句来注意完全不同的行为。本质上,我在电路板上使用了三个按钮:当按下第一个按钮btn(0)时,8个开关的状态存储在寄存器中。当我按下btn(1)时,开关的状态应显示在8个LED中,LED应该保持这种状态。当我按下btn(2)时,我强制所有LED点亮,如果没有按下btn 1或2,它们应该保持这种状态。通过交换if和elsif下的按钮1和按钮1的操作。 2,行为改变:只有当我按下相应的按钮时才会显示开关的状态,一旦我放开,所有的LED都会亮起。
除了寻找“这就是你需要使它工作的东西”之外,我还在解释为什么vhdl的行为与C ++有如此不同的说法(在这种情况下订单无关紧要)
以下是代码摘录;我指出哪些行要评论/取消注释以获得行为'a'或行为'b'。
`
处理(CLK)
开始
if (clk'event and clk='1') then
if (db_btn(0)='1') then --load sw state into data_reg data_reg <= sw; end if;
结束如果; 结束过程;
process(btn,data_reg)
begin
if btn(1)='1' then
data_s2f <= "1111111111111111"; --behvr a; comment this line for behvr b
-- data_s2f <= "00000000" & data_reg; -- uncomment for behvr b; comment for behvr a
elsif btn(2)='1' then -- read
data_s2f <= "00000000" & data_reg; --behvr a; comment this line for behvr b
--data_s2f <= "1111111111111111"; -- uncomment for behvr b; comment for behvr a
end if;
end process;
-- output
led <= data_s2f(7 downto 0); --display data_s2f in LEDs
这是我的模拟测试平台。每当我执行所有信号的结果是UUU..UU任何评论将不胜感激:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY ifstmt_tb IS
END ifstmt_tb;
ARCHITECTURE behavior OF ifstmt_tb IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT ram_ctrl_test
PORT(
clk : IN std_logic;
reset : IN std_logic;
sw : IN std_logic_vector(7 downto 0);
btn : IN std_logic_vector(2 downto 0);
led : OUT std_logic_vector(7 downto 0)
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal reset : std_logic := '0';
signal sw : std_logic_vector(7 downto 0) := (others => '0');
signal btn : std_logic_vector(2 downto 0) := (others => '0');
--Outputs
signal led : std_logic_vector(7 downto 0);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: ram_ctrl_test PORT MAP (
clk => clk,
reset => reset,
sw => sw,
btn => btn,
led => led
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
reset <= '1';
sw <= "11001100";
btn<= (others => '0');
wait for 100 ns;
reset <= '0';
wait for clk_period*10;
-- load register
btn<= (0=>'1', others => '0');
wait for clk_period*2;
btn<= (others => '0');
wait for clk_period*10;
-- display with btn 1
btn<= (1=>'1', others => '0');
wait for clk_period*5;
btn<= (others => '0');
wait for clk_period*10;
-- display with btn 2
btn<= (2=>'1', others => '0');
wait for clk_period*5;
btn<= (others => '0');
wait for clk_period*10;
-- change pattern
sw <= "11100111";
wait for clk_period;
-- load register
btn<= (0=>'1', others => '0');
wait for clk_period*2;
btn<= (others => '0');
wait for clk_period*10;
-- display with btn 2
btn<= (2=>'1', others => '0');
wait for clk_period*5;
btn<= (others => '0');
wait for clk_period*10;
-- display with btn 1
btn<= (1=>'1', others => '0');
wait for clk_period*5;
btn<= (others => '0');
-- insert stimulus here
wait;
end process;
END;
答案 0 :(得分:2)
如果使用级联顺序执行语句,VHDL将执行驱动各种条件语句的输出。所有条件都是完全计算的(让我们忽略此点的传播延迟)。硬件“选择”满足您条件的第一个语句(如果elsif分支驱动下级语句的启用,则后续输出,因此如果一个计算结果为false,则启用下一个语句)。
我认为你看到的行为确实显得“奇怪”,但实际上你的期望是什么。如果您未提供默认值,则会根据硬件获得意外结果。你需要以黑白编程。现在你正在编程灰色。 VHDL对程序员意图的宽容程度要低得多。你必须始终是明确的和明确的。
一个可能的答案是,这不是编写此if语句的最佳方法。一种更好的方法是创建一个“滴答”信号,指示“确定”按钮按下,该信号驱动记录按下选项的单独的顺序锁存过程。我想你看到的行为是硬件依赖的,因此难以解释。
这里没有提到的另一点是你应该实现一个开关去抖动器。有效地,当按下并以您不期望的方式操作时,开关可能会切换很多(将其连接到示波器并将其置于边缘模式,您将看到)。您应该在按下开关时计算一段时间(例如1ms),并且仅在该时间段后打开。关闭也一样。这可能会更好地缓冲您可能拥有的任何弹性。这就是你如何让你的“确定”按钮压下“滴答”
答案 1 :(得分:1)
听起来btn(2)的硬件投入的时间比你期望的要高1,或者更频繁地获得高信号。查看映射到其他硬件按钮是否有帮助。确保btn(2)设置为上拉模式而不是下拉。
至于代码部分,请注意结构是嵌套的if,因此当BOTH btn(1)和btn(2)为高时,您将看到行为上的差异。
答案 2 :(得分:0)
除了使用模拟器检查行为......
1
-
有时它们会浮动到1
并在按下时生成0
。