3
votes

I am using webPack ISE v 13 to program a Nexys 3 board with the following piece of code and notice completely different behavior by swapping statements in the if elsif statement. In essence, I'm using three pushbuttons on the board: when pressing the first pushbutton btn(0), the state of 8 switches is stored in a register. When I press btn(1), the state of the switches should be displayed in the 8 leds and the leds should keep this state. When I press btn(2), I force all leds to be lit and they should stay this way if neither btn 1 or 2 is pressed. By swapping the actions under the if and elsif for buttons 1 & 2, the behavior changes: the state of the switches is only displayed when I press the corresponding button and once I let go, all LEDs light up.

More than looking for a "this is what you need to make it work", I'm after an explanation of why vhdl behaves so differently from C++ let's say (in this instance where the order wouldn't matter)

Below is the code excerpt; I indicate which lines to comment/uncomment to get behavior 'a' or behavior 'b'.

Behavior 'a':

  • when pressing btn(0) the state of the 8 switches loads correctly into the data_reg
  • when I press the btn(1), the LEDs are all ON ("111...11")
  • if I press btn(2), the LEDs display the data_reg contents
  • If no button is pressed, the state of the LEDs is that commanded by the last button press

Behavior 'b':

  • when pressing btn(0) the state of the 8 switches loads correctly into the data_reg
  • when I press btn(1), the LEDs display the data_reg contents
  • if I press btn(2), the LEDs are all ON ("111...11")
  • If no button is pressed, all LEDs are ON & the only way to see the contents of the data_reg is to hold btn(1) depressed.

`

process(clk)

begin

if (clk'event and clk='1') then
   if (db_btn(0)='1') then          --load sw state into data_reg
      data_reg <= sw;
   end if;

end if; end process;

   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

SIMULATION TESTBENCH

Here is my simulation testbench. Whenever I executed the result for all signals is UUU..UU Any comments would be greatly appreciated:

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;
3
How are db_btn and btn connected? - bmk
What does your simulator say? - simon
bmk: btn is the input to a debounce component whose output is db_btn. - irobot
Simon: I have been trying to simulate this code as you and @MartinThompson suggested, but all signals come out as UUUU. I have checked and rechecked my code, but can't find the problem. Would you guys be able to look over the code (is not too long). How would I post it? (one thing that occurs to me is editing the original post but somehow that doesn't sound kosher). - irobot
@irobot: might be a bit late, but editing your post to include your simulator testbench code isn't a bad idea... we might be able to sort your Us for you. - Martin Thompson

3 Answers

3
votes

VHDL executes if statements sequentially with cascading enables driving the output of your various conditional statements. All of the conditions are completely calculated all the time (lets ignore propagation delay for this point). The hardware "selects" the first statement that meets your conditions (the output from subsequent if elsif branches drive the enables for lower statements so if one evaluates to false the next is enabled).

I think the behavior you see does appear "odd" but in reality what do you expect. If you don't give a default value you will get unexpected results based on the hardware. You need to program in black and white. Right now you are programming gray. VHDL is much less forgiving with programmer intent. You must always be definitive and explicit.

One potential answer is that this is not the best way to code this if statement. A better method would be to create a "tick" signal indicating a "sure" button depress which drives a separate sequential latching process recording the depressed option. I imagine the behavior you see is hardware dependent and hence difficult to explain.

One other point that is not mentioned here is that you should implement a switch debouncer. Effectively the switch might be toggling a lot when held down and acting in a manner you dont expect (wire it up to an oscilliscope and put it in edge mode and youll see). You should count for a time period (eg 1ms) while a switch is depressed and only switch on after that period. Same for turning off. This might do better to buffer any bounciness you might have. This is how you would make your "sure" button depress "tick"

1
votes

It sounds like the hardware for btn(2) is throwing more '1's then you expect, or is otherwise getting a high signal more often. See if mapping to a different hardware button helps. Make sure btn (2) is set up in a pullup mode rather than pull down.

As for the code portion, be aware that the structure is a nested if, so you will see a difference in behavior when BOTH btn(1) and btn(2) are high.

0
votes

In addition to checking the behaviour with a simulator...

  • Are you sure that your switches are mapped to the correct pins on the FPGA?
  • Are the switches wired such that pressing them produces a 1 - sometimes they float to a 1 and produce 0 when pressed.