2

我正在使用 webPack ISE v 13 使用以下代码对 Nexys 3 板进行编程,并通过在 if elsif 语句中交换语句来注意到完全不同的行为。本质上,我在板上使用了三个按钮:当按下第一个按钮 btn(0) 时,8 个开关的状态存储在一个寄存器中。当我按下 btn(1) 时,开关的状态应显示在 8 个 LED 中,并且 LED 应保持此状态。当我按下 btn(2) 时,我强制点亮所有 LED,如果没有按下 btn 1 或 2,它们应该保持这种状态。通过交换按钮 1 和 2 的 if 和 elsif 下的操作,行为会发生变化:仅当我按下相应的按钮时才会显示开关的状态,一旦松开,所有 LED 都会亮起。

不仅仅是寻找“这是你需要让它工作的东西”,我还在解释为什么 vhdl 的行为与 C++ 如此不同,比如说(在这种情况下,顺序无关紧要)

以下是代码摘录;我指出要评论/取消评论哪些行以获得行为“a”或行为“b”。

行为“一”:

  • 按下 btn(0) 时,8 个开关的状态会正确加载到 data_reg
  • 当我按下 btn(1) 时,LED 全部亮起(“111...11”)
  • 如果我按 btn(2),LED 会显示 data_reg 内容
  • 如果未按下任何按钮,则 LED 的状态为最后一次按下按钮所指示的状态

行为'b':

  • 按下 btn(0) 时,8 个开关的状态会正确加载到 data_reg
  • 当我按下 btn(1) 时,LED 显示 data_reg 内容
  • 如果我按 btn(2),LED 全部亮起(“111...11”)
  • 如果未按下任何按钮,则所有 LED 都亮起,查看 data_reg 内容的唯一方法是按住 btn(1)。

`

进程(时钟)

开始

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;
4

3 回答 3

3

VHDL 使用级联顺序执行 if 语句,从而可以驱动各种条件语句的输出。所有的条件都是完全计算的(让我们忽略这一点的传播延迟)。硬件“选择”第一个满足您条件的语句(后续 if elsif 分支的输出驱动较低语句的启用,因此如果一个评估为假,则启用下一个)。

我认为您看到的行为确实看起来“奇怪”,但实际上您期望什么。如果您不提供默认值,您将获得基于硬件的意外结果。您需要进行黑白编程。现在你正在编程灰色。对于程序员的意图,VHDL 的宽容度要低得多。你必须始终是明确的和明确的。

一个可能的答案是,这不是编写此 if 语句的最佳方式。一种更好的方法是创建一个指示“确定”按钮按下的“滴答”信号,该信号驱动一个单独的顺序锁存过程,记录按下的选项。我想您看到的行为取决于硬件,因此难以解释。

这里没有提到的另一点是你应该实现一个开关去抖动器。实际上,当按住并以您不期望的方式操作时,开关可能会切换很多(将其连接到示波器并将其置于边缘模式,您会看到)。您应该在按下开关时计算一段时间(例如 1 毫秒),并且仅在该时间段后打开。关机也是一样。这可能会更好地缓冲您可能拥有的任何弹性。这就是你如何让你的“确定”按钮按下“勾号”

于 2012-06-18T19:55:12.703 回答
1

听起来 btn(2) 的硬件抛出的 '1' 比您预期的要多,或者更频繁地获得高信号。看看映射到不同的硬件按钮是否有帮助。确保 btn (2) 设置为上拉模式而不是下拉模式。

至于代码部分,请注意结构是嵌套的 if,因此当 btn(1) 和 btn(2) 都为高时,您会看到行为上的差异。

于 2012-06-14T19:22:41.483 回答
0

除了用模拟器检查行为...

  • 您确定您的开关已映射到 FPGA 上的正确引脚吗?
  • 开关是否接线以便按下它们会产生1- 有时它们会浮动到 a10在按下时产生。
于 2012-06-14T09:38:06.413 回答