if-elsif-vhdl行为

if-elsif-vhdl行为,vhdl,xilinx,Vhdl,Xilinx,我使用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下的操作,行为会发生变化:只有当我按下相应的按钮

我使用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++有很大的不同,比如说(在这个例子中,顺序不重要)< /P> 下面是代码摘录;我指出要注释/取消注释哪些行以获得行为“a”或行为“b”

行为‘a’:
  • 按下btn(0)时,8个开关的状态正确加载到数据_reg
  • 当我按下btn(1)时,LED都亮起(“111…11”)
  • 如果我按下btn(2),LED将显示数据内容
  • 如果未按下任何按钮,则LED的状态与上次按下按钮时的状态相同
行为‘b’:
  • 按下btn(0)时,8个开关的状态正确加载到数据_reg
  • 当我按下btn(1)时,LED显示数据_reg内容
  • 如果我按btn(2),LED都亮起(“111…11”)
  • 如果未按下任何按钮,则所有LED都亮起&查看数据内容的唯一方法是按住btn(1)
`

过程(clk)

开始

if(db_btn(0)='1')然后——将软件状态加载到数据_reg
数据注册btn,
发光二极管=>发光二极管
);
--时钟进程定义
clk_流程:流程
开始
时钟‘0’;
等待时钟周期*5;
btn'0');
--在这里插入刺激
等待
结束过程;
结束;

除了用模拟器检查行为外

  • 您确定交换机已映射到服务器上的正确引脚吗 FPGA
  • 开关接线是否正确,按下开关会产生
    1
    - 有时它们浮动到
    1
    ,按下时产生
    0

听起来,btn(2)的硬件比您预期的“1”更多,或者更频繁地接收到高信号。查看映射到其他硬件按钮是否有帮助。确保btn(2)设置为上拉模式,而不是下拉模式


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

VHDL按顺序执行if语句,通过级联可以驱动各种条件语句的输出。所有的条件都会一直被完全计算出来(让我们忽略这一点的传播延迟)。硬件“选择”满足您条件的第一条语句(后续if elsif分支的输出驱动ENABLE for lower语句,因此,如果一条语句的计算结果为false,则启用下一条语句)

我认为你看到的行为确实显得“奇怪”,但实际上你期望什么呢。如果不提供默认值,将根据硬件得到意外的结果。你需要用白纸黑字编程。现在你正在编程格雷。VHDL对于程序员的意图来说就不那么宽容了。你必须始终是明确的和明确的

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


这里没有提到的另一点是,您应该实现一个开关去Bouncer。实际上,当按下开关时,开关可能会频繁切换,并以您意想不到的方式工作(将其连接到示波器,并将其置于边缘模式,您将看到)。按下开关时,您应计算一段时间(如1ms),并仅在该时间段后打开。关闭时也一样。这可能会更好地缓冲您可能有的任何反弹。这就是你如何确保你的“确定”按钮按下“勾选”

如何连接
db_btn
btn
的方法?你的模拟器怎么说?bmk:btn是一个去盎司组件的输入,其输出为db_btn。西蒙:我一直在尝试按照你和@MartinThompson的建议模拟这个代码,但所有信号都显示为UUUU。我已经反复检查了我的代码,但没有发现问题。你们能看一下代码吗(不会太长)。我该如何邮寄?(我想到的一件事是编辑原始帖子,但不知怎么的,这听起来不太符合犹太教义)。@irobot:可能有点晚了,但编辑你的帖子以包含你的模拟器测试台代码并不是一个坏主意。。。我们也许可以为您排序
U
s。马丁。谢谢你的回复。这是一个现成的面板,我以前测试过按钮。同样,UCF来自电路板制造商。此外,代码在一个实例中重复地按预期工作,但即使在我更改if-then循环时它有一个意外的行为,但该行为是一致的,而不是虚假的,因为如果这是一个浮动输入,它的行为将是虚假的……感谢Voider。我尝试了其他按钮在董事会和行为是不变的。我还没有测试的btn(1)和btn(2)高的情况下。。。我会的,稍后会报告。谢谢你非常详细的回复。
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
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;